/* Shared chrome for the pieces js/site.js renders on every page: the
 * "keep exploring" strip, the footer atlas, the day/night theme, and the
 * motion layer. Written against the site's common tokens with fallbacks,
 * so it sits quietly under any page's own inline styles and never fights
 * them.
 *
 * Night mode: pages declare their (light) tokens in a plain `:root` block
 * that comes AFTER this stylesheet, so the dark overrides below use the
 * selector `html:not([data-theme="light"])` / `html[data-theme="dark"]`
 * — one specificity step above `:root` — to win the cascade by rank
 * alone, never by force. js/site.js stamps `data-theme` from the visitor's saved
 * choice; with no choice saved, the media query follows the system. */

/* ---------- day tokens for the shared patterns ---------- */

/* Six patterns were copy-pasted across the site as raw hex — a tinted info
 * card, the long-form doc kit's blue-bordered furniture, the warm page
 * gradient, white `code` chips, the 3D studio backdrop, and the label
 * checkerboard. Raw hex cannot follow a theme, so every one of them stayed
 * white at night. They live here as tokens instead: these are the *day*
 * values, and the night blocks below flip all of them at once.
 *
 * Day rendering is held still deliberately: each value is the literal it
 * replaced, except where tokenising folded together several copies of the
 * same color that had drifted a few units apart (four hairline grays within
 * 9/255, two near-blacks within 8). tests/dark-mode.test.mjs allows that
 * folding up to 12/255 and fails anything wider, which is what a real
 * mistake — a white mapped onto a dark token — actually looks like.
 *
 * This block is a plain `:root`, same rank as each page's own `:root`. It
 * loses to a page that declares the same token — which is what we want, a
 * page may still speak for itself — and applies everywhere else. Pages
 * reference them as `var(--token, #literal)` so the old value survives even
 * if this stylesheet fails to load. */
:root {
  --surface-2: #f4f4f5;      /* recessed surface, one step under --surface */
  --surface-raised: #ffffff; /* a card sitting above --bg */
  --tint: #eff6ff;           /* brand-tinted wash */
  --tint-2: #fafafa;         /* the pale end of a tinted gradient */
  --tint-border: #dbeafe;    /* the border that pairs with --tint */
  --tint-border-strong: #bfdbfe; /* the same border, one step louder */
  --studio-1: #ffffff;        /* 3D studio backdrop: center */
  --studio-2: #eef1f6;        /*                     mid */
  --studio-3: #e6eaf2;        /*                     edge */
  --warm-1: #fff9ec;         /* the warm page gradient: canary top */
  --warm-2: #faf7f2;         /*                        paper middle */
  --warm-3: #f3f6ff;         /*                        cool bottom */
  --checker-a: #eceef3;      /* transparency checkerboard */
  --checker-b: #f7f8fb;
  --deck: #3f3f46;           /* hero deck / section lead: deliberately one
                              * step darker than --text-secondary, so it gets
                              * its own token rather than being folded in */
}

/* ---------- night tokens ---------- */

