/* Sophia — "golden hour on a sunny patio".
   Day: warm cream, terracotta, sage, a little soft blue, gold touches.
   Evening: warm brown. Contrast checked to WCAG AA in both (gold is decorative only). */

@font-face {
  font-family: "DM Serif Display";
  src: url("/static/fonts/dm-serif-display.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "DM Serif Display";
  src: url("/static/fonts/dm-serif-display-italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Manrope";
  src: url("/static/fonts/manrope.woff2") format("woff2");
  font-weight: 200 800;
  font-display: swap;
}

:root {
  color-scheme: light;
  --bg: #fbf4e8;
  --bg-glow: rgba(240, 196, 120, 0.32);   /* low sun, top right */
  --bg-glow-2: rgba(150, 178, 140, 0.16); /* sage shade, bottom left */
  --surface: #fffaf2;
  --surface-2: #f6ecdd;
  --ink: #3b2a20;
  --muted: #6b5546;
  --line: #e9dcc8;
  --accent: #a64b29;      /* terracotta */
  --accent-soft: #f4dfcc; /* your bubbles */
  --on-accent: #fffaf2;
  --sage: #8fa98a;
  --sage-ink: #4a6845;
  --sage-soft: #e6eedf;
  --blue: #3f6390;        /* soft blue: focus and links */
  --blue-soft: #e3ebf4;
  --gold: #c99a3c;        /* decorative only */
  --gold-glow: rgba(214, 166, 72, 0.45);
  --shadow: 0 1px 2px rgba(76, 48, 28, 0.06), 0 8px 24px rgba(76, 48, 28, 0.06);
  --serif: "DM Serif Display", "Iowan Old Style", "Palatino", Georgia, serif;
  --sans: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, monospace;
  --radius: 22px;
  --slow: 600ms;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --tap: 44px;
  --column: 46rem;
}

:root[data-theme="evening"] {
  color-scheme: dark;
  --bg: #2a1e17;
  --bg-glow: rgba(226, 150, 90, 0.16);
  --bg-glow-2: rgba(120, 150, 110, 0.10);
  --surface: #36281f;
  --surface-2: #2f231b;
  --ink: #f6eadb;
  --muted: #cdb6a0;
  --line: #4a382c;
  --accent: #e8946a;
  --accent-soft: #4a3326;
  --on-accent: #2a1e17;
  --sage: #9fbb96;
  --sage-ink: #b5cdaa;
  --sage-soft: #33372a;
  --blue: #a9c3e3;
  --blue-soft: #2c3440;
  --gold: #e2bf6a;
  --gold-glow: rgba(226, 191, 106, 0.38);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 10px 30px rgba(0, 0, 0, 0.25);
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; height: 100%; }
html { -webkit-text-size-adjust: 100%; }

body {
  min-height: 100%;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  background:
    radial-gradient(120% 60% at 100% 0%, var(--bg-glow), transparent 60%),
    radial-gradient(90% 50% at 0% 100%, var(--bg-glow-2), transparent 60%),
    var(--bg);
  background-attachment: fixed;
  color: var(--ink);
  font: 400 1.0625rem/1.6 var(--sans);
  transition: background-color var(--slow) var(--ease), color var(--slow) var(--ease);
}

:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; border-radius: 12px; }
a { color: var(--blue); text-underline-offset: 3px; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Buttons ------------------------------------------------------------------ */
button { font: inherit; color: inherit; cursor: pointer; }
.btn {
  min-height: var(--tap);
  min-width: var(--tap);
  padding: 0.6rem 1.25rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font-weight: 700;
  letter-spacing: 0.01em;
  transition: background-color 300ms var(--ease), border-color 300ms var(--ease), opacity 300ms var(--ease);
}
.btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary:hover { filter: brightness(1.05); }
.btn-quiet { background: transparent; border-color: var(--line); color: var(--ink); }
.btn-quiet:hover { background: var(--surface-2); }
.btn:disabled { opacity: 0.55; cursor: default; }
.icon-btn {
  display: inline-grid;
  place-items: center;
  width: var(--tap);
  height: var(--tap);
  border-radius: 999px;
  border: 0;
  background: transparent;
  color: var(--muted);
  transition: background-color 300ms var(--ease), color 300ms var(--ease);
}
.icon-btn:hover { background: var(--surface-2); color: var(--ink); }
.icon-btn svg { width: 22px; height: 22px; }

/* Avatar ----------------------------------------------------------------- */
.avatar {
  position: relative;
  flex: none;
  width: var(--size, 48px);
  height: var(--size, 48px);
  border-radius: 50%;
  overflow: hidden;
  background: var(--surface-2);
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--gold);
}
.avatar img, .avatar video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}
.avatar video { opacity: 0; transition: opacity 900ms var(--ease); }
.avatar video.playing { opacity: 1; }
/* Talking: the speaking loop eases in over the resting one while a reply arrives. */
.avatar video.talk, .avatar video.talk.playing { opacity: 0; transition: opacity 220ms var(--ease); }
.avatar.talking video.talk.playing { opacity: 1; }

/* Thinking: a calm, slow breathing glow around her picture. */
@keyframes breathe {
  0%, 100% { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--gold), 0 0 0 0 var(--gold-glow); }
  50% { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--gold), 0 0 22px 8px var(--gold-glow); }
}
body.busy .top .avatar, .thinking .avatar { animation: breathe 3.6s ease-in-out infinite; }

/* Header --------------------------------------------------------------------- */
.top {
  position: sticky;
  top: 0;
  z-index: 5;
  padding: calc(env(safe-area-inset-top) + 0.5rem) max(1rem, env(safe-area-inset-right)) 0.6rem max(1rem, env(safe-area-inset-left));
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  -webkit-backdrop-filter: saturate(1.2) blur(14px);
  backdrop-filter: saturate(1.2) blur(14px);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
}
.top-inner { display: flex; align-items: center; gap: 0.8rem; max-width: var(--column); margin: 0 auto; }
.top .avatar { --size: 52px; }
.who { display: flex; flex-direction: column; margin-right: auto; min-width: 0; }
.who h1 {
  margin: 0;
  font: 400 1.6rem/1.1 var(--serif);
  letter-spacing: 0.005em;
}
.status { font-size: 0.9rem; color: var(--muted); display: flex; align-items: center; gap: 0.4rem; }
.status::before {
  content: "";
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--sage);
  transition: background-color var(--slow) var(--ease);
}
body.offline .status::before { background: var(--muted); }
/* A soft pulse on the green dot while she's listening to you or speaking. */
@keyframes presence-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(143, 169, 138, 0.55); transform: scale(1); }
  50% { box-shadow: 0 0 0 5px rgba(143, 169, 138, 0); transform: scale(1.15); }
}
body[data-presence="listening"] .status::before,
body[data-presence="speaking"] .status::before { animation: presence-pulse 1.8s ease-in-out infinite; }

.menu { position: relative; }
.menu > summary { list-style: none; }
.menu > summary::-webkit-details-marker { display: none; }
.menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  min-width: 16.5rem;
  padding: 0.4rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow);
  animation: fade-in 300ms var(--ease);
  /* never taller than the screen: on a phone the rest scrolls */
  max-height: calc(100dvh - 5rem - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.menu-panel form { margin: 0; }
.menu-item {
  display: flex; align-items: center; gap: 0.6rem;
  width: 100%;
  min-height: var(--tap);
  padding: 0.5rem 0.8rem;
  border: 0; border-radius: 12px;
  background: transparent;
  text-align: left;
  font-weight: 600;
}
.menu-item:hover { background: var(--surface-2); }
.menu-version { margin: 0.3rem 0.8rem 0.2rem; font-size: 0.78rem; color: var(--muted); }
.menu-item svg { flex: none; width: 20px; height: 20px; color: var(--muted); }
.menu-item .label { white-space: nowrap; }

/* Layout: on phones, just the chat. On wide screens, her presence panel sits beside it. */
.stage { flex: 1; display: flex; min-height: 0; }
.chat { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }

/* Presence panel ----------------------------------------------------------------------- */
.presence { display: none; }
.presence .avatar {
  --size: 196px;
  box-shadow: 0 0 0 4px var(--surface), 0 0 0 6px var(--gold), 0 24px 60px var(--gold-glow);
}
body.busy .presence .avatar { animation: breathe-big 3.6s ease-in-out infinite; }
@keyframes breathe-big {
  0%, 100% { box-shadow: 0 0 0 4px var(--surface), 0 0 0 6px var(--gold), 0 24px 60px var(--gold-glow); }
  50% { box-shadow: 0 0 0 4px var(--surface), 0 0 0 6px var(--gold), 0 24px 60px var(--gold-glow), 0 0 46px 18px var(--gold-glow); }
}
.presence-name { font: 400 2.1rem/1.1 var(--serif); margin: 1.4rem 0 0.3rem; }
.presence-state {
  margin: 0;
  min-height: 3em;
  text-align: center;
  color: var(--muted);
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.1rem;
  transition: color var(--slow) var(--ease);
}
body.busy .presence-state { color: var(--ink); }
.presence-heading {
  align-self: stretch;
  margin: 2rem 0 0.6rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--line);
  font: 800 0.8rem/1 var(--sans);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.activity { align-self: stretch; list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.activity li {
  display: flex; justify-content: space-between; gap: 0.75rem;
  padding: 0.45rem 0;
  font-size: 0.98rem;
  animation: fade-in 700ms var(--ease) both;
}
.activity li::before {
  content: "";
  flex: none;
  width: 7px; height: 7px; margin-top: 0.55rem;
  border-radius: 50%;
  background: var(--sage);
}
.activity li.failed::before { background: var(--accent); }
.activity li span { flex: 1; }
.activity li time { color: var(--muted); font-size: 0.85rem; white-space: nowrap; }
.activity li.activity-empty { color: var(--muted); font-style: italic; }
.activity li.activity-empty::before { display: none; }

@media (min-width: 1100px) {
  .presence {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: none;
    width: 320px;
    padding: 3rem 1.75rem 2rem;
    border-right: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
    overflow-y: auto;
  }
  .top .avatar { display: none; }
  .top-inner { max-width: none; }
  .top .who {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap;
  }
  .top { padding-top: calc(env(safe-area-inset-top) + 0.35rem); padding-bottom: 0.35rem; }
  .top-inner { justify-content: flex-end; }
}

/* Conversation ------------------------------------------------------------------- */
#messages {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 1.5rem max(1rem, env(safe-area-inset-right)) 1rem max(1rem, env(safe-area-inset-left));
}
.thread { max-width: var(--column); margin: 0 auto; display: flex; flex-direction: column; gap: 1rem; }

@keyframes fade-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.msg { display: flex; flex-direction: column; max-width: min(88%, 38rem); animation: fade-in 700ms var(--ease) both; }
.msg time { font-size: 0.8rem; color: var(--muted); margin: 0.3rem 0.9rem 0; }
.msg .meta { display: flex; align-items: center; gap: 0.1rem; }
.msg .meta time { margin-right: 0.2rem; }
.msg.user .meta { justify-content: flex-end; }

/* Her voice: a quiet speaker beside the time; a stop square while she's talking. */
.speak { margin-top: 0.2rem; }
.speak svg { width: 22px; height: 22px; }
.speak .hush { display: none; width: 16px; height: 16px; }
.speak[data-state="playing"] { color: var(--accent); background: var(--accent-soft); }
.speak[data-state="playing"] .say { display: none; }
.speak[data-state="playing"] .hush { display: block; }
.speak[data-state="loading"] svg { animation: listen 1.6s ease-in-out infinite; }
.speak[data-state="failed"], .speak[data-state="blocked"] { color: var(--accent); }
@keyframes listen { 50% { opacity: 0.35; } }
.voice-note { font-size: 0.8rem; color: var(--muted); margin-top: 0.2rem; }
.voice-note:empty { display: none; }

.menu-item .switch {
  margin-left: auto; flex: none;
  width: 38px; height: 22px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--line, rgba(0,0,0,0.15));
  position: relative; transition: background-color 300ms var(--ease);
}
.menu-item .switch::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--muted); transition: transform 300ms var(--ease), background-color 300ms var(--ease);
}
.menu-item[aria-checked="true"] .switch { background: var(--accent); border-color: var(--accent); }
.menu-item[aria-checked="true"] .switch::after { transform: translateX(16px); background: var(--surface); }
.bubble {
  padding: 0.85rem 1.15rem;
  border-radius: var(--radius);
  font-size: 1.1875rem;
  line-height: 1.6;
  overflow-wrap: anywhere;
}
.bubble p { margin: 0 0 0.7em; }
.bubble p:last-child { margin-bottom: 0; }
.bubble ul, .bubble ol { margin: 0.2em 0 0.7em; padding-left: 1.3em; }
.bubble li { margin: 0.25em 0; }
.bubble strong { font-weight: 800; }
.bubble code { font: 0.85em var(--mono); background: var(--surface-2); padding: 0.1em 0.35em; border-radius: 6px; }

