/* ============================================================
   Wallace — site.css · v2.0 (matches the app's design system)
   ----------------------------------------------------------------
   Type scale: t-h1..t-h6 (54/42/32/24/20/18) — never larger.
   Color: lime-200 primary, panel-warm sidebar, pastel categorical.
   Button signature: 2px var(--lime-350) stroke on primary.
   Radii: --r-xl (20px) default, nested ≤ outer − 8px.
   ============================================================ */

/* ---- 0. Reset --------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  font-feature-settings: "rlig" 1, "calt" 1;
  /* Match body bg so iOS Safari's overscroll bounce reveals the same
     warm paper tone instead of the browser's default white. Without
     this, pulling past the top or bottom of the page flashes white
     under the body — looks like a "white band" under the footer. */
  background: var(--canvas);
  /* Stop the rubber-band bounce from chaining out to the page itself.
     Internal scroll containers (the mobile drawer) still scroll
     naturally because they have their own overflow context. */
  overscroll-behavior-y: none;
}
body {
  background: var(--canvas);
  color: var(--k-200);
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
img, svg, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, h5, h6, p { margin: 0; }
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-sans);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: 0;
}
::selection { background: var(--lime-100); color: var(--k-200); }
button { font: inherit; color: inherit; cursor: pointer; }

/* Hide tweaks-trigger from view but keep it accessible. */
.tweaks-trigger { opacity: 0.18; transition: opacity .2s; }
.tweaks-trigger:hover, .tweaks-trigger:focus-visible { opacity: 1; }

/* ---- 1. A11y -------------------------------------------- */
.skip-link {
  position: absolute; left: -9999px;
  background: var(--k-200); color: var(--paper);
  padding: 12px 16px; border-radius: var(--r-md);
  font-weight: 500; font-size: 14px;
}
.skip-link:focus { left: 16px; top: 16px; z-index: 999; }

:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--lime-350) 60%, transparent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

/* ---- 2. Type helpers (mirror of App.css) ----------------- */
.t-h1 { font: var(--fw-h1)   var(--fs-h1)/var(--lh-h1)   var(--font-sans); letter-spacing: var(--ls-h1); }
.t-h2 { font: var(--fw-h2)   var(--fs-h2)/var(--lh-h2)   var(--font-sans); letter-spacing: var(--ls-h2); }
.t-h3 { font: var(--fw-h3)   var(--fs-h3)/var(--lh-h3)   var(--font-sans); }
.t-h4 { font: var(--fw-h4)   var(--fs-h4)/var(--lh-h4)   var(--font-sans); }
.t-h5 { font: var(--fw-h5)   var(--fs-h5)/var(--lh-h5)   var(--font-sans); }
.t-h6 { font: var(--fw-h6)   var(--fs-h6)/var(--lh-h6)   var(--font-sans); }
.t-sub-m  { font: var(--fw-sub-m)  var(--fs-sub-m)/var(--lh-sub-m)   var(--font-sans); }
.t-sub-s  { font: var(--fw-sub-s)  var(--fs-sub-s)/var(--lh-sub-s)   var(--font-sans); }
.t-body-l { font: var(--fw-body-l) var(--fs-body-l)/var(--lh-body-l) var(--font-sans); }
.t-body-m { font: var(--fw-body-m) var(--fs-body-m)/var(--lh-body-m) var(--font-sans); }
.t-body-s { font: var(--fw-body-s) var(--fs-body-s)/var(--lh-body-s) var(--font-sans); }
.t-body-xs{ font: var(--fw-body-xs)var(--fs-body-xs)/var(--lh-body-xs)var(--font-sans); }
.t-caption { font: var(--fw-caption) var(--fs-caption)/var(--lh-caption) var(--font-sans); letter-spacing: var(--ls-caption); text-transform: uppercase; }
.t-mono    { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.02em; }

/* Eyebrow — tiny mono caption used as section markers. */
.eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--font-mono);
  font-size: 11px; line-height: 1;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--g-500);
  font-weight: 500;
}
.eyebrow .num { color: var(--lime-500); font-weight: 600; }
.eyebrow::before {
  content: ""; width: 18px; height: 1px;
  background: currentColor; opacity: 0.5;
}

/* ---- 3. Wallace primitives in CSS (mirror Card/Button/Badge) --- */

/* Card — paper variant by default. */
.ui-card {
  display: flex; flex-direction: column; gap: 16px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  box-shadow: var(--e-2);
  color: var(--k-200);
  transition: border-color var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.ui-card.is-padded { padding: 24px; }
.ui-card.is-compact { padding: 16px; gap: 8px; }
.ui-card.is-comfortable { padding: 32px; gap: 20px; }

/* Hero variant — lime-200 fill + 2px lime-350 stroke. THE Wallace signature. */
.ui-card.variant-hero {
  background: var(--lime-200);
  border: 2px solid var(--lime-350);
  box-shadow: var(--e-3);
}

/* Dark variant — k-200 fill, lime-200 foreground. */
.ui-card.variant-dark {
  background: var(--k-200);
  color: var(--lime-200);
  border-color: var(--k-100);
  box-shadow: var(--e-3);
}

/* Interactive — paper + hover lifts to k-200 border. */
.ui-card.variant-interactive {
  cursor: pointer;
}
.ui-card.variant-interactive:hover {
  border-color: var(--k-200);
  box-shadow: var(--e-3);
}

/* Buttons — 2 px lime-350 stroke is the recognizable Wallace primary. */
.ui-btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 8px;
  border-radius: var(--r-xl);
  border: 2px solid transparent;
  font-family: var(--font-sans);
  font-weight: 500;
  letter-spacing: 0.5px;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              transform var(--dur-fast) var(--ease-standard);
}

/* Sizes — match button label scale (t-btn-l/m/s). */
.ui-btn-lg { font-size: 16px; line-height: 1; padding: 12px 24px; min-height: 44px; }
.ui-btn-md { font-size: 14px; line-height: 1; padding: 10px 18px; min-height: 38px; }
.ui-btn-sm { font-size: 13px; line-height: 1; padding: 8px 14px;  min-height: 32px; }

.ui-btn-primary {
  background: var(--lime-200);
  color: var(--k-200);
  border-color: var(--lime-350);
}
.ui-btn-primary:hover {
  background: var(--lime-300);
  border-color: var(--lime-400);
}
.ui-btn-primary:active {
  background: var(--lime-400);
  border-color: var(--lime-500);
}

.ui-btn-dark {
  background: var(--k-200);
  color: var(--lime-200);
  border-color: var(--k-200);
}
.ui-btn-dark:hover { background: var(--k-100); border-color: var(--k-100); }

.ui-btn-ghost {
  background: transparent;
  color: var(--k-200);
  border-color: var(--hairline);
}
.ui-btn-ghost:hover {
  background: var(--panel-warm);
  border-color: var(--g-200);
}

.ui-btn-icon-right { transition: transform var(--dur-fast) var(--ease-standard); }
.ui-btn:hover .ui-btn-icon-right { transform: translateX(2px); }

/* Badge — pastel + brand variants. */
.ui-badge {
  display: inline-flex; align-items: center; gap: 4px;
  height: 20px;
  padding: 0 8px;
  border-radius: var(--r-full);
  border: 1px solid transparent;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0;
  white-space: nowrap;
}
.ui-badge.tone-default,
.ui-badge.tone-live {
  background: var(--lime-200);
  color: var(--k-200);
  border-color: var(--lime-350);
}
.ui-badge.tone-mint    { background: var(--mint-100); color: var(--mint-700); }
.ui-badge.tone-forest  { background: var(--forest-100); color: var(--forest-700); }
.ui-badge.tone-warm    { background: var(--panel-warm); color: var(--g-600); border-color: var(--hairline); }
.ui-badge.tone-mono    { background: var(--panel-warm); color: var(--g-600); font-family: var(--font-mono); padding: 0 6px; min-width: 20px; }
.ui-badge.tone-fail    { background: var(--coral-100); color: var(--coral-500); }
.ui-badge.tone-dark    { background: var(--k-200); color: var(--lime-200); }
.ui-badge.tone-arxiv   { background: var(--pastel-blue); color: var(--k-200); }
.ui-badge.tone-doi     { background: var(--pastel-lavender); color: var(--k-200); }
.ui-badge.tone-pdf     { background: var(--pastel-pink); color: var(--k-200); }
.ui-badge.tone-url     { background: var(--pastel-sage); color: var(--k-200); }
.ui-badge.tone-extension{ background: var(--pastel-yellow); color: var(--k-200); }
.ui-badge.tone-peach   { background: var(--pastel-peach); color: var(--k-200); }
.ui-badge-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 0.5px currentColor inset;
}

/* Input — used in mock app demos. */
.ui-input {
  display: flex; align-items: center; gap: 8px;
  height: 36px;
  padding: 0 12px;
  border-radius: var(--r-md);
  border: 1px solid var(--hairline);
  background: var(--paper);
  font-size: 14px;
  color: var(--k-200);
}
.ui-input.is-ghost {
  background: var(--panel-warm);
  border-color: transparent;
}
.ui-input input {
  border: 0; background: transparent; outline: none;
  flex: 1; min-width: 0; color: inherit;
  font-size: 14px; font-family: inherit;
}
.ui-input input::placeholder { color: var(--g-400); }
.ui-input-ic {
  color: var(--g-400);
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 14px; height: 14px;
  flex-shrink: 0;
}
.ui-input-ic svg { width: 100%; height: 100%; }

/* Kbd — mono key caps. */
.ui-kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px;
  padding: 0 4px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-xs);
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--g-600);
  line-height: 1;
}
.ui-kbd-row { display: inline-flex; gap: 2px; }

