/* ==========================================================================
   echo//log — design tokens & base theme
   Phase 1 / Chapter 1: foundation only. No component restructuring here.
   Palette: white bg, ink, dim gray, 5 jewel rarity tones.
   Grid: 4px. No border-radius. Fonts: SF Pro Rounded / Nunito + Roboto Mono.
   ========================================================================== */

:root {
  /* ---- colors (Classic light — safe no-JS fallback) ---- */
  --bg: #fcfcfc;
  --bg-soft: #f0f0f1;
  --bg-alt: #e2e2e4;
  --bg-term: #0b0b0b;
  --term-ink: #e4e4e4;
  --term-ink-dim: #8e8e90;
  --term-ink-faint: #5a5a5c;

  --ink: #0e0e10;
  --ink-dim: #5e5e64;
  --ink-invert: #fcfcfc;

  --line: #d4d4d7;
  --line-strong: #9c9ca0;
  --line-ink: #0e0e10;

  /* stage layers */
  --stage-halo: transparent;
  --stage-bg-ink: #b8b8bc;

  /* Rarity — 6 tiers.
     Order: gray → green → blue → purple → orange/warm → accent.
     Tier 6 is reserved for glitch species; see rarity.js. */
  --r-1: #8a8a90; /* common    — gray   */
  --r-2: #2a9d4a; /* uncommon  — green  */
  --r-3: #4d6fdf; /* rare      — blue   */
  --r-4: #8446d8; /* epic      — purple */
  --r-5: #e07a1c; /* legendary — orange */
  --r-6: #c92a3a; /* glitch    — red    */

  --danger: #c92a3a;
  --nav-bg: rgba(252, 252, 252, 0.9);

  /* ---- spacing (4px grid, 9 stops) ---- */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 20px;
  --s-7: 28px;
  --s-9: 36px;
  --s-12: 48px;
  --s-16: 64px;

  /* ---- sizes ---- */
  --top-h: 56px;
  --nav-h: 64px;

  /* ---- radius (locked to 0) ---- */
  --radius: 0;

  /* ---- fonts ----
     UI stack: SF Pro via -apple-system on Apple devices, Inter elsewhere.
     Noto Sans JP added as a fall-through so Hiragana/Katakana/Kanji render
     consistently on non-Apple platforms. Inter / SF cover Latin + Cyrillic. */
  --font-ui: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
    "Roboto", "Inter", "Noto Sans JP", "Hiragino Kaku Gothic ProN", "Yu Gothic",
    system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Roboto Mono", ui-monospace, "SF Mono", Menlo, Monaco, Consolas,
    "Liberation Mono", monospace;

  /* ---- motion ---- */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --dur-1: 120ms;
  --dur-2: 160ms;
  --dur-3: 240ms;

  /* ============================================================
     Block 1 — semantic aliases (additive, no behaviour change).
     Components should migrate to these over time; the raw tokens
     above remain for backward compat while Block 2 lands new
     themes. Layer rule: bg < surface-1 < surface-2 by depth.
     ============================================================ */
  --surface-1:      var(--bg-soft);
  --surface-2:      var(--bg-alt);
  --text-primary:   var(--ink);
  --text-secondary: var(--ink-dim);
  --border:         var(--line);
  --border-strong-alias: var(--line-strong);

  /* System colors — restricted to warnings / success / alerts.
     Not for general UI surfaces. --sys-green intentionally mirrors
     the current rarity-2 value; Block 2 may diverge them. */
  --sys-red:    #ef4444;
  --sys-green:  #22c55e;
  --sys-yellow: #f59e0b;

  /* Opacity scale — replaces scattered literals (0.45, 0.7, 0.85).
     Interaction feedback stays visually consistent. */
  --o-muted: 0.45;
  --o-hover: 0.7;
  --o-press: 0.85;
}

/* ==========================================================================
   Reset
   ========================================================================== */

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

html,
body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
}
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  font-family: var(--font-ui);
  font-weight: 400;
  font-size: 15px;
  line-height: 24px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
  touch-action: manipulation;
}
a {
  color: inherit;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  padding: 0;
}
input,
select,
textarea {
  font: inherit;
  font-size: 16px; /* prevent iOS zoom */
}
pre {
  font-family: var(--font-mono);
  margin: 0;
}
h1,
h2,
h3,
h4,
h5,
h6,
p {
  margin: 0;
}
:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ==========================================================================
   Typography tokens — exactly 8 styles.
   Usage: apply class OR compose values inline in a component.
   ========================================================================== */

.t-display {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 28px;
  line-height: 36px;
  letter-spacing: -0.3px;
  color: var(--ink);
}
.t-heading {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 20px;
  line-height: 28px;
  letter-spacing: -0.2px;
  color: var(--ink);
}
.t-body {
  font-family: var(--font-ui);
  font-weight: 400;
  font-size: 15px;
  line-height: 24px;
  color: var(--ink);
}
.t-body-dim {
  font-family: var(--font-ui);
  font-weight: 400;
  font-size: 12px;
  line-height: 18px;
  color: var(--ink-dim);
}
.t-caption {
  font-family: var(--font-ui);
  font-weight: 400;
  font-size: 10px;
  line-height: 16px;
  color: var(--ink-dim);
}
.t-label {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 10px;
  line-height: 14px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.t-label--strong {
  color: var(--ink);
}
.t-button {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 0.2px;
}
.t-data {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 12px;
  line-height: 18px;
  color: var(--ink);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   App shell
   ========================================================================== */

#app {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}

/* ---- topbar ---- */
.topbar {
  height: var(--top-h);
  padding: 0 var(--s-4);
  padding-top: env(safe-area-inset-top);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 10;
}
.topbar__brand {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  line-height: 16px;
  letter-spacing: 0;
  color: var(--ink);
}
.topbar__brand-slash {
  color: var(--ink-dim);
}

.chip {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 var(--s-3);
  border: 1px solid var(--ink);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  line-height: 16px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* ---- screen container ---- */
.screen-root {
  flex: 1;
  padding: var(--s-5) var(--s-4);
  padding-bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + var(--s-7));
  max-width: 640px;
  width: 100%;
  margin: 0 auto;
}

/* ---- screen-level typography (mapped to .t-display / .t-body-dim) ---- */
/* .screen-head wraps a title + subtitle into a single rhythm block at the
   top of each screen. Screens that skip the title (Collection) can still
   emit a lone .screen-sub without a .screen-head wrapper. */
.screen-head {
  margin: 0 0 var(--s-5);
}
.screen-title {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 28px;
  line-height: 36px;
  letter-spacing: -0.3px;
  color: var(--ink);
  margin: 0 0 var(--s-1);
}
.screen-head .screen-sub {
  margin-bottom: 0;
}
.screen-sub {
  font-family: var(--font-ui);
  font-weight: 400;
  font-size: 12px;
  line-height: 18px;
  color: var(--ink-dim);
  margin: 0 0 var(--s-5);
}

/* ==========================================================================
   Bottom nav
   ========================================================================== */

.bottom-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: calc(var(--nav-h) + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  /* Use the theme background token — falls through both light and dark. */
  background: var(--nav-bg, var(--bg));
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  z-index: 20;
}
.bottom-nav a {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-1);
  min-height: 44px;
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 400;
  line-height: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
  transition: color var(--dur-2) var(--ease);
}
.bottom-nav a.is-active {
  color: var(--ink);
}
.bottom-nav a:active {
  color: var(--ink);
}
.nav__glyph {
  font-family: var(--font-mono);
  font-size: 18px;
  line-height: 1;
}

/* ==========================================================================
   Buttons

   System:
     .btn             — primary, solid ink, 48px, UI font
     .btn.btn--ghost  — outline, transparent, ink text, same size/font
     .btn.btn--sm     — compact 36px mono label variant (inline CTA)
     .btn.btn--inline — shrink to content width (default is 100%)
     .btn.is-secondary — legacy alias for .btn--ghost (backward compat)
   ========================================================================== */

/* ---- Button: base ----
   3 sizes:  (default) 48px  |  --sm 40px  |  --xs 32px
   5 styles: primary (filled) | --ghost (strong outline) | --soft (light outline)
             --text (underline link) | --danger (red filled)
   All mono. All have :active scale + :disabled gray-out.
   --inline removes width:100%.
   ======================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 48px;
  padding: var(--s-3) var(--s-4);
  background: var(--ink);
  color: var(--ink-invert);
  font-family: var(--font-ui);
  font-weight: 400;
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 0.08em;
  border: 1px solid var(--ink);
  cursor: pointer;
  transition: transform var(--dur-1) var(--ease),
    opacity var(--dur-1) var(--ease);
}
.btn:active {
  transform: scale(0.985);
  opacity: 0.9;
}
.btn:disabled {
  background: var(--bg-alt);
  color: var(--ink-dim);
  border-color: var(--line);
  cursor: not-allowed;
  transform: none;
  opacity: 1;
}

/* Size: small (40px) — row actions */
.btn.btn--sm {
  min-height: 40px;
  padding: var(--s-2) var(--s-4);
  font-size: 12px;
  font-weight: 400;
  line-height: 16px;
}

/* Size: extra-small (32px) — inline compact */
.btn.btn--xs {
  min-height: 32px;
  padding: var(--s-1) var(--s-3);
  font-size: 10px;
  font-weight: 400;
  line-height: 16px;
}

/* Width: auto (shrink to content) */
.btn.btn--inline {
  width: auto;
}

/* Style: ghost (strong outline, transparent fill) */
.btn.btn--ghost,
.btn.is-secondary {
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--ink);
}
.btn.btn--ghost:disabled,
.btn.is-secondary:disabled {
  color: var(--ink-dim);
  border-color: var(--line);
  background: transparent;
}