.msg.assistant { align-self: flex-start; }
.msg.assistant .bubble {
  background: var(--surface);
  border: 1px solid var(--line);
  border-bottom-left-radius: 8px;
  box-shadow: var(--shadow);
}
.msg.user { align-self: flex-end; align-items: flex-end; }
.msg.user .bubble { background: var(--accent-soft); border-bottom-right-radius: 8px; }

.msg.system {
  align-self: center;
  max-width: 34rem;
  text-align: center;
  font-size: 0.95rem;
  color: var(--muted);
  white-space: pre-wrap;
  padding: 0.4rem 1rem;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.msg.tool { align-self: flex-start; max-width: 100%; }
.msg.tool summary {
  display: inline-flex; align-items: center; gap: 0.45rem;
  min-height: var(--tap);
  padding: 0 0.9rem;
  border-radius: 999px;
  background: var(--sage-soft);
  color: var(--sage-ink);
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
  list-style: none;
}
.msg.tool summary::-webkit-details-marker { display: none; }
.msg.tool summary::after { content: "Details"; font-weight: 600; opacity: 0.8; margin-left: 0.25rem; }
.msg.tool details[open] summary::after { content: "Hide"; }
.msg.tool.failed summary { background: var(--accent-soft); color: var(--accent); }

pre {
  font: 0.85rem/1.5 var(--mono);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 0.8rem 0.95rem;
  margin: 0.5rem 0 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 50vh;
  overflow: auto;
}

/* New replies: words settle in one after another, slowly. */
@keyframes word-in { from { opacity: 0; } to { opacity: 1; } }
.bubble.staged .w { opacity: 0; }
.bubble.reveal .w { animation: word-in 380ms var(--ease) both; }

/* Thinking row */
.thinking { display: flex; align-items: center; gap: 0.75rem; color: var(--muted); font-size: 1rem; animation: fade-in 700ms var(--ease) both; }
.thinking .avatar { --size: 34px; }
.thinking span { font-family: var(--serif); font-style: italic; }

/* Empty state */
.welcome { text-align: center; margin: 12vh auto 0; max-width: 26rem; animation: fade-in 900ms var(--ease) both; }
.welcome .avatar { --size: 128px; margin: 0 auto 1.25rem; box-shadow: 0 0 0 3px var(--surface), 0 0 0 5px var(--gold), 0 18px 50px var(--gold-glow); }
.welcome h2 { font: 400 2rem/1.2 var(--serif); margin: 0 0 0.5rem; }
.welcome p { color: var(--muted); margin: 0; font-size: 1.05rem; }

/* Approvals -------------------------------------------------------------------- */
#approvals {
  max-width: var(--column);
  margin: 0 auto;
  display: flex; flex-direction: column; gap: 1rem;
}
#approvals:not(:empty) { margin-top: 1.25rem; }
#ready { max-width: var(--column); margin: 0 auto; display: flex; flex-direction: column; gap: 1rem; }
#ready:not(:empty) { margin-top: 1.25rem; }
.ready-card { border-color: var(--line, var(--sage-soft)); box-shadow: var(--shadow); }  /* quieter than a card that needs an OK */
.ready-content { white-space: pre-wrap; }
.approval .approval-detail { max-height: 50vh; }
.approval {
  background: var(--surface);
  border: 1.5px solid var(--gold);
  border-radius: 24px;
  padding: 1rem 1.1rem 0.9rem;
  box-shadow: var(--shadow), 0 0 0 4px color-mix(in srgb, var(--gold) 14%, transparent);
  animation: fade-in 700ms var(--ease) both;
}
.approval-head { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.approval-title { font: 400 1.15rem/1.3 var(--serif); margin: 0; }
.approval-kind {
  font-size: 0.8rem; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 0.2rem 0.6rem; border-radius: 999px;
  background: var(--sage-soft); color: var(--sage-ink);
}
.approval-kind.careful { background: var(--accent-soft); color: var(--accent); }
.approval-summary { margin: 0.6rem 0 0.4rem; font-size: 1.0625rem; line-height: 1.55; overflow-wrap: anywhere; }
.approval details { margin-top: 0.2rem; }
.approval details summary {
  display: inline-flex; align-items: center;
  min-height: var(--tap);
  color: var(--blue);
  font-weight: 700;
  cursor: pointer;
}
.approval-actions {
  display: flex; justify-content: flex-end; gap: 0.6rem;
  margin-top: 0.6rem;
}

/* Composer ------------------------------------------------------------------------ */
.composer-wrap {
  padding: 0.6rem max(1rem, env(safe-area-inset-right)) calc(0.75rem + env(safe-area-inset-bottom)) max(1rem, env(safe-area-inset-left));
  background: linear-gradient(to top, var(--bg) 70%, transparent);
}
#composer {
  max-width: var(--column);
  margin: 0 auto;
  display: grid;
  grid-template-columns: auto 1fr; /* attach · message, then camera · microphone · send as they apply */
  grid-auto-flow: column;
  grid-auto-columns: auto;
  align-items: end;
  gap: 0.5rem;
  padding: 0.4rem 0.4rem 0.4rem 0.3rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 28px;
  box-shadow: var(--shadow);
  transition: border-color 300ms var(--ease), box-shadow 300ms var(--ease);
}
@media (max-width: 400px) { #composer { gap: 0.15rem; } } /* more room for the message on a phone */
#composer:focus-within { border-color: var(--blue); box-shadow: var(--shadow), 0 0 0 3px var(--blue-soft); }

/* Talking with her: the microphone, and a calm status line above the composer. */
#mic svg { width: 24px; height: 24px; }
#mic .mic-end { display: none; width: 18px; height: 18px; }
#mic[aria-pressed="true"] { background: var(--accent); color: var(--surface); }
#mic[aria-pressed="true"] .mic-on { display: none; }
#mic[aria-pressed="true"] .mic-end { display: block; }
/* Her live face during a spoken conversation (Simli): it plays inside her avatar picture. */
.avatar video.live-face { opacity: 0; z-index: 2; transition: opacity 300ms var(--ease); }
.avatar.live video.live-face { opacity: 1; display: block; }
/* Her live face during a spoken conversation (Simli) */
.face {
  width: min(62vw, 260px); aspect-ratio: 1; margin: 0 auto 10px; border-radius: 28px; overflow: hidden;
  background: var(--surface-2, #2a2420); box-shadow: 0 10px 30px rgba(0, 0, 0, .25);
}
.face[hidden] { display: none; }
.face video { width: 100%; height: 100%; object-fit: cover; display: block; }

.talk-bar {
  max-width: var(--column);
  margin: 0 auto 0.5rem;
  display: flex; align-items: center; gap: 0.6rem;
  min-height: 2.5rem;
  padding: 0.45rem 1rem;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.95rem;
  --level: 0;
}
.talk-bar[data-state="problem"] { color: var(--accent); border-color: var(--accent); }
.talk-level { display: inline-flex; align-items: center; gap: 3px; height: 18px; }
.talk-level i {
  display: block; width: 3px; height: 18px; border-radius: 2px;
  background: var(--sage-ink);
  transform: scaleY(calc(0.2 + var(--level) * 0.8));
  transition: transform 120ms linear;
}
.talk-level i:nth-child(2), .talk-level i:nth-child(4) { transform: scaleY(calc(0.2 + var(--level) * 0.55)); }
.talk-level i:nth-child(1), .talk-level i:nth-child(5) { transform: scaleY(calc(0.2 + var(--level) * 0.3)); }
.talk-bar[data-state="waiting"] .talk-level i,
.talk-bar[data-state="sending"] .talk-level i { background: var(--gold, var(--muted)); animation: listen 1.6s ease-in-out infinite; }
.talk-bar[data-state="speaking"] .talk-level i { background: var(--accent); }
.talk-bar[data-state="problem"] .talk-level { display: none; }
#input {
  width: 100%;
  resize: none;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--ink);
  font: 400 1.125rem/1.5 var(--sans); /* 18px: also stops iOS zooming in on focus */
  padding: 0.55rem 0;
  min-height: var(--tap);
  max-height: 180px;
  overflow-y: hidden; /* no scroll bar until a long message actually needs one */
}
#input.overflowing { overflow-y: auto; }
#input::placeholder { color: var(--muted); opacity: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#send { width: 48px; height: 48px; padding: 0; display: grid; place-items: center; }
#send svg { width: 22px; height: 22px; }

