/* MyCoworkFellow — styles.css */
/* (c) 2026 Resonant Catalyst. All rights reserved. */
/* 3D Tubing Aesthetic — warm taupe, dimensional, premium */

:root {
  /* Interior = GOLDEN HOUR (Tom-APPROVED 2026-06-03 Track A): MThF shifts purple→gold to match
     its new golden-sunset-sea gate. Cool dusk-indigo field (no brown), warmth only in the sunset
     bloom (body::before). Accent gold #f0c46e. REVERT to purple: --bg #0d0a18; --bg-warm #110e20;
     --bg-deep #080610; --surface #1a1530; --surface-lit #24203e; --surface-hover #2e2950;
     --text #e0dce8; --text-bright #f0ecf8; --accent/--fellow #f0c46e; purples were rgba(240, 196, 110,*). */
  --bg: #21223e;
  --bg-warm: #2a2236;
  --bg-deep: #16182e;
  --surface: #232140;
  --surface-lit: #2e2c4a;
  --surface-hover: #36345a;
  --border: rgba(240,196,110,0.16);
  --border-bright: rgba(240,196,110,0.24);
  --text: #efe7d6;
  --text-dim: rgba(225,215,195,0.45);
  --text-bright: #f6f0e2;
  --accent: #f0c46e;
  --title-word: #ab85e0;  /* function word "Thinking" in purple vs gold My/Fellow (two-tone wordmark, Tom 2026-06-05) */

  /* CHAT INTERIOR = the Fellow's two contrasting wordmark tones (ported from MUF pilot, Tom 2026-06-05).
     Cool/brand tone = --accent (gold #f0c46e), function tone = --title-word (purple #ab85e0).
     Two-tone is a TEXT flip on identical dark boxes (subtle, not a colour-box):
       Fellow = gold/glowing label + purple text.   You = purple label + gold text.
     Purple brightened for body legibility on the dark box. Easy on the eyes at night = key test. */
  --bubble-fellow-text: #c2a4e6;     /* purple, brightened for body */
  --bubble-fellow-label: #f0c46e;    /* gold, glowing label */
  --bubble-fellow-strong: #d4bef0;   /* purple a touch brighter (no white pop) */
  --user-text: #f0c46e;              /* gold body text = the Fellow's label tone (the flip) */
  --user-label: #c2a4e6;             /* purple label (the flip of the Fellow's gold label) */
  --accent-glow: rgba(240,196,110,0.20);
  --accent-soft: rgba(240,196,110,0.10);
  --fellow: #f0c46e;
  --fellow-dim: rgba(240,196,110,0.5);
  --danger: #c45a5a;
  --sans: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --serif: 'Cormorant Garamond', Georgia, serif;
  --mono: 'DM Mono', monospace;

  /* Neural glass tubing */
  --tube-highlight: rgba(240,196,110,0.06);
  --tube-shadow: rgba(0,0,0,0.5);
  --tube-inset: rgba(0,0,0,0.35);
  --tube-rim: rgba(240,196,110,0.03);
  --neural-glow: rgba(240,196,110,0.03);
  --glass-bg: rgba(28,28,46,0.65);
  --glass-border: rgba(240,196,110,0.14);
}

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

html, body {
  height: 100%;
  overflow: hidden;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 17px;
  font-weight: 400;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

/* Neural field background — dark void with warm synaptic glow */
/* GOLDEN HOUR interior field (Tom-APPROVED 2026-06-03): cool dusk-indigo with a saturated sunset
   bloom low-centre (warmth lives only in the bloom → no brown). Brain-canvas retired so it shows. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background:
    radial-gradient(130% 95% at 50% 80%, rgba(251,210,140,0.20) 0%, rgba(238,173,120,0.07) 32%, rgba(238,173,120,0) 60%),
    linear-gradient(180deg, #16182e 0%, #1b1d36 30%, #21223e 60%, #241f3a 84%, #2a2236 100%);
  background-attachment: fixed;
  pointer-events: none;
  z-index: 0;
}
/* Subtle neural dot pattern overlay */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  background-image: radial-gradient(rgba(240, 196, 110,0.04) 1px, transparent 1px);
  background-size: 32px 32px;
  pointer-events: none;
  z-index: 0;
}

/* ── Layout ── */
#app {
  display: flex;
  flex-direction: column;
  height: 100dvh;
  max-width: 720px;
  margin: 0 auto;
  position: relative;
  z-index: 1;
}

/* ── Header — neural rail with glow ── */
/* Top banner = the MIRROR of the 3D floating reply-zone (Tom 2026-06-04): a floating plane the chat
   slides UNDER. Long DOWNWARD shadow + gold rim on the leading (bottom) edge + rounded bottom corners.
   Part of the finished format — per-Fellow, swap the gold (240,196,110) for that Fellow's --accent. */
.header {
  flex-shrink: 0;
  padding: 18px 24px 14px;
  text-align: center;
  position: relative;
  z-index: 50;                        /* above .messages (z-index:1) so its shadow paints over the chat */
  background: rgba(26,24,44,0.97);    /* solid — same material as .reply-zone */
  border-radius: 0 0 14px 14px;       /* rounded BOTTOM corners (reply-zone is rounded top) */
  border-bottom: 1px solid rgba(240,196,110,0.22);   /* gold rim on the leading (bottom) edge */
  box-shadow:
    0 22px 44px -10px rgba(0,0,0,0.62),              /* long DOWNWARD shadow (reply-zone's casts up) */
    0 8px 18px -8px rgba(0,0,0,0.5),
    0 -2px 0 0 rgba(240,196,110,0.16) inset,         /* gold inner rim */
    0 -1px 0 0 rgba(255,255,255,0.05) inset;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.header::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 24px;
  right: 24px;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(240, 196, 110,0.25), transparent);
  box-shadow: 0 0 12px rgba(240, 196, 110,0.08);
}
.header-title {
  font-family: var(--serif);
  font-size: 1.6rem;
  font-weight: 600;
  font-style: italic;
  color: var(--accent);
  letter-spacing: 0.02em;
  text-shadow: 0 1px 3px rgba(0,0,0,0.3);
}
.header-sub {
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-dim);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-top: 3px;
}
/* Header kebab — ALWAYS-ON (desktop + mobile), 2026-06-23: one ⋮ replaces the loose PDF/past/lang/out
   cluster on EVERY width so the title + subtitle own the panel. Donor: MLF. */