/* Style: soft (light outline, transparent fill) */
.btn.btn--soft {
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--line-strong);
  font-weight: 400;
}
.btn.btn--soft:disabled {
  color: var(--ink-dim);
  border-color: var(--line);
  background: transparent;
}

/* Style: text (underlined link, no border) */
.btn.btn--text {
  background: transparent;
  border: none;
  color: var(--ink);
  font-size: 12px;
  font-weight: 400;
  padding: var(--s-2) 0;
  width: auto;
  min-height: 40px;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.btn.btn--text:hover {
  color: var(--ink-dim);
}
.btn.btn--text:disabled {
  color: var(--ink-dim);
  background: transparent;
  border: none;
}

/* ==========================================================================
   Collection grid
   ========================================================================== */

.collection-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-2);
}
@media (min-width: 520px) {
  .collection-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* Card = flex column: square art area on top, label below.
   Rarity border is on the art square, not the outer card.
   `min-width: 0` prevents long labels from blowing out the grid. */
.insect-card {
  display: flex;
  flex-direction: column;
  background: var(--bg);
  min-width: 0;
  overflow: hidden;
  transition: transform var(--dur-2) var(--ease);
}
.insect-card:active {
  transform: scale(0.97);
}
.insect-card__art {
  aspect-ratio: 1 / 1;
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  /* Halo must match the card's rendered bg so the per-line cushion
     behind the ASCII bug blends invisibly. */
  --stage-halo: var(--bg);
}
/* ==========================================================================
   ASCII insect art
   ==========================================================================
   Legacy `.ascii-bug` class is retained only for the tiny mini icon
   inside discovery log rows (log.js renders a plain <pre.ascii-bug>
   without the stage wrapper). The main collection/detail/reveal art
   all flows through `.variant-stage` + the Stage section below.      */

.ascii-bug {
  font-family: var(--font-mono);
  font-weight: 400;
  white-space: pre;
  line-height: 1;
  letter-spacing: 0;
  text-align: left;
  color: var(--ink);
  user-select: none;
  pointer-events: none;
}

/* ==========================================================================
   Rarity — border color on cards, dot color in badges, tier ink on hero
   ========================================================================== */

.rarity-1 {
  --r: var(--r-1);
  color: var(--r-1);
}
.rarity-2 {
  --r: var(--r-2);
  color: var(--r-2);
}
.rarity-3 {
  --r: var(--r-3);
  color: var(--r-3);
}
.rarity-4 {
  --r: var(--r-4);
  color: var(--r-4);
}
.rarity-5 {
  --r: var(--r-5);
  color: var(--r-5);
}
.rarity-6 {
  --r: var(--r-6);
  color: var(--r-6);
}

.insect-card.rarity-1 .insect-card__art {
  border-color: var(--r-1);
}
.insect-card.rarity-2 .insect-card__art {
  border-color: var(--r-2);
}
.insect-card.rarity-3 .insect-card__art {
  border-color: var(--r-3);
}
.insect-card.rarity-4 .insect-card__art {
  border-color: var(--r-4);
  border-width: 1.5px;
}
.insect-card.rarity-5 .insect-card__art {
  border-color: var(--r-5);
  border-width: 2px;
}
.insect-card.rarity-6 .insect-card__art {
  /* Glitch tier — thickest border to signal "this is not a normal specimen" */
  border-color: var(--r-6);
  border-width: 2px;
}

/* ASCII ink color: always --ink (deep black). Rarity shows via border
   and by the detail hero outline. */
.insect-card__art.variant-stage,
.insect-card .ascii-bug {
  color: var(--ink);
}

/* ==========================================================================
   Empty state
   ========================================================================== */

.empty-state {
  text-align: center;
  padding: var(--s-12) var(--s-5);
  color: var(--ink-dim);
  font-family: var(--font-ui);
  font-size: 12px;
  line-height: 20px;
}
.empty-state strong {
  display: block;
  color: var(--ink);
  font-size: 16px;
  font-weight: 700;
  line-height: 24px;
  margin-bottom: var(--s-2);
}

/* ==========================================================================
   Capture screen — Phase 2
   getUserMedia preview, MediaRecorder waveform, retake buttons.
   ========================================================================== */

.capture {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
.capture-card {
  border: 1px solid var(--line-strong);
  background: var(--bg);
  display: flex;
  flex-direction: column;
  transition: border-color var(--dur-2) var(--ease),
    background var(--dur-2) var(--ease);
}
.capture-card[data-state="live"] {
  border-color: var(--ink);
}
.capture-card[data-state="ready"] {
  border-color: var(--ink);
  background: var(--bg-soft);
}

.capture-card__head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  border-bottom: 1px solid var(--line);
}
.capture-card__icon {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border: 1px solid var(--line-strong);
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--ink);
}
.capture-card[data-state="live"] .capture-card__icon,
.capture-card[data-state="ready"] .capture-card__icon {
  border-color: var(--ink);
  background: var(--bg-alt);
}
.capture-card__title {
  flex: 1;
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 700;
  line-height: 20px;
  color: var(--ink);
}
.capture-card__status {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0.06em;
  color: var(--ink-dim);
}
.capture-card[data-state="ready"] .capture-card__status {
  color: var(--ink);
}
.capture-card[data-state="live"] .capture-card__status {
  color: var(--r-5);
}

.capture-card__stage {
  position: relative;
  min-height: 120px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-3);
  background: var(--bg-alt);
}
.capture-card__video {
  width: 100%;
  max-width: 280px;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: #000;
  display: block;
}
.capture-card__preview {
  width: 72px;
  height: 72px;
  object-fit: cover;
  background: #000;
  display: block;
  flex-shrink: 0;
}
/* Ready state: horizontal layout with thumbnail + signal info */
.capture-card__ready-row {
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;
  width: 100%;
}
.capture-card__placeholder {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0.06em;
  color: var(--ink-dim);
  text-align: center;
}
.capture-card__live-actions {
  display: flex;
  gap: var(--s-2);
  width: 100%;
  max-width: 360px;
}
.capture-card__live-actions .btn {
  flex: 1;
}

.capture-card__timer {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 1px;
  color: var(--ink-dim);
}
.capture-card[data-state="live"] .capture-card__timer {
  color: var(--ink);
}

.waveform {
  width: 100%;
  max-width: 280px;
  height: 48px;
  background: var(--bg);
  border: 1px solid var(--line);
  display: block;
}

.capture-card__actions {
  display: flex;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
}
.capture-card__actions .btn {
  flex: 1;
}

/* ---------- Signal readout (post-capture analysis) ---------- */

.signal-readout {
  flex: 1;
  min-width: 0;
}
.signal-readout__ascii {
  display: none; /* hidden in compact layout — info conveyed by thumbnail */
}
.signal-readout__hash {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0.06em;
  color: var(--ink-dim);
  margin-bottom: var(--s-1);
}
.signal-readout__tags {
  display: flex;
  gap: var(--s-1);
  flex-wrap: wrap;
}

/* ---------- Signal merge preview ---------- */

.signal-merge {
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line-strong);
  background: var(--bg-term);
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
}
.signal-merge__title {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0.06em;
  color: var(--term-ink);
}
.signal-merge__hashes {
  display: flex;
  gap: var(--s-3);
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--term-ink-dim);
}
.signal-merge__bits {
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 0.15em;
  color: var(--term-ink);
}
.signal-merge__hint {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--term-ink-dim);
  width: 100%;
}
.signal-merge__hint--good {
  color: var(--r-2);
}

/* ==========================================================================
   Reveal screen (transient)
   ========================================================================== */

.reveal {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-5);
  padding-top: var(--s-9);
}
.reveal__frame {
  width: 100%;
  max-width: 260px;
  aspect-ratio: 1 / 1;
  border: 1px dashed var(--line-strong);
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s-7);
  overflow: hidden;
  transition: border-color 240ms ease;
  /* Halo matches frame bg so per-line cushion blends invisibly. */
  --stage-halo: var(--bg);
}
.reveal__frame .ascii-bug {
  /* font-size lives lower in the file with the other stage context
     tunings; we only set colour here so the pre-reveal placeholder
     frame looks dim before a species is mounted.                        */
  color: var(--ink-dim);
}
.reveal__frame.rarity-1,
.reveal__frame.rarity-2,
.reveal__frame.rarity-3,
.reveal__frame.rarity-4,
.reveal__frame.rarity-5,
.reveal__frame.rarity-6 {
  border-style: solid;
  border-color: var(--r);
}
.reveal__frame.rarity-4 {
  border-width: 1.5px;
}
.reveal__frame.rarity-5,
.reveal__frame.rarity-6 {
  border-width: 2px;
}
.reveal__frame .ascii-bug.rarity-1,
.reveal__frame .ascii-bug.rarity-2,
.reveal__frame .ascii-bug.rarity-3,
.reveal__frame .ascii-bug.rarity-4,
.reveal__frame .ascii-bug.rarity-5,
.reveal__frame .ascii-bug.rarity-6 {
  color: var(--ink);
}
.reveal__label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  line-height: 16px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.reveal__name {
  margin: 0;
  text-align: center;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 22px;
  line-height: 26px;
  letter-spacing: -0.2px;
  color: var(--ink);
}
.reveal__rarity {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--r, var(--ink-dim));
}
.reveal__flavor {
  font-family: var(--font-ui);
  font-size: 12px;
  line-height: 20px;
  color: var(--ink-dim);
  text-align: center;
  max-width: 320px;
  margin: 0;
}