html[data-theme="dark"] {
  --bg: #0c0c0e; --bg-alt: #131316; --surface: #17171b;
  --border: #26262b; --border-strong: #3f3f46;
  --text: #f4f4f5; --text-secondary: #b6b6bd; --text-muted: #71717a;
  --brand: #7aa5f8; --brand-dark: #a5c0fa; --brand-darker: #5c8df0; --brand-light: #1b2440;
  --brand-glow: rgba(122, 165, 248, 0.35); --bg-code: #050507;
  --canary: #f5b301; --canary-soft: #2a2410; --canary-dark: #e8c25a;
  --success: #34d399; --success-bg: #10261d;
  --caution: #f0a34c; --caution-bg: #2a2110; --danger: #f87171;
  --surface-2: #111114; --surface-raised: #1c1c21;
  --tint: #16203a; --tint-2: #101319; --tint-border: #27395f;
  --tint-border-strong: #33497a;
  --studio-1: #1e2026; --studio-2: #16181c; --studio-3: #0e0f12;
  --stage-1: #16181c; --stage-2: #0e0f12;   /* showroom's own studio stops */
  --warm-1: #17140c; --warm-2: #121114; --warm-3: #0f1220;
  --checker-a: #17171b; --checker-b: #1c1c21;
  /* The semantic tint families. Pages declare these in their own `:root`
   * (a pale mint "good" card, amber "heads up", rose "danger", plum accent)
   * and until now nothing redefined them at night — so a page could be fully
   * dark and still hold three glowing pastel cards. Same hue, night
   * luminance, matched to the --success-bg / --caution-bg already above. */
  --moss-bg: #10261d; --moss-soft: #10261d; --moss-border: #1e4436;
  --good-bg: #10261d; --good-border: #1e4436;
  --amber-bg: #2a2110; --amber-soft: #2a2110; --warm-soft: #2a1e10;
  --danger-bg: #2c1416; --danger-soft: #2c1416; --rose-bg: #2c1418;
  --plum-bg: #1e1a35; --violet-soft: #1e1a35;
  /* …and the ink that sits on them. These were picked to read on a pale
   * pastel, so darkening only the card would trade a glaring card for an
   * illegible one — #059669 moss on a #10261d mint is nearly invisible.
   * Each lifts to the same hue at night weight. */
  --deck: #c6c6cf;
  --moss: #34d399; --good: #34d399;
  --warm: #f0a34c; --amber: #f0a34c;
  --rose: #fb7185; --alert: #f87171;
  --violet: #a78bfa; --plum: #a78bfa;
  /* Day shadows are near-black at low alpha — on a #0c0c0e page they are
   * invisible, so every raised card flattens into the background at night.
   * Night gets depth the way night actually reads it: a deeper, tighter
   * drop plus a hairline light rim, so elevation survives. */
  --shadow-sm: 0 1px 2px rgba(0,0,0,.55), 0 0 0 1px rgba(255,255,255,.045);
  --shadow-md: 0 8px 20px -8px rgba(0,0,0,.7), 0 0 0 1px rgba(255,255,255,.055);
  --shadow-lg: 0 28px 64px -20px rgba(0,0,0,.82), 0 0 0 1px rgba(255,255,255,.07);
  --shadow-brand: 0 16px 40px -16px rgba(122,165,248,.42);
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) {
    --bg: #0c0c0e; --bg-alt: #131316; --surface: #17171b;
    --border: #26262b; --border-strong: #3f3f46;
    --text: #f4f4f5; --text-secondary: #b6b6bd; --text-muted: #71717a;
    --brand: #7aa5f8; --brand-dark: #a5c0fa; --brand-darker: #5c8df0; --brand-light: #1b2440;
    --brand-glow: rgba(122, 165, 248, 0.35); --bg-code: #050507;
    --canary: #f5b301; --canary-soft: #2a2410; --canary-dark: #e8c25a;
    --success: #34d399; --success-bg: #10261d;
    --caution: #f0a34c; --caution-bg: #2a2110; --danger: #f87171;
    --surface-2: #111114; --surface-raised: #1c1c21;
    --tint: #16203a; --tint-2: #101319; --tint-border: #27395f;
    --tint-border-strong: #33497a;
    --studio-1: #1e2026; --studio-2: #16181c; --studio-3: #0e0f12;
    --stage-1: #16181c; --stage-2: #0e0f12;
    --warm-1: #17140c; --warm-2: #121114; --warm-3: #0f1220;
    --checker-a: #17171b; --checker-b: #1c1c21;
    --moss-bg: #10261d; --moss-soft: #10261d; --moss-border: #1e4436;
    --good-bg: #10261d; --good-border: #1e4436;
    --amber-bg: #2a2110; --amber-soft: #2a2110; --warm-soft: #2a1e10;
    --danger-bg: #2c1416; --danger-soft: #2c1416; --rose-bg: #2c1418;
    --plum-bg: #1e1a35; --violet-soft: #1e1a35;
    --deck: #c6c6cf;
    --moss: #34d399; --good: #34d399;
    --warm: #f0a34c; --amber: #f0a34c;
    --rose: #fb7185; --alert: #f87171;
    --violet: #a78bfa; --plum: #a78bfa;
    --shadow-sm: 0 1px 2px rgba(0,0,0,.55), 0 0 0 1px rgba(255,255,255,.045);
    --shadow-md: 0 8px 20px -8px rgba(0,0,0,.7), 0 0 0 1px rgba(255,255,255,.055);
    --shadow-lg: 0 28px 64px -20px rgba(0,0,0,.82), 0 0 0 1px rgba(255,255,255,.07);
    --shadow-brand: 0 16px 40px -16px rgba(122,165,248,.42);
    color-scheme: dark;
  }
}

/* Shared patterns the pages hard-code in light colors (the body gradient
 * and the frosted header). Both dark sources get the same overrides, so
 * night looks right even before a stored choice is stamped. */