/* Login ---------------------------------------------------------------------------- */
body.login { align-items: center; justify-content: center; padding: 2rem 1.25rem calc(2rem + env(safe-area-inset-bottom)); }
.login-card { width: min(24rem, 100%); text-align: center; animation: fade-in 900ms var(--ease) both; }
.login-card .avatar { --size: 132px; margin: 0 auto 1.4rem; box-shadow: 0 0 0 3px var(--surface), 0 0 0 5px var(--gold), 0 18px 50px var(--gold-glow); }
.login-card h1 { font: 400 2.6rem/1.1 var(--serif); margin: 0; }
.login-card .tagline { color: var(--muted); margin: 0.4rem 0 2rem; font-family: var(--serif); font-style: italic; font-size: 1.1rem; }
.login-card form { display: flex; flex-direction: column; gap: 0.7rem; text-align: left; }
.login-card label { font-weight: 700; color: var(--muted); font-size: 0.95rem; padding-left: 0.4rem; }
.login-card input {
  min-height: 52px;
  font: 400 1.125rem var(--sans);
  padding: 0.7rem 1.1rem;
  border-radius: 18px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
}
.login-card input:focus-visible { border-color: var(--blue); outline: 3px solid var(--blue-soft); outline-offset: 0; }
.login-card .btn { min-height: 52px; margin-top: 0.4rem; font-size: 1.05rem; }
.login-card .hint { margin: 0; padding-left: 0.4rem; color: var(--muted); font-size: 0.9rem; }
.login-card #passkey { width: 100%; margin-top: 1rem; }
.security-qr { width: 220px; height: 220px; justify-self: center; border-radius: 12px; background: #fff; }
.security-secret { font-family: ui-monospace, monospace; letter-spacing: 0.05em; word-break: break-all; user-select: all; }
.security-codes { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.3rem 1rem; margin: 0; padding: 0; list-style: none;
  font-family: ui-monospace, monospace; font-size: 1.05rem; user-select: all; }
.security-key { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; border-top: 1px solid var(--line); padding-top: 0.6rem; }
.security-key small { display: block; color: var(--muted); }
.error { color: var(--accent); font-weight: 700; margin: 0; padding-left: 0.4rem; }

/* Theme toggle icon shows the current mode. */
.theme-icon { display: none; }
:root[data-theme-mode="auto"] .theme-icon.auto,
:root[data-theme-mode="day"] .theme-icon.day,
:root[data-theme-mode="evening"] .theme-icon.evening { display: block; }

/* Wider screens ------------------------------------------------------------------------ */
@media (min-width: 900px) {
  .top .avatar { --size: 60px; }
  .who h1 { font-size: 1.85rem; }
  #messages { padding-top: 2.5rem; }
  .thread { gap: 1.2rem; }
}

/* Calm everything down for people who ask for less motion. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  body.busy .top .avatar, .thinking .avatar {
    box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--gold), 0 0 16px 5px var(--gold-glow);
  }
  .avatar video { display: none; }
}


/* Files: photos and download cards in the conversation, and files waiting to be sent. */
.files { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.4rem; max-width: 100%; }
.msg.user .files { align-items: flex-end; }
.file-photo { display: block; border-radius: var(--radius); overflow: hidden; border: 1px solid var(--line); max-width: min(100%, 18rem); min-width: 7rem; min-height: 7rem; background: var(--surface-2); }
.file-photo img { display: block; width: 100%; height: auto; max-height: 22rem; object-fit: cover; }
.file-card {
  display: flex; align-items: center; gap: 0.75rem;
  min-height: var(--tap); max-width: 100%;
  padding: 0.7rem 0.9rem;
  border-radius: 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--ink, inherit);
  text-decoration: none;
  box-shadow: var(--shadow);
}
.file-card:hover { border-color: var(--gold); }
.file-card > svg { flex: none; width: 30px; height: 30px; color: var(--accent); }
.file-card > span:first-of-type { display: flex; flex-direction: column; min-width: 0; }
.file-card strong { font-weight: 700; overflow-wrap: anywhere; }
.file-card small { color: var(--muted); font-size: 0.85rem; }
.file-get { margin-left: auto; flex: none; font-weight: 700; color: var(--accent); padding-left: 0.5rem; }
.attached {
  list-style: none; max-width: var(--column);
  margin: 0 auto 0.5rem; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.4rem;
}
.attached li {
  display: flex; align-items: center; gap: 0.2rem;
  max-width: 100%;
  padding-left: 0.9rem;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--line);
  font-size: 0.92rem;
}
.attached li span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#attach svg { width: 24px; height: 24px; }


/* Letting her see: a small live preview, so it's always obvious the camera is on. */
#look svg { width: 24px; height: 24px; }
#look[aria-pressed="true"] { background: var(--sage-soft); color: var(--sage-ink); }
.viewfinder {
  position: relative;
  width: 9.5rem; aspect-ratio: 3 / 4;
  margin: 0 0 0.5rem auto;
  border-radius: 20px; overflow: hidden;
  border: 2px solid var(--sage);
  background: #000;
  box-shadow: var(--shadow);
}
.composer-wrap > .viewfinder { max-width: var(--column); }
.viewfinder video { width: 100%; height: 100%; object-fit: cover; display: block; }
.viewfinder.selfie video { transform: scaleX(-1); }
.viewfinder .seeing {
  position: absolute; left: 0.45rem; bottom: 0.45rem;
  padding: 0.2rem 0.55rem; border-radius: 999px;
  background: rgba(30, 22, 16, 0.72); color: #f6eadb;
  font-size: 0.75rem; font-weight: 700;
}
.viewfinder .icon-btn {
  position: absolute; top: 0.25rem;
  background: rgba(30, 22, 16, 0.55); color: #f6eadb;
}
.viewfinder .icon-btn svg { width: 20px; height: 20px; }
#flip { left: 0.25rem; }
#look-off { right: 0.25rem; }
/* Guiding: she's watching and will speak up on her own. */
.viewfinder { transition: width var(--slow) var(--ease), border-color var(--slow) var(--ease); }
.viewfinder.guiding { width: 13rem; border-color: var(--accent); }
.viewfinder.guiding .seeing { background: var(--accent); color: var(--on-accent); max-width: calc(100% - 5.2rem); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.guide-stop {
  position: absolute; right: 0.45rem; bottom: 0.35rem; min-height: 32px; padding: 0 0.7rem;
  border: 0; border-radius: 999px; background: rgba(30, 22, 16, 0.72); color: #f6eadb; font-weight: 700; font-size: 0.8rem;
}
.files .earlier { display: flex; gap: 0.35rem; flex-wrap: wrap; justify-content: flex-end; }
.file-photo.small { min-width: var(--tap); min-height: var(--tap); width: 3.4rem; border-radius: 12px; }
.file-photo.small img { height: 3.4rem; max-height: none; }
/* Once she starts talking, the "Thinking…" note in the chat steps aside. */
body[data-presence="speaking"] #thinking { display: none; }

/* Sophia's apps ------------------------------------------------------------------------ */
body.app-host { display: flex; flex-direction: column; min-height: 100dvh; height: 100dvh; }
.app-bar {
  display: flex; align-items: center; gap: 0.5rem;
  padding: calc(0.5rem + env(safe-area-inset-top)) max(1rem, env(safe-area-inset-right)) 0.5rem max(0.6rem, env(safe-area-inset-left));
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.app-back { display: grid; place-items: center; width: var(--tap); height: var(--tap); border-radius: 12px; color: var(--ink); }
.app-back svg { width: 24px; height: 24px; }
.app-title { flex: 1; margin: 0; font: 400 1.4rem/1.2 var(--serif); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-note { font-size: 0.8rem; font-weight: 700; color: var(--accent); border: 1px solid var(--accent); border-radius: 999px; padding: 0.15rem 0.6rem; }
.app-frame { flex: 1; width: 100%; border: 0; background: #fff; }
.app-list { width: 100%; max-width: var(--column); margin: 0 auto; padding: 1rem max(1rem, env(safe-area-inset-right)) calc(1rem + env(safe-area-inset-bottom)) max(1rem, env(safe-area-inset-left)); display: grid; gap: 0.75rem; }
.app-card { display: block; padding: 1rem 1.1rem; border-radius: 18px; background: var(--surface); border: 1px solid var(--line); color: var(--ink); text-decoration: none; }
.app-card h2 { margin: 0 0 0.25rem; font: 400 1.25rem/1.25 var(--serif); }
.app-card p { margin: 0; color: var(--muted); }
.app-card .app-note { display: inline-block; margin-top: 0.5rem; }
.app-empty { color: var(--muted); text-align: center; margin-top: 2rem; }
.approval-try { display: inline-block; margin: 0.2rem 0 0.4rem; font-weight: 700; color: var(--blue); }
.approval-look { display: block; width: min(220px, 60%); aspect-ratio: 1; object-fit: cover; margin: 0.5rem 0; border-radius: 18px; box-shadow: var(--shadow); }
a.menu-item { color: inherit; text-decoration: none; }
.approve.armed { box-shadow: 0 0 0 3px var(--accent-soft), 0 0 0 5px var(--accent); }
.approval-problem { color: var(--accent); font-weight: 600; margin: 0.4rem 0; }

/* Spending ------------------------------------------------------------------------------ */
.spend-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 0.75rem; }
.spend-tile { padding: 0.9rem 1rem; border-radius: 18px; background: var(--surface); border: 1px solid var(--line); }
.spend-tile .label { color: var(--muted); font-size: 0.9rem; font-weight: 600; }
.spend-tile .value { font: 400 1.9rem/1.2 var(--serif); margin-top: 0.2rem; }
.spend-tile .sub { color: var(--muted); font-size: 0.85rem; }
.spend h2 { font: 400 1.25rem/1.3 var(--serif); margin: 1rem 0 0.2rem; }
.spend-bars { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.35rem; }
.spend-bars li { display: grid; grid-template-columns: 5.5rem 1fr 4.5rem; align-items: center; gap: 0.6rem; font-size: 0.92rem; }
.spend-bars .bar { height: 12px; border-radius: 6px; background: var(--accent); min-width: 2px; }
.spend-bars .amount { text-align: right; font-variant-numeric: tabular-nums; }
.spend-note { color: var(--muted); font-size: 0.85rem; }
.spend-kinds li { grid-template-columns: 1fr 0 4.5rem; gap: 0.6rem 0; }
.spend-tokens { display: block; color: var(--muted); font-size: 0.8rem; font-variant-numeric: tabular-nums; }
.app-card h3 { margin: 0 0 0.25rem; font: 400 1.1rem/1.3 var(--serif); }
.app-card summary { cursor: pointer; }
.mind-body { white-space: pre-wrap; margin-top: 0.5rem; }

/* Questions and the voice lesson: in-page sheets (the iPhone app can't always show the
   browser's own pop-ups). */
.sheet {
  width: min(92vw, 420px);
  padding: 1.3rem 1.3rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.25);
}
.sheet::backdrop { background: rgba(20, 12, 8, 0.45); }
.sheet h2 { margin: 0 0 0.5rem; font-size: 1.2rem; }
.sheet p { margin: 0 0 0.9rem; line-height: 1.45; }
.sheet-note { color: var(--muted); font-size: 0.92rem; }
.sheet-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: flex-end; }
.teach-line {
  padding: 0.9rem 1rem;
  border-radius: 14px;
  background: var(--surface-2);
  font-size: 1.1rem;
  font-weight: 600;
}
.teach-line:empty { display: none; }
#teach-record.recording { background: var(--sage-ink); }

.speakers-list { list-style: none; margin: 0 0 1rem; padding: 0; }
.speakers-list li {
  display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
  padding: 0.55rem 0; border-bottom: 1px solid var(--line);
}
.speakers-list li:last-child { border-bottom: 0; }
.speakers-list .seen { display: block; color: var(--muted); font-size: 0.85rem; }
.speakers-command {
  padding: 0.7rem 0.8rem; border-radius: 12px; background: var(--surface-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.85rem;
  overflow-wrap: anywhere; user-select: all;
}
.speakers-number { font-size: 2rem; font-weight: 700; letter-spacing: 0.2em; text-align: center; margin: 0.4rem 0; }

.sheet section { margin-bottom: 1rem; }
.sheet-sub { margin: 0.4rem 0 0.4rem; font-size: 1rem; }
.sheet-form { display: grid; gap: 0.5rem; margin-bottom: 0.6rem; }
.sheet-form input {
  min-height: var(--tap); padding: 0.5rem 0.8rem; border: 1px solid var(--line); border-radius: 12px;
  background: var(--surface-2); color: var(--ink); font: inherit;
}
.house-photo { display: block; max-width: 100%; border-radius: 10px; margin-top: 0.3rem; }
.sheet-check { display: flex; align-items: center; gap: 0.5rem; min-height: var(--tap); }
.sheet-check input { width: 1.2rem; height: 1.2rem; }

/* Status page */
.status-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
.status-list li {
  display: grid; grid-template-columns: 0.8rem 1fr auto; gap: 0.2rem 0.6rem; align-items: center;
  padding: 0.6rem 0.8rem; border-radius: 14px; background: var(--surface); border: 1px solid var(--line);
}
.status-dot { width: 0.7rem; height: 0.7rem; border-radius: 50%; background: var(--muted); }
.status-ok .status-dot { background: var(--sage); }
.status-attention .status-dot { background: var(--accent); }
.status-attention { border-color: var(--accent); }
.status-name { font-weight: 600; }
.status-state { color: var(--muted); font-size: 0.85rem; }
.status-detail { grid-column: 2 / 4; color: var(--muted); font-size: 0.9rem; }
.status-fix { display: block; color: var(--ink); margin-top: 0.15rem; }

/* Reactions: a small row of emoji under a message, and the picker that adds one. */
.msg > .bubble { -webkit-touch-callout: none; }
.reactions { display: flex; gap: 0.25rem; margin-top: -0.55rem; padding: 0 0.6rem; position: relative; z-index: 1; }
.msg.user .reactions { justify-content: flex-end; }
.reaction {
  font: inherit; font-size: 0.95rem; line-height: 1; padding: 0.25rem 0.45rem; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--line); color: inherit;
}
button.reaction { cursor: pointer; }
.reaction.mine { border-color: var(--accent); }
.react-btn svg { width: 20px; height: 20px; }
.react-picker {
  display: flex; gap: 0.15rem; padding: 0.3rem; margin-bottom: 0.35rem; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--line); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
  align-self: flex-start;
}
.msg.user .react-picker { align-self: flex-end; }
.react-picker button {
  font-size: 1.35rem; line-height: 1; padding: 0.35rem; border: 0; border-radius: 999px; background: none;
  cursor: pointer; min-width: 44px; min-height: 44px;
}
.react-picker button.chosen { background: var(--accent-soft); }
.react-picker button:focus-visible { outline: 2px solid var(--accent); }