/* ==========================================================================
   Detail screen (legacy block removed — all rules in the detail section below)
   ========================================================================== */

/* ==========================================================================
   Quests
   ========================================================================== */

/* Quest row — rhythm-matched to .cocoon-card (same border, soft bg,
   72px min-height, s-3 padding). The two stack vertically in Feed so
   they need to read as peers of the same component family. */
.quest {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3);
  margin-bottom: var(--s-2);
  border: 1px solid var(--line);
  background: var(--bg-soft);
  min-height: 72px;
}
.quest.is-done {
  border-color: var(--ink);
  background: var(--bg);
}
.quest__check {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border: 1.5px solid var(--line-strong);
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--ink-invert);
  background: transparent;
}
.quest.is-done .quest__check {
  background: var(--ink);
  border-color: var(--ink);
}
.quest__body {
  flex: 1;
  min-width: 0;
}
.quest__title {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 700;
  line-height: 20px;
  color: var(--ink);
}
.quest__meta {
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 16px;
  color: var(--ink-dim);
  margin-top: var(--s-1);
  letter-spacing: 0.4px;
}
.quest__reward {
  color: var(--ink);
}
/* quest__btn — now uses btn btn--ghost btn--xs btn--inline in JS */

/* ==========================================================================
   Profile
   ========================================================================== */

.profile-card {
  background: var(--bg);
  border: 1px solid var(--line);
  padding: var(--s-5);
  margin-bottom: var(--s-3);
}
.profile-card__row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--s-2) 0;
}
.profile-card__row span {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  line-height: 16px;
  color: var(--ink-dim);
  text-transform: uppercase;
  letter-spacing: 0.8px;
}
.profile-card__row b {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 12px;
  line-height: 20px;
  color: var(--ink);
}
.xp-bar {
  height: 4px;
  background: var(--bg-alt);
  overflow: hidden;
  margin-top: var(--s-3);
}
.xp-bar > div {
  height: 100%;
  background: var(--ink);
  transition: width 400ms var(--ease);
}

.profile-card__label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  line-height: 16px;
  color: var(--ink-dim);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin-bottom: var(--s-3);
}

/* lang-switcher — removed, was dead CSS (replaced by seg-switch) */

/* ==========================================================================
   Cocoon list
   ========================================================================== */

/* (legacy cocoon-card block removed — see Phase 5 block below) */

/* ---- gift code paste input — terminal style ---- */
.cocoon-paste {
  margin-top: var(--s-3);
  padding: var(--s-3);
  background: var(--bg-alt);
  border: 1px solid var(--line);
}
.cocoon-paste__label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-dim);
  margin-bottom: var(--s-2);
}
.cocoon-paste__row {
  display: flex;
  gap: 0;
  align-items: center;
}
.cocoon-paste__prompt {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-dim);
  padding-right: var(--s-2);
  user-select: none;
}
.cocoon-paste__input {
  flex: 1;
  min-width: 0;
  padding: var(--s-1) 0;
  border: none;
  background: transparent;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink);
}
.cocoon-paste__input::placeholder {
  color: var(--ink-dim);
}
/* cocoon-paste__btn — now uses btn btn--ghost btn--xs btn--inline in JS */

/* ==========================================================================
   Toast
   ========================================================================== */

.toast {
  position: fixed;
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + var(--s-3));
  background: var(--ink);
  color: var(--ink-invert);
  padding: var(--s-3) var(--s-5);
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 400;
  line-height: 20px;
  z-index: 50;
  opacity: 0;
  transition: opacity var(--dur-3) var(--ease),
    transform var(--dur-3) var(--ease);
  pointer-events: none;
  max-width: calc(100% - var(--s-9));
  text-align: center;
}
.toast.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ==========================================================================
   Phase 5 — energy widget, variants, friends, gift, detail facts
   ========================================================================== */

.topbar__status {
  display: flex;
  align-items: center;
  gap: var(--s-1);
}

/* Topbar icon button — shared base for topbar controls.
   Framed button with 1px hairline border + soft bg so it reads as a
   clearly tappable control, not a decorative glyph. 36x36 target size
   meets iOS minimum tap guidance. */
.topbar__icon-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--line-strong);
  background: var(--bg-soft);
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-1) var(--ease),
              border-color var(--dur-1) var(--ease),
              opacity var(--dur-1) var(--ease);
}
.topbar__icon-btn:hover {
  border-color: var(--ink);
}
.topbar__icon-btn:active {
  opacity: var(--o-hover);
  background: var(--bg-alt);
}
.topbar__icon-btn.is-off {
  color: var(--ink-dim);
  opacity: var(--o-muted);
}
.topbar__icon-btn.is-active {
  /* Subtle gray fill — matches seg-switch active style. Avoids the
     full ink-invert that previously made a single icon button scream
     louder than the surrounding topbar. */
  background: var(--bg-alt);
  color: var(--ink);
  border-color: var(--line-strong);
}
.topbar__icon-btn.is-hidden {
  display: none;
}
/* Unseen-events dot on the topbar Log button (same visual language as
   the old nav dot). Sits in the top-right corner of the button. */
.topbar__icon-btn.has-dot::after {
  content: "";
  position: absolute;
  top: 3px;
  right: 3px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--r-5, #ec4899);
}
.topbar__icon-glyph {
  /* inline-block so ::after pseudo (strikethrough on sound off) can
     position itself correctly relative to the glyph. */
  display: inline-block;
  position: relative;
  font-family: var(--font-mono);
  font-size: 18px;
  line-height: 1;
}
/* Notification badge for cocoon count (only shown when > 1 ready). */
.topbar__badge {
  position: absolute;
  top: 2px;
  right: 0;
  min-width: 14px;
  height: 14px;
  padding: 0 var(--s-1);
  border: 1px solid var(--ink);
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 9px;
  line-height: 12px;
  text-align: center;
}
.topbar__badge.is-hidden {
  display: none;
}

/* energy system hidden — commented out for now */
.energy-widget {
  display: none;
}
.energy-widget.is-empty {
  border-color: var(--ink);
  color: var(--ink);
}
.energy-widget.is-full {
  opacity: 0.65;
}
.energy-widget__icon { font-size: 10px; }
.energy-widget__value { font-weight: 700; }
.energy-widget__timer { color: var(--ink-dim); }

.energy-hint {
  display: none;
}

/* ---------- variant stage (Phase 6.1 two-layer rework) ----------
   Each stage is a fixed 15ch x 9em monospace box holding two
   independently layered <pre> elements produced by js/render.js:

     stage__bg   — full-canvas ASCII tile (bark/grass/leaf/water),
                   rendered at ~20% ink so it reads as grey texture
                   on both light and dark themes.
     stage__bug  — blank canvas with only the bug glyph stamped in
                   the centre. 100% ink, layered over the bg.

   DOM structure per variant (see js/render.js header):
     still        -> just stage__bug.frame-a
     background   -> stage__bug.frame-a + stage__bug.frame-b (flicker)
     animated     -> stage__bg x2 + stage__bug-group { fill, bug x2 }
     animated_bg  -> stage__bg x2 + stage__bug-group(phantomFade) { fill, bug x2 }

   The stage__bug-fill element is a --bg-coloured rectangle inside the
   bug-group that erases the tile behind the bug's bounding box. When
   the phantom variant fades the whole group, the fill fades with it
   and the bg becomes intact again — so the bug looks like it vanishes
   cleanly rather than punching a rectangular hole.

   Canvas geometry: bug is 5 cols x 4 rows, top-left at (col 5, row 2)
   of the 15 x 9 grid, i.e. fill sits at (left 5ch, top 2em, 5ch x 4em).
   Font-size is set per parent (.ascii-bug rules), so scaling is uniform
   — the tile texture grows proportionally with the bug.              */

/* Stage container — whatever the host element is (insect-card,
   detail hero, reveal frame), `.variant-stage` adds mono font + a
   per-context font-size that uniformly scales both layers. Both the
   bug and the bg are independently centred via translate, so they
   don't need to share any character grid — they just meet at the
   host's geometric centre. Monospace features are belt-and-suspendered
   here so any stray ligature / kerning can't nudge characters. */
.variant-stage {
  font-family: var(--font-mono);
  font-variant-ligatures: none;
  font-feature-settings: "liga" 0, "calt" 0, "kern" 0;
  line-height: 1;
}

/* Per-context font-size. Tuned so even a 9-row bespoke bug leaves
   visible margin on the smallest mobile card (~112px square). */
.insect-card__art.variant-stage {
  font-size: 9px;
}
.detail__hero.variant-stage {
  font-size: 17px;
  font-weight: 400;
}
.reveal__frame.variant-stage {
  font-size: 20px;
  font-weight: 400;
}

.stage {
  position: relative;
}

/* Both layers share centre-of-host positioning. No width/height —
   the <pre> element sizes itself to its content, so the bug's own
   bounding rectangle auto-matches whatever art is drawn (5x4 mealworm
   or 11x9 titan), while the bg is sized to a fixed 13x8 grid by
   render.js's composeBgLayer. */
.stage__bg,
.stage__bug {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
  padding: 0;
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: inherit;
  color: var(--ink);
  white-space: pre;
  display: block;
  line-height: 1;
  letter-spacing: 0;
  font-kerning: none;
  text-align: left;
  pointer-events: none;
  user-select: none;
}

/* Background layer: explicit glyph color instead of opacity so we
   get precise control over tile vs halo contrast in both themes. */
.stage__bg {
  color: var(--stage-bg-ink);
  z-index: 1;
}