html[data-theme="dark"] body {
  background: linear-gradient(180deg, #0e1017 0%, #0d0e12 30%, var(--bg, #0c0c0e) 100%);
}
html[data-theme="dark"] header.site {
  background: rgba(14, 14, 17, 0.88);
  border-bottom-color: var(--border, #26262b);
}
html[data-theme="dark"] .lab-promo-section {
  background: linear-gradient(180deg, var(--bg) 0%, #1c180d 55%, var(--bg) 100%);
}
/* the landing page's glass-and-orb hero, dimmed for night */
html[data-theme="dark"] .gradient-orb-1 { background: linear-gradient(135deg, #16295e 0%, #101c40 100%); }
html[data-theme="dark"] .gradient-orb-2 { background: linear-gradient(135deg, #251f52 0%, #171338 100%); }
html[data-theme="dark"] .gradient-orb-3 { background: linear-gradient(135deg, #4a3407 0%, #2a1e05 100%); }
html[data-theme="dark"] header.scrolled {
  background: rgba(14, 14, 17, 0.82);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
html[data-theme="dark"] .announce-badge { background: rgba(23, 23, 27, 0.94); }
html[data-theme="dark"] .btn-secondary { background: rgba(23, 23, 27, 0.8); }
html[data-theme="dark"] .btn-secondary:hover { background: var(--surface, #17171b); }
html[data-theme="dark"] nav .btn-nav { color: #0c0c0e; }
html[data-theme="dark"] .hero-code-block { background: var(--surface, #17171b); }
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) body {
    background: linear-gradient(180deg, #0e1017 0%, #0d0e12 30%, var(--bg, #0c0c0e) 100%);
  }
  html:not([data-theme="light"]) header.site {
    background: rgba(14, 14, 17, 0.88);
    border-bottom-color: var(--border, #26262b);
  }
  html:not([data-theme="light"]) .lab-promo-section {
    background: linear-gradient(180deg, var(--bg) 0%, #1c180d 55%, var(--bg) 100%);
  }
  html:not([data-theme="light"]) .gradient-orb-1 { background: linear-gradient(135deg, #16295e 0%, #101c40 100%); }
  html:not([data-theme="light"]) .gradient-orb-2 { background: linear-gradient(135deg, #251f52 0%, #171338 100%); }
  html:not([data-theme="light"]) .gradient-orb-3 { background: linear-gradient(135deg, #4a3407 0%, #2a1e05 100%); }
  html:not([data-theme="light"]) header.scrolled {
    background: rgba(14, 14, 17, 0.82);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  }
  html:not([data-theme="light"]) .announce-badge { background: rgba(23, 23, 27, 0.94); }
  html:not([data-theme="light"]) .btn-secondary { background: rgba(23, 23, 27, 0.8); }
  html:not([data-theme="light"]) .btn-secondary:hover { background: var(--surface, #17171b); }
  html:not([data-theme="light"]) nav .btn-nav { color: #0c0c0e; }
  html:not([data-theme="light"]) .hero-code-block { background: var(--surface, #17171b); }
}

/* Each page's own <style> block sets nav.main's flex/gap/font-size, but
 * none of them stop a link's own text from wrapping once the flex item
 * shrinks below its natural width — on narrow (iOS Safari) viewports that
 * splits "The Lab" onto two lines instead of letting the row scroll
 * horizontally, which is what overflow-x: auto below is actually for.
 * white-space + flex-shrink: 0 keep every link one line and its natural
 * width, so the row scrolls instead of wrapping. */
nav.main { overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
nav.main::-webkit-scrollbar { display: none; }
nav.main a { white-space: nowrap; flex-shrink: 0; }
nav.main a[aria-current="page"] { color: var(--text, #09090b); font-weight: 700; }

.site-next { max-width: 1100px; margin: 56px auto 0; padding: 0 20px; }
.site-next h2 {
  font-size: 15px; font-weight: 600; letter-spacing: 0.01em;
  color: var(--text-muted, #71717a); margin: 0 0 14px;
}
.site-next-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
.site-next-card {
  display: flex; flex-direction: column; gap: 6px;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #e4e4e7);
  border-radius: 18px; padding: 18px 20px;
  text-decoration: none;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.site-next-card:hover { border-color: var(--brand, #2563eb); transform: translateY(-1px); }
.site-next-card strong { color: var(--text, #09090b); font-size: 15px; }
.site-next-card span { color: var(--text-secondary, #52525b); font-size: 13.5px; line-height: 1.45; }

.site-atlas {
  margin-top: 48px;
  border-top: 1px solid var(--border, #e4e4e7);
  background: var(--bg-alt, var(--surface, #fff));
}
.site-atlas-inner {
  max-width: 1100px; margin: 0 auto; padding: 30px 20px 34px;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 22px 28px;
}
.site-atlas-col { display: flex; flex-direction: column; gap: 0; align-items: flex-start; }
.site-atlas-col h3 {
  font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--text-muted, #71717a); margin: 0 0 6px;
}
/* pages style their header `nav a` with button-ish padding; the atlas is a
 * nav too, so pin the compact directory look at class specificity */
.site-atlas-col a {
  color: var(--text-secondary, #52525b); text-decoration: none;
  font-size: 13px; line-height: 1.5; padding: 2.5px 0; margin: 0;
  font-weight: 400; display: inline-block;
}
.site-atlas-col a.stage-start { margin-top: 11px; }
.site-atlas-col a:hover { color: var(--brand, #2563eb); }
.site-atlas-col a[aria-current="page"] { color: var(--text, #09090b); font-weight: 600; }
/* The naming stack — who makes what, resolved once on every page. Shares the
   colophon's quiet register but carries the top border, so the two read as one
   closing block rather than two rules. */
.site-naming {
  grid-column: 1 / -1; margin: 12px 0 0; padding-top: 18px;
  border-top: 1px solid var(--border, #e4e4e7);
  font-size: 13px; color: var(--text-secondary, #52525b);
}
.site-naming a { color: inherit; font-weight: 600; text-decoration: none; }
.site-naming a:hover { color: var(--brand, #2563eb); text-decoration: underline; }

.site-colophon {
  grid-column: 1 / -1; margin: 10px 0 0; padding-top: 0;
  font-size: 12.5px; color: var(--text-muted, #71717a);
}
.site-colophon a { color: inherit; font-weight: 600; text-decoration: none; }
.site-colophon a:hover { color: var(--brand, #2563eb); }

/* ---------- header controls: day/night + chirps ---------- */

.site-controls { display: flex; align-items: center; gap: 6px; margin-left: 12px; flex: none; }
/* logo left; nav + controls together on the right, whatever the header's own layout */
.site-inner nav.main { margin-left: auto; }
.site-controls button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 999px;
  border: 1px solid var(--border, #e4e4e7);
  background: var(--surface, #fff); color: var(--text-secondary, #52525b);
  cursor: pointer; padding: 0;
  transition: color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.site-controls button:hover { color: var(--text, #09090b); border-color: var(--border-strong, #d4d4d8); }
.site-controls button:active { transform: scale(0.92); }
.site-controls svg { width: 16px; height: 16px; }
.site-controls .sound-toggle[aria-pressed="false"] { opacity: 0.55; }
.site-controls .sound-toggle[aria-pressed="true"] { color: var(--canary-dark, #8a6d00); border-color: var(--canary, #f5b301); opacity: 1; }

/* One-line microcopy toast, announced politely and gone in a breath. */
.site-toast {
  position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%) translateY(6px);
  background: var(--surface, #fff); color: var(--text-secondary, #52525b);
  border: 1px solid var(--border, #e4e4e7); border-radius: 999px;
  padding: 8px 18px; font-size: 13.5px; font-weight: 500;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10);
  opacity: 0; pointer-events: none; z-index: 60;
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.site-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- the motion layer (only for visitors who welcome motion) ---------- */

@media (prefers-reduced-motion: no-preference) {
  /* A brief, gentle cross-fade while day and night trade places. */
  html.theme-turning, html.theme-turning body, html.theme-turning header.site,
  html.theme-turning .site-next-card, html.theme-turning .site-atlas {
    transition: background 0.45s ease, background-color 0.45s ease,
      color 0.45s ease, border-color 0.45s ease;
  }
  /* The theme button's icon takes a slow half-turn, like a sun setting. */
  .site-controls .theme-toggle svg { transition: transform 0.45s cubic-bezier(0.3, 0.7, 0.4, 1.2); }
  .site-controls .theme-toggle.turned svg { transform: rotate(180deg); }

  /* Next stops and atlas columns drift up as they enter the view. */
  .site-next-card, .site-atlas-col {
    opacity: 0; transform: translateY(10px);
    transition: opacity 0.5s ease, transform 0.5s ease,
      border-color 0.15s ease;
  }
  .site-next-card.in-view, .site-atlas-col.in-view { opacity: 1; transform: none; }
  .site-next-card:nth-child(2), .site-atlas-col:nth-child(2) { transition-delay: 0.07s; }
  .site-next-card:nth-child(3), .site-atlas-col:nth-child(3) { transition-delay: 0.14s; }
  .site-next-card:nth-child(4), .site-atlas-col:nth-child(4) { transition-delay: 0.21s; }
  .site-next-card.in-view:hover { transform: translateY(-1px); }
}

/* ---------- the Canary: a sticky, static, ask-me-anything search buddy ----------
 * The floating mascot (js/canary-search.js) and its command-palette. Themed
 * from the same tokens as everything else; motion is opt-in; it never covers
 * the page until asked. */

.canary-fab {
  position: fixed; right: 20px; bottom: 20px; z-index: 65;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 14px 7px 8px; border-radius: 999px;
  background: var(--surface, #fff); color: var(--text, #09090b);
  border: 1px solid var(--border, #e4e4e7);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.16);
  cursor: pointer; font: inherit; font-weight: 600; font-size: 14px;
}
.canary-fab .canary-m { width: 34px; height: 34px; }
.canary-fab:hover { border-color: var(--canary, #f5b301); }
.canary-fab:focus-visible { outline: 2px solid var(--brand, #2563eb); outline-offset: 2px; }
.canary-fab-hint { padding-right: 4px; }
@media (max-width: 540px) { .canary-fab-hint { display: none; } .canary-fab { padding: 6px; } }

.canary-backdrop[hidden] { display: none; }
.canary-backdrop {
  position: fixed; inset: 0; z-index: 70;
  display: flex; align-items: flex-start; justify-content: center;
  padding: min(14vh, 120px) 16px 16px;
  background: rgba(9, 9, 11, 0.42); backdrop-filter: blur(2px);
}

.canary-panel {
  width: 100%; max-width: 560px; max-height: 72vh; overflow: hidden;
  display: flex; flex-direction: column;
  background: var(--surface, #fff); color: var(--text, #09090b);
  border: 1px solid var(--border-strong, #d4d4d8); border-radius: 16px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.34);
}
.canary-panel-top { padding: 12px; border-bottom: 1px solid var(--border, #e4e4e7); }
.canary-q {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 16px;
  padding: 11px 14px; border-radius: 10px;
  border: 1px solid var(--border, #e4e4e7);
  background: var(--bg, #fafafa); color: var(--text, #09090b);
}
.canary-q:focus { outline: none; border-color: var(--brand, #2563eb); }

.canary-results { list-style: none; margin: 0; padding: 8px; overflow-y: auto; }
.canary-chips { display: flex; flex-wrap: wrap; gap: 8px; padding: 6px 6px 10px; }
.canary-chip {
  font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
  padding: 6px 12px; border-radius: 999px;
  border: 1px solid var(--border, #e4e4e7);
  background: var(--bg, #fafafa); color: var(--text-secondary, #52525b);
}
.canary-chip:hover { border-color: var(--canary, #f5b301); color: var(--text, #09090b); }

.canary-hit {
  display: flex; align-items: center; gap: 12px; cursor: pointer;
  padding: 10px 12px; border-radius: 10px;
}
.canary-hit.is-active { background: var(--brand-light, #eff4ff); }
.canary-hit-body { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.canary-hit-body strong { font-size: 14.5px; }
.canary-hit-sub {
  font-size: 12.5px; color: var(--text-muted, #71717a);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.canary-hit-go { color: var(--text-muted, #a1a1aa); font-size: 13px; opacity: 0; }
.canary-hit.is-active .canary-hit-go { opacity: 1; }
.canary-tag {
  flex: none; font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.03em; padding: 3px 7px; border-radius: 6px;
  color: var(--text-secondary, #52525b); background: var(--bg-alt, #f4f4f5);
}
.canary-tag-action { color: var(--canary-dark, #8a6d00); background: var(--canary-soft, #fdf6e3); }
.canary-tag-board { color: var(--brand-darker, #1e40af); background: var(--brand-light, #eff4ff); }

.canary-none { padding: 14px 12px; color: var(--text-muted, #71717a); font-size: 13.5px; }
.canary-panel-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 14px; border-top: 1px solid var(--border, #e4e4e7);
}
.canary-voice { margin: 0; font-size: 13px; color: var(--text-secondary, #52525b); }
.canary-kbd { font-size: 11.5px; color: var(--text-muted, #a1a1aa); flex: none; }

/* The words that matched, lit in canary gold — an underline glow, not a
 * highlighter smear, so rows stay calm and nothing shifts. */
.canary-hit mark, .canary-featured mark {
  background: transparent; color: inherit; font-weight: 700;
  box-shadow: inset 0 -2px 0 var(--canary, #f5b301);
}
.canary-hit-sub mark { font-weight: 600; }

/* Where the hit lives — the route, quiet and monospaced, like a breadcrumb. */
.canary-hit-route {
  flex: none; font-family: ui-monospace, Menlo, monospace;
  font-size: 11px; color: var(--text-muted, #a1a1aa);
}
.canary-hit.is-active .canary-hit-route { color: var(--text-secondary, #52525b); }
@media (max-width: 540px) { .canary-hit-route { display: none; } }

/* Recent hops — the visitor's own last destinations (local only, clearable). */
.canary-recent {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  padding: 2px 6px 10px; margin-top: 2px;
}
.canary-recent-label {
  flex: none; font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--text-muted, #a1a1aa);
}
.canary-chip-recent { border-style: dashed; }
.canary-recent-x {
  flex: none; cursor: pointer; font: inherit; font-size: 15px; line-height: 1;
  background: none; border: none; padding: 2px 6px; border-radius: 6px;
  color: var(--text-muted, #a1a1aa);
}
.canary-recent-x:hover { color: var(--text, #09090b); }

/* "Did you mean …?" — the one-row soft landing when a query finds nothing. */
.canary-dym { padding: 4px 6px 10px; }
.canary-dym-btn {
  display: block; width: 100%; cursor: pointer; text-align: left;
  font: inherit; font-size: 14px; padding: 11px 12px; border-radius: 10px;
  color: var(--text-secondary, #52525b);
  background: var(--bg, #fafafa); border: 1px dashed var(--border-strong, #d4d4d8);
}
.canary-dym-btn strong { color: var(--text, #09090b); }
.canary-dym-btn:hover { border-color: var(--canary, #f5b301); color: var(--text, #09090b); }

@media (prefers-reduced-motion: no-preference) {
  .canary-fab { transition: transform 0.18s ease, border-color 0.18s ease; }
  .canary-fab:hover { transform: translateY(-2px); }
  .canary-fab:active { transform: scale(0.96); }
  .canary-backdrop { animation: canary-dim 0.14s ease-out; }
  .canary-panel { animation: canary-drop 0.18s cubic-bezier(0.2, 0.9, 0.3, 1.15); }
  .canary-hit { transition: background 0.1s ease; }
  @keyframes canary-dim { from { opacity: 0; } to { opacity: 1; } }
  @keyframes canary-drop {
    from { opacity: 0; transform: translateY(-8px) scale(0.985); }
    to { opacity: 1; transform: none; }
  }
}

/* ---------- the Canary, part two: nudging visitors toward the Lab ----------
 * A first-visit greeting bubble, a featured "Start in the Lab" row in the
 * search, and a brief one-time attention pulse on the launcher. All opt-out
 * (dismiss / open the search), motion is opt-in, themed from the same tokens. */

/* The featured Lab row at the top of the empty search state. */
.canary-featured { padding: 4px 6px 10px; }
.canary-featured-btn {
  display: flex; align-items: center; gap: 12px; width: 100%; cursor: pointer;
  text-align: left; font: inherit; padding: 11px 12px; border-radius: 10px;
  color: var(--text, #09090b);
  background: var(--canary-soft, #fdf6e3);
  border: 1px solid var(--canary, #f5b301);
}
.canary-featured-btn:hover { background: var(--brand-light, #eff4ff); border-color: var(--brand, #2563eb); }
.canary-featured-emoji { flex: none; display: flex; }
.canary-featured-body { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.canary-featured-body strong { font-size: 14.5px; }
.canary-featured-body span { font-size: 12.5px; color: var(--text-secondary, #52525b); }
.canary-featured-btn .canary-hit-go { opacity: 1; color: var(--canary-dark, #8a6d00); font-size: 16px; }

@media (prefers-reduced-motion: no-preference) {
  /* A brief golden ring that breathes out from the launcher — three beats,
     then it rests. Box-shadow only, so nothing reflows. */
  .canary-fab.is-fresh { animation: canary-pulse 1.5s ease-out 3; }
  @keyframes canary-pulse {
    0%   { box-shadow: 0 8px 28px rgba(0,0,0,.16), 0 0 0 0 var(--canary-glow, rgba(245,179,1,.55)); }
    70%  { box-shadow: 0 8px 28px rgba(0,0,0,.16), 0 0 0 14px rgba(245,179,1,0); }
    100% { box-shadow: 0 8px 28px rgba(0,0,0,.16), 0 0 0 0 rgba(245,179,1,0); }
  }
}

/* ---------- the Canary, part three: the living mascot ----------
 * The bird itself (js/canary-mascot.js) — inline SVG, no image fetch.
 * Expressions are class state on the <svg> root (canary-m--thinking etc.),
 * so a reduced-motion visitor still gets a fully expressive bird; only the
 * *movement* (blink, breathe, hop, wave, twinkle) is opt-in below. */

.canary-m { display: block; overflow: visible; }
.canary-m-eyes, .canary-m-pupils, .canary-m-wing, .canary-m-beak-lo,
.canary-m-bird, .canary-m-hop-layer, .canary-m-gesture-layer {
  transform-box: fill-box; transform-origin: center;
}
.canary-m-wing { transform-origin: 50% 15%; }
/* A nod pivots at the feet, a shake at the belly — otherwise both read as
 * the whole bird sliding rather than the bird moving. */
.canary-m-gesture-layer { transform-origin: 50% 92%; }
/* At rest the lower beak tucks up behind the upper one. */
.canary-m-beak-lo { transform: translateY(-2.6px); }
.canary-m-brows, .canary-m-think, .canary-m-sweat, .canary-m-spark,
.canary-m-zzz { opacity: 0; }

/* Moods. Thinking: eyes drift up-and-away, thought dots appear. Concerned:
 * worried brows, a sweat drop, downcast eyes. Happy/celebrate: open-beak
 * smile; celebrate also throws both wings up with sparkles. Shrug: wings out
 * and low, brows up — "search me". */
.canary-m--thinking .canary-m-think { opacity: 1; }
.canary-m--thinking .canary-m-pupils { transform: translate(1.6px, -1.9px); }
.canary-m--concerned .canary-m-sweat, .canary-m--concerned .canary-m-brows { opacity: 1; }
.canary-m--concerned .canary-m-pupils { transform: translate(0, 1.3px); }
.canary-m--happy .canary-m-beak-lo, .canary-m--celebrate .canary-m-beak-lo { transform: none; }
.canary-m--celebrate .canary-m-spark { opacity: 1; }
.canary-m--celebrate .canary-m-wing-l { transform: rotate(-62deg); }
.canary-m--celebrate .canary-m-wing-r { transform: rotate(62deg); }
.canary-m--shrug .canary-m-brows { opacity: 1; }
.canary-m--shrug .canary-m-wing-l { transform: rotate(28deg) translateX(-2px); }
.canary-m--shrug .canary-m-wing-r { transform: rotate(-28deg) translateX(2px); }

/* Dozing: eyes shut, a small "z". A state, not a mood — it layers over idle
 * and lifts the moment anything happens, so a sleeping bird can still be
 * handed a message and wake up mid-sentence. */
.canary-m-dozing .canary-m-eyes { transform: scaleY(0.08); }
.canary-m-dozing .canary-m-zzz { opacity: 1; }

/* Hovering the launcher raises a wing. This is the *pose*, kept out here so a
 * reduced-motion visitor still gets a greeting; the motion block below plays
 * a real two-beat wave on top of it, after which the wing stays up as long as
 * the pointer does. */
.canary-fab:hover .canary-m-wing-r { transform: rotate(58deg); }

/* The perch: the bird sits on the panel's top edge, feet over the border.
 * Decorative only — clicks fall through to the backdrop beneath it. */
.canary-panel-wrap { position: relative; width: 100%; max-width: 560px; }
.canary-panel-wrap .canary-panel { max-width: none; }
.canary-perch { position: absolute; top: -47px; right: 30px; pointer-events: none; }

@media (prefers-reduced-motion: no-preference) {
  /* Idle life: a slow breath and the occasional blink. Both periods come from
   * per-bird custom properties that js/canary-mascot.js stamps on each <svg>
   * — birds blinking in lockstep is the tell that they're one animation on
   * two elements rather than two creatures. The literals here are the
   * fallback if the JS never ran. */
  .canary-m-bird { animation: canary-m-breathe var(--breathe-every, 3.4s) ease-in-out infinite; }
  @keyframes canary-m-breathe { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(0.7px); } }
  .canary-m-eyes {
    animation: canary-m-blink var(--blink-every, 4.6s) ease-in-out var(--blink-delay, 0s) infinite;
  }
  @keyframes canary-m-blink {
    0%, 92%, 100% { transform: scaleY(1); }
    94%, 96.5% { transform: scaleY(0.08); }
  }

  /* Expression changes ease rather than snap. 0.16s = TIMING.mood. */
  .canary-m-pupils, .canary-m-wing, .canary-m-beak-lo, .canary-m-eyes {
    transition: transform 0.16s ease;
  }
  .canary-m-brows, .canary-m-think, .canary-m-sweat, .canary-m-spark,
  .canary-m-zzz { transition: opacity 0.16s ease; }

  /* Thought dots pulse while thinking; sparkles twinkle while celebrating. */
  .canary-m--thinking .canary-m-think circle { animation: canary-m-muse 1.3s ease-in-out infinite; }
  .canary-m--thinking .canary-m-think circle:nth-child(2) { animation-delay: 0.22s; }
  .canary-m--thinking .canary-m-think circle:nth-child(3) { animation-delay: 0.44s; }
  @keyframes canary-m-muse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
  .canary-m-spark path { transform-box: fill-box; transform-origin: center; }
  .canary-m--celebrate .canary-m-spark path { animation: canary-m-twinkle 1.1s ease-in-out infinite; }
  .canary-m--celebrate .canary-m-spark path:nth-child(2) { animation-delay: 0.18s; }
  .canary-m--celebrate .canary-m-spark path:nth-child(3) { animation-delay: 0.36s; }
  @keyframes canary-m-twinkle {
    0%, 100% { opacity: 0.25; transform: scale(0.8); }
    50% { opacity: 1; transform: scale(1.1); }
  }

  /* Asleep: the blink stops (the eyes are already shut) and the breath drops
   * to a slow, deeper swell. The "z"s drift up and fade, staggered. */
  .canary-m-dozing .canary-m-eyes { animation: none; }
  .canary-m-dozing .canary-m-bird { animation-duration: 5.4s; }
  .canary-m-zzz path { transform-box: fill-box; transform-origin: center; }
  .canary-m-dozing .canary-m-zzz path { animation: canary-m-snooze 3.2s ease-in-out infinite; }
  .canary-m-dozing .canary-m-zzz path:nth-child(2) { animation-delay: 1.6s; }
  @keyframes canary-m-snooze {
    0%   { opacity: 0; transform: translate(0, 3px) scale(0.7); }
    35%  { opacity: 1; }
    100% { opacity: 0; transform: translate(3px, -7px) scale(1.05); }
  }

  /* ---- gestures: one-shot, fired from JS as .canary-m-g-<name> ----
   * Each keyframe is named canary-m-g-<name> so the module can clear its own
   * class on animationend without a lookup table. Durations mirror TIMING. */

  /* The happy hop — squash on the crouch, stretch at the top, per the
   * animation guide. 0.56s = TIMING.hop. */
  .canary-m-g-hop .canary-m-hop-layer { animation: canary-m-g-hop 0.56s cubic-bezier(0.34, 0.8, 0.4, 1); }
  @keyframes canary-m-g-hop {
    0% { transform: translateY(0) scale(1, 1); }
    18% { transform: translateY(1.5px) scale(1.07, 0.9); }
    46% { transform: translateY(-5px) scale(0.95, 1.06); }
    72% { transform: translateY(0.5px) scale(1.05, 0.94); }
    100% { transform: translateY(0) scale(1, 1); }
  }

  /* Hello — the wing comes up and waves twice before settling. 0.9s =
   * TIMING.wave. The launcher borrows the same keyframe on hover, so a
   * hovered bird waves for real instead of holding a raised wing. */
  .canary-m-g-wave .canary-m-wing-r,
  .canary-fab:hover .canary-m-wing-r { animation: canary-m-g-wave 0.9s ease-in-out; }
  @keyframes canary-m-g-wave {
    0%   { transform: rotate(0deg); }
    22%  { transform: rotate(58deg); }
    45%  { transform: rotate(34deg); }
    68%  { transform: rotate(58deg); }
    100% { transform: rotate(0deg); }
  }

  /* Yes — a small tip forward and back. 0.52s = TIMING.nod. */
  .canary-m-g-nod .canary-m-gesture-layer { animation: canary-m-g-nod 0.52s ease-in-out; }
  @keyframes canary-m-g-nod {
    0%, 100% { transform: rotate(0deg) translateY(0); }
    35% { transform: rotate(6deg) translateY(1.2px); }
    70% { transform: rotate(-2deg); }
  }

  /* No — a quick shake. 0.56s = TIMING.shake. */
  .canary-m-g-shake .canary-m-gesture-layer { animation: canary-m-g-shake 0.56s ease-in-out; }
  @keyframes canary-m-g-shake {
    0%, 100% { transform: translateX(0) rotate(0deg); }
    20% { transform: translateX(-2px) rotate(-4deg); }
    50% { transform: translateX(2px) rotate(4deg); }
    80% { transform: translateX(-1px) rotate(-2deg); }
  }
}

/* ---------- the Canary, part four: the Herald ----------
 * The header mascot promoted to assistant (js/canary-herald.js): the logo
 * bird, and the one speech bubble that carries both its chat and the site's
 * alerts. The bubble is fixed-position and JS-placed — anchored under the
 * bird while the header is on screen, docked to the top of the viewport once
 * it isn't, so a message is never delivered somewhere you can't see it. */

/* The bird in the logo. It keeps the exact box the page's own CSS gave the
 * image it replaced (JS measures and sets the size inline), so forty-odd
 * hand-styled headers all keep their layout. */
.canary-logo-shell { display: inline-flex; flex: none; cursor: pointer; }
.canary-logo-shell .canary-m { width: 100%; height: 100%; }

.canary-herald[hidden] { display: none; }
.canary-herald {
  position: fixed; z-index: 64; /* under the search panel, over the page */
  display: flex; align-items: flex-start; gap: 10px;
  width: max-content; max-width: min(340px, calc(100vw - 20px));
  padding: 10px 8px 10px 13px; border-radius: 14px;
  background: var(--surface, #fff); color: var(--text, #09090b);
  border: 1px solid var(--canary, #f5b301);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
}
/* Tone is carried by the left edge, not by repainting the whole card — the
 * bubble stays legible in day and night without a second color scheme. */
.canary-herald[data-tone="info"] { border-color: var(--brand, #2563eb); }
.canary-herald[data-tone="good"] { border-color: var(--success, #16a34a); }
.canary-herald[data-tone="warn"] { border-color: var(--caution, #d97706); }

.canary-herald-avatar { display: none; flex: none; width: 22px; height: 22px; }
.canary-herald-avatar .canary-m { width: 22px; height: 22px; }
.canary-herald-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.canary-herald-text { margin: 0; font-size: 13.5px; line-height: 1.45; }
.canary-herald-cta {
  font-size: 13px; font-weight: 600; text-decoration: none; white-space: nowrap;
  color: var(--brand, #2563eb); width: max-content;
}
.canary-herald-cta[hidden] { display: none; }
.canary-herald-cta:hover { text-decoration: underline; }
.canary-herald-x {
  flex: none; cursor: pointer; font: inherit; font-size: 17px; line-height: 1;
  background: none; border: none; color: var(--text-muted, #a1a1aa);
  padding: 2px 6px; border-radius: 6px;
}
.canary-herald-x:hover { color: var(--text, #09090b); }

/* A tail pointing up at the header bird — only while we're anchored to it. */
.canary-herald::after {
  content: ''; position: absolute; left: 18px; top: -7px;
  width: 12px; height: 12px; background: var(--surface, #fff);
  border-left: 1px solid; border-top: 1px solid; border-color: inherit;
  transform: rotate(45deg);
}

/* Docked: the header has scrolled away, so the bubble becomes the header —
 * a slim bar across the top, carrying its own small bird so it still reads
 * as the Canary speaking. */
.canary-herald.is-docked {
  left: 50%; top: 10px; transform: translateX(-50%);
  align-items: center; border-radius: 999px; padding: 8px 8px 8px 12px;
}
.canary-herald.is-docked::after { display: none; }
.canary-herald.is-docked .canary-herald-avatar { display: flex; }
.canary-herald.is-docked .canary-herald-body { flex-direction: row; align-items: center; gap: 10px; }
/* Docked, the line is one line: the message elides before the action does,
 * so the thing you can act on never gets squeezed off the bar. */
.canary-herald.is-docked .canary-herald-text {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.canary-herald.is-docked .canary-herald-cta { flex: none; }
@media (max-width: 540px) {
  .canary-herald.is-docked { max-width: calc(100vw - 16px); }
}

@media (prefers-reduced-motion: no-preference) {
  .canary-herald {
    opacity: 0; transform: translateY(-6px);
    transition: opacity 0.22s ease, transform 0.22s cubic-bezier(0.2, 0.9, 0.3, 1.2);
  }
  .canary-herald.is-visible { opacity: 1; transform: none; }
  .canary-herald.is-docked { transform: translateX(-50%) translateY(-6px); }
  .canary-herald.is-docked.is-visible { transform: translateX(-50%); }
  .canary-logo-shell { transition: transform 0.18s ease; }
  .canary-logo-shell:hover { transform: translateY(-1px) scale(1.06); }
  .canary-logo-shell:active { transform: scale(0.94); }
}

/* ==========================================================================
 * "View in your room" AR — reusable button + modal (see js/ar-launch.js).
 * Tokens resolve to whichever :root the host page declares, so this adapts
 * to light pages and night mode alike.
 * ====================================================================== */
.ar-cta {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  border: 0; border-radius: 999px;
  background: var(--brand, #2563eb); color: #fff;
  font: 600 14.5px/1 'Inter', system-ui, sans-serif;
  padding: 11px 18px; box-shadow: 0 8px 20px var(--brand-glow, rgba(37,99,235,.32));
  text-decoration: none; transition: background .15s ease, transform .15s ease;
}
.ar-cta:hover { background: var(--brand-darker, var(--brand-dark, #1d4ed8)); transform: translateY(-1px); }
.ar-cta::before {
  content: ''; width: 17px; height: 17px; flex: none;
  background: currentColor;
  -webkit-mask: center/contain no-repeat var(--ar-ico); mask: center/contain no-repeat var(--ar-ico);
  --ar-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2 3 7v10l9 5 9-5V7z'/%3E%3Cpath d='M3 7l9 5 9-5'/%3E%3Cpath d='M12 22V12'/%3E%3C/svg%3E");
}
.ar-cta.in-viewer { position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%); }
.ar-cta.in-viewer:hover { transform: translateX(-50%) translateY(-1px); }

.ar-modal { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; }
.ar-modal[hidden] { display: none; }
.ar-modal-backdrop { position: absolute; inset: 0; background: rgba(6,8,15,0.66); backdrop-filter: blur(4px); }
.ar-modal-card {
  position: relative; z-index: 1; width: min(92vw, 760px);
  background: var(--surface, #fff); color: var(--text, #09090b);
  border: 1px solid var(--border, #e4e4e7); border-radius: 18px; overflow: hidden;
  box-shadow: 0 30px 80px rgba(0,0,0,.45);
}
.ar-modal-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 15px 20px 10px; }
.ar-modal-title { font-size: 16px; font-weight: 700; letter-spacing: -0.01em; }
.ar-modal-dims { font-size: 12.5px; color: var(--text-secondary, #52525b); font-variant-numeric: tabular-nums; }
.ar-modal-x {
  position: absolute; top: 8px; right: 12px; z-index: 2; border: 0; background: transparent;
  color: var(--text-muted, #a1a1aa); font-size: 26px; line-height: 1; cursor: pointer; padding: 4px 8px;
}
.ar-modal-x:hover { color: var(--text, #09090b); }
.ar-modal-stage { position: relative; }
.ar-modal-stage model-viewer {
  width: 100%; height: min(64vh, 520px); display: block;
  background: radial-gradient(120% 120% at 50% 16%, #ffffff 0%, #eef1f6 60%, #e4e8ef 100%);
}
.ar-modal-foot { padding: 12px 20px; border-top: 1px solid var(--border, #e4e4e7);
  font-size: 12.5px; color: var(--text-secondary, #52525b); background: var(--bg-alt, #f4f4f5); min-height: 20px; }
@media (prefers-reduced-motion: reduce) { .ar-cta { transition: none; } }

/* ==========================================================================
   Three-things — the "camera + notary + vault = one witness" positioning
   block. Shared so the same pitch reads identically on /witness, the home
   page, and anywhere else it's embedded. It leans only on tokens that
   site.css already themes, so it's correct in light and dark with no
   per-page overrides. Canonical markup lives in docs/brand-narrative.md.
   ========================================================================== */
.tt-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px; text-align: left; }
.tt-card { position: relative; overflow: hidden; background: var(--surface, #fff);
  border: 1px solid var(--border, #e4e4e7); border-radius: 18px; padding: 22px 24px;
  box-shadow: 0 16px 44px rgba(9, 9, 11, .05); }
.tt-card::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 4px; background: var(--tt-accent, var(--brand, #2563eb)); }
.tt-card[data-c="camera"] { --tt-accent: var(--brand, #2563eb); }
.tt-card[data-c="notary"] { --tt-accent: var(--canary, #f5b301); }
.tt-card[data-c="vault"]  { --tt-accent: #7c3aed; }
.tt-ic { font-size: 30px; line-height: 1; }
.tt-role { font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted, #a1a1aa); margin-top: 12px; }
.tt-card h3 { font-size: 20px; margin: 3px 0 0; letter-spacing: -0.02em; line-height: 1.15; }
.tt-card p { font-size: 14.5px; color: var(--text-secondary, #52525b); margin-top: 10px; line-height: 1.55; }
.tt-card p.tt-old { font-size: 13px; color: var(--text-muted, #a1a1aa); margin-top: 8px; }
.tt-card code { font-family: ui-monospace, Menlo, monospace; font-size: 12.5px; background: var(--bg-alt, #f4f4f5); padding: 1px 6px; border-radius: 5px; }
.tt-merge { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px 14px; margin-top: 28px; }
.tt-op { font-size: 26px; font-weight: 300; color: var(--text-muted, #a1a1aa); }
.tt-chip { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 92px;
  background: var(--surface, #fff); border: 1px solid var(--border, #e4e4e7); border-radius: 14px; padding: 14px 12px; }
.tt-chip .tt-e { font-size: 26px; line-height: 1; }
.tt-chip .tt-l { font-size: 12.5px; font-weight: 600; color: var(--text-secondary, #52525b); }
.tt-chip.tt-out { border-color: var(--canary, #f5b301); background: var(--canary-soft, #fff7e0); box-shadow: 0 12px 34px rgba(245, 179, 1, .22); }
.tt-chip.tt-out .tt-l { color: var(--canary-dark, #8a6d00); font-weight: 800; }