.hdr-cluster{display:none !important}               /* the loose action row is consolidated into the ⋮ (!important beats the inline display:flex on the cluster) */
.hdr-kebab{display:flex;align-items:center;gap:6px;height:36px;padding:0 11px;position:absolute;right:14px;top:50%;transform:translateY(-50%);cursor:pointer;color:#d6def0;background:linear-gradient(180deg,#3a4356,#212a3b 90%);border:1px solid rgba(0,0,0,0.45);border-top-color:rgba(255,255,255,0.18);border-radius:11px;box-shadow:inset 0 1px 0 rgba(255,255,255,0.16),0 2px 5px rgba(0,0,0,0.55)}
.hdr-kebab .kb-txt{font-size:0.6rem;font-weight:700;letter-spacing:0.1em}
.hdr-kebab .kb-dot{font-size:1.3rem;line-height:1}
.hdr-menu{display:none;position:absolute;top:54px;right:12px;width:212px;z-index:60;background:linear-gradient(180deg,#2a3346,#161d2b);border:1px solid rgba(255,255,255,0.12);border-radius:14px;box-shadow:0 18px 40px rgba(0,0,0,0.6);padding:7px}
.hdr-menu.open{display:block}
.hdr-menu .hmi{display:flex;align-items:center;gap:10px;width:100%;text-align:left;cursor:pointer;color:#d6def0;font-weight:600;font-size:0.9rem;padding:11px 12px;border-radius:10px;border:none;background:transparent;font-family:inherit}
.hdr-menu .hmi:active{background:rgba(255,255,255,0.06)}
.hdr-menu .hmi .ic{font-size:1.05rem}

/* ── Gate ──
   U-5b fix 2026-05-18 (Tom: "REALLY faint AND not the brain-synapse directive"):
   Was rgba(8,6,16,0.78) — animation was technically visible but compounded
   visibility was 0.62 × 0.22 ≈ 14% effective, way too dim. Dropped to 0.50.
   Combined with synapse-canvas opacity bump 0.62→0.85 in index.html, effective
   visibility during gate state is now 0.85 × 0.50 ≈ 42%. Clearly visible
   atmosphere without compromising input legibility (form fields have their own
   surface backgrounds that maintain contrast against the animated layer).
   Prior fix U-5: rgba(8,6,16,0.78). Phase 0: opaque var(--bg-deep). */
.gate {
  position: fixed;
  inset: 0;
  background: rgba(8, 6, 16, 0.50);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  flex-direction: column;
  justify-content: flex-start;   /* TOP-ALIGN (Cowork/Tom 2026-06-04): centering pushed .gate-title above the top edge → clipped; top-align keeps the title fully visible, the rest scrolls */
  gap: 20px;
  overflow-y: auto;
  padding: 28px 16px 64px;       /* top: title clear of edge; bottom: reserves the fixed footer so "Forgot password?" clears it. Side: 16px (was 40px) so the framed image can fill + CENTER on narrow/mobile widths — 40px squeezed the frame off-center to the right (Cowork/Tom 2026-06-04 mobile fix). */
}
.gate::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at 50% 40%, rgba(240, 196, 110,0.06) 0%, transparent 65%);
  pointer-events: none;
}
.gate.hidden { display: none; }
/* tighten title→tagline gap (was full 20px flex-gap) 2026-06-17 */
.gate-sub { margin-top: -14px; }
.gate-title {
  font-family: var(--serif);
  font-size: 38px;   /* shrunk from 3rem (Cowork/Tom 2026-06-04): smaller title → bigger image, more brain to play with */
  font-weight: 600;
  font-style: italic;
  color: var(--accent);
  text-shadow: 0 2px 12px rgba(0,0,0,0.6), 0 0 40px rgba(240, 196, 110,0.2);
  position: relative;
  letter-spacing: 0.02em;
}
.gate-sub {
  font-size: 1.1rem;
  font-weight: 400;
  color: var(--text-primary);
  max-width: 360px;
  text-align: center;
  line-height: 1.55;
  position: relative;
  text-shadow: 0 2px 8px rgba(0,0,0,0.5);
  letter-spacing: 0.03em;
}
.gate-input {
  background: var(--surface);
  border: 1px solid var(--border-bright);
  border-radius: 24px;
  padding: 14px 22px;
  font-family: var(--sans);
  font-size: 1.05rem;
  font-weight: 400;
  color: var(--text-bright);
  outline: none;
  width: 300px;
  text-align: center;
  transition: border-color 0.2s, box-shadow 0.2s;
  box-shadow:
    inset 0 2px 4px var(--tube-inset),
    0 1px 0 var(--tube-rim);
  position: relative;
}
.gate-input:focus {
  border-color: var(--accent);
  box-shadow:
    inset 0 2px 4px var(--tube-inset),
    0 0 0 3px var(--accent-soft),
    0 1px 0 var(--tube-rim);
}
.gate-btn {
  background: linear-gradient(180deg, #d4b880, #b49860);
  color: var(--bg-deep);
  border: none;
  border-radius: 24px;
  padding: 13px 36px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 1rem;
  cursor: pointer;
  transition: opacity 0.2s, transform 0.1s;
  box-shadow:
    0 2px 6px rgba(0,0,0,0.3),
    inset 0 1px 0 rgba(255,255,255,0.15);
  position: relative;
}
.gate-btn:hover { opacity: 0.9; }
.gate-btn:active { transform: scale(0.98); }

/* ── Messages ── */
.messages {
  flex: 1;
  overflow-y: auto;
  padding: 24px 24px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  scroll-behavior: smooth;
  position: relative;
  z-index: 1;          /* below the floating reply-zone (z-index:50) so the chat recedes behind it */
}
.messages::-webkit-scrollbar { width: 4px; }
.messages::-webkit-scrollbar-thumb {
  background: rgba(240, 196, 110,0.15);
  border-radius: 2px;
}

.msg {
  max-width: 85%;
  padding: 16px 20px;
  border-radius: 20px;
  font-size: 1.05rem;
  font-weight: 400;
  line-height: 1.7;
  letter-spacing: 0.01em;
  animation: msgIn 0.35s ease;
  position: relative;
}
@keyframes msgIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

/* User messages — frosted glass, recessed */
.msg.user {
  align-self: flex-end;
  background: rgba(46,44,64,0.52);                 /* golden hour bubble (Tom 2026-06-03) — SAME box as Fellow (two-tone is a text flip) */
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(240,196,110,0.16);        /* faint gold */
  color: var(--user-text);                         /* gold body text = the flip */
  border-bottom-right-radius: 6px;
  box-shadow:
    0 4px 16px rgba(0,0,0,0.35),
    0 0 30px rgba(240,196,110,0.05),
    inset 0 1px 0 rgba(240,196,110,0.06);
}

/* Fellow messages — golden-hour glass with soft sunset glow */
.msg.fellow {
  align-self: flex-start;
  background: rgba(46,44,64,0.52);                 /* golden hour bubble (Tom 2026-06-03) */
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(240,196,110,0.16);        /* faint gold */
  color: var(--bubble-fellow-text);                /* purple body text */
  border-bottom-left-radius: 6px;
  box-shadow:
    0 4px 16px rgba(0,0,0,0.35),
    0 0 30px rgba(240,196,110,0.05),
    inset 0 1px 0 rgba(240,196,110,0.06);
}
.msg.fellow strong {
  color: var(--bubble-fellow-strong);
  font-weight: 600;
}
.msg.fellow .fellow-label {
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--bubble-fellow-label);               /* gold, glowing label */
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  text-shadow: 0 1px 3px rgba(0,0,0,0.25);
}
.msg.user .user-label {
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--user-label);                        /* purple label (the flip) */
  margin-bottom: 8px;
  text-shadow: 0 1px 3px rgba(0,0,0,0.25);
}

/* Thinking indicator */
.thinking {
  align-self: flex-start;
  padding: 14px 18px;
  color: var(--text-dim);
  font-style: italic;
  font-size: 0.95rem;
  font-weight: 400;
  background: rgba(240, 196, 110,0.03);
  border-radius: 20px;
  border: 1px solid rgba(240, 196, 110,0.06);
}
.thinking::after {
  content: '';
  animation: dots 1.5s steps(4,end) infinite;
}
@keyframes dots {
  0%  { content: ''; }
  25% { content: '.'; }
  50% { content: '..'; }
  75% { content: '...'; }
}

/* ── Reply zone — neural glass channel ── */
/* ⑤ 3D floating-slot toolbar (Tom-approved "subtle but EFFECTIVE"): the reply zone lifts to its
   own plane via a long upward drop shadow; the chat slides behind it. Accent = MThF gold. */
.reply-zone {
  flex-shrink: 0;
  padding: 14px 24px 62px;
  position: relative;
  z-index: 50;                                      /* ABOVE .messages so content recedes behind it */
  background: rgba(26,24,44,0.97);                  /* dark-surface tone */
  border-radius: 14px 14px 0 0;
  border-top: 1px solid rgba(240,196,110,0.22);     /* gold rim — catch-light lip */
  border-left: 1px solid rgba(240,196,110,0.08);
  border-right: 1px solid rgba(0,0,0,0.40);
  border-bottom: 0;
  box-shadow:
    0 -22px 44px -10px rgba(0,0,0,0.62),            /* THE long drop shadow — cast UP onto the chat */
    0 -8px 18px -8px rgba(0,0,0,0.50),
    inset 0 2px 0 rgba(240,196,110,0.16),           /* gold inner rim */
    inset 0 1px 0 rgba(255,255,255,0.05);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.reply-zone::before {
  content: '';
  position: absolute;
  top: 0;
  left: 24px;
  right: 24px;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(240, 196, 110,0.2), transparent);
  box-shadow: 0 0 8px rgba(240, 196, 110,0.06);
}
.reply-row {
  display: flex;
  align-items: flex-end;
  gap: 10px;
}
.reply-input {
  flex: 1;
  background: rgba(28,28,46,0.82);                 /* golden hour input zone (Tom 2026-06-03) */
  border: 1px solid rgba(240,196,110,0.18);        /* gold */
  border-radius: 24px;
  padding: 13px 20px;
  font-family: var(--sans);
  font-size: 1.05rem;
  font-weight: 400;
  color: var(--text-bright);
  outline: none;
  resize: none;
  min-height: 48px;
  max-height: 160px;
  line-height: 1.55;
  transition: border-color 0.2s, box-shadow 0.2s;
  box-shadow: inset 0 2px 4px var(--tube-inset);
}
.reply-input:focus {
  border-color: var(--accent);
  box-shadow:
    inset 0 2px 4px var(--tube-inset),
    0 0 0 3px var(--accent-soft);
}
.reply-input::placeholder { color: rgba(239,231,214,0.45); }

/* Buttons — 3D tube caps */
/* Mic is the STAR of the bar (2026-06-11): dominant on desktop too, not just mobile.
   #voice-btn (id) beats .voice-btn (class) so the speaker/vol button stays at 48px.
   The mobile media query (#voice-btn 76px !important) still wins on mobile. Pulse preserved. */
#voice-btn {
  width: 64px;
  height: 64px;
}
#voice-btn svg { width: 30px; height: 30px; }