/* Bug pre: transparent background — the halo mask is applied per-line
   by .stage__halo spans so it follows the silhouette, not the full
   rectangular bounding box. */
.stage__bug {
  z-index: 3;
}

/* Per-line halo: covers only the active characters (first non-space to
   last non-space) on each row of the bug art.
   The background lives in a ::before with z-index:-1 so that ALL halo
   backgrounds paint before ANY text within the .stage__bug stacking
   context.  Without this, line N's background covers the descenders /
   bottom of characters on line N-1. */
.stage__halo {
  position: relative;  /* anchor for ::before */
}
.stage__halo::before {
  content: "";
  position: absolute;
  inset: -0.1em -0.2ch;
  background: var(--stage-halo);
  border-radius: 2px;
  z-index: -1;
}

/* Bug group wraps the frame-a/frame-b prees so phantomFade can fade
   them together. Zero-size anchor at the stage centre — child prees
   self-centre around it via their own translate. */
.stage__bug-group {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 2;
}
.stage__bug-group .stage__bug {
  position: absolute;
  top: 0;
  left: 0;
  transform: translate(-50%, -50%);
}

/* Frame-swap animation. All 4 variants now animate the bug (2-frame
   flicker). 1400ms cycle = 700ms per pose. BG flicker applies to
   background, animated, animated_bg (all variants that have bg). */
.stage .stage__bug.frame-a {
  animation: stageBugFrameA 1400ms steps(1, end) infinite;
}
.stage .stage__bug.frame-b {
  animation: stageBugFrameB 1400ms steps(1, end) infinite;
}
.stage--background  .stage__bg.frame-a,
.stage--animated    .stage__bg.frame-a,
.stage--animated_bg .stage__bg.frame-a {
  animation: stageBgFrameA 1400ms steps(1, end) infinite;
}
.stage--background  .stage__bg.frame-b,
.stage--animated    .stage__bg.frame-b,
.stage--animated_bg .stage__bg.frame-b {
  animation: stageBgFrameB 1400ms steps(1, end) infinite;
}

@keyframes stageBugFrameA {
  0%, 49%   { opacity: 1; }
  50%, 100% { opacity: 0; }
}
@keyframes stageBugFrameB {
  0%, 49%   { opacity: 0; }
  50%, 100% { opacity: 1; }
}
@keyframes stageBgFrameA {
  0%, 49%   { opacity: 1; }
  50%, 100% { opacity: 0; }
}
@keyframes stageBgFrameB {
  0%, 49%   { opacity: 0; }
  50%, 100% { opacity: 1; }
}

/* Jitter: JS-driven per-species movement (render.js startJitter).
   No CSS animation — transform is set directly via JS every 1400ms
   (synced with frame swap). The class is kept as a semantic marker. */
.stage__bug-group--jitter {
  transition: none;
}

/* Background subtype hooks (reserved for future per-type styling). */
.stage--bg-bark  .stage__bg { /* default ink */ }
.stage--bg-leaf  .stage__bg { /* default ink */ }
.stage--bg-grass .stage__bg { /* default ink */ }
.stage--bg-water .stage__bg { /* default ink */ }

/* Glitch / absolute / legendary background type hooks */
.stage--bg-static_noise .stage__bg { }
.stage--bg-echo_ring    .stage__bg { }
.stage--bg-void_dot     .stage__bg { }
.stage--bg-pixel_grid   .stage__bg { }
.stage--bg-hatch        .stage__bg { }
.stage--bg-binary       .stage__bg { }
.stage--bg-scanline     .stage__bg { }
.stage--bg-sacred       .stage__bg { }
.stage--bg-starfield    .stage__bg { }
.stage--bg-mimic        .stage__bg { }

.variant-img {
  max-width: 100%;
  height: auto;
  display: block;
}

/* ---------- specimen viewer (hero + variant tabs) ---------- */

.detail__specimen {
  border: 1px solid var(--line-strong);
  background: var(--bg);
}
.detail__specimen.rarity-2,
.detail__specimen.rarity-3,
.detail__specimen.rarity-4,
.detail__specimen.rarity-5,
.detail__specimen.rarity-6 {
  border-color: var(--tier-color);
}
/* no extra thickness for epic/legendary — 1px everywhere */

.detail__hero {
  width: 100%;
  aspect-ratio: 4 / 3;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s-2);
  overflow: hidden;
  /* Halo matches hero bg so per-line cushion blends invisibly. */
  --stage-halo: var(--bg);
}

.variant-slider {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  margin: 0;
}
.variant-slot {
  width: auto;
  height: auto;
  min-height: 36px;
  padding: var(--s-2) var(--s-1);
  border: none;
  border-bottom: 1px solid var(--line);
  background: var(--bg-soft);
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background var(--dur-1) var(--ease),
              color var(--dur-1) var(--ease);
}
.variant-slot + .variant-slot {
  border-left: 1px solid var(--line);
}
.variant-slot.is-selected {
  background: var(--bg);
  color: var(--ink);
  border-bottom-color: var(--tier-color, var(--ink));
}
.variant-slot.is-locked {
  color: var(--ink-dim);
  background: var(--bg-alt);
  cursor: not-allowed;
  opacity: 0.6;
}

/* ---------- detail screen ---------- */

.detail {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  padding-bottom: var(--s-9);
  color: var(--ink);
}
.detail__name {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 24px;
  line-height: 28px;
  letter-spacing: -0.3px;
  color: var(--ink);
  margin: 0;
  flex: 1;
  min-width: 0;
}
.detail__heading {
  /* no centering — left-aligned layout */
}
.detail__name-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}
.detail__stats {
  display: flex;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin-top: var(--s-2);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-dim);
  letter-spacing: 0.02em;
}
.detail__stat {
  white-space: nowrap;
}
.detail__rarity {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: var(--s-1) var(--s-2);
  border: 1px solid currentColor;
}
.detail__facts {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 0;
  padding: var(--s-4);
  border: 1px solid var(--line);
  background: var(--bg-soft);
}
.detail__facts dt {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  color: var(--ink-dim);
  letter-spacing: 0.06em;
  margin: 0 0 var(--s-1);
}
.detail__facts dd {
  margin: 0 0 var(--s-4);
  font-size: 14px;
  line-height: 22px;
  color: var(--ink);
}
.detail__facts dd:last-child {
  margin-bottom: 0;
}

/* ---- section wrappers ---- */
.detail__section-title {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 0 0 var(--s-2);
}

/* ---- field notes ---- */
.detail__notes-title {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 0 0 var(--s-2);
}
.detail__notes-body {
  font-size: 14px;
  line-height: 22px;
  color: var(--ink);
  margin: 0 0 var(--s-3);
}
.detail__notes-body:last-child {
  margin-bottom: 0;
}

/* ---- wiki link ---- */
.detail__wiki-link {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--ink);
  text-decoration: none;
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line-strong);
  background: var(--bg);
}
.detail__wiki-link:hover {
  background: var(--ink);
  color: var(--bg);
}

/* ---- category chips ---- */
.detail__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: var(--s-1) var(--s-2);
  border: 1px solid var(--line-strong);
  background: var(--bg);
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: lowercase;
  color: var(--ink-dim);
}
/* Phase 6.3 signal tag chips. The image/sound accents are subtle so
   the chip row reads as "two kinds of signal" without fighting the
   rarity glow around it. `.is-matched` is used on the reveal screen
   for signals the current input satisfied — bumps the chip to full
   ink on the tier accent. Block 3 (2026-04-17): ::before adds an
   ASCII prefix — solid gradient for image, waveform for sound. The
   prefix is decorative only (no i18n impact). */
.tag-chip--image {
  border-left: 2px solid var(--ink-dim);
}
.tag-chip--image::before {
  content: "▓▒░";
  font-family: var(--font-mono);
  letter-spacing: 0;
  color: var(--ink-dim);
  opacity: var(--o-hover);
}
.tag-chip--sound {
  border-left: 2px solid var(--line-strong);
  border-left-style: dashed;
}
.tag-chip--sound::before {
  content: "∿∿";
  font-family: var(--font-mono);
  letter-spacing: 0;
  color: var(--ink-dim);
  opacity: var(--o-hover);
}
.tag-chip.is-matched::before {
  color: var(--tier-color, var(--ink));
  opacity: 1;
}
.tag-chip.is-matched {
  color: var(--ink);
  border-color: var(--tier-color, var(--ink));
  background: var(--bg-soft, var(--bg));
}

.reveal__tags {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-3);
}
.reveal__tags-header {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-dim);
}
.reveal__tags-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--s-2);
}