/* Section header — used inside scenes (eyebrow + h2 + optional desc). */
.section-head {
  display: flex; flex-direction: column; gap: 16px;
  margin-bottom: 48px;
  max-width: 720px;
}
.section-head .desc {
  color: var(--g-500);
  max-width: 56ch;
}

/* ---- 4. Layout primitives -------------------------------- */
.wrap {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 clamp(20px, 4vw, 40px);
}

.section {
  width: 100%;
  padding: clamp(56px, 10vh, 112px) 0;
  background: var(--canvas);
}
.section-warm { background: var(--panel-warm); }
.section-paper { background: var(--paper); }
.section-dark {
  background: var(--k-200);
  color: var(--paper);
}
.section-dark .eyebrow { color: var(--g-400); }
.section-dark .eyebrow .num { color: var(--lime-200); }

/* ---- 5. Top bar ------------------------------------------ */
.nav {
  position: sticky; top: 0; z-index: 100;
  background: color-mix(in srgb, var(--canvas) 84%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease;
}
.nav.is-scrolled { border-bottom-color: var(--hairline); }
.nav-inner {
  display: flex; align-items: center; justify-content: space-between;
  height: 64px; gap: 24px;
}
.nav-brand {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: 36px;
  font-weight: 600; font-size: 16px;
  color: var(--k-200);
}
/* Mascot is portrait (674×858). Lock the height, let width auto so the
   monkey keeps its natural aspect ratio. No border-radius — the mark
   already has transparent edges, and the circular mask would clip
   the hair/limbs poking outside a square box. */
.nav-brand img { height: 28px; width: auto; display: block; }
.nav-brand .alpha {
  display: inline-flex; align-items: center; gap: 4px;
  margin-left: 4px;
  padding: 2px 8px;
  height: 18px;
  border-radius: var(--r-full);
  background: var(--lime-200);
  border: 1px solid var(--lime-350);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--k-200);
  font-weight: 600;
}
.nav-brand .alpha::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: var(--mint-500);
  box-shadow: 0 0 6px var(--mint-500);
}
.nav-links {
  display: flex; align-items: center; gap: 2px;
}
.nav-links a {
  display: inline-flex; align-items: center;
  height: 36px;
  padding: 0 12px;
  font-size: 14px;
  color: var(--g-500);
  border-radius: var(--r-md);
  transition: color .15s ease, background .15s ease;
}
.nav-links a:hover { color: var(--k-200); background: var(--panel-warm); }
.nav-cta { display: inline-flex; align-items: center; gap: 8px; }
.nav-signin {
  display: inline-flex; align-items: center;
  height: 36px;
  padding: 0 12px;
  font-size: 14px;
  color: var(--g-500);
  border-radius: var(--r-md);
}
.nav-signin:hover { color: var(--k-200); background: var(--panel-warm); }

@media (max-width: 880px) { .nav-links { display: none; } }
@media (max-width: 560px) {
  .nav-brand .alpha { display: none; }
  .nav-signin { display: none; }
}
@media (max-width: 480px) {
  .nav-inner { height: 56px; }
  .nav-cta .ui-btn-md { padding: 0 14px; min-height: 36px; font-size: 13px; }
}

/* ---- 6. Hero --------------------------------------------- */
/* The "fold" combines the hero and the trusted-by strip into a single
   100-vh container that sits just below the 64-px nav. The hero
   `flex: 1`s to fill, so the trusted strip naturally pins to the
   bottom of the viewport with its hairline at the fold. `100svh`
   keeps iOS Safari from jittering when the URL bar slides. */
.fold {
  min-height: calc(100vh - 64px);
  min-height: calc(100svh - 64px);
  display: flex;
  flex-direction: column;
}
.hero {
  flex: 1;
  display: flex;
  align-items: center;
  padding: clamp(32px, 5vh, 64px) 0;
}
.hero > .wrap { width: 100%; }
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(40px, 6vw, 80px);
  align-items: center;
}
.hero-text { display: flex; flex-direction: column; gap: 24px; max-width: 560px; }
.hero-text h1 {
  font: var(--fw-h1) clamp(36px, 5.5vw, 64px)/1.05 var(--font-sans);
  letter-spacing: -0.02em;
  color: var(--k-200);
}
/* Hand-brushed lime highlight on the emphasized phrase. The brush is
   intentionally TALLER than the offset so it rises up into the lower
   portion of the letters — reading as a highlighter swipe rather than
   a thin underline. `box-decoration-break: clone` keeps each wrapped
   line of the em with its own brush if the H1 ever wraps. */
.hero-text h1 em {
  font-style: normal;
  display: inline-block;
  padding-bottom: 4px;
  margin-bottom: -4px;
  background-image: url("assets/hero-underline.png");
  background-repeat: no-repeat;
  background-position: center bottom;
  background-size: 100% 0.55em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
.hero-text .lede {
  color: var(--g-600);
  font: 400 18px/1.5 var(--font-sans);
  max-width: 52ch;
}
.hero-ctas {
  display: flex; gap: 12px; flex-wrap: wrap;
  margin-top: 8px;
}

@media (max-width: 880px) {
  .hero-grid { grid-template-columns: 1fr; gap: 40px; }
  .hero-text h1 { font-size: clamp(32px, 8vw, 44px); }
  .hero-text .lede { font-size: 16px; }
}
/* Phones use a 56-px nav, so re-base the fold subtraction to match. */
@media (max-width: 480px) {
  .fold {
    min-height: calc(100vh - 56px);
    min-height: calc(100svh - 56px);
  }
}

/* Hero mock + floaters stack — relative wrapper so the floating evidence
   cards can absolute-position around the app-mock without disturbing
   the grid math. The hero section uses overflow visible at this level
   so floaters are allowed to peek past the mock's edges. */
.hero-mock-stack {
  position: relative;
  width: 100%;
}

/* Hero app-mock — a slice of the actual Wallace dashboard. */
.app-mock {
  display: grid;
  grid-template-columns: 180px 1fr;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-2xl);
  overflow: hidden;
  box-shadow: var(--e-4);
  min-height: 460px;
  transform: translateZ(0);
  position: relative;
  z-index: 1;
}

/* ---- Hero floaters: pinned evidence cards ----------------------------
 * Three small cards (paper highlight, X tweet, note) that sit around
 * the app-mock at slight rotations. They demonstrate the actual
 * snipping/clipping output Wallace produces: a saved paper excerpt,
 * a pinned X post, a personal note. Hover lifts + straightens.
 * Hidden on mobile so the preview doesn't get cluttered.
 * ---------------------------------------------------------------- */
.hero-floaters {
  position: absolute;
  inset: 0;
  pointer-events: none; /* ensure card hits, not the empty void around them */
  z-index: 2;
}
.hero-floaters .floater {
  position: absolute;
  pointer-events: auto;
  /* Subtle glassmorphism — paper at ~78% over a 12-px backdrop blur,
     so the canvas tint reads through without softening the text. */
  background: rgba(255, 255, 255, 0.78);
  -webkit-backdrop-filter: saturate(140%) blur(12px);
          backdrop-filter: saturate(140%) blur(12px);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  padding: 12px 14px;
  box-shadow: var(--e-3);
  width: 232px;
  display: flex; flex-direction: column; gap: 6px;
  transform-origin: center;
  will-change: transform;
  transition:
    transform 280ms cubic-bezier(0.2, 0, 0, 1.1),
    box-shadow 220ms ease,
    border-color 200ms ease,
    background 200ms ease;
}
/* On hover, lift the glass closer to opaque so the focused card reads
   as the foreground. */
.hero-floaters .floater:hover,
.hero-floaters .floater:focus-within {
  background: rgba(255, 255, 255, 0.94);
}
/* Browsers without backdrop-filter support fall back to a slightly
   higher-opacity fill so the cards still feel solid, not see-through. */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .hero-floaters .floater { background: rgba(255, 255, 255, 0.92); }
}
.hero-floaters .floater:hover,
.hero-floaters .floater:focus-within {
  transform: rotate(0deg) translateY(-6px) scale(1.025) !important;
  box-shadow: var(--e-5);
  border-color: var(--g-300);
  z-index: 4;
}

/* Card meta row (the small mono header at top of each card). */
.floater .floater-meta {
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--g-500);
}
.floater .floater-tag { color: var(--g-600); }
.floater .floater-page {
  background: var(--panel-warm-2);
  padding: 1px 6px;
  border-radius: 4px;
  color: var(--g-700);
}

.floater .floater-title {
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--k-200);
  line-height: 1.25;
}
.floater .floater-title em { font-style: italic; }
.floater .floater-author {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--g-500);
  letter-spacing: 0.04em;
}
.floater .floater-excerpt {
  margin: 0;
  font-family: 'Times New Roman', Times, serif;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--k-200);
}
.floater .floater-hl {
  background: var(--lime-200);
  padding: 0 2px;
  border-radius: 2px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* Tweet card overrides */
.floater-tweet .floater-meta-tweet { gap: 6px; justify-content: flex-start; }
.floater-tweet .floater-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px;
  color: var(--k-200);
}
.floater-tweet .floater-x svg { width: 100%; height: 100%; }
.floater-tweet .floater-quote {
  margin: 0;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--k-200);
  line-height: 1.35;
}

/* Note card — translucent lime body to match the glass treatment.
   Slightly higher opacity than the paper cards so the lime stays
   recognizable through the blur. */
.floater-note {
  background: rgba(247, 255, 204, 0.82) !important;
  border-color: var(--lime-200) !important;
}
.hero-floaters .floater-note:hover,
.hero-floaters .floater-note:focus-within {
  background: rgba(247, 255, 204, 0.96) !important;
}
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .floater-note { background: rgba(247, 255, 204, 0.95) !important; }
}
.floater-note .floater-tag { color: var(--g-700); }
.floater-note .floater-note-body {
  margin: 0;
  font-family: 'Times New Roman', Times, serif;
  font-size: 14px;
  font-style: italic;
  line-height: 1.35;
  color: var(--k-200);
}