/* Screen effects: drawn over everything, never in the way of a tap. */
.screen-effect {
  position: fixed; inset: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 1000;
  opacity: 1; transition: opacity 420ms var(--ease);
}
.screen-effect.leaving { opacity: 0; }
#send { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.effect-picker {
  display: flex; flex-direction: column; width: 15rem; margin: 0 0 0.6rem auto; padding: 0.3rem 0;
  border-radius: 16px; border: 1px solid var(--line); overflow: hidden;
  box-shadow: 0 12px 32px rgba(40, 24, 14, 0.22), 0 2px 6px rgba(40, 24, 14, 0.08);
}
.effect-picker button {
  display: flex; align-items: center; gap: 0.75rem; width: 100%; min-height: 46px; padding: 0 1.1rem;
  font: inherit; font-size: 1.02rem; text-align: left; color: inherit; background: none; border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent); cursor: pointer;
}
.effect-picker button span { font-size: 1.25rem; width: 1.6rem; text-align: center; }
.effect-picker button:hover, .effect-picker button:focus-visible { background: color-mix(in srgb, var(--accent-soft) 70%, transparent); outline: none; }
.effect-picker .effect-cancel { border-bottom: 0; justify-content: center; color: var(--muted); font-weight: 600; }
.effect-picker .effect-title { padding: 0.45rem 1.1rem 0.35rem; font-size: 0.78rem; color: var(--muted); letter-spacing: 0.02em; }

/* Smooth, springy motion for the pickers and reactions (iOS-like timing). */
:root { --spring: cubic-bezier(0.34, 1.36, 0.64, 1); }
@keyframes pop-in { from { opacity: 0; transform: translateY(6px) scale(0.86); } to { opacity: 1; transform: none; } }
@keyframes chip-in { 0% { opacity: 0; transform: scale(0.4); } 70% { opacity: 1; transform: scale(1.12); } 100% { transform: scale(1); } }
.react-picker, .effect-picker {
  animation: pop-in 260ms var(--spring) both; transform-origin: bottom left;
  -webkit-backdrop-filter: saturate(1.4) blur(18px); backdrop-filter: saturate(1.4) blur(18px);
  background: color-mix(in srgb, var(--surface) 86%, transparent);
}
.msg.user .react-picker, .effect-picker { transform-origin: bottom right; }
.react-picker button { transition: transform 180ms var(--spring), background-color 180ms var(--ease); }
.react-picker button:hover, .react-picker button:focus-visible { transform: scale(1.22) translateY(-2px); }
.react-picker button:active { transform: scale(0.92); }
.effect-picker button { transition: transform 160ms var(--spring), background-color 160ms var(--ease); }
.effect-picker button:active { background: color-mix(in srgb, var(--accent-soft) 90%, transparent); }
.effect-picker button:nth-child(1) { animation: pop-in 280ms 20ms var(--spring) both; }
.effect-picker button:nth-child(2) { animation: pop-in 280ms 45ms var(--spring) both; }
.effect-picker button:nth-child(3) { animation: pop-in 280ms 70ms var(--spring) both; }
.effect-picker button:nth-child(4) { animation: pop-in 280ms 95ms var(--spring) both; }
.effect-picker button:nth-child(5) { animation: pop-in 280ms 120ms var(--spring) both; }
.reaction { animation: chip-in 320ms var(--spring) both; box-shadow: 0 2px 6px rgba(76, 48, 28, 0.12); }
.msg > .bubble { transition: transform 220ms var(--spring); }
.msg.pressing > .bubble { transform: scale(0.97); }
#send { transition: transform 220ms var(--spring); }
#send.pressing { transform: scale(0.9); }
@media (prefers-reduced-motion: reduce) {
  .react-picker, .effect-picker, .effect-picker button, .reaction { animation: none; }
  .msg.pressing > .bubble, #send.pressing { transform: none; }
}

/* On her own: the research budget inputs sit side by side. */
.own-money { grid-template-columns: 1fr 1fr auto; align-items: end; }
.own-money label { display: grid; gap: 0.25rem; font-size: 0.85rem; color: var(--muted); }
@media (max-width: 420px) { .own-money { grid-template-columns: 1fr 1fr; } .own-money button { grid-column: span 2; } }

/* The babysitter's page (/sitter/<link>) */
body.sitter { display: flex; flex-direction: column; min-height: 100dvh; max-width: var(--column); margin: 0 auto; }
.sitter-head { display: flex; align-items: center; gap: 0.8rem; padding: calc(1rem + env(safe-area-inset-top)) 1.25rem 0.8rem; border-bottom: 1px solid var(--line); }
.sitter-head img { border-radius: 50%; box-shadow: 0 0 0 2px var(--surface), 0 0 0 3px var(--gold); }
.sitter-head h1 { font: 400 1.5rem/1.1 var(--serif); margin: 0; }
.sitter-head p { margin: 0.1rem 0 0; color: var(--muted); font-size: 0.9rem; }
.sitter-log { flex: 1; display: flex; flex-direction: column; gap: 0.6rem; padding: 1.2rem 1.25rem; overflow-y: auto; }
.sitter-hello { color: var(--muted); font-size: 0.95rem; line-height: 1.5; margin: 0 0 0.6rem; }
.sitter-msg { margin: 0; padding: 0.7rem 1rem; border-radius: var(--radius); max-width: 85%; white-space: pre-wrap; line-height: 1.45; animation: fade-in 400ms var(--ease) both; }
.sitter-msg.from-you { align-self: flex-end; background: var(--accent-soft); }
.sitter-msg.from-sophia { align-self: flex-start; background: var(--surface); box-shadow: var(--shadow); }
.sitter-msg.from-parent { align-self: center; background: var(--sage-soft); color: var(--sage-ink); font-weight: 600; max-width: 95%; }
.sitter-send { display: flex; gap: 0.6rem; padding: 0.8rem 1.25rem calc(0.8rem + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); background: var(--bg); position: sticky; bottom: 0; }
.sitter-send textarea { flex: 1; resize: none; font: inherit; padding: 0.7rem 1rem; border-radius: var(--radius); border: 1px solid var(--line); background: var(--surface); color: var(--ink); min-height: var(--tap); }
.sitter-send textarea:focus-visible { border-color: var(--blue); outline: 3px solid var(--blue-soft); outline-offset: 0; }
.sitter-ended { text-align: center; color: var(--muted); padding: 2rem 1.25rem; font-family: var(--serif); font-style: italic; }