.detail__signals-title {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-dim);
  margin: 0 0 var(--s-2) 0;
}
.detail__signals-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}
/* ---- gift section ---- */
.detail__gift {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  margin-top: var(--s-2);
}
/* detail__gift-btn — now uses btn btn--soft btn--sm in JS */
.detail__gift-hint {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-dim);
  letter-spacing: 0.02em;
}
.detail__friend-picker {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-3) 0;
}
.detail__friend-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
}
.detail__friend-row--fallback {
  margin-top: var(--s-1);
  padding-top: var(--s-2);
  border-top: 1px solid var(--line);
}
.detail__friend-label {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.detail__no-friends {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.detail__no-friends-text {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-dim);
}

/* ---- locked variant placeholder ---- */
.detail__locked {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  width: 100%;
  height: 100%;
  min-height: 160px;
}
.detail__locked-art {
  font-family: var(--font-mono);
  font-size: 17px;
  font-weight: 400;
  line-height: 1;
  white-space: pre;
  color: var(--ink-dim);
  text-align: center;
}
.detail__locked-msg {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-dim);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* ---------- rarity tint helpers ---------- */

.rarity-1 { --tier-color: var(--r-1); }
.rarity-2 { --tier-color: var(--r-2); }
.rarity-3 { --tier-color: var(--r-3); }
.rarity-4 { --tier-color: var(--r-4); }
.rarity-5 { --tier-color: var(--r-5); }
.rarity-6 { --tier-color: var(--r-6); }

.detail__rarity.rarity-1,
.reveal__rarity.rarity-1 { color: var(--r-1); }
.detail__rarity.rarity-2,
.reveal__rarity.rarity-2 { color: var(--r-2); }
.detail__rarity.rarity-3,
.reveal__rarity.rarity-3 { color: var(--r-3); }
.detail__rarity.rarity-4,
.reveal__rarity.rarity-4 { color: var(--r-4); }
.detail__rarity.rarity-5,
.reveal__rarity.rarity-5 { color: var(--r-5); }
.detail__rarity.rarity-6,
.reveal__rarity.rarity-6 { color: var(--r-6); }

/* ---------- collection card extras ---------- */

.insect-card {
  /* outer card: no extra rules — flex column set above */
}
/* All decorative card overlays sit ABOVE the stage layers (stage__bg
   z=1, stage__bug-group z=2, stage__bug z=3). Without an explicit
   z-index here the default `auto` would paint these underneath the
   stage prees, so the label / count / rarity dot / variant pip would
   be obscured by bark tile characters on animated/animated_bg cards. */
.insect-card__count,
.insect-card__grade,
.insect-card__label {
  z-index: 4;
}
.insect-card__count {
  position: absolute;
  bottom: var(--s-2);
  right: var(--s-2);
  font-family: var(--font-mono);
  font-size: 10px;
  padding: var(--s-1) var(--s-1);
  background: var(--bg);
  color: var(--ink-dim);
}
.insect-card__grade {
  position: absolute;
  top: var(--s-2);
  right: var(--s-2);
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  color: var(--r, var(--ink-dim));
  padding: var(--s-1) var(--s-1);
  background: var(--bg);
}
.insect-card__label {
  padding: var(--s-1) var(--s-2);
  font-size: 10px;
  font-family: var(--font-mono);
  color: var(--ink);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- cocoon card ---------- */

.cocoon-list {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.cocoon-card {
  display: grid;
  grid-template-columns: 56px 1fr;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3);
  min-height: 72px;
  border: 1px solid var(--line);
  background: var(--bg-soft);
}
.cocoon-card.is-ready {
  border-color: var(--ink);
  background: var(--bg);
  cursor: pointer;
}
.cocoon-card.is-ready:active {
  opacity: var(--o-press);
}
.cocoon-card__icon {
  width: 56px;
  height: 56px;
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
  border: 1px solid var(--tier-color, var(--line-strong));
  background: var(--bg-alt);
}
.cocoon-card.is-ready .cocoon-card__icon {
  background: var(--bg);
}
.cocoon-card__art {
  position: absolute;
  margin: 0;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 400;
  line-height: 1;
  white-space: pre;
  color: var(--tier-color, var(--ink));
  font-variant-ligatures: none;
}
.cocoon-card__art--a {
  animation: stageBugFrameA 1800ms steps(1) infinite;
}
.cocoon-card__art--b {
  animation: stageBugFrameB 1800ms steps(1) infinite;
}
.cocoon-card__body {
  min-width: 0;
}
.cocoon-card__status {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--ink);
}
.cocoon-card__status--ready {
  color: var(--r-2);
}
.cocoon-card__sender {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cocoon-card__time {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink);
}
.cocoon-card.is-ready .cocoon-card__time {
  color: var(--ink-dim);
}

/* ---------- friends screen ---------- */

.friend-form {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: var(--s-2);
  margin-bottom: var(--s-3);
}
.input {
  width: 100%;
  border: 1px solid var(--line-strong);
  background: var(--bg);
  padding: var(--s-2) var(--s-3);
  font-family: var(--font-ui);
  color: var(--ink);
}
.input--mono {
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.friend-list {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.friend-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line);
}
.friend-row__label { font-weight: 700; }
.friend-row__code  { font-size: 12px; color: var(--ink-dim); }

.mono { font-family: var(--font-mono); }

.profile-card.is-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--s-3) var(--s-4);
  cursor: pointer;
}
.profile-card__row.is-clickable { cursor: pointer; }
.profile-card__row.is-clickable:active { opacity: var(--o-hover); }

/* ---------- reveal additions ---------- */

.reveal__variant {
  font-family: var(--font-mono);
  font-size: 12px;
  text-transform: uppercase;
  color: var(--ink-dim);
  text-align: center;
  letter-spacing: 0.06em;
}
.reveal__xp {
  text-align: center;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink);
}

/* ---------- receive screen ---------- */

.receive {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-7) var(--s-4);
  text-align: center;
}
.receive__icon {
  font-family: var(--font-mono);
  font-size: 24px;
  font-weight: 400;
  line-height: 1;
  white-space: pre;
  color: var(--ink);
  margin: 0;
}
.receive__title {
  font-size: 22px;
  font-weight: 700;
  margin: 0;
}
.receive__body {
  color: var(--ink-dim);
  max-width: 420px;
  margin: 0;
}

/* ==========================================================================
   Accessibility / reduced motion
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* ==========================================================================
   === Phase 5 / Nav redesign — additive block ==============================
   Everything below is added on top of the original Phase 1/5 styles. It
   exists so the new Feed / Collection hub / Log / About layout and the
   dark theme can be reviewed and reverted as one cohesive chunk.
   ========================================================================== */

/* ---- Dark theme token overrides (Classic dark — safe no-JS fallback) ----
   Each named palette has its own .theme-dark override below; this block
   catches any state where no palette class is yet on <body>. */
body.theme-dark {
  --bg: #000000; --bg-soft: #0c0c0d; --bg-alt: #18181a; --bg-term: #000000;
  --term-ink: #ededed; --term-ink-dim: #868688; --term-ink-faint: #545456;
  --ink: #f2f2f3; --ink-dim: #86868a; --ink-invert: #000000;
  --line: #242428; --line-strong: #3e3e44; --line-ink: #f2f2f3;
  --stage-halo: transparent; --stage-bg-ink: #323236;
  --r-1: #86868a; --r-2: #34c759; --r-3: #6680ff; --r-4: #bf5af2; --r-5: #ff9500; --r-6: #ff3b30;
  --danger: #ff3b30;
  --nav-bg: rgba(0, 0, 0, 0.9);
}

/* ==========================================================================
   Color palettes — 8 themes × light/dark = 16 combos.
   Applied as body.palette-<id> alongside body.theme-light / body.theme-dark.
   ========================================================================== */

/* ---- CLASSIC — watch-face / OLED dashboard ---- */
body.palette-classic {
  --bg: #fcfcfc; --bg-soft: #f0f0f1; --bg-alt: #e2e2e4; --bg-term: #0b0b0b;
  --term-ink: #e4e4e4; --term-ink-dim: #8e8e90; --term-ink-faint: #5a5a5c;
  --ink: #0e0e10; --ink-dim: #5e5e64; --ink-invert: #fcfcfc;
  --line: #d4d4d7; --line-strong: #9c9ca0; --line-ink: #0e0e10;
  --stage-halo: transparent; --stage-bg-ink: #b8b8bc;
  --r-1: #8a8a90; --r-2: #2a9d4a; --r-3: #4d6fdf; --r-4: #8446d8; --r-5: #e07a1c; --r-6: #c92a3a;
  --danger: #c92a3a; --nav-bg: rgba(252, 252, 252, 0.9);
}
body.palette-classic.theme-dark {
  --bg: #000000; --bg-soft: #0c0c0d; --bg-alt: #18181a; --bg-term: #000000;
  --term-ink: #ededed; --term-ink-dim: #868688; --term-ink-faint: #545456;
  --ink: #f2f2f3; --ink-dim: #86868a; --ink-invert: #000000;
  --line: #242428; --line-strong: #3e3e44; --line-ink: #f2f2f3;
  --stage-halo: transparent; --stage-bg-ink: #323236;
  --r-1: #86868a; --r-2: #34c759; --r-3: #6680ff; --r-4: #bf5af2; --r-5: #ff9500; --r-6: #ff3b30;
  --danger: #ff3b30; --nav-bg: rgba(0, 0, 0, 0.9);
}

/* ---- PLAKAT — PAN poster / print-shop CMYK ---- */
body.palette-plakat {
  --bg: #fbfbfd; --bg-soft: #eeeef5; --bg-alt: #dfdfeb; --bg-term: #1a1a22;
  --term-ink: #e8e8f0; --term-ink-dim: #9898a8; --term-ink-faint: #60606e;
  --ink: #0a0a12; --ink-dim: #56566a; --ink-invert: #fbfbfd;
  --line: #d4d4e0; --line-strong: #0a0a12; --line-ink: #0a0a12;
  --stage-halo: transparent; --stage-bg-ink: #b8b8c8;
  --r-1: #7a7a88; --r-2: #00c853; --r-3: #0047ff; --r-4: #7a2dff; --r-5: #ff0090; --r-6: #ffd400;
  --danger: #ff1744; --nav-bg: rgba(251, 251, 253, 0.88);
}
body.palette-plakat.theme-dark {
  --bg: #1a1816; --bg-soft: #242220; --bg-alt: #2f2c28; --bg-term: #0c0a08;
  --term-ink: #ede8de; --term-ink-dim: #8a8680; --term-ink-faint: #5a5650;
  --ink: #f0ece2; --ink-dim: #8a867e; --ink-invert: #1a1816;
  --line: #3a3632; --line-strong: #f0ece2; --line-ink: #f0ece2;
  --stage-halo: transparent; --stage-bg-ink: #44403a;
  --r-1: #8a8680; --r-2: #5ca855; --r-3: #4a88b8; --r-4: #8a5cb4; --r-5: #d45090; --r-6: #e6c840;
  --danger: #dc6850; --nav-bg: rgba(26, 24, 22, 0.88);
}