.send-btn, .voice-btn {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid var(--border-bright);
  background: linear-gradient(145deg, var(--surface-lit), var(--surface));
  color: var(--accent);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
  flex-shrink: 0;
  box-shadow:
    0 2px 6px rgba(0,0,0,0.25),
    inset 0 1px 0 var(--tube-highlight);
}
.send-btn:hover, .voice-btn:hover {
  background: linear-gradient(145deg, var(--surface-hover), var(--surface-lit));
  border-color: var(--accent);
  box-shadow:
    0 3px 8px rgba(0,0,0,0.3),
    inset 0 1px 0 var(--tube-highlight),
    0 0 12px var(--accent-soft);
}
.send-btn:active, .voice-btn:active {
  transform: scale(0.95);
  box-shadow:
    0 1px 3px rgba(0,0,0,0.3),
    inset 0 2px 4px var(--tube-inset);
}
.voice-btn.active {
  background: linear-gradient(145deg, #d4b880, #b49860);
  color: var(--bg-deep);
  border-color: var(--accent);
  box-shadow:
    0 2px 8px rgba(240, 196, 110,0.3),
    inset 0 1px 0 rgba(255,255,255,0.15);
  animation: voicePulse 2s ease infinite;
}
@keyframes voicePulse {
  0%, 100% { box-shadow: 0 2px 8px rgba(240, 196, 110,0.3), inset 0 1px 0 rgba(255,255,255,0.15); }
  50% { box-shadow: 0 2px 16px rgba(240, 196, 110,0.45), 0 0 24px rgba(240, 196, 110,0.15), inset 0 1px 0 rgba(255,255,255,0.15); }
}
.send-btn svg, .voice-btn svg { width: 22px; height: 22px; }

/* ── Upload button ── */
.upload-btn {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: linear-gradient(145deg, var(--surface), var(--bg-deep));
  color: var(--text-dim);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
  flex-shrink: 0;
  box-shadow: 0 1px 4px rgba(0,0,0,0.2), inset 0 1px 0 var(--tube-highlight);
}
.upload-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 2px 6px rgba(0,0,0,0.25), 0 0 10px var(--accent-soft);
}
.upload-btn:active { transform: scale(0.95); }
.upload-btn svg { width: 18px; height: 18px; }