/* The vault -------------------------------------------------------------------------------- */
.vault-card { display: grid; gap: 0.7rem; }
.vault-card h2 { margin: 0; }
.vault-card p { margin: 0; color: var(--muted); line-height: 1.5; }
.vault-form { display: grid; gap: 0.5rem; }
.vault-form label, .vault-card > label { font-weight: 700; color: var(--muted); font-size: 0.95rem; }
.vault-form input, .vault-form textarea, .vault-card select {
  font: inherit; color: var(--ink); background: var(--surface); border: 1px solid var(--line);
  border-radius: 14px; padding: 0.7rem 0.9rem; min-height: var(--tap); width: 100%; box-sizing: border-box;
}
.vault-form textarea { resize: vertical; line-height: 1.5; }
.vault-form input:focus-visible, .vault-form textarea:focus-visible, .vault-card select:focus-visible { border-color: var(--blue); outline: 3px solid var(--blue-soft); outline-offset: 0; }
.vault-problem { color: var(--accent) !important; font-weight: 600; }
.vault-entry { border-top: 1px solid var(--line); padding: 0.6rem 0; }
.vault-entry summary { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; cursor: pointer; min-height: var(--tap); align-items: center; font-weight: 700; }
.vault-entry summary small { color: var(--muted); font-weight: 500; white-space: nowrap; }
.vault-body { white-space: pre-wrap; color: var(--ink) !important; background: var(--surface-2); border-radius: 12px; padding: 0.8rem 1rem; margin-top: 0.4rem !important; }
.vault-actions { display: flex; gap: 0.5rem; justify-content: flex-end; margin-top: 0.5rem; }
.vault-check { display: flex; align-items: center; gap: 0.6rem; min-height: var(--tap); font-weight: 600; }
.vault-check input { width: 1.25rem; height: 1.25rem; accent-color: var(--accent); }
.vault-key { display: block; padding: 0.8rem 1rem; border-radius: 12px; background: var(--surface-2); font: 0.85rem/1.4 var(--mono); word-break: break-all; user-select: all; }
.vault-dialog { width: min(36rem, calc(100vw - 2rem)); border: 0; border-radius: var(--radius); padding: 1.2rem; background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }
.vault-dialog::backdrop { background: rgba(40, 25, 15, 0.35); }
.vault-dialog h2 { margin: 0 0 0.4rem; font: 400 1.35rem/1.2 var(--serif); }
.mind-list { margin: 0.4rem 0 0; padding-left: 1.2rem; display: grid; gap: 0.45rem; line-height: 1.45; color: var(--ink); }
.face-to-face {
  position: absolute; left: 50%; transform: translateX(-50%); top: 3rem; min-height: 32px; padding: 0 0.7rem;
  border: 0; border-radius: 999px; background: rgba(30, 22, 16, 0.72); color: #f6eadb; font-weight: 700; font-size: 0.75rem;
  white-space: nowrap;
}
.face-to-face[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }

/* Inside the Mac app ------------------------------------------------------------------------
   The Mac app (ios/SophiaMac) marks the page with data-shell="mac". It has its own sidebar,
   toolbar and menus, so the page drops its phone header and menu, uses the Mac's own type at
   desktop size, and always shows her presence beside the conversation. */
:root[data-shell="mac"] {
  font-size: 14px;
  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Manrope", sans-serif;
  --tap: 30px;
  --radius: 14px;
  --column: 52rem;
}
:root[data-shell="mac"] body { font-size: 1rem; line-height: 1.5; background-attachment: scroll; }
:root[data-shell="mac"] .top { display: none; }
:root[data-shell="mac"] button,
:root[data-shell="mac"] summary { cursor: default; }
:root[data-shell="mac"] .presence {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: none;
  width: 240px;
  padding: 1.75rem 1.25rem 1.25rem;
  border-right: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
  overflow-y: auto;
}
:root[data-shell="mac"] .presence .avatar { --size: 132px; }
:root[data-shell="mac"] .presence-name { font-size: 1.7rem; margin-top: 1.1rem; }
:root[data-shell="mac"] .presence-state { font-size: 1rem; min-height: 2.6em; }
:root[data-shell="mac"] .activity li { font-size: 0.92rem; padding: 0.3rem 0; }
:root[data-shell="mac"] #messages { padding-top: 1.5rem; }
:root[data-shell="mac"] .msg { max-width: min(80%, 40rem); }
:root[data-shell="mac"] .composer-wrap { padding: 0.6rem 1.25rem 1rem; }
:root[data-shell="mac"] #composer { border-radius: 18px; padding: 0.3rem 0.3rem 0.3rem 0.25rem; }
:root[data-shell="mac"] #composer:focus-within { box-shadow: var(--shadow), 0 0 0 3px color-mix(in srgb, var(--blue) 35%, transparent); }
:root[data-shell="mac"] .btn { padding: 0.35rem 0.9rem; }
@media (max-width: 760px) { :root[data-shell="mac"] .presence { display: none; } }

/* The board (board.js): a shared screen for a child and Sophia ------------------------------- */
.board {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  flex: 3 1 0;
  min-height: 0;
  width: 100%;
  max-width: 72rem;
  margin: 0 auto;
  padding: 0.5rem max(1rem, env(safe-area-inset-right)) 0 max(1rem, env(safe-area-inset-left));
}
.board[hidden] { display: none; }
body.board-open #messages { flex: 1 1 0; min-height: 6rem; }
.board-top { display: flex; align-items: center; gap: 0.5rem; }
.board-caption { flex: 1; margin: 0; font-size: 1.35rem; font-weight: 600; color: var(--ink); text-align: center; }
.board-stage {
  position: relative;
  flex: 1;
  min-height: 12rem;
  border-radius: 20px;
  background: #fff;
  border: 2px solid var(--line);
  overflow: hidden;
  touch-action: none;
}
.board-scene, .board-ink { position: absolute; inset: 0; width: 100%; height: 100%; }
.board-scene { display: grid; place-items: center; pointer-events: none; }
.board-scene img, .board-scene video { max-width: 100%; max-height: 100%; width: 100%; height: 100%; object-fit: contain; }
.board-ink { touch-action: none; cursor: crosshair; }
.board-waiting { font-size: 2rem; color: #6b5546; animation: board-pulse 1.6s ease-in-out infinite; }
@keyframes board-pulse { 50% { opacity: 0.45; } }
.board-choices { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem; }
.board-choices:empty { display: none; }
.board-choice {
  min-width: 4.5rem;
  min-height: 3.5rem;
  padding: 0.5rem 1.2rem;
  font: inherit;
  font-size: 1.6rem;
  font-weight: 700;
  border-radius: 16px;
  border: 2px solid var(--line);
  background: var(--surface);
  color: var(--ink);
}
.board-choice.picked { background: var(--accent-soft); border-color: var(--accent); }
.board-choice:disabled:not(.picked) { opacity: 0.5; }
.board-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem; }
.board-gap { flex: 1; }
.board-colour {
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  border: 3px solid var(--surface);
  box-shadow: 0 0 0 1px var(--line);
}
.board-colour.on { box-shadow: 0 0 0 3px var(--accent); }
.board-btn {
  min-height: 2.6rem;
  min-width: 2.6rem;
  padding: 0.3rem 0.8rem;
  font: inherit;
  font-size: 1.1rem;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
}
.board-btn.on { box-shadow: 0 0 0 3px var(--accent); }
.board-done { background: var(--accent); color: var(--on-accent); border-color: var(--accent); font-weight: 700; }
.board-btn:disabled { opacity: 0.5; }
a.board-btn { display: inline-grid; place-items: center; text-decoration: none; }

/* Trading page */
.trading-state { margin: 0; font-weight: 600; color: var(--muted); }
.trading-state.on { color: var(--sage-ink); }
.trading-state.off { color: var(--accent); }
.trading-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.5rem; }
.trading-page em { font-style: normal; color: var(--muted); }

/* Sweepstakes page */
.sweep-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
.sweep-actions .btn { text-decoration: none; }
.sweeps-page .status-detail a { color: var(--accent); }

/* The family table: who's at it, and a way to end it */
.table-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 8px 16px 0;
  padding: 8px 12px; border-radius: 14px; background: var(--bubble-bg, rgba(127, 127, 127, 0.12)); font-size: 0.95rem; }
.table-bar[hidden] { display: none; }

/* My drawings (drawings.html) ------------------------------------------------------ */
.book { max-width: 72rem; margin: 0 auto; padding: 1.5rem max(1rem, env(safe-area-inset-right)) 3rem max(1rem, env(safe-area-inset-left)); }
.book h1 { font-family: "DM Serif Display", serif; font-weight: 400; margin: 0 0 0.25rem; }
.book h2 { margin: 2rem 0 0.75rem; }
.book a.back { color: var(--accent); }
.pages { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr)); gap: 1rem; }
.page { margin: 0; background: var(--surface); border: 1px solid var(--line); border-radius: 16px; overflow: hidden; }
.page img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: contain; background: #fff; }
.page figcaption { padding: 0.5rem 0.75rem; font-size: 0.95rem; color: var(--muted); }
.empty { color: var(--muted); }

/* Bar widths (data-w="1"…"100"): the security policy refuses inline style attributes. */
.bar[data-w="1"] { width: 1%; }
.bar[data-w="2"] { width: 2%; }
.bar[data-w="3"] { width: 3%; }
.bar[data-w="4"] { width: 4%; }
.bar[data-w="5"] { width: 5%; }
.bar[data-w="6"] { width: 6%; }
.bar[data-w="7"] { width: 7%; }
.bar[data-w="8"] { width: 8%; }
.bar[data-w="9"] { width: 9%; }
.bar[data-w="10"] { width: 10%; }
.bar[data-w="11"] { width: 11%; }
.bar[data-w="12"] { width: 12%; }
.bar[data-w="13"] { width: 13%; }
.bar[data-w="14"] { width: 14%; }
.bar[data-w="15"] { width: 15%; }
.bar[data-w="16"] { width: 16%; }
.bar[data-w="17"] { width: 17%; }
.bar[data-w="18"] { width: 18%; }
.bar[data-w="19"] { width: 19%; }
.bar[data-w="20"] { width: 20%; }
.bar[data-w="21"] { width: 21%; }
.bar[data-w="22"] { width: 22%; }
.bar[data-w="23"] { width: 23%; }
.bar[data-w="24"] { width: 24%; }
.bar[data-w="25"] { width: 25%; }
.bar[data-w="26"] { width: 26%; }
.bar[data-w="27"] { width: 27%; }
.bar[data-w="28"] { width: 28%; }
.bar[data-w="29"] { width: 29%; }
.bar[data-w="30"] { width: 30%; }
.bar[data-w="31"] { width: 31%; }
.bar[data-w="32"] { width: 32%; }
.bar[data-w="33"] { width: 33%; }
.bar[data-w="34"] { width: 34%; }
.bar[data-w="35"] { width: 35%; }
.bar[data-w="36"] { width: 36%; }
.bar[data-w="37"] { width: 37%; }
.bar[data-w="38"] { width: 38%; }
.bar[data-w="39"] { width: 39%; }
.bar[data-w="40"] { width: 40%; }
.bar[data-w="41"] { width: 41%; }
.bar[data-w="42"] { width: 42%; }
.bar[data-w="43"] { width: 43%; }
.bar[data-w="44"] { width: 44%; }
.bar[data-w="45"] { width: 45%; }
.bar[data-w="46"] { width: 46%; }
.bar[data-w="47"] { width: 47%; }
.bar[data-w="48"] { width: 48%; }
.bar[data-w="49"] { width: 49%; }
.bar[data-w="50"] { width: 50%; }
.bar[data-w="51"] { width: 51%; }
.bar[data-w="52"] { width: 52%; }
.bar[data-w="53"] { width: 53%; }
.bar[data-w="54"] { width: 54%; }
.bar[data-w="55"] { width: 55%; }
.bar[data-w="56"] { width: 56%; }
.bar[data-w="57"] { width: 57%; }
.bar[data-w="58"] { width: 58%; }
.bar[data-w="59"] { width: 59%; }
.bar[data-w="60"] { width: 60%; }
.bar[data-w="61"] { width: 61%; }
.bar[data-w="62"] { width: 62%; }
.bar[data-w="63"] { width: 63%; }
.bar[data-w="64"] { width: 64%; }
.bar[data-w="65"] { width: 65%; }
.bar[data-w="66"] { width: 66%; }
.bar[data-w="67"] { width: 67%; }
.bar[data-w="68"] { width: 68%; }
.bar[data-w="69"] { width: 69%; }
.bar[data-w="70"] { width: 70%; }
.bar[data-w="71"] { width: 71%; }
.bar[data-w="72"] { width: 72%; }
.bar[data-w="73"] { width: 73%; }
.bar[data-w="74"] { width: 74%; }
.bar[data-w="75"] { width: 75%; }
.bar[data-w="76"] { width: 76%; }
.bar[data-w="77"] { width: 77%; }
.bar[data-w="78"] { width: 78%; }
.bar[data-w="79"] { width: 79%; }
.bar[data-w="80"] { width: 80%; }
.bar[data-w="81"] { width: 81%; }
.bar[data-w="82"] { width: 82%; }
.bar[data-w="83"] { width: 83%; }
.bar[data-w="84"] { width: 84%; }
.bar[data-w="85"] { width: 85%; }
.bar[data-w="86"] { width: 86%; }
.bar[data-w="87"] { width: 87%; }
.bar[data-w="88"] { width: 88%; }
.bar[data-w="89"] { width: 89%; }
.bar[data-w="90"] { width: 90%; }
.bar[data-w="91"] { width: 91%; }
.bar[data-w="92"] { width: 92%; }
.bar[data-w="93"] { width: 93%; }
.bar[data-w="94"] { width: 94%; }
.bar[data-w="95"] { width: 95%; }
.bar[data-w="96"] { width: 96%; }
.bar[data-w="97"] { width: 97%; }
.bar[data-w="98"] { width: 98%; }
.bar[data-w="99"] { width: 99%; }
.bar[data-w="100"] { width: 100%; }