/* ---- NEWSPRINT — DIY flyer / architectural proof paper ---- */
body.palette-newsprint {
  --bg: #eef1f2; --bg-soft: #e2e6e8; --bg-alt: #d1d7da; --bg-term: #0a0c10;
  --term-ink: #dce1e4; --term-ink-dim: #80868c; --term-ink-faint: #55595e;
  --ink: #0a0b0e; --ink-dim: #4d5258; --ink-invert: #eef1f2;
  --line: #c0c6ca; --line-strong: #0a0b0e; --line-ink: #0a0b0e;
  --stage-halo: transparent; --stage-bg-ink: #a8aeb2;
  --r-1: #7d8388; --r-2: #1c8e54; --r-3: #1b4fd8; --r-4: #5830b0; --r-5: #c8e02c; --r-6: #e8268e;
  --danger: #d91f1f; --nav-bg: rgba(238, 241, 242, 0.88);
}
body.palette-newsprint.theme-dark {
  --bg: #0a0c10; --bg-soft: #14171c; --bg-alt: #1e2128; --bg-term: #04060a;
  --term-ink: #d8dde2; --term-ink-dim: #80868c; --term-ink-faint: #4e5258;
  --ink: #e8ecf0; --ink-dim: #888e94; --ink-invert: #0a0c10;
  --line: #282c34; --line-strong: #484d56; --line-ink: #e8ecf0;
  --stage-halo: transparent; --stage-bg-ink: #34383e;
  --r-1: #9ca2a8; --r-2: #4ab872; --r-3: #6686ff; --r-4: #8570d8; --r-5: #d6ee55; --r-6: #ff5cb0;
  --danger: #ef4850; --nav-bg: rgba(10, 12, 16, 0.88);
}

/* ---- OLD DAYS — sage / dusty textile / Steam olive-military ---- */
body.palette-olddays {
  --bg: #f2efe9; --bg-soft: #e6e2d9; --bg-alt: #d6d1c5; --bg-term: #26221c;
  --term-ink: #e5dfd1; --term-ink-dim: #9a9082; --term-ink-faint: #6a6254;
  --ink: #27231f; --ink-dim: #746e64; --ink-invert: #f2efe9;
  --line: #c9c2b5; --line-strong: #8d8578; --line-ink: #27231f;
  --stage-halo: transparent; --stage-bg-ink: #b5ada0;
  --r-1: #9a8c78; --r-2: #7a9670; --r-3: #4e6b8e; --r-4: #8d7aa8; --r-5: #c27a52; --r-6: #d58ba0;
  --danger: #b8463f; --nav-bg: rgba(242, 239, 233, 0.88);
}
body.palette-olddays.theme-dark {
  --bg: #2a3129; --bg-soft: #333b32; --bg-alt: #3e453c; --bg-term: #151a14;
  --term-ink: #d8d8c4; --term-ink-dim: #8a9080; --term-ink-faint: #5a6054;
  --ink: #e6e6d2; --ink-dim: #96998a; --ink-invert: #2a3129;
  --line: #4a5247; --line-strong: #6c7266; --line-ink: #e6e6d2;
  --stage-halo: transparent; --stage-bg-ink: #4f554a;
  --r-1: #9ea090; --r-2: #a8c470; --r-3: #7a98c0; --r-4: #b29fcc; --r-5: #d68c5e; --r-6: #eab3c4;
  --danger: #d86a63; --nav-bg: rgba(42, 49, 41, 0.88);
}

/* ---- YOU KNOW — Y2K icy-chrome / aubergine substrate ---- */
body.palette-youknow {
  --bg: #f5f7fc; --bg-soft: #e8ecf4; --bg-alt: #d4dae6; --bg-term: #12121e;
  --term-ink: #e4e8f4; --term-ink-dim: #8890a8; --term-ink-faint: #5a6278;
  --ink: #0c0e1c; --ink-dim: #565c72; --ink-invert: #f5f7fc;
  --line: #c0c8d8; --line-strong: #0c0e1c; --line-ink: #0c0e1c;
  --stage-halo: transparent; --stage-bg-ink: #a4acbc;
  --r-1: #8890a8; --r-2: #6fd94a; --r-3: #2196ff; --r-4: #5a3cd8; --r-5: #ff7a1c; --r-6: #ff2d9d;
  --danger: #ff2d55; --nav-bg: rgba(245, 247, 252, 0.88);
}
body.palette-youknow.theme-dark {
  --bg: #1e1226; --bg-soft: #281a32; --bg-alt: #33223f; --bg-term: #0c0610;
  --term-ink: #ece2e8; --term-ink-dim: #9c8ea6; --term-ink-faint: #5e4e68;
  --ink: #f2e8ee; --ink-dim: #9c8ea6; --ink-invert: #1e1226;
  --line: #3e2a4e; --line-strong: #8470a0; --line-ink: #f2e8ee;
  --stage-halo: transparent; --stage-bg-ink: #42305a;
  --r-1: #b0a4b8; --r-2: #a8e87c; --r-3: #6eb0ff; --r-4: #b060ff; --r-5: #ff9842; --r-6: #ff6ac0;
  --danger: #ff5088; --nav-bg: rgba(30, 18, 38, 0.88);
}

/* ---- CORE — concrete / techwear / cold neutral ---- */
body.palette-core {
  --bg: #e7eaec; --bg-soft: #dadee1; --bg-alt: #c6cbcf; --bg-term: #121416;
  --term-ink: #d6d9dc; --term-ink-dim: #8a8d90; --term-ink-faint: #565a5e;
  --ink: #121416; --ink-dim: #5a5d60; --ink-invert: #e7eaec;
  --line: #b4b9be; --line-strong: #3a3d42; --line-ink: #121416;
  --stage-halo: transparent; --stage-bg-ink: #a8a8aa;
  --r-1: #8a8a8d; --r-2: #5a7a3c; --r-3: #4a8cb8; --r-4: #7a5abc; --r-5: #c4653a; --r-6: #ff7a20;
  --danger: #d83c32; --nav-bg: rgba(231, 234, 236, 0.88);
}
body.palette-core.theme-dark {
  --bg: #0d0d0e; --bg-soft: #161618; --bg-alt: #222224; --bg-term: #050505;
  --term-ink: #d8d8dc; --term-ink-dim: #8a8a90; --term-ink-faint: #545458;
  --ink: #f0f0f2; --ink-dim: #909094; --ink-invert: #0d0d0e;
  --line: #2a2a2c; --line-strong: #52525a; --line-ink: #f0f0f2;
  --stage-halo: transparent; --stage-bg-ink: #323238;
  --r-1: #a2a2a8; --r-2: #78a048; --r-3: #68a0d4; --r-4: #9a7ce0; --r-5: #e48050; --r-6: #ff9240;
  --danger: #ed5a50; --nav-bg: rgba(13, 13, 14, 0.88);
}

/* ---- DIFFERENT — Brain Dead × MTG / comic-ink WUBRG ---- */
body.palette-different {
  --bg: #ededed; --bg-soft: #e0e0e0; --bg-alt: #cdcdcd; --bg-term: #0a0a0a;
  --term-ink: #ededed; --term-ink-dim: #8a8a8a; --term-ink-faint: #565656;
  --ink: #0a0a0a; --ink-dim: #525252; --ink-invert: #ededed;
  --line: #bdbdbd; --line-strong: #0a0a0a; --line-ink: #0a0a0a;
  --stage-halo: transparent; --stage-bg-ink: #a8a8a8;
  --r-1: #e8b842; --r-2: #2eb855; --r-3: #2b6ee8; --r-4: #9338d8; --r-5: #e02d2e; --r-6: #4a2654;
  --danger: #e02d2e; --nav-bg: rgba(237, 237, 237, 0.88);
}
body.palette-different.theme-dark {
  --bg: #0a0a0a; --bg-soft: #141414; --bg-alt: #1f1f1f; --bg-term: #000000;
  --term-ink: #ededed; --term-ink-dim: #8a8a8a; --term-ink-faint: #555555;
  --ink: #fafafa; --ink-dim: #909090; --ink-invert: #0a0a0a;
  --line: #2a2a2a; --line-strong: #fafafa; --line-ink: #fafafa;
  --stage-halo: transparent; --stage-bg-ink: #3a3a3a;
  --r-1: #f5d96a; --r-2: #4ccc6c; --r-3: #4a8cff; --r-4: #b96eed; --r-5: #ff4c48; --r-6: #9a6abe;
  --danger: #ff4c48; --nav-bg: rgba(10, 10, 10, 0.88);
}