/* Per-card placement around the app-mock. Resting rotations are subtle
   so they read as a "stack of saved sources" not a chaotic pile. */
.hero-floaters .floater-paper {
  top: -28px;
  left: -56px;
  transform: rotate(-3.5deg);
  width: 240px;
}
.hero-floaters .floater-tweet {
  top: 32%;
  right: -64px;
  transform: rotate(2.8deg);
  width: 220px;
}
.hero-floaters .floater-note {
  bottom: -22px;
  left: -36px;
  transform: rotate(-4deg);
  width: 196px;
}

/* On the marketing-site overall layout, the hero wrap should let the
   floaters peek past the right gutter without horizontal scroll. The
   .hero already sits inside .wrap which is centered with padding; the
   floaters' negative offsets are bounded by the column gap so they
   never extend past the page edge on a normal desktop. */
.hero { overflow-x: clip; }

/* MOBILE — hide the entire floater stack. The user wanted the mobile
   preview to stay uncluttered. */
@media (max-width: 960px) {
  .hero-floaters { display: none; }
}

/* Sidebar mock — flat warm panel, no gradient. Matches the actual app:
   a single paler-than-canvas surface, hairline divider on the right. */
.app-mock-sidebar {
  background: var(--panel-warm);
  border-right: 1px solid var(--hairline);
  padding: 16px 12px;
  display: flex; flex-direction: column;
  gap: 18px;
  position: relative;
}
.app-mock-org {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px;
  border-radius: var(--r-md);
}
.app-mock-org-mark {
  width: 22px; height: 22px;
  border-radius: var(--r-sm);
  background: var(--k-200);
  color: var(--lime-200);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
}
.app-mock-org-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--k-200);
}
.app-mock-section {
  position: relative;
  display: flex; flex-direction: column; gap: 2px;
}
.app-mock-section-label {
  padding: 4px 8px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--g-400);
  font-weight: 500;
}
.app-mock-nav {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px;
  border-radius: var(--r-md);
  font-size: 13px;
  color: var(--g-600);
  cursor: default;
}
.app-mock-nav.is-active {
  background: var(--paper);
  color: var(--k-200);
  font-weight: 500;
  box-shadow: var(--e-1);
}
.app-mock-nav-ic {
  width: 16px; height: 16px;
  display: inline-flex; align-items: center; justify-content: center;
  color: currentColor;
  flex-shrink: 0;
  opacity: 0.85;
}
.app-mock-nav-ic svg { width: 100%; height: 100%; display: block; }
.app-mock-nav.is-active .app-mock-nav-ic { opacity: 1; }

/* Main content panel — the Library/Dashboard slice. */
.app-mock-main {
  display: flex; flex-direction: column;
  min-width: 0;
}
.app-mock-tabs {
  display: flex; align-items: center; gap: 2px;
  padding: 8px 14px 0;
  border-bottom: 1px solid var(--hairline);
  overflow-x: auto;
  scrollbar-width: none;
}
.app-mock-tabs::-webkit-scrollbar { display: none; }
.app-mock-tab {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  font-size: 12px;
  color: var(--g-500);
  border-radius: var(--r-md) var(--r-md) 0 0;
  border: 1px solid transparent;
  border-bottom: 0;
  white-space: nowrap;
}
.app-mock-tab.is-active {
  background: var(--paper);
  color: var(--k-200);
  font-weight: 500;
  border-color: var(--hairline);
  margin-bottom: -1px;
}
.app-mock-toolbar {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--hairline);
}
.app-mock-toolbar .ui-input { flex: 1; height: 30px; font-size: 12px; }
.app-mock-toolbar .ui-input input { font-size: 12px; }

.app-mock-body {
  padding: 16px 14px;
  display: flex; flex-direction: column;
  gap: 14px;
  flex: 1;
}

/* Library card mock (compact paper card). */
.lib-card {
  display: grid;
  grid-template-columns: 24px 1fr auto;
  gap: 10px;
  align-items: flex-start;
  padding: 10px 12px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.lib-card:hover { border-color: var(--k-200); }
/* Library card glyph chip — one neutral surface for every source type.
   The actual Wallace app uses the same monochrome + lime palette and
   distinguishes sources with the mark itself, not chip color. We
   follow that exactly: a single warm-panel chip with a hairline edge. */
.lib-card-glyph {
  width: 26px; height: 26px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel-warm-2);
  border: 1px solid var(--hairline);
  color: var(--k-200);
  flex-shrink: 0;
}
.lib-card-glyph svg { width: 14px; height: 14px; display: block; }
/* Variants kept as no-op classes for semantics / future per-source tweaks. */
.lib-card-glyph.is-arxiv,
.lib-card-glyph.is-doi,
.lib-card-glyph.is-pdf,
.lib-card-glyph.is-url,
.lib-card-glyph.is-x { /* same neutral chip across all source types */ }
.lib-card-body { min-width: 0; }
.lib-card-title {
  font-size: 13px;
  font-weight: 500;
  color: var(--k-200);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lib-card-meta {
  font-size: 11px;
  color: var(--g-500);
  margin-top: 2px;
}
.lib-card-time {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--g-400);
  letter-spacing: 0.04em;
}

/* Ask-Wallace input — the lime-bordered prompt at the bottom. */
.ask-wallace {
  margin-top: auto;
  padding: 14px;
  background: var(--paper);
  border-top: 1px solid var(--hairline);
}
.ask-input {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  box-shadow: var(--e-1);
}
.ask-input .ask-input-ic {
  width: 22px; height: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--lime-500);
  flex-shrink: 0;
}
.ask-input .ask-input-ic svg { width: 100%; height: 100%; }
/* The wallace mark is portrait (674×858). Lock height, let width follow
   so the monkey isn't squashed into a square. */
.ask-input .ask-input-mascot img {
  height: 22px;
  width: auto;
  display: block;
}
.ask-input:focus-within {
  border-color: var(--lime-350);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lime-200) 35%, transparent);
}
.ask-input input {
  flex: 1; min-width: 0;
  border: 0; background: transparent; outline: none;
  font-size: 13px; color: var(--k-200);
}
.ask-input input::placeholder { color: var(--g-400); }
.ask-send {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border-radius: var(--r-full);
  background: var(--lime-200);
  border: 2px solid var(--lime-350);
  color: var(--k-200);
  cursor: pointer;
  flex-shrink: 0;
  transition: background var(--dur-fast);
}
.ask-send svg { width: 16px; height: 16px; display: block; }
.ask-send:hover { background: var(--lime-300); }

@media (max-width: 880px) {
  .app-mock { min-height: 380px; }
  .app-mock-sidebar { display: none; }
  .app-mock { grid-template-columns: 1fr; }
}

/* ---- 7. Trusted strip ------------------------------------ */
.trusted {
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  padding: 40px 0;
}
.trusted-eyebrow {
  display: block; text-align: center;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--g-500);
  margin-bottom: 20px;
}
.trusted-row {
  display: flex; flex-wrap: wrap;
  justify-content: center; align-items: center;
  gap: clamp(20px, 4vw, 44px);
}
/* SVG logo treatment — uniform height, capped width so a wide
   wordmark can't dominate, grayscale + dimmed opacity at rest so
   logos of varying complexity (a 200-byte glyph next to a 400KB
   detailed seal) read as one bar. Lift to full color on hover. */
.trusted-logo {
  height: 28px;
  width: auto;
  max-width: 120px;
  display: block;
  object-fit: contain;
  filter: grayscale(1);
  opacity: 0.55;
  transition: opacity .2s ease, filter .2s ease;
}
.trusted-logo:hover {
  opacity: 1;
  filter: grayscale(0);
}
/* Square-aspect logos (seals, monograms) need a height boost so they
   don't disappear next to wide wordmarks. Set `boost: true` on the
   TRUSTED_BY entry to opt in. */
.trusted-logo.is-boost { height: 40px; }

@media (max-width: 720px) {
  .trusted-logo { height: 22px; max-width: 96px; }
  .trusted-logo.is-boost { height: 32px; }
}

.trusted-mark {
  font-size: 16px;
  font-weight: 500;
  color: var(--g-500);
  letter-spacing: -0.005em;
  opacity: 0.85;
  transition: opacity .15s, color .15s;
}
.trusted-mark:hover { opacity: 1; color: var(--k-200); }
.trusted-mark.serif      { font-family: 'Georgia', 'Times New Roman', serif; font-weight: 500; }
.trusted-mark.serif-caps { font-family: 'Georgia', serif; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.trusted-mark.bold       { font-weight: 700; }

/* ---- 8. How it works (3 product-shaped cards) ----------- */
.how-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
}
.how-card {
  display: flex; flex-direction: column;
  gap: 16px;
  padding: 24px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  box-shadow: var(--e-2);
  min-height: 380px;
}
.how-card-head {
  display: flex; flex-direction: column; gap: 8px;
}
.how-card-num {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--lime-500);
  font-weight: 600;
  display: inline-flex; align-items: center; gap: 10px;
}
.how-card-num::after {
  content: ""; width: 24px; height: 1px;
  background: var(--lime-300);
}
.how-card-title {
  font: 700 22px/1.2 var(--font-sans);
  letter-spacing: -0.01em;
  color: var(--k-200);
}
.how-card-body {
  font-size: 14px;
  line-height: 1.5;
  color: var(--g-600);
}
.how-demo {
  margin-top: auto;
  padding: 14px;
  background: var(--canvas);
  border: 1px dashed var(--hairline);
  border-radius: var(--r-md);
  display: flex; flex-direction: column;
  gap: 10px;
}