/* ── Voice status bar ── */
.voice-bar {
  display: none;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px;
  font-size: 0.75rem;
  color: var(--fellow-dim);
  font-style: italic;
}
.voice-bar.visible { display: flex; }
.voice-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 6px rgba(240, 196, 110,0.4);
  animation: voicePulse 1.5s ease infinite;
}
/* Recording state (mobile tap/tap): make "tap to send" unmistakable — big, bright, not a faded
   italic whisper. The whole point is the user must know to tap the mic again to send. 2026-06-09 */
.voice-bar.recording {
  font-size: 1.05rem;
  font-weight: 600;
  font-style: normal;
  color: var(--text-bright);
}
.voice-bar.recording .voice-dot {
  width: 12px; height: 12px;
  background: #e5484d;
  box-shadow: 0 0 10px rgba(229,72,77,0.75);
}
#voice-btn.recording {
  background: linear-gradient(145deg, #e5675b, #c83f3f);
  color: #fff;
  border-color: #e5484d;
  animation: recPulse 1.2s ease infinite;
}
/* While recording, the mic shows the instruction ON the button itself — the clearest possible cue
   that a second tap sends. Icon hides, "TAP AGAIN TO SEND" shows. 2026-06-09 */
.ptt-send-label { display: none; }
#voice-btn.recording svg { display: none; }
#voice-btn.recording .ptt-send-label {
  display: block;
  text-transform: uppercase;
  font-weight: 800;
  font-size: 0.5rem;
  line-height: 1.1;
  letter-spacing: 0.3px;
  text-align: center;
  color: #fff;
  padding: 0 3px;
}
@keyframes recPulse {
  0%, 100% { box-shadow: 0 2px 14px rgba(229,72,77,0.5), inset 0 1px 0 rgba(255,255,255,0.2); }
  50% { box-shadow: 0 2px 22px rgba(229,72,77,0.8), 0 0 28px rgba(229,72,77,0.3), inset 0 1px 0 rgba(255,255,255,0.2); }
}

/* ── Beta badge ── */
.beta-badge {
  position: fixed;
  top: 8px;
  right: 12px;
  font-size: 0.6rem;
  font-family: var(--mono);
  color: var(--text-dim);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.4;
  z-index: 2;
}

/* Footer standard (chips + tighten, ported from MluF 2026-06-05; gold accent).
   Legal links as discrete pill chips: faint gold rim + bg, text brighter than the 0.35
   tagline. Anchor inline styles stripped in index.html so these class rules apply.
   The !important flags fight the footer/tagline/nav INLINE padding/font/gap (substrate trap). */