/* ---- ORBIT — starfield HUD / split-complementary amber ---- */
body.palette-orbit {
  --bg: #ecedf0; --bg-soft: #dfe1e5; --bg-alt: #cdd0d6; --bg-term: #0a0f18;
  --term-ink: #d4d8e0; --term-ink-dim: #808898; --term-ink-faint: #4a5060;
  --ink: #0d1118; --ink-dim: #505668; --ink-invert: #ecedf0;
  --line: #b5b9c4; --line-strong: #0d1118; --line-ink: #0d1118;
  --stage-halo: transparent; --stage-bg-ink: #989ca8;
  --r-1: #7a8294; --r-2: #3d9a6c; --r-3: #2b4d7d; --r-4: #6b4bb0; --r-5: #c72138; --r-6: #d4ac63;
  --danger: #c72138; --nav-bg: rgba(236, 237, 240, 0.88);
}
body.palette-orbit.theme-dark {
  --bg: #050810; --bg-soft: #0c1018; --bg-alt: #161c28; --bg-term: #020408;
  --term-ink: #d4d8e0; --term-ink-dim: #7a8090; --term-ink-faint: #484e5e;
  --ink: #e4e8f0; --ink-dim: #808896; --ink-invert: #050810;
  --line: #20283a; --line-strong: #3e4658; --line-ink: #e4e8f0;
  --stage-halo: transparent; --stage-bg-ink: #2e3648;
  --r-1: #8e96a8; --r-2: #5fc88e; --r-3: #6090d0; --r-4: #9b7ce0; --r-5: #ed5a6a; --r-6: #e8c06a;
  --danger: #ed5a6a; --nav-bg: rgba(5, 8, 16, 0.88);
}

/* ---- Primary nav: 5 tabs, center CTA, notification dot ---- */
.bottom-nav a.is-primary {
  position: relative;
}
.bottom-nav a.is-primary .nav__glyph {
  transform: scale(1.2);
  font-weight: 700;
}
.bottom-nav a.is-primary.is-active .nav__glyph {
  color: var(--ink);
}
.bottom-nav .nav__dot {
  position: absolute;
  top: 6px;
  right: calc(50% - 18px);
  width: 8px;
  height: 8px;
  background: var(--r-5);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-1) var(--ease);
}
.bottom-nav a.has-dot .nav__dot {
  opacity: 1;
}

/* ---- Feed screen ---- */
.feed__quests {
  margin: var(--s-4) 0;
}
.feed__placeholder {
  margin-top: var(--s-5);
  padding: var(--s-5);
  border: 1px dashed var(--line);
  text-align: center;
}
.feed__placeholder strong {
  display: block;
  margin-bottom: var(--s-2);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink);
}
.feed__placeholder p {
  color: var(--ink-dim);
  font-size: 12px;
  line-height: 20px;
}

/* ---- Data chip — unified mono stat pill ---- */
.data-chip {
  display: inline-block;
  padding: var(--s-1) var(--s-2);
  background: var(--bg-alt);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 400;
  color: var(--ink);
  white-space: nowrap;
}
.data-chip--outline {
  background: none;
  border: 1px solid var(--line-strong);
}
.data-chip--bold {
  background: none;
  border: 1px solid var(--ink);
}
.data-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}
.data-chip-row--stretch {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  gap: var(--s-2);
}
.data-chip-row--stretch .data-chip {
  text-align: center;
}

/* ---- Profile widget (flat layout — Figma match) ---- */
.profile-widget {
  padding: 0;
  margin-bottom: var(--s-5);
}
.profile-widget__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--s-2);
}
.profile-widget__code {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: -0.048px;
  color: var(--ink);
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  font-weight: 400;
}
.profile-widget__code:active {
  opacity: var(--o-hover);
}
.profile-widget__right {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
}
.profile-widget__level {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: -0.048px;
  font-weight: 400;
  color: var(--ink);
}
.profile-widget__xp-text {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: -0.048px;
  color: var(--ink-dim);
}
.profile-widget__xp {
  height: 4px;
  background: var(--bg-alt);
  margin-bottom: var(--s-4);
  overflow: hidden;
}
.profile-widget__xp-fill {
  height: 100%;
  background: var(--r-2);
  transition: width var(--dur-3) var(--ease);
}
.profile-widget__stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}
.profile-widget__stat {
  display: inline-block;
  padding: var(--s-1) var(--s-2);
  background: var(--bg-alt);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: -0.048px;
  color: var(--ink);
  text-decoration: none;
}
.profile-widget__stat--outline {
  background: none;
  border: 1px solid var(--line-strong);
}
.profile-widget__stat--bold {
  background: none;
  border: 1px solid var(--ink);
}

/* ---- Collection sections / debug footer ---- */
.collection__section {
  margin-top: var(--s-5);
}
.collection__section-title {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: var(--s-2);
}
.collection__section-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--s-3);
}
.collection__section-header__title {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: -0.048px;
  color: var(--ink);
}
.collection__section-header__action {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: -0.048px;
  color: var(--ink-dim);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}
.collection__section-header__action:hover {
  color: var(--ink);
}
.collection__empty-inline {
  padding: var(--s-3);
  font-size: 12px;
  color: var(--ink-dim);
  background: var(--bg-soft);
  border: 1px dashed var(--line);
}
.collection__debug {
  margin-top: var(--s-9);
  padding: var(--s-3) 0;
  border-top: 1px solid var(--line);
  text-align: center;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.5px;
  color: var(--ink-dim);
  user-select: all;
}

/* Full-width link that replaces the removed Log nav tab — sits below
   the species grid on the Collection page. */
.collection__log-entry {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: var(--s-5);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line-strong);
  background: var(--bg-soft);
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  transition: background var(--dur-1) var(--ease);
}
.collection__log-entry:active {
  background: var(--bg-alt);
}
.collection__log-entry__arrow {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--ink-dim);
}

/* ---- Discovery Log — Phase 6 minimal stream ---- */
.log-stream {
  list-style: none;
  margin: var(--s-4) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}
.log-row {
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;
  padding: 0;
  background: transparent;
  border: 0;
}
.log-row__icon {
  flex: 0 0 auto;
  margin: 0;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 11px;
  color: var(--ink);
  white-space: pre;
  background: transparent;
}
.log-row__body {
  flex: 1 1 auto;
  min-width: 0;
}
.log-row__name {
  font-weight: 700;
  font-size: 14px;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-bottom: var(--s-1);
}
.log-row__meta {
  font-size: 10px;
  color: var(--ink-dim);
  letter-spacing: 0.3px;
}
.log-row__tags {
  font-size: 10px;
  color: var(--ink-dim);
  letter-spacing: 0.3px;
  margin-top: var(--s-1);
}

/* ---- Typography utilities (shared across screens) ---- */
.text-mono {
  font-family: var(--font-mono);
}
.text-tag {
  font-size: 10px;
  letter-spacing: 0.3px;
  color: var(--ink-dim);
}

/* ---- About screen ---- */
.about-section {
  margin-top: var(--s-5);
}
.about-rules__p {
  margin-bottom: var(--s-2);
  color: var(--ink);
  font-size: 14px;
  line-height: 21px;
}

/* Setting rows — unified control pattern for preferences */
.setting-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--line);
  gap: var(--s-3);
}
.setting-row--stack {
  flex-direction: column;
  align-items: stretch;
}
.setting-row__label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-dim);
}
.about-controls {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-2);
  margin-top: var(--s-3);
}
.about-controls .btn {
  width: 100%;
}

/* Segmented switch (used for theme + language in About). */
.seg-switch {
  display: inline-flex;
  border: 1px solid var(--line-strong);
}
.seg-switch__btn {
  padding: var(--s-2) var(--s-4);
  min-height: 36px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
  cursor: pointer;
  border-right: 1px solid var(--line);
}
.seg-switch__btn:last-child {
  border-right: none;
}
.seg-switch__btn.is-active {
  /* Subtle gray fill — aligned with `.topbar__icon-btn.is-active`.
     Ink-invert was too heavy for what is essentially a selection state. */
  background: var(--bg-alt);
  color: var(--ink);
}
.seg-switch__btn:active {
  opacity: 0.8;
}

/* Danger-colored button variant used in About.
   --danger is kept as a semantic alias; its value tracks the system
   red in light mode and a softer red in dark mode so the button stays
   readable without glare against the dark background. */
:root           { --danger: var(--sys-red); }
body.theme-dark { --danger: #ef5b5b; }

.btn.btn--danger {
  background: var(--danger);
  color: var(--ink-invert);
  border-color: var(--danger);
}
.btn.btn--danger:active {
  opacity: var(--o-press);
}
body.theme-dark .btn.btn--danger {
  color: var(--bg);
}

/* ---- Palette picker (About screen) ---- */
.palette-picker {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-2);
  margin-top: var(--s-2);
}
@media (max-width: 380px) {
  .palette-picker { grid-template-columns: repeat(2, 1fr); }
}
.palette-picker__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-1);
  padding: var(--s-2);
  border: 1px solid var(--line);
  background: var(--bg);
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease);
}
.palette-picker__item.is-active {
  border-color: var(--ink);
}
.palette-picker__swatches {
  display: flex;
  gap: var(--s-1);
  width: 100%;
}
.palette-picker__swatch {
  flex: 1;
  height: 12px;
}
.palette-picker__name {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.5px;
  color: var(--ink-dim);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
}
.palette-picker__item.is-active .palette-picker__name {
  color: var(--ink);
}