/* Capture demo — import URL field + 4 source-type badges. */
.demo-import-input {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--g-500);
}
.demo-import-input b { color: var(--k-200); font-weight: 500; }
.demo-import-types { display: flex; gap: 6px; flex-wrap: wrap; }

/* Read demo — paper preview with highlight + side note. */
.demo-read {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 8px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  padding: 10px;
}
.demo-read-paper {
  font-family: var(--font-manuscript);
  font-size: 11px;
  line-height: 1.45;
  color: var(--k-200);
}
.demo-read-paper .hl {
  background: var(--lime-200);
  padding: 0 1px;
}
.demo-read-note {
  background: var(--pastel-yellow);
  border-radius: var(--r-sm);
  padding: 6px 8px;
  font-size: 11px;
  line-height: 1.4;
  color: var(--k-200);
}

/* Ask demo — chat exchange with citation pills. */
.demo-ask { display: flex; flex-direction: column; gap: 8px; }
.demo-ask-q {
  align-self: flex-end;
  background: var(--panel-warm);
  border-radius: var(--r-md);
  padding: 6px 10px;
  font-size: 11px;
  max-width: 80%;
  color: var(--k-200);
}
.demo-ask-a {
  align-self: flex-start;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  padding: 8px 10px;
  font-size: 11px;
  max-width: 92%;
  color: var(--k-200);
  display: flex; flex-direction: column; gap: 6px;
}
.demo-ask-cites { display: flex; gap: 4px; flex-wrap: wrap; }

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

/* ---- 8.5. Library section — supported-formats grid ------ */
/* IMPORTANT: classes here use the .formats-* prefix, NOT .lib-*.
   The dashboard mock in HeroAppMock already uses .lib-card / -title /
   -body / -meta / -time for its source-card list, so reusing those
   names collided and forced the mock cards into a vertical stack
   (which made the hero ~200px taller than it should be).
   --------------------------------------------------------------
   4-column on desktop, 2 on tablet, 1 on phone. Each card is a
   compact format chip — small mono "ic" badge, name, one-line note.
   Visually quieter than the How cards (no images, no demos) so they
   read as a manifest rather than competing with the active scenes
   above and below. */
/* (formerly .formats-grid + .formats-card — replaced by the compact
   .lib-preview mockup which carries the "every format" message
   visually without enumerating eight cards.) */

/* ============================================================
   8b. How → Library merged subsection (Wallace v2.1)
   ============================================================
   The library used to live in its own #library section. It now lives
   INSIDE #how, after a labeled divider, so the page reads:
     "Here's the loop"  →  divider  →  "And here's everything that
     lands in it." Two related ideas, one section.
   ============================================================ */

/* Hairline-only chapter break inside #how. No label — the headline
   below carries the pivot. Faded edges keep it from feeling like a
   hard rule. */
.how-divider {
  display: flex; align-items: center;
  margin: clamp(72px, 9vw, 112px) auto clamp(40px, 5vw, 64px);
  max-width: 920px;
}
.how-divider-line {
  flex: 1;
  height: 1px;
  background: linear-gradient(to right,
    transparent,
    var(--hairline) 20%,
    var(--hairline) 80%,
    transparent);
}

/* Library subsection — minimal: short header + visual + one-line
   trade caption. The visual (LibraryPreview) carries the message. */
.library-block {
  display: flex; flex-direction: column;
  gap: clamp(28px, 3.5vw, 40px);
}
.library-intro {
  display: flex; flex-direction: column;
  gap: 12px;
  /* 96ch (~760px at 15.5px font) lets the 89-char lede sit on a
     single line on desktop. The title is short and self-balances via
     text-wrap, so widening here only affects the lede. Falls back to
     the wrap's natural width on narrow viewports. */
  max-width: 96ch;
  text-align: center;
  margin: 0 auto;
}
.library-title {
  letter-spacing: -0.015em;
  text-wrap: balance;
}
.library-lede {
  color: var(--g-600);
  font-size: 15.5px;
  line-height: 1.5;
  /* Override .library-intro's 56ch cap so the lede sits on one line
     on desktop instead of orphaning the last few words ("side by
     side.") onto a second row. text-wrap: balance handles the
     graceful fallback on narrower viewports — when the lede must
     wrap, both lines end up roughly equal width instead of
     "long line + tiny orphan". */
  max-width: 80ch;
  text-wrap: balance;
  margin: 0 auto;
}

/* Compact app-shaped library preview — replaces the 8-card grid AND
   the trade strip. One row per source kind drives the "every format"
   message visually rather than as enumerated copy. */
.lib-preview {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  box-shadow: var(--e-3);
  overflow: hidden;
  max-width: 880px;
  margin: 0 auto;
  width: 100%;
}
.lib-preview-bar {
  display: flex; align-items: center; gap: 4px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--hairline);
  background: linear-gradient(180deg, var(--panel-warm) 0%, var(--paper) 100%);
}
.lib-preview-tab {
  display: inline-flex; align-items: center;
  height: 28px;
  padding: 0 12px;
  border-radius: var(--r-md);
  font-size: 12.5px;
  color: var(--g-500);
  font-weight: 500;
  white-space: nowrap;
}
.lib-preview-tab.is-active {
  background: var(--paper);
  color: var(--k-200);
  box-shadow: 0 0 0 1px var(--hairline);
}
.lib-preview-tab.is-add {
  width: 24px; padding: 0;
  justify-content: center;
  color: var(--g-400);
  font-size: 14px;
}
.lib-preview-count {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--g-500);
}

.lib-preview-rows {
  list-style: none; padding: 0; margin: 0;
}
.lib-preview-row {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr) auto auto;
  gap: 14px;
  align-items: center;
  padding: 12px 16px;
  border-bottom: 1px solid var(--hairline);
  transition: background var(--dur-fast) var(--ease-standard);
}
.lib-preview-row:last-child { border-bottom: 0; }
.lib-preview-row:hover { background: var(--panel-warm); }

/* Pastel categorical glyph — the colored circle is the *container*;
   the actual icon inside (LibIcon component) is either a brand SVG
   (X, YouTube), an italic α (arXiv), or a tight mono type badge
   (PDF / MD / TeX / DOI). Same source-type vocabulary as the hero
   app-mock so the system reads consistently across the page. */
.lib-glyph {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border-radius: 50%;
  color: var(--k-200);
  flex: none;
}
.lib-glyph.is-arxiv { background: var(--pastel-blue); }
.lib-glyph.is-doi   { background: var(--pastel-lavender); }
.lib-glyph.is-x     { background: var(--k-200); color: var(--paper); }
.lib-glyph.is-video { background: var(--pastel-peach); }
.lib-glyph.is-pdf   { background: var(--pastel-pink); }
.lib-glyph.is-md    { background: var(--pastel-yellow); }
.lib-glyph.is-bib   { background: var(--pastel-sage); }

/* Icon-side rendering — mono "PDF / MD / DOI" badges stay tight and
   uppercase so they read like a corner stamp, not a sentence. */
.lib-glyph-text {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1;
}
.lib-glyph-md  { font-size: 10px; letter-spacing: 0.04em; }
.lib-glyph-tex { font-size: 9px;  letter-spacing: -0.01em; text-transform: none; }

/* arXiv's wordmark — italic α. Renders cleaner as text than as SVG
   path data (font hinting > exported curves at 16 px). */
.lib-glyph-arxiv {
  font-family: 'Georgia', 'Times New Roman', serif;
  font-style: italic;
  font-size: 17px;
  font-weight: 600;
  line-height: 1;
}

.lib-glyph-svg { display: block; }
.lib-glyph-yt {
  /* YouTube play-button keeps native fills (brand red + white).
     A subtle outline keeps it crisp against the peach pastel at
     small sizes. */
  filter: drop-shadow(0 0 0.4px rgba(0, 0, 0, 0.1));
}

.lib-row-title {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--k-200);
  letter-spacing: -0.005em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.lib-row-title i { font-style: italic; }
.lib-row-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--g-500);
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.lib-row-time {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--g-400);
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* Single-line import/export caption beneath the preview. Mono so it
   reads as fineprint; bold sub-labels carry the contrast. */
.library-trade-line {
  display: flex; flex-wrap: wrap;
  justify-content: center; align-items: center;
  gap: 12px;
  margin: 0 auto;
  max-width: 880px;
  padding: 0 8px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--g-500);
  text-align: center;
}
.library-trade-line b {
  color: var(--k-200);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-right: 6px;
}
.library-trade-sep { color: var(--g-300); }

/* Phone — drop the meta column; keep glyph + title + time. The meta
   row is "arXiv · Patel" which is repetition with the glyph color
   anyway, so no information loss. */
@media (max-width: 720px) {
  .lib-preview-row {
    grid-template-columns: 28px minmax(0, 1fr) auto;
    gap: 10px;
    padding: 10px 12px;
  }
  .lib-row-meta { display: none; }
  .lib-preview-bar { padding: 8px 10px; }
  .lib-preview-tab { padding: 0 10px; font-size: 12px; height: 26px; }
  .library-trade-line { font-size: 11px; gap: 6px; }
  .library-trade-sep { display: none; }
}

/* ---- 9. Browser extension (lime hero card) -------------- */
/* The extension scene fits one viewport — section min-heights to
   100vh-nav so the lime card sits centered with breathing room rather
   than over-bleeding into the next section. */