.site-footer { line-height: 1.2; }
.legal-links a {
  padding: 2px 9px;
  border: 1px solid rgba(240,196,110,0.28);
  border-radius: 999px;
  background: rgba(240,196,110,0.07);
  color: rgba(255,255,255,0.68);
  text-decoration: none; white-space: nowrap;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.legal-links a:hover { border-color: rgba(240,196,110,0.5); background: rgba(240,196,110,0.10); color: rgba(255,255,255,0.82); }
.legal-links a.ecosystem-link { color: rgba(240,196,110,0.85); border-color: rgba(240,196,110,0.30); }

/* ── Responsive ── */
/* (header kebab is now always-on at base CSS — no mobile-only block needed) */

@media (max-width: 600px) {
  .messages { padding: 16px 16px; }
  .site-footer { padding: 3px 10px 4px !important; }
  .site-footer .footer-tagline { font-size: 0.48rem !important; line-height: 1.15; }
  .site-footer .legal-links { margin-top: 2px !important; gap: 0.1rem 0.5rem !important; font-size: 0.48rem !important; }
  .legal-links a { padding: 1.5px 7px; }
  .reply-zone { padding: 10px 16px 78px; }   /* clears the tightened chip-row footer (2026-06-05) */
  .msg { max-width: 92%; }
  .header { padding: 12px 16px 10px; }
  .header-title { font-size: 1.15rem; }       /* smaller on mobile so the centered title doesn't crowd the PDF/EN/out buttons (2026-06-04) */
  .header-sub { font-size: 0.65rem; }
  /* shrink the absolute-positioned action buttons on mobile so they don't crowd the title (inline styles → need !important) */
  /* scoped to .hdr-cluster (kebab sweep 2026-06-19) so it never shrinks the .hdr-menu dropdown items */
  .hdr-cluster button, .hdr-cluster select { font-size: 0.56rem !important; padding: 0.18rem 0.3rem !important; }

  /* Mobile speaker buttons - 44px min tap target */
  .speak-btn {
    padding: 10px 12px;
    min-width: 44px;
    min-height: 44px;
    -webkit-tap-highlight-color: transparent;
  }
  .speak-btn svg {
    width: 22px !important;
    height: 22px !important;
  }

  /* ── Driving-friendly mobile toolbar (2026-06-09) ──
     The mic both speaks AND sends (tap to speak, tap to send), so make it the big, obvious,
     hands-free target and recede everything else. Easy + safe to hit without looking. */
  #voice-btn {
    width: 76px !important;
    height: 76px !important;
  }
  #voice-btn svg { width: 36px !important; height: 36px !important; }
  .send-btn {
    width: 40px !important;
    height: 40px !important;
  }
  .send-btn svg { width: 18px !important; height: 18px !important; }
  .upload-btn {
    width: 34px !important;
    height: 34px !important;
  }
  .upload-btn svg { width: 15px !important; height: 15px !important; }
  #voiceVolBtn {
    width: 36px !important;
    height: 36px !important;
  }
  #voiceVolBtn svg { width: 16px !important; height: 16px !important; }
  .reply-row { gap: 8px; align-items: center; }
}

/* ── Per-message Speaker Button ── */
.speak-btn {
  background: none;
  border: none;
  color: var(--accent);
  cursor: pointer;
  padding: 3px 6px;
  margin-left: 8px;
  vertical-align: middle;
  transition: all 0.2s;
  display: inline-flex;
  align-items: center;
  opacity: 0.7;
}
.speak-btn svg {
  width: 18px !important;
  height: 18px !important;
}
.speak-btn:hover {
  opacity: 1;
  color: var(--text-bright);
  filter: drop-shadow(0 0 6px rgba(240, 196, 110,0.5));
  transform: scale(1.15);
}

/* ── Onboarding Progressive Reveal ── */
.ob-beat {
  opacity: 0;
  transform: translateY(8px);
  animation: ob-in 0.5s ease forwards;
}

@keyframes ob-in {
  to { opacity: 1; transform: translateY(0); }
}

.ob-title {
  font-family: 'Cormorant Garamond', serif;
  font-size: 2.6rem;
  font-weight: 600;
  color: #d4b878;
  margin-bottom: 1.2rem;
  line-height: 1.15;
  text-shadow: 0 2px 6px rgba(0,0,0,0.3);
}

.ob-line {
  font-family: 'DM Sans', sans-serif;
  font-size: 1.1rem;
  font-weight: 400;
  color: rgba(255,255,255,0.88);
  margin-bottom: 0.55rem;
  line-height: 1.6;
}

.ob-detail {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.92rem;
  font-weight: 400;
  color: rgba(255,255,255,0.45);
  margin-bottom: 0.55rem;
  line-height: 1.6;
  padding-left: 0.5rem;
}

.ob-section {
  font-family: 'DM Mono', monospace;
  font-size: 0.78rem;
  font-weight: 500;
  color: rgba(240, 196, 110,0.7);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-top: 0.5rem;
  margin-bottom: 0.6rem;
}

.ob-fellow {
  font-family: 'DM Sans', sans-serif;
  font-size: 1.05rem;
  font-weight: 400;
  font-style: italic;
  color: rgba(255,255,255,0.6);
  padding: 1.1rem 1.3rem;
  background: rgba(240, 196, 110,0.05);
  border-left: 3px solid rgba(240, 196, 110,0.3);
  border-radius: 0 4px 4px 0;
  margin-top: 0.5rem;
  line-height: 1.65;
  box-shadow: inset 2px 0 8px rgba(240, 196, 110,0.05);
}

.ob-cta {
  margin-top: 1.4rem;
}