/* ---- Feed screen — terminal aesthetic ---- */
.feed-stream {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin-top: var(--s-3);
  background: var(--bg-term);
  padding: var(--s-5);
  font-family: var(--font-mono);
  color: var(--term-ink);
}
.feed-post {
  padding: 0;
  border: none;
  background: transparent;
  margin-bottom: var(--s-9);
}
.feed-post:last-child {
  margin-bottom: var(--s-5);
}
.feed-post--intro {
  background: transparent;
}
.feed-post__tag {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--term-ink-dim);
  margin-bottom: var(--s-1);
}
.feed-post__time {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--term-ink-dim);
  margin-bottom: var(--s-2);
}
.feed-post__body {
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 18px;
  color: var(--term-ink);
}
.feed-post__ascii {
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1.3;
  white-space: pre;
  color: var(--term-ink-dim);
  margin: var(--s-2) 0 0;
  overflow-x: auto;
}
.feed-intro__count {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--term-ink-faint);
  letter-spacing: 0.06em;
  margin-bottom: var(--s-2);
}
.feed-intro__title {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 14px;
  line-height: 20px;
  color: var(--term-ink);
  margin-bottom: var(--s-1);
}
.feed-intro__body {
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 18px;
  color: var(--term-ink-dim);
}

/* ==========================================================================
   Responsive rules
   ==========================================================================
   Three breakpoint bands:
     narrow (≤ 380px): iPhone SE / mini / compact devices
     default (381–519px): standard mobile
     wide (≥ 520px): large phones / small tablets / centered desktop
   Each rule tunes rhythm of a specific screen region — kept in this block
   so the system is auditable in one place.
*/

@media (max-width: 380px) {
  /* Topbar: tighter padding so the energy slot / brand don't clip. */
  .topbar {
    padding-left: var(--s-3);
    padding-right: var(--s-3);
  }

  /* Screen container: less horizontal padding on narrow. */
  .screen-root {
    padding: var(--s-4) var(--s-3);
    padding-bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + var(--s-5));
  }

  /* Detail hero: smaller ASCII canvas so bugs stay within the hero. */
  .detail__hero {
    font-size: 16px;
    padding: var(--s-1);
  }

  /* Capture card stage: less vertical height so both cards fit. */
  .capture-card__stage {
    min-height: 96px;
    padding: var(--s-2);
  }

  /* Profile widget stats: wrap 4-up to 2×2 grid so labels don't squeeze. */
  .profile-widget__stats {
    flex-wrap: wrap;
  }
  .profile-widget__stats > * {
    flex: 1 1 calc(50% - var(--s-2));
  }

  /* About controls: stack 2-col button grid into 1 col on narrow. */
  .about-controls {
    grid-template-columns: 1fr;
  }
}

@media (min-width: 520px) {
  /* Detail hero: a bit more breathing room on wider screens. */
  .detail__hero {
    padding: var(--s-4);
  }

  /* Capture cards: restore larger stage padding for comfort. */
  .capture-card__stage {
    padding: var(--s-4);
  }
}

@media (min-width: 768px) {
  /* Tablet+: cap screen width tighter so lines stay readable. */
  .screen-root {
    max-width: 560px;
  }
}

/* ==========================================================================
   Onboarding route modifier: hide bottom nav + topbar status so the
   3-slide flow owns the entire viewport.
   ========================================================================== */
body.is-onboarding .bottom-nav { display: none; }
body.is-onboarding .topbar__status { display: none; }
body.is-onboarding .screen-root {
  padding: 0;
  padding-bottom: env(safe-area-inset-bottom);
}

/* ==========================================================================
   Onboarding — first-time user 3-slide intro
   ==========================================================================
   Layout: a vertical shell fills the viewport below the topbar. Header holds
   pagination dots + skip; middle is a fixed-width horizontal track of 3
   slides translated via transform; footer is the primary CTA.

   Visual language: stays inside the "lab instrument" aesthetic — mono type,
   ASCII corners, minimal colour. No imagery. */

.onboarding {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: calc(100vh - var(--top-h) - var(--nav-h) - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  padding: var(--s-4);
  gap: var(--s-5);
}

.onboarding__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--s-1);
}
.onboarding__dots {
  display: flex;
  gap: var(--s-2);
}
.onboarding__dot {
  width: 8px;
  height: 8px;
  border: 1px solid var(--line-strong);
  background: transparent;
  transition: background var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
.onboarding__dot.is-active {
  background: var(--ink);
  border-color: var(--ink);
}
.onboarding__skip {
  padding: var(--s-1) var(--s-2);
  background: transparent;
  border: 0;
  color: var(--ink-dim);
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  cursor: pointer;
}
.onboarding__skip:hover { color: var(--ink); }

/* Track-wrap clips overflow; track holds 3 slides each 100% wide. */
.onboarding__track-wrap {
  flex: 1;
  overflow: hidden;
  position: relative;
}
.onboarding__track {
  display: flex;
  height: 100%;
  transform: translateX(0);
  transition: transform var(--dur-2) var(--ease);
  touch-action: pan-y;   /* let the page scroll vertically; we handle X */
}

.onboarding__slide {
  flex: 0 0 100%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-3);
  text-align: center;
  user-select: none;
}

/* Visual block: framed ASCII "specimen window" with a single hero glyph. */
.onboarding__visual {
  position: relative;
  width: 176px;
  height: 176px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  background: var(--bg-soft);
  font-family: var(--font-mono);
  color: var(--ink-dim);
}
.onboarding__corner {
  position: absolute;
  font-size: 14px;
  line-height: 1;
  color: var(--ink-dim);
}
.onboarding__corner--tl { top: 4px;    left: 4px; }
.onboarding__corner--tr { top: 4px;    right: 4px; }
.onboarding__corner--bl { bottom: 4px; left: 4px; }
.onboarding__corner--br { bottom: 4px; right: 4px; }
.onboarding__glyph {
  font-size: 56px;
  color: var(--ink);
  line-height: 1;
}

.onboarding__index {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.onboarding__title {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 24px;
  line-height: 32px;
  letter-spacing: -0.3px;
  max-width: 22ch;
  margin: 0;
  color: var(--ink);
}
.onboarding__body {
  font-family: var(--font-ui);
  font-size: 14px;
  line-height: 22px;
  max-width: 42ch;
  margin: 0;
  color: var(--ink-dim);
}

.onboarding__foot {
  padding: 0 var(--s-1);
  padding-bottom: env(safe-area-inset-bottom);
}

@media (max-width: 380px) {
  .onboarding { padding: var(--s-3); gap: var(--s-4); }
  .onboarding__visual { width: 140px; height: 140px; }
  .onboarding__glyph { font-size: 44px; }
  .onboarding__title { font-size: 20px; line-height: 28px; }
  .onboarding__body  { font-size: 13px; line-height: 20px; }
}

/* ==========================================================================
   More (About) screen — fullscreen popup modifier + section styling
   ========================================================================== */

/* When a popup screen (#/about or #/log) is mounted, the bottom nav
   stays visible, and a pinned Close bar sits directly above the nav.
   The topbar icon shows pressed-in (.is-active) to confirm the state. */
body.is-more-open .screen-root,
body.is-log-open  .screen-root {
  /* Reserve space at the bottom for the pinned close bar + the nav
     itself, so scrollable content doesn't hide beneath the close.
     Close bar = 48px + var(--s-3) gap above nav. */
  padding-bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + 48px + var(--s-4));
}

/* Pinned Cancel bar — a distinct boxed button docked above the bottom
   nav. Dark background + 1px border in the same color as its label, so
   it reads as a clear exit affordance (not a transparent ghost bar).
   Visible only while a popup route is mounted. */
.popup-close {
  display: none;
}
body.is-more-open .popup-close,
body.is-log-open  .popup-close {
  position: fixed;
  left: var(--s-4);
  right: var(--s-4);
  bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + var(--s-2));
  display: flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  padding: 0 var(--s-4);
  background: var(--bg);
  border: 1px solid var(--ink);
  color: var(--ink);
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  z-index: 19; /* just below .bottom-nav (z-index: 20) */
  transition: background var(--dur-1) var(--ease),
              color var(--dur-1) var(--ease),
              opacity var(--dur-1) var(--ease);
}
body.is-more-open .popup-close:hover,
body.is-log-open  .popup-close:hover {
  background: var(--ink);
  color: var(--bg);
}
body.is-more-open .popup-close:active,
body.is-log-open  .popup-close:active {
  opacity: var(--o-press);
}

/* Sound off state — muted read comes from the dim ink color + reduced
   opacity rule on `.topbar__icon-btn.is-off` (see the topbar block
   above). No strike-through overlay: it clashed with the clean
   geometric-glyph aesthetic and made the button look broken. */

/* Section body paragraph used in the Contact + Account groups. Friendly
   prose, dim ink, sits below the section title and above its buttons. */
.about-section__body {
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 20px;
  color: var(--ink-dim);
  margin: 0 0 var(--s-3);
  max-width: 60ch;
}

/* "Intro" replay row at the top of More. Single full-width tappable
   block with a title, short body, and a chevron. */
.about-intro-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line-strong);
  background: var(--bg-soft);
  color: var(--ink);
  text-decoration: none;
  transition: background var(--dur-1) var(--ease);
}
.about-intro-row:active { background: var(--bg-alt); }
.about-intro-row__title {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 14px;
  line-height: 20px;
  color: var(--ink);
}
.about-intro-row__body {
  font-family: var(--font-ui);
  font-size: 12px;
  line-height: 18px;
  color: var(--ink-dim);
  margin-top: 2px;
}
.about-intro-row__arrow {
  font-family: var(--font-mono);
  font-size: 18px;
  color: var(--ink-dim);
}

/* Danger-ghost button — red text + red border but no fill. Used for
   "Log out" so it lives between the neutral ghosts (Export/Import) and
   the fully-filled Delete button below it. */
.btn.btn--danger-ghost {
  background: transparent;
  color: var(--danger);
  border-color: var(--danger);
}
.btn.btn--danger-ghost:disabled {
  background: var(--bg-alt);
  color: var(--ink-dim);
  border-color: var(--line);
}