/* Her lips, in-house (lips.js): her resting picture always underneath, each mouth shape and blink
   fading in over it, and a slow breath so she isn't a photo. */
.avatar .lips { position: absolute; inset: 0; z-index: 3; pointer-events: none; transform-origin: 50% 75%;
                animation: lips-breathe 6s ease-in-out infinite; }
.avatar .lips img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0;
                    transition: opacity 45ms linear; }
.avatar .lips-head { position: absolute; inset: 0; transform-origin: 50% 85%; }
.avatar .lips-head.nod { animation: lips-nod 0.9s ease-in-out; }
.avatar .lips img[data-frame="rest"] { transition: none; }
.avatar .lips img[data-frame="blink"] { transition-duration: 80ms; transition-timing-function: ease-in-out; }
.avatar .lips img[data-frame="smile"],
.avatar .lips img[data-frame="brows_up"],
.avatar .lips img[data-frame="concern"] { transition-duration: 220ms; transition-timing-function: ease-in-out; }
.avatar .lips img.on { opacity: 1; }
.avatar.lipsync video { opacity: 0 !important; }
@keyframes lips-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.006) translateY(-0.2%); } }
@keyframes lips-nod { 0%, 100% { transform: none; } 35% { transform: translateY(0.7%) rotate(0.3deg); }
                      65% { transform: translateY(-0.15%); } }
@media (prefers-reduced-motion: reduce) { .avatar .lips, .avatar .lips-head.nod { animation: none; } }

/* =====================================================================================================
   Refinement: warm, quiet, precise. The same golden-hour palette, made calmer and more exact.
   Glass materials that let the warm light through; hairlines instead of borders; one soft, long
   shadow; type set a touch tighter; chrome that steps back so the conversation leads; and motion
   that settles like something physical. Everything here is CSS only (the page's policy allows no
   inline styles), and reduced motion and contrast are respected.
   ===================================================================================================== */
:root {
  --hairline: color-mix(in srgb, var(--ink) 9%, transparent);
  --glass: color-mix(in srgb, var(--surface) 68%, transparent);
  --glass-strong: color-mix(in srgb, var(--surface) 84%, transparent);
  --glass-edge: rgba(255, 255, 255, 0.7);       /* the lit top edge of a glass surface */
  --float: 0 0.5px 0 rgba(255, 255, 255, 0.6) inset, 0 1px 2px rgba(70, 40, 20, 0.05),
           0 18px 48px -18px rgba(70, 40, 20, 0.22);
  --lift: 0 1px 1px rgba(70, 40, 20, 0.04), 0 6px 20px -10px rgba(70, 40, 20, 0.18);
  --bubble-radius: 24px;
  --settle: cubic-bezier(0.2, 0.9, 0.25, 1);    /* quick, then a long, soft landing */
  --spring: cubic-bezier(0.34, 1.3, 0.64, 1);
}
:root[data-theme="evening"] {
  --hairline: color-mix(in srgb, var(--ink) 11%, transparent);
  --glass: color-mix(in srgb, var(--surface) 62%, transparent);
  --glass-strong: color-mix(in srgb, var(--surface) 82%, transparent);
  --glass-edge: rgba(255, 236, 214, 0.10);
  --float: 0 0.5px 0 rgba(255, 236, 214, 0.08) inset, 0 1px 2px rgba(0, 0, 0, 0.2),
           0 22px 56px -20px rgba(0, 0, 0, 0.55);
  --lift: 0 1px 1px rgba(0, 0, 0, 0.18), 0 8px 24px -12px rgba(0, 0, 0, 0.45);
}

body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility;
       font-feature-settings: "kern" 1, "liga" 1, "calt" 1; }

/* The header: a pane of warm glass the conversation slips beneath. */
.top {
  background: var(--glass);
  -webkit-backdrop-filter: saturate(1.8) blur(28px);
  backdrop-filter: saturate(1.8) blur(28px);
  border-bottom: 0.5px solid var(--hairline);
  box-shadow: 0 0.5px 0 var(--glass-edge) inset;
}
.top .avatar { --size: 46px; box-shadow: 0 0 0 1.5px var(--surface), 0 0 0 2.5px color-mix(in srgb, var(--gold) 80%, transparent),
                                        0 6px 18px -6px var(--gold-glow); }
.who h1 { font-size: 1.45rem; letter-spacing: 0.01em; }
.status { font-size: 0.82rem; letter-spacing: 0.01em; }
.status::before { width: 7px; height: 7px; box-shadow: 0 0 0 3px color-mix(in srgb, var(--sage) 22%, transparent); }
.icon-btn { color: color-mix(in srgb, var(--ink) 62%, transparent); }
.icon-btn:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }

/* The conversation: dissolves softly into the chrome above and below. */
#messages {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 18px, #000 calc(100% - 22px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 18px, #000 calc(100% - 22px), transparent 100%);
  scroll-padding-bottom: 2rem;
}
.thread { gap: 0.85rem; }
@keyframes settle-in { from { opacity: 0; transform: translateY(10px) scale(0.985); filter: blur(3px); }
                       to { opacity: 1; transform: none; filter: none; } }
.msg { animation: settle-in 620ms var(--settle) both; }

.bubble {
  font-size: 1.125rem;
  line-height: 1.52;
  letter-spacing: -0.003em;
  padding: 0.8rem 1.1rem;
  border-radius: var(--bubble-radius);
}
.bubble p { margin-bottom: 0.62em; }
/* Hers: warm paper under glass, lit from above, no hard edge. */
.msg.assistant .bubble {
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--surface) 96%, white 4%), var(--surface));
  border: 0.5px solid var(--hairline);
  border-bottom-left-radius: 10px;
  box-shadow: 0 0.5px 0 var(--glass-edge) inset, var(--lift);
}
/* Yours: a soft terracotta wash. */
.msg.user .bubble {
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent-soft) 88%, var(--surface)), var(--accent-soft));
  border: 0.5px solid color-mix(in srgb, var(--accent) 14%, transparent);
  border-bottom-right-radius: 10px;
  box-shadow: 0 0.5px 0 var(--glass-edge) inset, 0 6px 18px -12px color-mix(in srgb, var(--accent) 45%, transparent);
}

/* Time and actions: present, never loud. The react button appears when you reach for it. */
.msg time { font-size: 0.74rem; letter-spacing: 0.02em; font-variant-numeric: tabular-nums; opacity: 0.8; margin-top: 0.25rem; }
.msg .meta .icon-btn { width: 36px; height: 36px; }
.react-btn { opacity: 0; transition: opacity 260ms var(--ease), background-color 260ms var(--ease); }
.msg:hover .react-btn, .msg:focus-within .react-btn, .react-btn:focus-visible { opacity: 1; }
@media (hover: none) { .react-btn { display: none; } } /* on a phone: press and hold the message */
.reactions { margin-top: -0.6rem; }
.reaction { background: var(--glass-strong); border: 0.5px solid var(--hairline);
            -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); box-shadow: var(--lift); }
.reaction.mine { border-color: color-mix(in srgb, var(--accent) 55%, transparent); }

/* The composer: a floating glass capsule. */
.composer-wrap { background: linear-gradient(to top, var(--bg) 55%, color-mix(in srgb, var(--bg) 0%, transparent)); }
#composer {
  background: var(--glass-strong);
  -webkit-backdrop-filter: saturate(1.8) blur(26px);
  backdrop-filter: saturate(1.8) blur(26px);
  border: 0.5px solid var(--hairline);
  border-radius: 30px;
  box-shadow: var(--float);
}
#composer:focus-within { border-color: color-mix(in srgb, var(--accent) 35%, transparent);
                         box-shadow: var(--float), 0 0 0 4px color-mix(in srgb, var(--accent) 12%, transparent); }
#send { background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 88%, white), var(--accent));
        box-shadow: 0 0.5px 0 rgba(255, 255, 255, 0.35) inset, 0 6px 16px -6px color-mix(in srgb, var(--accent) 70%, transparent); }
#send:active { transform: scale(0.92); }

/* Menus and sheets: glass, with a little more room and rounder corners. */
.menu-panel, .sheet {
  background: var(--glass-strong);
  -webkit-backdrop-filter: saturate(1.8) blur(30px);
  backdrop-filter: saturate(1.8) blur(30px);
  border: 0.5px solid var(--hairline);
  box-shadow: var(--float);
}
.menu-panel { border-radius: 22px; padding: 0.45rem; animation: pop-in 280ms var(--spring) both; transform-origin: top right; }
.menu-item { border-radius: 14px; font-weight: 600; letter-spacing: -0.005em; }
.menu-item:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.sheet { border-radius: 28px; padding: 1.5rem 1.4rem 1.2rem; }
.sheet::backdrop { background: rgba(28, 16, 10, 0.32); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.sheet[open] { animation: pop-in 340ms var(--spring) both; }
.sheet h2 { font: 400 1.45rem/1.2 var(--serif); letter-spacing: 0.005em; margin-bottom: 0.6rem; }
.btn { letter-spacing: 0; }
.btn-primary { background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 88%, white), var(--accent));
               box-shadow: 0 0.5px 0 rgba(255, 255, 255, 0.3) inset, 0 6px 16px -8px color-mix(in srgb, var(--accent) 70%, transparent); }