.ob-cta-btn {
  display: block;
  width: 100%;
  padding: 1rem;
  background: linear-gradient(145deg, var(--surface-lit), var(--surface));
  color: #d4b878;
  border: 1px solid rgba(240, 196, 110,0.3);
  border-radius: 24px;
  font-family: 'DM Sans', sans-serif;
  font-size: 1.1rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s;
  box-shadow:
    0 2px 8px rgba(0,0,0,0.25),
    inset 0 1px 0 var(--tube-highlight);
}

.ob-cta-btn:hover {
  background: linear-gradient(145deg, var(--surface-hover), var(--surface-lit));
  border-color: rgba(240, 196, 110,0.45);
  box-shadow:
    0 3px 12px rgba(0,0,0,0.3),
    0 0 16px rgba(240, 196, 110,0.06),
    inset 0 1px 0 var(--tube-highlight);
}

/* ── Verification System ── */
.verify-bar {
  margin-top: 0.6rem;
  padding: 0.4rem 0.7rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  border-radius: 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.2rem;
  transition: opacity 1.5s ease;
}

.verify-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  margin-right: 0.35rem;
  margin-top: 0.3rem;
  flex-shrink: 0;
}

.verify-running {
  color: rgba(255,255,255,0.35);
  background: rgba(255,255,255,0.03);
}
.verify-running .verify-dot {
  background: rgba(255,255,255,0.3);
  box-shadow: 0 0 4px rgba(255,255,255,0.15);
  animation: verify-pulse 1.2s ease-in-out infinite;
}

.verify-pass {
  color: rgba(130,190,130,0.7);
  background: rgba(130,190,130,0.05);
}
.verify-pass .verify-dot {
  background: rgba(130,190,130,0.7);
  box-shadow: 0 0 4px rgba(130,190,130,0.3);
}

.verify-info {
  color: rgba(180,180,220,0.7);
  background: rgba(180,180,220,0.05);
}
.verify-info .verify-dot {
  background: rgba(180,180,220,0.7);
  box-shadow: 0 0 4px rgba(180,180,220,0.3);
}

.verify-caution {
  color: rgba(220,190,100,0.85);
  background: rgba(220,190,100,0.06);
}
.verify-caution .verify-dot {
  background: rgba(220,190,100,0.85);
  box-shadow: 0 0 4px rgba(220,190,100,0.3);
}

.verify-critical {
  color: rgba(220,120,120,0.9);
  background: rgba(220,120,120,0.08);
}
.verify-critical .verify-dot {
  background: rgba(220,120,120,0.9);
  box-shadow: 0 0 4px rgba(220,120,120,0.3);
}

.verify-flags {
  width: 100%;
  margin-top: 0.3rem;
}

.verify-flag {
  padding: 0.25rem 0;
  font-size: 0.72rem;
  line-height: 1.4;
}

.verify-flag-icon {
  display: inline-block;
  width: 1.1em;
  text-align: center;
  font-weight: 600;
  margin-right: 0.3rem;
}

.verify-flag-critical .verify-flag-icon { color: rgba(220,120,120,0.9); }
.verify-flag-caution .verify-flag-icon { color: rgba(220,190,100,0.85); }
.verify-flag-info .verify-flag-icon { color: rgba(180,180,220,0.7); }

@keyframes verify-pulse {
  0%, 100% { opacity: 0.3; }
  50% { opacity: 1; }
}

/* ════════════════════════════════════════════════════════════════════
   GATE IMAGE FRAME — Golden-Hour gate (Track A 2026-06-03). Canvas→image conversion;
   recipe ported from MluF/MDefF. gate-bg.png 1024×768 (4:3). FOUR slots: email/password/
   sign-in stacked over the sea (slots 1-3) + a 4th on the foreground book/altar = the quiet
   "?" explainer affordance (Tom's pick). Slot coords eyeballed — REFINE ±1-2% at draft.
   @import is line 1; #brain-canvas retired below. ════════════════════════════════════════ */
.gate-image-frame {
  position: relative;
  width: min(100vw - 32px, 1200px, calc((100vh - 196px) * 4 / 3)) !important;  /* TRAP: !important or :has() drops the vh-fit. Tuned (Cowork 2026-06-04): reserve 196px grows the image (more brain room) while the frame bottom still clears the fixed footer (~4px gap); don't drop below ~190px. `100vw - 32px` (was 95vw) caps the frame to the viewport minus the gate's 2×16px side padding so it fits AND centers on narrow/mobile widths (95vw overflowed the padded box → pinned left/off-center). */
  max-width: none !important;                                          /* TRAP 2: beats inherited max-width:380px */
  margin: 8px auto 0;
  aspect-ratio: 4 / 3;
  background-image: url('/gate-bg.jpg');   /* crisp 2400px JPEG — the soft 1280 .png washed out the brain linework (Cowork/Tom 2026-06-04) */
  background-size: 100% 100%;
  background-position: center;
  background-repeat: no-repeat;
  z-index: 2;
  /* 3D framed portal (gate redo 2026-06-04): depth + a thin gold frame catching light, so it floats. */
  border-radius: 10px;
  box-shadow:
    0 32px 80px -22px rgba(0,0,0,0.72),
    0 4px 18px -8px rgba(0,0,0,0.55),
    0 0 0 1px rgba(240,196,110,0.14);
}
/* ── GATE v2 (2026-06-04): ONE cohesive parchment FORM-CARD over the painted tablet. Abandons the
   per-slot matching (kept mismatching). The card fully covers the tablet → no painted parchment can
   peek; styled native to the source art (parchment fill, warm border, soft + inner shadow). Email/
   Password/Sign-in flow INSIDE it, all consistent. Position/size by % so it scales to mobile too.
   Coords are a visual estimate — refine the card's top/width/height ±1-2% with Tom. ── */