#extension {
  min-height: calc(100vh - 64px);
  min-height: calc(100svh - 64px);
  display: flex;
  align-items: center;
  padding: clamp(40px, 6vh, 80px) 0;
}
.ext-hero {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: clamp(32px, 5vw, 64px);
  align-items: center;
  background: var(--lime-200);
  border: 2px solid var(--lime-350);
  border-radius: var(--r-2xl);
  padding: clamp(28px, 4vw, 48px);
  box-shadow: var(--e-3);
  width: 100%;
}
.ext-hero-text { display: flex; flex-direction: column; gap: 16px; max-width: 480px; }
.ext-hero-text .eyebrow { color: rgba(25,25,26,0.6); }
.ext-hero-text .eyebrow .num { color: var(--lime-600); }
.ext-hero h2 {
  font: var(--fw-h2) clamp(28px, 3.6vw, 42px)/1.1 var(--font-sans);
  letter-spacing: -0.01em;
  color: var(--k-200);
}
.ext-hero p {
  font-size: 15px; line-height: 1.5;
  color: rgba(25,25,26,0.78);
  max-width: 44ch;
}
.ext-hero-cta { display: inline-flex; gap: 12px; flex-wrap: wrap; }

/* ─── Browser-extension popup ────────────────────────────────────
   Faithful DOM reproduction of the Wallace "Save source" popup
   (Figma 4MQTIlm7gq0ZGQHAelttBE · node 753:840). Built from Wallace
   tokens — lime-50/200/350, forest-500, hairline, canvas, paper,
   k-200/g-400/g-500. No Tailwind, no ad-hoc hexes. */
.ext-popup {
  width: 100%;
  max-width: 380px;
  margin-left: auto;
  background: var(--canvas);
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  box-shadow:
    0 1px 2px rgba(13, 13, 14, 0.03),
    0 6px 14px rgba(13, 13, 14, 0.04),
    0 30px 60px rgba(13, 13, 14, 0.08);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* Header — Wallace mark + settings + close */
.ep-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hairline);
}
.ep-brand {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 18px;
  color: var(--forest-500);
  letter-spacing: -0.011em;
}
.ep-header-actions { display: flex; align-items: center; gap: 2px; }
.ep-icon-btn {
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: transparent;
  border-radius: var(--r-full);
  color: var(--g-500);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-standard);
}
.ep-icon-btn:hover { background: var(--panel-warm); color: var(--k-200); }

/* Template chip + spotted-on-source indicator */
.ep-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px;
  padding: 12px 14px 0;
}
.ep-template {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 10px;
  background: var(--lime-50);
  border: 1px solid var(--lime-350);
  border-radius: var(--r-full);
  font-size: 11px;
  color: var(--g-500);
}
.ep-template .muted { color: var(--g-500); }
.ep-template .strong { color: var(--k-200); font-weight: 500; }
.ep-template svg:last-child { color: var(--g-500); }

.ep-spotted {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 8px;
  font-size: 11px;
  color: var(--g-500);
  font-weight: 500;
  letter-spacing: 0.02em;
}
.ep-spotted .dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--mint-500);
  box-shadow: 0 0 0 0.5px rgba(16, 215, 99, 0.3);
}

/* Source preview */
.ep-source {
  margin: 12px 14px 0;
  padding: 12px 14px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  display: flex; flex-direction: column;
  gap: 6px;
}
.ep-source-meta {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 10px;
}
.ep-source-kind {
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--g-500);
}
.ep-dot { color: var(--g-400); }
.ep-source-id { color: var(--g-500); font-weight: 500; }
.ep-source-title {
  font-weight: 700;
  font-size: 15px;
  line-height: 1.25;
  color: var(--k-200);
  letter-spacing: -0.005em;
}

/* Section wrapper — repeated for Properties/Project/Tags/Note */
.ep-section {
  display: flex; flex-direction: column; gap: 4px;
  padding: 0 14px;
  margin-top: 12px;
}
.ep-section-head {
  display: flex; align-items: center; justify-content: space-between;
}
.ep-section-label {
  font-weight: 700;
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--g-500);
}

/* "+ Add" chip used in Properties + Tags */
.ep-add {
  display: inline-flex; align-items: center; gap: 4px;
  background: transparent; border: 0; padding: 0;
  font-size: 11px; font-weight: 500;
  color: var(--g-500);
  cursor: pointer;
}
.ep-add:hover { color: var(--k-200); }

/* Properties — list of metadata rows */
.ep-prop-list {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  overflow: hidden;
}
.ep-prop {
  display: grid;
  grid-template-columns: 14px 62px 1fr;
  gap: 8px;
  align-items: center;
  padding: 8px 12px;
  border-bottom: 1px solid var(--hairline);
}
.ep-prop:last-child { border-bottom: 0; }
.ep-prop-ic { color: var(--g-500); display: inline-flex; }
.ep-prop-lbl {
  font-weight: 500;
  font-size: 10px;
  letter-spacing: 0.05em;
  color: var(--g-500);
}
.ep-prop-val {
  font-size: 12px;
  line-height: 1.25;
  color: var(--k-200);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Project picker */
.ep-project {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px;
  padding: 8px 12px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 14px;
}
.ep-project-mark {
  width: 10px; height: 10px;
  border-radius: 3px;
  background: var(--forest-500);
  flex: none;
}
.ep-project-name {
  flex: 1;
  font-size: 13px;
  font-weight: 500;
  color: var(--k-200);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ep-chevron { color: var(--g-500); flex: none; }

/* Tag chips */
.ep-tags {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 8px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 14px;
}
.ep-tag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 6px 4px 10px;
  background: var(--lime-50);
  border: 1px solid var(--hairline);
  border-radius: var(--r-full);
  font-size: 11px;
  font-weight: 500;
  color: var(--k-200);
  letter-spacing: 0.02em;
}
.ep-tag svg { color: var(--g-500); }
.ep-tag-add {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 8px;
  border-radius: var(--r-full);
  font-size: 11px;
  color: var(--g-400);
}
.ep-tag-add svg { color: var(--g-400); }

/* Personal note */
.ep-note {
  padding: 8px 12px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  font-size: 12px;
  line-height: 1.35;
  color: var(--k-200);
}

/* Footer — primary Save + shortcut + Open Wallace */
.ep-footer {
  margin-top: 14px;
  padding: 12px 14px;
  background: var(--paper);
  border-top: 1px solid var(--hairline);
  display: flex; flex-direction: column; gap: 8px;
}
.ep-save {
  display: inline-flex; align-items: center; justify-content: center;
  width: 100%;
  padding: 12px 16px;
  background: var(--lime-200);
  border: 2px solid var(--lime-350);
  border-radius: var(--r-xl);
  color: var(--k-200);
  font-weight: 500;
  font-size: 16px;
  letter-spacing: 0.5px;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.ep-save:hover { background: var(--lime-300); border-color: var(--lime-400); }
.ep-footer-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px;
}
.ep-shortcut {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px;
  color: var(--g-400);
}
.ep-open {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px;
  font-weight: 500;
  color: var(--k-200);
  cursor: pointer;
}
.ep-open:hover { color: var(--lime-500); }
.ep-open svg { transition: transform var(--dur-fast) var(--ease-standard); }
.ep-open:hover svg { transform: translateX(2px); }

/* On phones the popup goes full-width inside the lime hero card. */
@media (max-width: 880px) {
  .ext-popup { max-width: 100%; margin: 0 auto; }
}

@media (max-width: 880px) {
  .ext-hero { grid-template-columns: 1fr; gap: 32px; }
  .ext-popup { max-width: 100%; margin: 0 auto; }
}

/* ---- 10. Origin (editorial moment) -----------------------
 * Two-column layout: portrait on the left at a sensible cap, the
 * naturalist's life story on the right anchored to the top of the
 * portrait so the rhythm matches the rest of the marketing site. */
.origin-grid {
  display: grid;
  grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
  gap: clamp(36px, 5vw, 72px);
  align-items: start;
}
/* Portrait column: the framed image card sits up top, the typographic
   caption ("A. R. WALLACE   1823 — 1913") sits BELOW it in normal flow
   so it never overlaps the figure. */
.origin-portrait {
  display: flex; flex-direction: column;
  gap: 14px;
  margin: 0;
}
.origin-portrait-frame {
  position: relative;
  aspect-ratio: 4 / 5;
  background: var(--paper);
  border-radius: var(--r-xl);
  border: 1px solid var(--hairline);
  overflow: hidden;
}
.origin-portrait-frame img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 20%;
}
.origin-portrait-mark {
  display: flex; justify-content: space-between;
  padding: 0 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--g-500);
  font-weight: 500;
}
.origin-prose {
  display: flex; flex-direction: column; gap: 18px;
  max-width: 60ch;
}
.origin-prose p {
  font-size: 17px;
  line-height: 1.6;
  color: var(--k-200);
  margin: 0;
}
.origin-prose b { font-weight: 600; }

/* Multi-line lime pull — same gradient device used for short pulls
   elsewhere, but with extra leading + box-decoration-break so each
   wrapped line gets its own highlight band cleanly. */