.btn-quiet { border-color: var(--hairline); }

/* The menu you get by pressing a message: opens right where you are. */
.react-menu {
  position: fixed; z-index: 900; display: flex; flex-direction: column; gap: 0.45rem; align-items: stretch;
}
/* (the parts animate, not the menu: an animated parent would stop their glass from blurring what's behind) */
.react-menu > * { animation: pop-in 280ms var(--spring) both; }
.react-menu > .react-actions { animation-delay: 40ms; }
.react-menu .react-picker { margin: 0; align-self: auto; }
.react-picker, .react-actions, .emoji-panel {
  background: color-mix(in srgb, var(--surface) 90%, transparent);
  -webkit-backdrop-filter: saturate(1.8) blur(30px);
  backdrop-filter: saturate(1.8) blur(30px);
  border: 0.5px solid var(--hairline);
  box-shadow: var(--float);
}
.react-picker { border-radius: 999px; }
.react-menu .react-picker button:focus-visible, .emoji-grid button:focus-visible { outline: none; background: color-mix(in srgb, var(--ink) 8%, transparent); }
.emoji-panel input:focus-visible { outline: none; border-color: color-mix(in srgb, var(--accent) 45%, transparent);
                                   box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent); }
.react-more { display: grid; place-items: center; color: var(--muted); }
.react-more svg { width: 22px; height: 22px; }
.react-actions { border-radius: 18px; overflow: hidden; min-width: 12rem; align-self: flex-start; }
.react-actions button {
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; width: 100%;
  min-height: 46px; padding: 0 1rem; border: 0; background: none; font-weight: 600; text-align: left;
}
.react-actions button:hover, .react-actions button:focus-visible { background: color-mix(in srgb, var(--ink) 6%, transparent); outline: none; }
.react-actions svg { width: 20px; height: 20px; color: var(--muted); }
.emoji-panel { width: min(22rem, calc(100vw - 20px)); border-radius: 24px; padding: 0.6rem; display: flex; flex-direction: column; gap: 0.45rem; }
.emoji-panel input {
  width: 100%; min-height: 40px; padding: 0 0.9rem; border-radius: 12px; border: 0.5px solid var(--hairline);
  background: color-mix(in srgb, var(--ink) 5%, transparent); color: var(--ink); font: inherit; font-size: 1rem;
}
.emoji-tabs { display: flex; justify-content: space-between; }
.emoji-tabs button { width: 36px; height: 36px; border: 0; border-radius: 10px; background: none; font-size: 1.2rem; opacity: 0.55;
                     transition: opacity 200ms var(--ease), background-color 200ms var(--ease); }
.emoji-tabs button.on { opacity: 1; background: color-mix(in srgb, var(--ink) 7%, transparent); }
.emoji-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(42px, 1fr)); max-height: min(46vh, 300px);
              overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.emoji-grid button { height: 42px; border: 0; border-radius: 10px; background: none; font-size: 1.55rem; line-height: 1; cursor: pointer;
                     transition: transform 160ms var(--spring), background-color 160ms var(--ease); }
.emoji-grid button:hover, .emoji-grid button:focus-visible { background: color-mix(in srgb, var(--ink) 7%, transparent); transform: scale(1.15); outline: none; }
.emoji-grid button.chosen { background: var(--accent-soft); }
.copy-scratch { position: fixed; top: -1000px; left: 0; opacity: 0; }
.copied {
  position: fixed; left: 50%; bottom: calc(6.5rem + env(safe-area-inset-bottom)); z-index: 950;
  padding: 0.5rem 1rem; border-radius: 999px; font-weight: 600; font-size: 0.92rem;
  background: var(--glass-strong); -webkit-backdrop-filter: blur(24px); backdrop-filter: blur(24px);
  border: 0.5px solid var(--hairline); box-shadow: var(--float);
  opacity: 0; transform: translate(-50%, 8px) scale(0.96); pointer-events: none;
  transition: opacity 240ms var(--ease), transform 320ms var(--spring);
}
.copied.on { opacity: 1; transform: translate(-50%, 0) scale(1); }

/* The wide layout: her portrait column becomes a calm side panel of glass. */
@media (min-width: 1100px) {
  .presence { border-right: 0.5px solid var(--hairline); background: color-mix(in srgb, var(--surface) 22%, transparent); }
}

/* Without glass, or with more contrast asked for: solid surfaces. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .top, #composer, .menu-panel, .sheet, .react-picker, .react-actions, .emoji-panel, .reaction, .copied { background: var(--surface); }
}
@media (prefers-contrast: more) {
  .top, #composer, .menu-panel, .sheet, .react-picker, .react-actions, .emoji-panel, .reaction, .copied {
    background: var(--surface); -webkit-backdrop-filter: none; backdrop-filter: none; border: 1px solid var(--line);
  }
  .msg.assistant .bubble { border: 1px solid var(--line); }
}
@media (prefers-reduced-motion: reduce) {
  .msg, .react-menu > *, .menu-panel, .sheet[open], .copied { animation: none; transition: none; }
}
/* A run of messages from one side: closer together, one time at the end of it. */
.msg.in-run + .msg { margin-top: -0.45rem; }
.msg.user.in-run > .bubble { border-bottom-right-radius: var(--bubble-radius); }
.msg.assistant.in-run > .bubble { border-bottom-left-radius: var(--bubble-radius); }

/* Time, quietly: a small centered mark when a while has passed; each message's time and buttons
   sit in the margin beside it (its time on hover, and in its press-and-hold menu), so every message
   is spaced the same; the last message keeps its time. */
.time-mark { align-self: center; margin: 0.9rem 0 0.1rem; font-size: 0.74rem; font-weight: 600; letter-spacing: 0.04em;
             color: var(--muted); opacity: 0.85; font-variant-numeric: tabular-nums; }
.thread > .time-mark:first-child { margin-top: 0.2rem; }
.msg { position: relative; }
.msg > .meta {
  position: absolute; bottom: 0; display: flex; align-items: center; gap: 0; white-space: nowrap;
}
.msg.assistant > .meta { left: calc(100% + 0.2rem); }
.msg.user > .meta { right: calc(100% + 0.2rem); flex-direction: row-reverse; }
.msg > .meta time { margin: 0 0.35rem; opacity: 0; transition: opacity 260ms var(--ease); }
.msg:hover > .meta time, .msg:focus-within > .meta time, .thread > .msg:last-child > .meta time { opacity: 0.8; }
.msg > .meta .voice-note { position: absolute; top: 100%; left: 0.4rem; font-size: 0.75rem; }
.msg.user > .meta .voice-note { left: auto; right: 0.4rem; }
.msg.has-reactions { margin-bottom: 0.2rem; }
.msg.in-run + .msg { margin-top: -0.35rem; }
.react-when { margin: 0; padding: 0.45rem 1rem 0.6rem; font-size: 0.78rem; color: var(--muted);
              border-top: 0.5px solid var(--hairline); letter-spacing: 0.01em; }
/* Wide bubbles leave little margin: there the time and buttons tuck just under the corner instead. */
@media (max-width: 560px) {
  .msg { max-width: 82%; }
}

/* The header, quieter still: her name in the serif, everything else small and soft. */
.top { padding-top: calc(env(safe-area-inset-top) + 0.4rem); padding-bottom: 0.5rem; }
.top .avatar { --size: 42px; }
.who h1 { font-size: 1.32rem; }
.status { color: color-mix(in srgb, var(--muted) 90%, transparent); }
.top .icon-btn svg { width: 20px; height: 20px; }

.react-menu .react-picker { padding: 0.25rem; gap: 0; }
.react-menu .react-picker button { min-width: 40px; min-height: 42px; padding: 0.3rem; font-size: 1.3rem; }
@media (max-width: 380px) { .react-menu .react-picker button { min-width: 36px; } }

/* =====================================================================================================
   Her own design, years on: her words stand free on the warm page, like someone speaking in the
   room, not boxed in; yours rest in soft capsules. A slow, living light drifts behind everything.
   On a phone her portrait and name sit centred above the conversation.
   ===================================================================================================== */
body { background: var(--bg); }
body::before {
  content: ""; position: fixed; inset: -25%; z-index: -1; pointer-events: none;
  background:
    radial-gradient(38% 30% at 78% 18%, var(--bg-glow), transparent 70%),
    radial-gradient(34% 28% at 18% 82%, var(--bg-glow-2), transparent 70%),
    radial-gradient(30% 24% at 60% 60%, color-mix(in srgb, var(--gold-glow) 35%, transparent), transparent 70%);
  animation: light-drift 48s ease-in-out infinite alternate;
}
@keyframes light-drift {
  0% { transform: translate3d(0, 0, 0) scale(1); }
  50% { transform: translate3d(-3%, 2%, 0) scale(1.05); }
  100% { transform: translate3d(2%, -2%, 0) scale(1.02); }
}

/* Hers: back in her warm bubble (free text read less clearly as hers), a touch larger. */
.msg.assistant { max-width: min(88%, 37rem); }
.msg.assistant > .bubble { font-size: 1.14rem; line-height: 1.54; }
/* Her time and voice button sit just under her bubble, in line with its edge. */
.msg.assistant > .meta { position: static; margin: 0.2rem 0 0 0.35rem; min-height: 0; }
.thread > .msg.assistant:not(:last-child) > .meta:not(:has(.speak, .voice-note:not(:empty))) { display: none; }
@media (hover: hover) { .thread > .msg.assistant:not(:last-child):hover > .meta { display: flex; } }
.msg.assistant > .meta .speak { width: 32px; height: 32px; margin-top: 0; }
.msg.user + .msg.assistant, .msg.assistant + .msg.user { margin-top: 0.4rem; }

/* Yours: a soft capsule. */
.msg.user { max-width: min(80%, 30rem); }