.gate-form-card {
  position: absolute;
  top: 42%; left: 50.8%; transform: translate(-50%, -50%);   /* Tuned (Cowork/Tom 2026-06-04 vs reference mock): top:42% parks it over the brain's center (≈22→62%); left:50.8% (NOT 50%) lands on the brain's fissure — the brain sits a hair right of frame-center. Don't drop below ~45% (re-covers the table) or widen past ~255px. */
  width: min(252px, 82%); max-width: 252px;                 /* COMPACT so the brain reads around it (v1 was too big, hid the brain) */
  box-sizing: border-box;
  display: flex; flex-direction: column; justify-content: center;
  gap: 8px;
  padding: 12px 13px;
  background: linear-gradient(160deg, #f3e9cf 0%, #ecdfbf 100%);
  border: 1px solid rgba(120,90,40,0.45);
  border-radius: 8px;
  box-shadow:
    0 8px 22px -8px rgba(0,0,0,0.45),
    inset 0 1px 0 rgba(255,255,255,0.55),
    inset 0 0 26px rgba(150,110,50,0.10);
  z-index: 3;
}
/* text fields — subtle cream fields on the parchment, dark text, light underline (NO navy boxes) */
.gate-form-card .gate-input,
.gate-form-card #gate-email,
.gate-form-card #gate-password {
  width: 100% !important; max-width: none !important; min-height: 0; margin: 0 0 6px !important;
  background: rgba(255,250,238,0.5) !important;
  border: none !important;
  border-bottom: 1.5px solid rgba(120,90,40,0.4) !important;
  border-radius: 5px 5px 0 0 !important;
  color: #3a2e20 !important; -webkit-text-fill-color: #3a2e20 !important; caret-color: #3a2e20 !important;
  padding: 8px 11px !important;     /* tuned (Cowork/Tom 2026-06-04) — keeps the card compact */
  font-size: 14px !important;
  text-align: left !important; line-height: normal !important;
  box-shadow: none !important; backdrop-filter: none !important;
}
.gate-form-card .gate-input::placeholder { color: rgba(90,72,46,0.7) !important; }
.gate-form-card .gate-input:-webkit-autofill,
.gate-form-card #gate-email:-webkit-autofill,
.gate-form-card #gate-password:-webkit-autofill { -webkit-text-fill-color: #3a2e20 !important; }
.gate-form-card .gate-password-wrap { position: relative; width: 100%; }
.gate-form-card .gate-password-wrap #gate-password { padding-right: 2.4rem !important; }
.gate-form-card .gate-password-wrap #pw-toggle {
  position: absolute; right: 0.5rem; top: 50%; transform: translateY(-50%);
  background: none; border: none; cursor: pointer; color: rgba(58,46,32,0.7); padding: 4px; line-height: 0;
}
.gate-form-card #gate-btn {
  width: 100% !important; margin-top: clamp(2px,0.6vw,6px) !important;
  background: linear-gradient(180deg, #d4b880, #b49860) !important;   /* warm gold button, dark text */
  color: #2a2118 !important; border: none !important; border-radius: 6px !important;
  padding: 8px 11px !important; min-height: 0;
  font-weight: 600; font-size: 14px !important; letter-spacing: 0.03em !important; cursor: pointer;
}
/* slot4 — the cream book/altar panel = the "?" explainer (gate redo 2026-06-04): a DARK, always-
   readable label centered INSIDE the cream book panel (gold vanished on the lit parchment). The whole
   panel is the click target → opens the explainer popover. */
/* "?" explainer — clean discreet parchment pill near the open book on the table (the clean art has
   no painted panel now). Readable dark text, unobtrusive; opens the existing popover. */