.origin-pull {
  background: linear-gradient(to bottom, transparent 62%, var(--lime-200) 62%);
  padding: 0 4px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* Closing line — set in the marker (Caveat) at forest green so it lands
   as a hand-signed signature under the editorial prose. Caveat reads
   smaller-per-px than Aeonik because of its tall ascenders/descenders,
   so we use ~30px to match the visual weight of an 18–20px body kicker. */
.origin-coda {
  margin-top: 8px !important;
  padding-top: 22px;
  border-top: 1px solid var(--hairline);
  font-family: var(--font-marker) !important;
  font-size: 30px !important;
  font-weight: 500;
  line-height: 1.2 !important;
  letter-spacing: 0 !important;
  color: var(--forest-500) !important;
  text-wrap: balance;
}

/* Section-head variant for sections that don't carry a right-column desc.
   Tighter bottom margin so the section reads as head + body, not head +
   blank space + body. */
.section-head.section-head-tight {
  margin-bottom: clamp(28px, 4vh, 40px);
}

@media (max-width: 960px) {
  .origin-grid {
    grid-template-columns: minmax(0, 260px) minmax(0, 1fr);
    gap: 32px;
  }
}
@media (max-width: 720px) {
  .origin-grid { grid-template-columns: 1fr; gap: 28px; }
  .origin-portrait { max-width: 260px; margin: 0 auto; }
  .origin-prose p { font-size: 16px; }
  /* Caveat reads small per-px, keep the kicker generous on mobile too.
     Center on mobile so the kicker reads as a closing flourish under
     the prose block rather than orphaned at the left edge. */
  .origin-coda {
    font-size: 26px !important;
    text-align: center;
  }
}

/* ---- 11. Pricing ----------------------------------------- */
.pricing-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 20px;
}
.tier {
  position: relative;
  display: flex; flex-direction: column; gap: 20px;
  padding: 32px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  box-shadow: var(--e-2);
}
.tier.is-featured {
  background: var(--lime-200);
  border: 2px solid var(--lime-350);
  isolation: isolate;
  /* Slow, gentle aura breath. 8s cycle + a small opacity-only delta
     reads as "alive" without jitter — the eye notices the card but
     no element on the surface is moving, so nothing demands attention.
     The shimmer streak this replaced was the loud part; this is the
     ambient glow only. */
  box-shadow:
    var(--e-3),
    0 20px 50px -20px rgba(206, 237, 12, 0.35);
  animation: tier-aura 8s ease-in-out infinite;
  transition:
    transform 0.25s ease,
    box-shadow 0.25s ease;
}
/* Hover intensifies the aura and lifts the card a hair. We pause the
   breath while the user is hovering so the lift is the only motion —
   crisp affordance, no two motions fighting at the same time. */
.tier.is-featured:hover {
  transform: translateY(-2px);
  box-shadow:
    var(--e-3),
    0 28px 70px -18px rgba(206, 237, 12, 0.65);
  animation-play-state: paused;
}
@keyframes tier-aura {
  0%, 100% {
    box-shadow:
      var(--e-3),
      0 20px 50px -20px rgba(206, 237, 12, 0.30);
  }
  50% {
    box-shadow:
      var(--e-3),
      0 24px 60px -20px rgba(206, 237, 12, 0.48);
  }
}
@media (prefers-reduced-motion: reduce) {
  .tier.is-featured { animation: none; }
}
.tier-name {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--g-500);
}
.tier.is-featured .tier-name { color: rgba(25,25,26,0.6); }
.tier-blurb {
  font-size: 14px;
  color: var(--g-600);
}
.tier.is-featured .tier-blurb { color: rgba(25,25,26,0.78); }
.tier-price {
  display: flex; align-items: baseline; gap: 8px;
  margin-top: 4px;
}
.tier-amt {
  font: 700 48px/1 var(--font-sans);
  letter-spacing: -0.025em;
  color: var(--k-200);
}
.tier-per {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--g-500);
}
.tier.is-featured .tier-per { color: rgba(25,25,26,0.65); }
.tier-rule {
  height: 1px;
  background: var(--hairline);
}
.tier.is-featured .tier-rule { background: rgba(25,25,26,0.18); }
.tier-features {
  display: flex; flex-direction: column; gap: 10px;
  flex: 1;
}
.tier-features li {
  display: flex; gap: 10px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--k-200);
}
.tier-features li::before {
  content: "";
  flex: none;
  width: 14px; height: 14px;
  margin-top: 3px;
  border-radius: 50%;
  background: var(--lime-100);
  border: 1px solid var(--lime-300);
}
.tier.is-featured .tier-features li::before {
  background: rgba(25,25,26,0.12);
  border-color: rgba(25,25,26,0.28);
}

/* Dark Enterprise tier — same shape and rhythm as the others, inverted
   color treatment. Lime bullets and CTA pop against the black ground;
   subtle dark glow at rest, intensifies on hover — mirrors the
   featured tier's affordance pattern in dark. */
.tier.is-dark {
  background: var(--k-200);
  border: 2px solid var(--k-200);
  color: var(--paper);
  box-shadow:
    var(--e-3),
    0 20px 50px -20px rgba(13, 13, 14, 0.45);
  transition:
    transform 0.25s ease,
    box-shadow 0.25s ease;
}
.tier.is-dark:hover {
  transform: translateY(-2px);
  box-shadow:
    var(--e-3),
    0 28px 70px -18px rgba(13, 13, 14, 0.65);
}
.tier.is-dark .tier-name { color: rgba(245, 245, 242, 0.55); }
.tier.is-dark .tier-blurb { color: rgba(245, 245, 242, 0.72); }
.tier.is-dark .tier-amt {
  color: var(--paper);
  /* "Let's talk" is a phrase, not a $ amount — smaller size keeps the
     tier-price row from blowing out the column width. */
  font-size: 36px;
  letter-spacing: -0.02em;
}
.tier.is-dark .tier-per { color: rgba(245, 245, 242, 0.55); }
.tier.is-dark .tier-rule { background: rgba(245, 245, 242, 0.16); }
.tier.is-dark .tier-features li { color: rgba(245, 245, 242, 0.85); }
.tier.is-dark .tier-features li::before {
  background: var(--lime-200);
  border-color: var(--lime-300, var(--lime-200));
}

.tier-features b { font-weight: 600; }
.tier-cta { margin-top: 4px; }

.pricing-note {
  text-align: center;
  margin-top: 32px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--g-500);
  letter-spacing: 0.04em;
}

/* Three cards crush below ~960px — switch to a single stacked column
   well before the cards become unreadable. The featured Premium card
   sits in the middle of the stack, which keeps it visually anchored
   on tablet/mobile too. */
@media (max-width: 960px) {
  .pricing-grid { grid-template-columns: 1fr; }
}

/* ---- 12. FAQ --------------------------------------------- */
.faq-card {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  box-shadow: var(--e-2);
  overflow: hidden;
}
.faq-item {
  border-bottom: 1px solid var(--hairline);
  cursor: pointer;
}
.faq-item:last-child { border-bottom: 0; }
.faq-q {
  display: grid; grid-template-columns: 24px 1fr auto;
  align-items: center; gap: 16px;
  padding: 18px 20px;
}
.faq-q-num {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--g-400);
  font-weight: 500;
  letter-spacing: 0.04em;
}
.faq-q-text {
  font-size: 16px;
  font-weight: 500;
  color: var(--k-200);
  line-height: 1.35;
  letter-spacing: -0.005em;
}
.faq-q-icon {
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--panel-warm);
  display: flex; align-items: center; justify-content: center;
  font-size: 14px;
  color: var(--g-600);
  transition: transform .25s var(--ease-standard),
              background .15s, color .15s;
}
.faq-item.is-open .faq-q-icon {
  transform: rotate(45deg);
  background: var(--lime-200);
  color: var(--k-200);
}
.faq-a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .3s var(--ease-standard);
}
.faq-a > div { overflow: hidden; }
.faq-a-text {
  padding: 0 20px 20px 60px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--g-600);
  max-width: 64ch;
}
.faq-item.is-open .faq-a { grid-template-rows: 1fr; }

.faq-tail {
  margin-top: 24px;
  text-align: center;
  font-size: 13px;
  color: var(--g-500);
}
.faq-tail a {
  display: inline-block;
  min-height: 32px;
  line-height: 32px;
  color: var(--link);
  text-decoration: underline;
  text-underline-offset: 0.18em;
  transition: color .15s;
}
.faq-tail a:hover { color: var(--link-hover); }

@media (max-width: 720px) {
  .faq-q { grid-template-columns: 20px 1fr 24px; gap: 12px; padding: 16px; }
  .faq-q-text { font-size: 15px; }
  .faq-a-text { padding: 0 16px 18px 48px; }
}

/* ---- 13. Final CTA --------------------------------------- */
/* Lime-card variant kept for any other CTA reusing this class. */
.final-card {
  position: relative;
  display: flex; flex-direction: column;
  align-items: center; text-align: center;
  gap: 16px;
  padding: clamp(48px, 7vh, 80px) clamp(32px, 4vw, 56px);
  background: var(--lime-200);
  border: 2px solid var(--lime-350);
  border-radius: var(--r-2xl);
  box-shadow: var(--e-3);
  overflow: hidden;
}
.final-card h2 {
  font: 700 clamp(32px, 4.5vw, 54px)/1.05 var(--font-sans);
  letter-spacing: -0.02em;
  color: var(--k-200);
  max-width: 18ch;
  text-wrap: balance;
}
.final-card p {
  font-size: 16px;
  line-height: 1.5;
  color: rgba(25,25,26,0.7);
  max-width: 42ch;
}
.final-card .ui-btn-dark { margin-top: 12px; }

.final-mascot {
  position: absolute;
  right: -32px; bottom: -32px;
  width: 200px; height: 200px;
  opacity: 0.18;
  transform: rotate(-6deg);
  pointer-events: none;
}
.final-mascot img { width: 100%; height: 100%; }

@media (max-width: 720px) {
  .final-mascot { width: 140px; height: 140px; right: -20px; bottom: -20px; }
}

/* Dark variant — black ground, content left, rocket→moon illustration
   right. The handwriting flourish (.final-script) uses Caveat (loaded
   via Google Fonts in index.html) for the personal "want in?" beat. */
.final-card-dark {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 0.95fr);
  gap: clamp(32px, 5vw, 64px);
  align-items: center;
  text-align: left;
  padding: clamp(48px, 7vh, 88px) clamp(36px, 5vw, 72px);
  background: var(--k-200);
  border: none;
  border-radius: var(--r-2xl);
  color: var(--paper);
  overflow: hidden;
}
.final-card-dark .final-text {
  display: flex; flex-direction: column;
  gap: 18px;
  align-items: flex-start;
}
.final-card-dark h2 {
  font: 700 clamp(28px, 3.6vw, 44px)/1.1 var(--font-sans);
  letter-spacing: -0.02em;
  color: var(--paper);
  max-width: 20ch;
  text-wrap: balance;
  margin: 0;
}
/* Handwriting flourish — Caveat at a much larger size with a small
   negative rotation makes "Want in?" feel scribbled in a margin. The
   lime accent picks it out from the white headline body, and the
   inline-block lets the rotation apply without breaking text flow. */