/* On a phone: her portrait and name centred, the two controls at the sides. */
@media (max-width: 1099px) {
  .top-inner { display: grid; grid-template-columns: 1fr auto 1fr; grid-template-areas: "theme avatar menu" "theme who menu";
               align-items: center; row-gap: 0.15rem; }
  .top .avatar { grid-area: avatar; justify-self: center; --size: 40px; }
  .top .who { grid-area: who; margin: 0; align-items: center; text-align: center; }
  .who h1 { font-size: 1.28rem; line-height: 1.05; letter-spacing: 0.01em; }
  .status { font-size: 0.74rem; justify-content: center; }
  #theme-toggle { grid-area: theme; justify-self: start; }
  .top .menu { grid-area: menu; justify-self: end; }
}
@media (prefers-reduced-motion: reduce) { body::before { animation: none; } }
/* With a message's menu open, the rest of the conversation steps back. */
.thread > * { transition: opacity 280ms var(--ease), filter 280ms var(--ease); }
body.menu-open .thread > :not(.menu-target) { opacity: 0.32; filter: blur(1.5px) saturate(0.8); }
/* Wide screens: her portrait column is the header; the top bar is just its two controls. */
@media (min-width: 1100px) {
  .top { background: transparent; border-bottom: 0; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
}
.msg { animation-fill-mode: backwards; } /* once it has settled, the message's own styles apply again */
/* A hidden time takes no room, so her voice button sits right at the bubble's edge. */
.thread > .msg:not(:last-child) > .meta time { display: none; }
@media (hover: hover) { .thread > .msg:not(:last-child):hover > .meta time { display: inline; } }

/* Messages: the family's own, sealed end to end (messages.html). */
.msg-lock { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.78rem; color: var(--sage-ink);
            padding: 0.25rem 0.6rem; border-radius: 999px; background: var(--sage-soft); }
.msg-lock svg { width: 14px; height: 14px; }
.msg-main { max-width: 60rem; margin: 0 auto; padding: 0.75rem 16px calc(1rem + env(safe-area-inset-bottom));
            display: grid; gap: 1rem; }
.chat-list { display: grid; gap: 0.35rem; align-content: start; }
.chat-row { display: flex; align-items: center; gap: 0.6rem; padding: 0.85rem 1rem; border-radius: 16px; color: var(--ink);
            text-decoration: none; background: var(--surface); border: 1px solid var(--hairline, var(--line)); }
.chat-row:hover, .chat-row.on { background: var(--surface-2); }
.chat-row-name { flex: 1; font-weight: 600; }
.chat-row-tag { font-size: 0.74rem; color: var(--muted); }
.chat-row-unread { min-width: 1.4rem; height: 1.4rem; padding: 0 0.4rem; border-radius: 999px; display: grid; place-items: center;
                   font-size: 0.74rem; font-weight: 700; background: var(--accent); color: var(--on-accent); }
.chat-pane { display: flex; flex-direction: column; min-height: 0; }
.chat-pane[hidden] { display: none; }
.chat-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding-bottom: 0.5rem;
             border-bottom: 1px solid var(--hairline, var(--line)); }
.chat-head h2 { margin: 0; font: 400 1.3rem/1.2 var(--serif); }
.chat-who { margin: 0.15rem 0 0; font-size: 0.8rem; color: var(--muted); }
.chat-thread { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 0.35rem; padding: 0.9rem 0;
               min-height: 40vh; max-height: calc(100dvh - 15rem); overscroll-behavior: contain; }
.chat-msg { display: flex; flex-direction: column; align-items: flex-start; max-width: min(80%, 30rem); }
.chat-msg.mine { align-self: flex-end; align-items: flex-end; }
.chat-from { font-size: 0.72rem; color: var(--muted); margin: 0 0 0.15rem 0.7rem; }
.chat-bubble { margin: 0; padding: 0.55rem 0.9rem; border-radius: 20px; background: var(--surface); color: var(--ink);
               border: 1px solid var(--hairline, var(--line)); white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.45; }
.chat-msg.mine .chat-bubble { background: var(--accent-soft); border-color: transparent; }
.chat-msg.sophia .chat-bubble { background: var(--sage-soft); border-color: transparent; }
.chat-bubble.sealed { font-style: italic; color: var(--muted); }
.chat-note { align-self: center; text-align: center; font-size: 0.76rem; color: var(--muted); margin: 0.4rem 1rem; }
.chat-form { display: flex; gap: 0.5rem; align-items: flex-end; padding-top: 0.5rem; }
.chat-form textarea { flex: 1; resize: none; min-height: var(--tap); max-height: 9rem; padding: 0.65rem 0.95rem; border-radius: 22px;
                      font: inherit; color: var(--ink); background: var(--surface); border: 1px solid var(--hairline, var(--line)); }
.chat-form textarea:focus { outline: 2px solid var(--blue); outline-offset: 1px; }
.chat-keys { margin: 0.6rem 0 0; font-size: 0.72rem; color: var(--muted); line-height: 1.45; overflow-wrap: anywhere; }
@media (min-width: 760px) { .msg-main { grid-template-columns: 17rem 1fr; } }
@media (max-width: 759px) { body.in-chat .chat-list { display: none; } }
.chat-head .btn { white-space: nowrap; flex: none; }
.chat-head > div { min-width: 0; }
@media (max-width: 759px) { .chat-head .btn { min-height: 36px; padding: 0.35rem 0.85rem; font-size: 0.85rem; } }

/* Her typing, between the bubbles of a reply (app.js followBubbles). */
.msg.assistant .bubble + .bubble { margin-top: 0.3rem; }
.bubble.typing { display: inline-flex; gap: 0.25rem; align-items: center; padding: 0.7rem 0.9rem; width: auto; }
.bubble.typing[hidden] { display: none; }
.bubble.typing span { width: 0.42rem; height: 0.42rem; border-radius: 50%; background: currentColor; opacity: 0.35;
  animation: typing-dot 1.1s infinite ease-in-out; }
.bubble.typing span:nth-child(2) { animation-delay: 0.15s; }
.bubble.typing span:nth-child(3) { animation-delay: 0.3s; }
@keyframes typing-dot { 0%, 60%, 100% { opacity: 0.25; transform: none; } 30% { opacity: 0.8; transform: translateY(-2px); } }
@media (prefers-reduced-motion: reduce) { .bubble.typing span { animation: none; } }

/* Tap her picture to see it full size (avatar-zoom.js, chat page only). */
body.can-zoom-avatar [data-avatar] { cursor: zoom-in; -webkit-tap-highlight-color: transparent; }
.avatar-zoom { position: fixed; inset: 0; z-index: 2000; display: grid; place-items: center; cursor: zoom-out;
               padding: calc(1rem + env(safe-area-inset-top)) 1rem calc(1rem + env(safe-area-inset-bottom));
               background: rgba(10, 8, 6, 0.86); animation: avatar-zoom-in 200ms ease-out; outline: none; }
.avatar-zoom img { display: block; width: auto; height: auto; max-width: min(94vw, 900px); max-height: 88dvh;
                   object-fit: contain; border-radius: 22px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); }
@keyframes avatar-zoom-in { from { opacity: 0; transform: scale(0.97); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .avatar-zoom { animation: none; } }

/* Video call (app.js startCall): her face fills the screen, yours sits small in the corner, and
   she reads your expression as you talk (app/expressions.py). */
#call svg { width: 24px; height: 24px; }
body.in-call { overflow: hidden; }
body.in-call .top, body.in-call .presence { -webkit-backdrop-filter: none; backdrop-filter: none; z-index: 1500; }
body.in-call [data-avatar].call-face {
  position: fixed; inset: 0; z-index: 1500;
  width: 100vw; height: 100vh; height: 100dvh; display: block;
  border-radius: 0; box-shadow: none; animation: none;
  background: radial-gradient(circle at 50% 42%, #4a3324 0%, #1c130d 60%, #0b0806 100%);
}
/* All of her, not a close crop: her picture is square and the screen is tall. */
body.in-call .call-face img, body.in-call .call-face video, body.in-call .call-face canvas,
body.in-call .call-face .face { border-radius: 0; object-fit: contain; }
/* Her live face is up: only it, never her still picture (or its clips) peeking out around it. */
body.in-call .call-face.live > picture, body.in-call .call-face.live > img,
body.in-call .call-face.live > video:not(.live-face), body.in-call .call-face.live > canvas { visibility: hidden; }
body.in-call .composer-wrap {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1600; background: none;
  padding: 0 1rem calc(env(safe-area-inset-bottom) + 1rem);
}
body.in-call #composer, body.in-call #attached, body.in-call #table-bar { display: none; }
body.in-call .viewfinder {
  position: fixed; z-index: 1600; margin: 0;
  top: calc(env(safe-area-inset-top) + 0.75rem); right: max(0.75rem, env(safe-area-inset-right));
  width: min(7.25rem, 28vw); border-color: rgba(255, 255, 255, 0.85);
}
body.in-call .viewfinder .icon-btn, body.in-call .viewfinder .face-to-face, body.in-call .viewfinder .guide-stop { display: none; }
body.in-call .talk-bar { background: rgba(20, 15, 11, 0.62); color: #f6eadb; border-color: transparent;
                         -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); }
.call-bar {
  max-width: var(--column); margin: 0 auto; display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem; padding: 0.4rem 0.4rem 0.4rem 1rem; border-radius: 999px;
  background: rgba(20, 15, 11, 0.62); color: #f6eadb; font-size: 0.9rem; font-weight: 600;
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
}
.call-bar[hidden] { display: none; }
.call-end {
  flex: none; width: 3.25rem; height: 3.25rem; border: 0; border-radius: 50%;
  display: grid; place-items: center; background: #e5483e; color: #fff; cursor: pointer;
}
.call-end svg { width: 26px; height: 26px; }

/* Her 3D face's renderer needs a place on the page; in the headset it draws to the headset instead. */
.head-stage { position: fixed; left: -4px; top: -4px; width: 2px; height: 2px; overflow: hidden; }

/* Her full body as pictures (/full-body): front, back and sides side by side, each with "make again". */
.full-body-views { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.8rem; }
.full-body-view { margin: 0; display: grid; gap: 0.35rem; }
.full-body-view img { width: 100%; aspect-ratio: 2 / 3; object-fit: cover; border-radius: 12px; background: var(--surface); }
.full-body-view figcaption { font-weight: 700; color: var(--muted); font-size: 0.9rem; }
.full-body-again { display: grid; gap: 0.3rem; }
.full-body-again input { font: inherit; padding: 0.35rem 0.5rem; border-radius: 8px; border: 1px solid var(--line); }
.full-body-video { width: 100%; max-height: 70vh; border-radius: 12px; background: var(--surface); }
/* Her live 3D face on her 3D body (static/whole-preview.js): turn her round by dragging. */
.full-body-whole { position: relative; width: 100%; height: min(75vh, 720px); border-radius: 12px; overflow: hidden; background: #edeae6; touch-action: none; }
.full-body-whole canvas { display: block; width: 100% !important; height: 100% !important; }
.full-body-nudges { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.full-body-saved { color: var(--muted); font-size: 0.9rem; }

/* Linking a bank (/connect/plaid): what you agree to, and the banks linked. */
.plaid-consent label { display: flex; gap: 0.6rem; align-items: flex-start; text-align: left; }
.plaid-consent input { margin-top: 0.3rem; }
.plaid-banks { list-style: none; padding: 0; display: grid; gap: 0.4rem; text-align: left; }
.plaid-banks li { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }
/* Health page: a twelve-week line under each number */
.health-spark { display: block; width: 100%; height: 34px; margin-top: 0.4rem; color: var(--accent); }
.health-spark polyline { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  vector-effect: non-scaling-stroke; }
.health-spark circle { fill: currentColor; }