.gate-image-frame #gate-explainer-btn {
  position: absolute; top: 82.5%; left: 51.3%;   /* Tuned: nestled in the shadow band in front of the pedestal; left:51.3% over the table's visual center (a hair right of the card) */
  transform: translate(-50%, -50%); margin: 0;
  background: rgba(38,30,22,0.6); color: #f3e9cf;     /* dark pill, cream text — reads on the lit stone (Cowork/Tom 2026-06-04) */
  border: 1px solid rgba(243,233,207,0.35);
  border-radius: 999px; cursor: pointer;
  font-family: var(--serif); font-style: italic; font-weight: 600;
  font-size: 13.65px; white-space: nowrap;     /* +5% per Tom */
  padding: 5.25px 14.7px;
  display: inline-flex; align-items: center; justify-content: center;
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
  transition: background 0.2s, color 0.2s;
}
.gate-image-frame #gate-explainer-btn:hover,
.gate-image-frame #gate-explainer-btn:focus-visible { background: rgba(38,30,22,0.82); color: #fff; outline: none; }
/* explainer panel — quiet, dismissible, centered over the frame */
.gate-explainer-panel {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
  width: min(80%, 380px); z-index: 6;
  background: linear-gradient(180deg, #f6edd6 0%, #efe3c6 100%);   /* parchment */
  border: 1px solid rgba(169,121,27,0.45);
  border-radius: 12px; padding: 1.3rem 1.4rem 1.2rem; box-shadow: 0 14px 44px rgba(0,0,0,0.5);
  font-family: var(--serif); color: #3a2e20; text-align: center;
}
.gate-explainer-panel p { font-size: 1rem; line-height: 1.55; margin: 0; }
.gate-explainer-panel .gate-explainer-voiceline {
  margin-top: 0.7rem; font-style: italic; font-size: 0.9rem; color: #6a5638;
}
.gate-explainer-close {
  position: absolute; top: 4px; right: 10px; background: none; border: none;
  color: #8a6a1e; font-size: 1.3rem; line-height: 1; cursor: pointer; padding: 2px 6px;
}
/* (v2: per-slot input styling removed — the .gate-form-card rules above own all input styling now.) */
/* Retire the brain-canvas gate animation (painted image is the bg now). JS also early-returns;
   engine left in-file, reversible. */
#brain-canvas { display: none !important; }
/* Gate redo 2026-06-04: the OLD "<600px form returns to flow over a cover backdrop" fallback was
   REMOVED — it broke the mobile view. The framed image is a 4:3 box with %-positioned cream inputs,
   so the SAME framed portal scales proportionally to mobile (no separate layout). Tom: "the middle
   image translates well to mobile." */

/* ── Voice VOLUME control (pilot 2026-06-04): speaker button (reuses .voice-btn chrome) + slider
   popover, grouped with the mic/voice toggle in the reply row. ── */
.vol-control { position: relative; display: flex; align-items: center; flex-shrink: 0; }
.vol-btn.is-muted { color: var(--text-dim); opacity: 0.8; }
.vol-popover {
  position: absolute; bottom: calc(100% + 10px); left: 50%; transform: translateX(-50%);
  background: rgba(20,18,30,0.96); border: 1px solid var(--border-bright);
  border-radius: 12px; padding: 12px 14px; box-shadow: 0 10px 30px rgba(0,0,0,0.5);
  z-index: 10001; line-height: 0;
}
.vol-popover::after {   /* little pointer down to the speaker button */
  content: ''; position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  border: 6px solid transparent; border-top-color: rgba(20,18,30,0.96);
}
.vol-popover input[type=range] {
  width: 120px; height: 4px; accent-color: var(--accent); cursor: pointer; vertical-align: middle;
}


/* 2026-06-09 gate washed-text legibility fix (fleet; validated on MTherF) -- title/subtitle/footer read
   over busy gate art via a dark halo + brightening. */
.gate-title, .gate-title span { text-shadow: 0 2px 8px rgba(0,0,0,0.6), 0 0 3px rgba(0,0,0,0.5) !important; }
.gate-sub { color: rgba(245,238,225,0.96) !important; text-shadow: 0 1px 5px rgba(0,0,0,0.72), 0 0 2px rgba(0,0,0,0.5) !important; }
.site-footer .footer-tagline { color: rgba(245,238,225,0.92) !important; font-size: 0.62rem !important; text-shadow: 0 1px 3px rgba(0,0,0,0.72) !important; }
.legal-links a { color: rgba(246,239,226,0.9) !important; text-shadow: 0 1px 3px rgba(0,0,0,0.68) !important; }

/* ════════════════════════ CANONICAL CHAT-HEADER (Tom 06-23) — fleet-unify ════════════════════════
   Kebab freed the bar; unify the in-chat title/subtitle across the chat-style family. Stale later
   overrides had knocked the title to ~1.6rem ("reads tiny") and the subtitle to 0.72rem in
   --text-dim (near-invisible). One confident centered title + readable subtitle, kebab-safe
   symmetric padding, text-wrap:balance to kill orphans. Gate hero (.gate-title) untouched.
   Appended last = wins the cascade. Matches MMF (approved). */
.header { padding-left: clamp(52px, 8vw, 84px); padding-right: clamp(52px, 8vw, 84px); }
.header-title { font-size: clamp(1.95rem, 2.6vw, 2.35rem); margin-bottom: 6px; }
.header-sub { font-size: 0.84rem; color: var(--text-bright); opacity: 0.74; margin-left: auto; margin-right: auto; text-wrap: balance; }

/* [Claude 07-23] DESKTOP ROOM (fleet pass): the transcript and app shell were capped at a 720px
   phone column on every screen. On big screens the room opens to a readable measure. Mobile
   untouched. Appended at end of file so the cascade wins at equal specificity. Sweep report:
   DESKTOP_ROOM_SWEEP_2026-07-23.md */
@media (min-width: 1100px) {
  #app { max-width: 960px; }
  #messages, .fellow-messages { max-width: 860px; }
}

/* [New Sesh 10-05] GATE ONLY - MThF bleed restored. Tom's own 09-24 tuner numbers (position 50% -468px,
   size auto 150%, 0.50 scrim, fleet dissolve), recovered byte-for-byte from styles.css.bak-2026-09-30-mthf-ship.
   Stripped 09-30 only because it was UNSCOPED (bled into the room). Now scoped like the seven
   (body:has(#gate:not(.hidden))::before), blur 30px = the fleet standard since 09-29. Room untouched. */
body:has(#gate:not(.hidden))::before,
body:has(.gate:not(.hidden))::before,
body:has(.fellow-gate:not(.hidden))::before {
  background:
    radial-gradient(130% 95% at 50% 80%, rgba(251,210,140,0.20) 0%, rgba(238,173,120,0.07) 32%, rgba(238,173,120,0) 60%),
    linear-gradient(180deg, rgba(22,24,46,0.50) 0%, rgba(27,29,54,0.50) 30%, rgba(33,34,62,0.50) 60%, rgba(36,31,58,0.50) 84%, rgba(42,34,54,0.50) 100%),
    radial-gradient(ellipse 70% 85% at 50% 48%, rgba(0,0,0,0.04) 0%, rgba(0,0,0,0.16) 52%, rgba(0,0,0,0.34) 100%),
    url('/gate-bg.jpg') 50% -468px / auto 150% no-repeat;
  background-attachment: fixed;
  filter: blur(30px) saturate(0.94);
  transform: scale(1.06);
}