.final-card-dark h2 .final-script {
  display: inline-block;
  font-family: var(--font-marker);
  font-style: normal;
  font-weight: 700;
  font-size: 1.5em;
  line-height: 1;
  color: var(--lime-200);
  transform: rotate(-3deg) translateY(0.05em);
  margin-left: 0.1em;
}
.final-card-dark p {
  font-size: clamp(15px, 1.2vw, 17px);
  line-height: 1.5;
  color: rgba(245, 245, 242, 0.72);
  max-width: 38ch;
  margin: 0;
}
.final-card-dark .ui-btn { margin-top: 6px; }

/* Illustration column — rocket arcs to the moon. The new SVG is
   already tightly cropped (1297×471) so we just let it fill the
   column at its natural aspect. */
.final-illu {
  display: flex; align-items: center; justify-content: center;
}
.final-illu img {
  width: 100%; height: auto; display: block;
  max-width: 520px;
}

@media (max-width: 880px) {
  .final-card-dark {
    grid-template-columns: 1fr;
    text-align: center;
    gap: 32px;
    padding: 56px 28px;
  }
  .final-card-dark .final-text { align-items: center; }
  .final-card-dark h2 { max-width: none; }
  .final-illu img { max-width: 360px; margin: 0 auto; }
}

/* ---- 14. Footer ------------------------------------------ */
.foot {
  background: var(--panel-warm);
  border-top: 1px solid var(--hairline);
  padding: 48px 0 24px;
}
.foot-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 4vw, 56px);
  margin-bottom: 32px;
}
.foot-brand { display: flex; flex-direction: column; gap: 12px; }
.foot-brand-mark {
  display: inline-flex; align-items: center; gap: 10px;
  font-weight: 600; font-size: 16px;
  color: var(--k-200);
}
.foot-brand-mark img { height: 28px; width: auto; display: block; }
.foot-brand-tag {
  font-size: 13px;
  line-height: 1.5;
  color: var(--g-500);
  max-width: 32ch;
}
.foot-col h4 {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--g-500);
  margin-bottom: 12px;
}
.foot-col ul { display: flex; flex-direction: column; gap: 4px; }
.foot-col a {
  display: inline-block;
  padding: 4px 0;
  min-height: 32px;
  line-height: 24px;
  font-size: 13px;
  color: var(--g-600);
  transition: color .15s;
}
.foot-col a:hover { color: var(--k-200); }
.foot-end {
  display: flex; justify-content: space-between; align-items: center;
  flex-wrap: wrap; gap: 12px;
  padding-top: 16px;
  border-top: 1px solid var(--hairline);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--g-500);
}
/* Doppel Labs hyperlink in the copyright row — inherits the muted mono
   tone of the line, gains a subtle underline + ink on hover so it's
   discoverable without screaming "click me". */
.foot-doppel-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color .12s ease, border-color .12s ease;
}
.foot-doppel-link:hover,
.foot-doppel-link:focus-visible {
  color: var(--k-200);
  border-bottom-color: currentColor;
  outline: none;
}

@media (max-width: 720px) {
  .foot-grid { grid-template-columns: 1fr 1fr; }
  .foot-brand { grid-column: 1 / -1; }
}

/* ---- 15. Reduced motion ---------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================
   17. Section sizing — full viewport, free scroll (no snap)
   ============================================================
   Each top-level section claims at least 100vh so each scene
   gets its own breathing room and never feels "cut". The
   previous version ALSO had `scroll-snap-type: y proximity`
   which made trackpad/mouse-wheel scroll feel yanked between
   scenes — that snap is removed. Free scroll, Framer-style;
   the 100vh rhythm stays.

   `scroll-padding-top` keeps anchor-link jumps (How / Extension /
   About / Pricing / FAQ in the nav) landing flush with the bottom
   of the sticky nav. The value MUST equal the nav height (64 px
   desktop, 56 px on phones) — anything larger leaves a strip where
   the previous section bleeds through under the nav. */
html {
  scroll-padding-top: 64px;
}
@media (max-width: 480px) {
  html { scroll-padding-top: 56px; }
}

@media (min-width: 721px) {
  /* Every nav-target section becomes its own viewport-filling
     scene. .hero is excluded because it lives inside .fold,
     which already manages its own min-height (calc(100vh - 64px)). */
  .section:not(.hero) {
    min-height: 100vh;
    /* `safe center` vertically centers content when it fits, and
       gracefully falls back to top-aligned when content is taller
       than the viewport (so nothing gets clipped above the fold). */
    display: flex;
    flex-direction: column;
    justify-content: safe center;
  }
}

/* ============================================================
   18. Footer link-button & Feedback modal
   ============================================================
   The Lab column needed a "Send feedback" entry that opens a modal
   instead of a mailto. To keep the visual rhythm identical to the
   surrounding <a> rows, the button is reset to look like an anchor.
   ============================================================ */

/* Match the surrounding `.foot-col a` rules 1:1 so the button reads as
   a peer link instead of a heavier black 16-px label. */
.foot-link-btn {
  display: inline-block;
  background: none;
  border: 0;
  margin: 0;
  padding: 4px 0;
  min-height: 32px;
  line-height: 24px;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--g-600);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: color .15s ease;
}
.foot-link-btn:hover { color: var(--k-200); }
.foot-link-btn:focus-visible {
  outline: 2px solid var(--lime-300);
  outline-offset: 4px;
  border-radius: 4px;
}

/* ---- Feedback modal -----------------------------------------
   Full-viewport overlay with a centered card. Backdrop fades in,
   card scales up slightly. Both share the same timing so the
   open/close motion reads as one gesture. */

.fb-modal {
  position: fixed; inset: 0;
  z-index: 200;
  display: none;
  background: rgba(13, 13, 14, 0);
  visibility: hidden;
  transition: background .22s ease, visibility 0s linear .22s;
  align-items: center; justify-content: center;
  padding: 24px;
}
.fb-modal.is-open {
  display: flex;
  background: rgba(13, 13, 14, 0.55);
  visibility: visible;
  transition: background .22s ease, visibility 0s linear 0s;
}

.fb-card {
  position: relative;
  width: min(520px, 100%);
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-2xl);
  box-shadow: 0 20px 60px rgba(13, 13, 14, 0.25);
  padding: 28px clamp(24px, 4vw, 36px);
  transform: translateY(8px) scale(0.98);
  opacity: 0;
  transition: transform .25s cubic-bezier(0.32, 0.72, 0, 1), opacity .2s ease;
}
.fb-modal.is-open .fb-card {
  transform: translateY(0) scale(1);
  opacity: 1;
}

.fb-close {
  position: absolute;
  top: 16px; right: 16px;
  width: 32px; height: 32px;
  border: 0; padding: 0;
  background: transparent;
  border-radius: 50%;
  font-size: 18px; line-height: 1;
  color: var(--g-500);
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .15s ease, color .15s ease;
}
.fb-close:hover { background: var(--panel-warm); color: var(--k-200); }
.fb-close:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--lime-350) 60%, transparent);
  outline-offset: 2px;
}

/* Form & success share one vertical rhythm so the dialog reads as a
   single column with consistent gaps between every block. */
.fb-form,
.fb-success {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.fb-title {
  font: 700 22px/1.2 var(--font-sans);
  letter-spacing: -0.015em;
  color: var(--text);
  margin: 0;
}
.fb-sub {
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--text-muted);
  margin: -8px 0 0; /* tightens the title-to-body gap; .fb-form gap handles
                       the gap from sub to next field */
  max-width: 42ch;
}

/* Each labelled block (Type / Email / Message) — label + control with
   a consistent 10px gap between them. */
.fb-field {
  display: flex; flex-direction: column;
  gap: 10px;
  border: 0; padding: 0; margin: 0;
}
.fb-label {
  font: 500 11px/1 var(--font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
}
/* <legend> inside a fieldset doesn't participate in the parent's
   flex `gap` — it positions itself like a block-level header. We
   give it explicit bottom spacing so the chip row sits clear of the
   TYPE label, matching the 10px gap used by every other label/control
   pair in the form. Float clears the legend so the next flex item
   doesn't overlap it. */
fieldset.fb-field > legend.fb-label {
  float: none;
  display: block;
  width: 100%;
  padding: 0;
  margin: 0 0 10px;
}
.fb-optional {
  text-transform: none;
  letter-spacing: 0;
  font-family: var(--font-sans);
  color: var(--text-subtle, var(--text-muted));
  font-size: 11px;
  margin-left: 4px;
}

/* Type chips — same <input type=radio> under the hood for accessibility,
   visually styled as toggleable pills. Sized down from the previous
   (38px / 8×20 padding / 14px font) so the row sits comfortably under
   the TYPE label without crowding it. Equal gap of 8px between chips. */
.fb-chips {
  display: flex; flex-wrap: wrap; gap: 8px;
}
.fb-chip {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 30px;
  padding: 5px 14px;
  border: 1px solid var(--border, var(--hairline));
  border-radius: 999px;
  font: 500 13px/1 var(--font-sans);
  letter-spacing: 0;
  color: var(--text-muted);
  background: var(--paper);
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.fb-chip input[type="radio"] {
  position: absolute;
  opacity: 0; pointer-events: none;
}
.fb-chip:hover { color: var(--text); }
.fb-chip.is-on {
  background: var(--text);
  color: var(--paper);
  border-color: var(--text);
}

.fb-input,
.fb-textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--border, var(--hairline));
  border-radius: 10px;
  background: var(--paper);
  color: var(--text);
  font: 400 15px/1.4 var(--font-sans);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.fb-input::placeholder,
.fb-textarea::placeholder {
  color: var(--text-subtle, var(--text-muted));
  opacity: 0.7;
}
.fb-input:focus,
.fb-textarea:focus {
  outline: none;
  border-color: var(--lime-350);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lime-200) 35%, transparent);
}
.fb-textarea {
  resize: vertical;
  min-height: 96px;
  font-family: var(--font-sans);
}

/* Inline error banner shown above the actions row when /api/feedback
   returns a non-2xx. Soft coral fill so it reads as a non-fatal warning
   matching the design system's --coral-100 token. */
.fb-error {
  background: var(--coral-100);
  border: 1px solid var(--coral-300);
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--k-200);
}
.fb-error a { color: inherit; text-decoration: underline; }
.fb-error-detail {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-muted);
}

.fb-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 8px;
}
.fb-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 42px;
  padding: 10px 22px;
  border-radius: var(--r-xl);
  font: 500 14px/1 var(--font-sans);
  letter-spacing: 0.5px;
  cursor: pointer;
  border: 2px solid transparent;
  transition: background .15s ease, color .15s ease, border-color .15s ease, transform .1s ease;
}
.fb-btn:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--lime-350) 60%, transparent);
  outline-offset: 3px;
}
.fb-btn:disabled { cursor: not-allowed; opacity: 0.55; }
/* Cancel — solid k-200 text on hairline border, panel-warm on hover.
   Reads as a real action, not a faded throwaway. */
.fb-btn-ghost {
  background: transparent;
  color: var(--k-200);
  border-color: var(--hairline);
}
.fb-btn-ghost:hover:not(:disabled) {
  background: var(--panel-warm);
  border-color: var(--g-200);
}
/* Send feedback — Wallace primary signature: lime-200 fill + 2px lime-350
   stroke. Same recipe as the hero CTA, the Save-source button in the
   extension popup, and the Premium pricing button. */
.fb-btn-primary {
  background: var(--lime-200);
  color: var(--k-200);
  border-color: var(--lime-350);
}
.fb-btn-primary:hover:not(:disabled) {
  background: var(--lime-300);
  border-color: var(--lime-400);
}
.fb-btn-primary:active:not(:disabled) { transform: translateY(1px); }

/* Success state — large checkmark, centered. */
.fb-success {
  align-items: center;
  text-align: center;
  padding: 8px 0;
}
.fb-success-mark {
  width: 56px; height: 56px;
  border-radius: 50%;
  background: var(--lime-200);
  color: var(--text);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 28px; font-weight: 700;
  margin-bottom: 4px;
}
.fb-success .fb-btn { margin-top: 12px; }

@media (max-width: 480px) {
  .fb-modal { padding: 16px; }
  .fb-card { padding: 24px 20px; }
  .fb-actions { flex-direction: column-reverse; }
  .fb-actions .fb-btn { width: 100%; }
}

/* ============================================================
   19. Mobile nav: hamburger + drawer
   ============================================================
   Below 880px the inline CTA + Sign in are removed and replaced by a
   hamburger button. Tapping it opens a right-side drawer with all
   five nav links, the Sign in pill, and the primary CTA. Backdrop
   click and ESC both close. Mounted always so transitions animate.
   ============================================================ */

.nav-burger {
  display: none;
  width: 40px; height: 40px;
  flex: 0 0 40px;
  padding: 0; margin: 0;
  background: transparent; border: 0; cursor: pointer;
  position: relative;
  border-radius: 8px;
  transition: background .15s ease;
}
.nav-burger:hover { background: var(--panel-warm); }
.nav-burger-bar {
  position: absolute; left: 10px; right: 10px;
  height: 2px;
  background: var(--k-200);
  border-radius: 2px;
  transition: transform .2s ease, opacity .2s ease, top .2s ease;
}
.nav-burger-bar:nth-child(1) { top: 13px; }
.nav-burger-bar:nth-child(2) { top: 19px; }
.nav-burger-bar:nth-child(3) { top: 25px; }
.nav-burger.is-open .nav-burger-bar:nth-child(1) {
  top: 19px; transform: rotate(45deg);
}
.nav-burger.is-open .nav-burger-bar:nth-child(2) { opacity: 0; }
.nav-burger.is-open .nav-burger-bar:nth-child(3) {
  top: 19px; transform: rotate(-45deg);
}

/* Drawer overlay — full viewport with a top-anchored panel that
   slides DOWN from the top edge. Backdrop fades up + blurs the page
   content behind it; panel translates. Same timing on both so the
   open/close motion reads as one gesture. */
.nav-drawer {
  position: fixed; inset: 0;
  z-index: 110;
  background: rgba(13, 13, 14, 0);
  /* backdrop-filter is animated via the .is-open class below.
     Setting it here at 0 keeps the transition smooth on close. */
  backdrop-filter: blur(0);
  -webkit-backdrop-filter: blur(0);
  visibility: hidden;
  transition:
    background .22s ease,
    backdrop-filter .22s ease,
    -webkit-backdrop-filter .22s ease,
    visibility 0s linear .22s;
  display: none;
}
.nav-drawer.is-open {
  /* Lighter dim than before (was 0.45) so the blur does most of the
     "page receding" work without the heavy darkening. The blur is
     what the user actually feels — the dim is just a tiny floor. */
  background: rgba(13, 13, 14, 0.22);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  visibility: visible;
  transition:
    background .22s ease,
    backdrop-filter .22s ease,
    -webkit-backdrop-filter .22s ease,
    visibility 0s linear 0s;
}
.nav-drawer-panel {
  position: absolute;
  /* Anchored to the top edge, full width, content-driven height.
     Slides down from above on open. Subtle rounded bottom corners
     give it a "card peeking in from the top" feel rather than a
     flat sheet edge. */
  top: 0; left: 0; right: 0;
  background: var(--paper);
  box-shadow: 0 16px 48px rgba(13, 13, 14, 0.18);
  border-bottom: 1px solid var(--hairline);
  border-bottom-left-radius: 18px;
  border-bottom-right-radius: 18px;
  display: flex; flex-direction: column;
  /* Cap height so the panel never exceeds the viewport on devices
     with tiny vertical space; long menus would scroll inside. */
  max-height: min(560px, 92vh);
  overflow-y: auto;
  transform: translateY(-100%);
  transition: transform .32s cubic-bezier(0.32, 0.72, 0, 1);
}
.nav-drawer.is-open .nav-drawer-panel { transform: translateY(0); }

/* Drawer header — sticky at the top so the close button stays
   reachable even after the user scrolls down through a long link list.
   Mirrors the main nav's height (64px) so the visual rhythm is
   continuous across the open/closed states. */
.nav-drawer-header {
  position: sticky; top: 0;
  z-index: 1;
  display: flex; align-items: center; justify-content: space-between;
  height: 64px;
  padding: 0 16px 0 20px;
  background: var(--paper);
  border-bottom: 1px solid var(--hairline);
}
.nav-drawer-brand {
  display: inline-flex; align-items: center; gap: 10px;
  text-decoration: none;
  color: var(--k-200);
  font-weight: 600; font-size: 17px;
  letter-spacing: -0.01em;
}
.nav-drawer-brand img { height: 28px; width: auto; display: block; }

.nav-drawer-close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  padding: 0; margin: 0;
  background: transparent;
  border: 0;
  border-radius: 50%;
  color: var(--k-200);
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.nav-drawer-close:hover { background: var(--panel-warm); }
.nav-drawer-close:focus-visible {
  outline: 2px solid var(--lime-300, var(--lime-500));
  outline-offset: 2px;
}

.nav-drawer-links {
  list-style: none; padding: 8px 12px;
  margin: 0;
  display: flex; flex-direction: column;
}
.nav-drawer-links a {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 12px;
  font-size: 18px; font-weight: 600;
  color: var(--k-200);
  letter-spacing: -0.005em;
  text-decoration: none;
  border-radius: 10px;
  transition: background .15s ease, color .15s ease;
  /* min-height keeps each row at a comfortable thumb target even
     when font rendering shrinks below 50px box height. */
  min-height: 56px;
}
.nav-drawer-links a:hover,
.nav-drawer-links a:active {
  background: var(--panel-warm);
}
.nav-drawer-links li + li {
  border-top: 1px solid var(--hairline);
}
/* Subtle right-arrow on each link — tiny visual cue that tapping
   navigates somewhere, common on mobile menus. Muted at rest, brand
   color on hover/focus. */
.nav-drawer-chev {
  font-size: 18px;
  color: var(--g-400, var(--text-muted, var(--g-500)));
  transition: color .15s ease, transform .2s ease;
}
.nav-drawer-links a:hover .nav-drawer-chev,
.nav-drawer-links a:focus-visible .nav-drawer-chev {
  color: var(--lime-500, var(--k-200));
  transform: translateX(2px);
}

.nav-drawer-cta {
  display: flex; flex-direction: column; gap: 10px;
  padding: 16px 20px 24px;
  margin-top: auto;
  border-top: 1px solid var(--hairline);
}
.nav-drawer-signin {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px;
  padding: 12px 16px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  font-size: 15px; font-weight: 500;
  color: var(--k-200);
  background: transparent;
  text-decoration: none;
  transition: background .15s ease;
}
.nav-drawer-signin:hover { background: var(--panel-warm); }
.nav-drawer-cta .ui-btn {
  width: 100%; justify-content: center;
  min-height: 48px;
}

/* Below 880px: hide the inline CTA + signin, show the burger and drawer.
   Below 520px the existing rule already hid .nav-signin; that's
   redundant now since .nav-cta is hidden, but harmless. */
@media (max-width: 880px) {
  .nav-cta { display: none; }
  .nav-burger { display: block; }
  .nav-drawer { display: block; }
}
