/* AntonDev Chat — e06 design shell.
   Single light theme. Every color comes from the locked tokens below;
   see specs/product/e06-design-research.md. No CDN: Inter is self-hosted. */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/inter-latin.woff2') format('woff2');
}

@font-face {
  font-family: 'Newsreader';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('/assets/fonts/newsreader-latin.woff2') format('woff2');
}

@font-face {
  font-family: 'Newsreader';
  font-style: normal;
  font-weight: 600 800;
  font-display: swap;
  src: url('/assets/fonts/newsreader-bold-latin.woff2') format('woff2');
}

@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/fraunces-latin.woff2') format('woff2');
}

:root {
  --canvas: #e5e9f0;
  --surface: #f6f8fb;
  --inset: #dbe1e9;
  --ink: #232633;
  --fog: #4b5261;
  --ash: #7b8290;
  --limestone: #616876;
  --rim: rgba(35, 38, 51, 0.14);
  --accent: #4f7cae;
  --online: #2fa353;
  --cue-lift: #353a4c; /* keycap CTA: cap lit from above */
  --cue-side: #14161f; /* keycap CTA: anchored side face */
  --font: 'Inter', system-ui, -apple-system, sans-serif;
  --mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  --r-card: 12px;
  --r-bubble: 10px;
  --r-input: 10px;
  --r-pill: 9999px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { -webkit-font-smoothing: antialiased; scroll-behavior: smooth; }
body {
  font-family: var(--font);
  background: var(--canvas);
  color: var(--ink);
  font-size: 16px;
  line-height: 1.5;
}

/* ---------- brand bar / wordmark ---------- */
.brand-bar {
  position: sticky;
  top: 0;
  z-index: 5;
  background: rgba(229, 233, 240, 0.97);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rim);
  padding: 18px 24px;
  display: flex;
  align-items: center;
  gap: 14px;
}

/* theme toggle: visitor-facing, top-left corner of the bar (owner call).
   Shows the current skin: moon while dark, sun while light. */
#theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--rim);
  border-radius: 8px;
  background: transparent;
  color: var(--fog);
  cursor: pointer;
}
#theme-toggle:hover { color: var(--ink); border-color: var(--fog); }
#theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#theme-toggle svg { width: 15px; height: 15px; }
#theme-toggle .icon-moon { display: none; }
html[data-theme="terminal"] #theme-toggle .icon-sun { display: none; }
html[data-theme="terminal"] #theme-toggle .icon-moon { display: block; }
.wordmark {
  font-family: var(--font);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  font-size: 22px;
  line-height: 1;
}
.wordmark i { font-style: normal; color: var(--accent); }
.wordmark.sm { font-size: 14px; letter-spacing: -0.01em; }

/* ---------- hero ---------- */
.chat-card {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 945px;
  background: var(--surface);
  border: 1px solid var(--rim);
  border-radius: var(--r-card);
  box-shadow: 0 10px 34px rgba(45, 52, 68, 0.12);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  height: 600px;
  max-height: calc(100vh - 160px);
  will-change: transform, opacity;
}

/* ---------- avatar ---------- */
.avatar {
  width: 44px;
  height: 44px;
  flex: 0 0 44px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--rim);
}
.row .avatar { width: 34px; height: 34px; flex: 0 0 34px; }

/* ---------- card header ---------- */
.chat-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--rim);
}
.chat-head .who strong { font-size: 14px; font-weight: 600; display: block; line-height: 1.2; }
.chat-head .who span {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--limestone);
}
.chat-head .who span::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--online);
  margin-right: 5px;
  vertical-align: 1px;
}
.chat-head .locator {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ash);
  letter-spacing: 0.02em;
}
/* ---------- thread ---------- */
.thread {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.row { display: flex; gap: 10px; align-items: flex-start; }
.row.user { flex-direction: row-reverse; }
.bubble {
  max-width: 90%;
  padding: 10px 14px;
  border-radius: var(--r-bubble);
  font-size: 14.5px;
  line-height: 1.55;
}
.row.anton .bubble { background: var(--inset); color: var(--fog); border-bottom-left-radius: 3px; }
.row.user .bubble { background: var(--ink); color: var(--canvas); border-bottom-right-radius: 3px; }
.bubble.error {
  background: var(--surface);
  color: var(--ash);
  border: 1px solid var(--rim);
  font-style: italic;
}

/* ---------- suggestions ---------- */
.suggest { padding: 4px 20px 12px; }
.suggest-cap {
  font-family: var(--mono);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--limestone);
  padding: 4px 4px 6px;
  display: flex;
  align-items: center;
  gap: 6px;
  user-select: none;
  background: none;
  border: none;
  cursor: pointer;
}
.suggest-cap:hover { color: var(--ink); }
.suggest-cap .chev { display: inline-block; transition: transform .25s; font-size: 9px; }
.suggest-cap.collapsed .chev { transform: rotate(-90deg); }
.sug-list {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .35s cubic-bezier(0.22, 1, 0.36, 1);
}
.sug-list.open { grid-template-rows: 1fr; }
.sug-inner { overflow: hidden; display: flex; flex-direction: column; gap: 2px; }
.sug {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--font);
  font-size: 13px;
  font-weight: 500;
  background: transparent;
  color: var(--fog);
  border: none;
  border-radius: 8px;
  padding: 8px 10px;
  cursor: pointer;
  text-align: left;
}
.sug:hover { background: rgba(35, 38, 51, 0.05); color: var(--ink); }
.sug .arr { color: var(--ash); font-size: 14px; opacity: 0; transition: opacity .15s; }
.sug:hover .arr { opacity: 1; color: var(--ink); }

/* ---------- composer ---------- */
.composer { padding: 12px 20px 16px; border-top: 1px solid var(--rim); }
.composer form { display: flex; gap: 10px; align-items: flex-end; }
.composer textarea {
  flex: 1;
  resize: none;
  overflow-y: hidden;
  font-family: var(--font);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--inset);
  border: 1px solid var(--rim);
  border-radius: var(--r-input);
  padding: 12px 16px;
  min-height: 46px;
  max-height: 140px;
  outline: none;
}
.composer textarea:focus { border-color: var(--ink); }
.composer textarea::placeholder { color: var(--ash); }
.send {
  width: 42px;
  height: 42px;
  flex: 0 0 42px;
  display: grid;
  place-items: center;
  background: var(--ink);
  color: var(--canvas);
  border: none;
  border-radius: 50%;
  cursor: pointer;
  transition: opacity .15s;
}
.send:disabled { opacity: 0.3; cursor: default; }
.send svg { width: 18px; height: 18px; }
.send.stop { background: var(--ink); }
.send.stop svg { width: 14px; height: 14px; }

/* stream control: appears when the reader detaches upward mid-stream */
.chat-jump {
  position: absolute;
  right: 16px;
  bottom: 86px;
  z-index: 6;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--canvas);
  background: var(--ink);
  border: none;
  border-radius: 9999px;
  padding: 8px 12px;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.chat-jump.show { opacity: 1; pointer-events: auto; }

/* ---------- scroll cue (chat-with-me CTA, inside hero-copy) ---------- */
.scroll-cue {
  position: relative;
  z-index: 1;
  margin: 60px auto 0;
  font-family: var(--mono);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--canvas);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  border: none;
  border-radius: 14px;
  background: linear-gradient(180deg, var(--cue-lift), var(--ink) 70%);
  padding: 16px 32px;
  /* keycap CTA (owner pick, cta-pop3 round 3): cap gradient lit from above,
     4px anchored side face + ambient grounding + gloss line; the cap travels
     on press, the base stays put */
  box-shadow: 0 4px 0 var(--cue-side), 0 5px 3px rgba(10, 12, 20, 0.22), inset 0 1px 0 rgba(255, 255, 255, 0.28);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.scroll-cue:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 0 var(--cue-side), 0 7px 4px rgba(10, 12, 20, 0.24), inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
.scroll-cue:active {
  transform: translateY(3px);
  box-shadow: 0 1px 0 var(--cue-side), 0 1px 1px rgba(10, 12, 20, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.15);
}
.scroll-cue .arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 26px;
  height: 26px;
  border-radius: 7px;
  background: rgba(0, 0, 0, 0.22);
  box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.4), inset 0 -1px 0 rgba(255, 255, 255, 0.12);
  transition: transform 0.18s ease;
}
.scroll-cue:hover .arrow { transform: translateY(2px); }
.scroll-cue:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ---------- about ---------- */
#about h2 { font-family: 'Fraunces', serif; font-weight: 400; }
#about .lede { font-family: 'Newsreader', serif; font-size: 19px; line-height: 1.72; color: var(--ink); max-width: 560px; margin-bottom: 4px; }
#about .lede strong { font-weight: 700; }
.about-bottom { margin-top: 32px; }
.about-p { margin-top: 18px; font-family: 'Newsreader', serif; font-size: 18px; line-height: 1.75; text-align: left; color: var(--ink); max-width: 58ch; }
.about-p::first-letter { font-family: 'Fraunces', serif; font-size: 52px; line-height: 0.82; float: left; padding: 4px 8px 0 0; }
.about-photo {
  width: 80%;
  margin: 0 auto;
  height: auto;
  display: block;
  border-radius: 6px; /* owner: near-square corners */
  border: 1px solid var(--rim);
}
/* one duotone treatment for every site photo (about + hobbies dump); shared
   so the tones can never drift apart (owner, e10s06) */
.about-photo, .hb-dump img {
  filter: grayscale(1) sepia(0.28) hue-rotate(195deg) saturate(0.55) contrast(1.1) brightness(1.1);
}

/* ---------- cv (e10s03) ---------- */
.xp-lede { font-family: 'Newsreader', serif; font-size: 18px; line-height: 1.7; color: var(--ink); max-width: 56ch; margin: 0 0 36px; }
.xp-logos { display: flex; align-items: center; justify-content: space-between; gap: 32px; margin: -14px 0 36px; }
.xp-logos img { display: block; filter: brightness(0); opacity: 0.9; }
.xp-logo-w { height: 26px; width: auto; }
.xp-logo-sq { height: 44px; width: auto; }
.xp-list { display: grid; }
.xp { display: grid; grid-template-columns: 132px 1fr; column-gap: 24px; padding: 24px 0; border-top: 1px solid var(--rim); }
.xp-where { font-family: var(--mono); font-size: 12px; line-height: 1.5; color: var(--ash); display: grid; gap: 3px; align-content: start; }
.xp-co { color: var(--ink); }
.xp-now { color: var(--accent); }
.xp-what h3 { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 6px; }
.xp-what p { font-family: 'Newsreader', serif; font-size: 16px; line-height: 1.65; color: var(--fog); max-width: 52ch; }
.xp-edu { margin-top: 8px; padding-top: 24px; border-top: 1px solid var(--rim); font-family: 'Newsreader', serif; font-size: 16px; line-height: 1.65; color: var(--ink); max-width: 56ch; }
.xp-what .xp-stack { margin: 8px 0 0; font-family: var(--mono); font-size: 12px; line-height: 1.6; color: var(--ash); }
.cta-row { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 0; }
.btn-primary {
  font-family: var(--font);
  font-size: 14px;
  font-weight: 600;
  background: var(--ink);
  color: var(--canvas);
  border: none;
  border-radius: var(--r-pill);
  padding: 11px 22px;
  cursor: pointer;
  text-decoration: none;
}
.btn-primary:hover { opacity: 0.9; }
.btn-secondary {
  font-family: var(--font);
  font-size: 14px;
  font-weight: 500;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--rim);
  border-radius: var(--r-pill);
  padding: 10px 22px;
  cursor: pointer;
  text-decoration: none;
}
.btn-secondary:hover { border-color: var(--ink); }

/* ---------- hobbies photo dump (owner: overlap after daniel.pizza) ---------- */
.hb-invite { margin: 0 0 52px; }
.hb-dump { display: flex; flex-wrap: wrap; align-items: flex-start; }
.hb-ph {
  display: block;
  width: 235px;
  height: auto;
  border-radius: 4px;
}
.hb-ph-b { width: 240px; height: auto; margin-left: -28px; margin-top: 56px; }
.hb-ph { cursor: zoom-in; }
.hb-fig {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ash);
  margin: -28px 0 20px;
}

/* ---------- e10s01: scrollytelling shell ---------- */
:root { --rail: 52.5vw; }
main.page { display: block; }
main.page .content {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 24px;
}
main.page .content section {
  padding: 96px 48px 88px 72px;
}
main.page .content .kicker {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ash);
  padding-left: 10px;
  border-left: 2px solid var(--accent);
  margin-bottom: 18px;
}
main.page .content h2 {
  font-size: clamp(28px, 2.5vw, 36px);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.05;
  margin-bottom: 16px;
}

/* chat-revealed sections (e10s03): hidden until an intent triggers them.
   Collapse via grid-rows 0fr -> 1fr so the height animates without knowing
   the content height (same trick as .sug-list). About stays static. Motion
   is integral to the feature, so no reduced-motion gate here (owner). */
main.page .content section.await-reveal {
  display: grid;
  grid-template-rows: 0fr;
  padding: 0;
  opacity: 0;
  transition: grid-template-rows 0.5s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.4s ease;
}
main.page .content section.await-reveal.revealed {
  grid-template-rows: 1fr;
  opacity: 1;
}
main.page .content section.await-reveal > .s-inner {
  overflow: hidden;
  min-height: 0;
  padding: 96px 48px 88px 72px;
}

/* reveal cascade (e10s03): the section expands when the intent event lands,
   but the blocks stay hidden until the glide brings the section into view
   (.anim-in, set by an IntersectionObserver in chat.js), so the visitor
   actually sees them rise. Applies to every reveal section; CV roles
   stagger individually. Motion is integral to the reveal, so no
   reduced-motion gate (owner, e10s02). */
main.page .content section.await-reveal.revealed > .s-inner > * {
  opacity: 0;
}
main.page .content section.await-reveal.anim-in > .s-inner > * {
  animation: rise 0.45s ease both;
}
main.page .content section.await-reveal.anim-in > .s-inner > :nth-child(1) { animation-delay: 0.10s; }
main.page .content section.await-reveal.anim-in > .s-inner > :nth-child(2) { animation-delay: 0.18s; }
main.page .content section.await-reveal.anim-in > .s-inner > :nth-child(3) { animation-delay: 0.26s; }
main.page .content section.await-reveal.anim-in > .s-inner > :nth-child(4) { animation-delay: 0.34s; }
main.page .content section.await-reveal.anim-in > .s-inner > :nth-child(5) { animation-delay: 0.42s; }
main.page .content section.await-reveal.anim-in > .s-inner > :nth-child(6) { animation-delay: 0.50s; }
main.page .content section.await-reveal.revealed .xp-list .xp {
  opacity: 0;
}
main.page .content section.await-reveal.anim-in .xp-list .xp {
  animation: rise 0.45s ease both;
}
main.page .content section.await-reveal.anim-in .xp-list .xp:nth-child(1) { animation-delay: 0.54s; }
main.page .content section.await-reveal.anim-in .xp-list .xp:nth-child(2) { animation-delay: 0.66s; }
main.page .content section.await-reveal.anim-in .xp-list .xp:nth-child(3) { animation-delay: 0.78s; }
main.page .content section.await-reveal.anim-in .xp-list .xp:nth-child(4) { animation-delay: 0.90s; }
@keyframes rise {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* ---------- hero backdrop ---------- */
.hero-bg {
  position: relative;
  height: 100vh;
  overflow: hidden;
}
/* type-led hero copy (Obscura pattern): compact and top-anchored on mobile
   (e10s04), the centered stage version on desktop below */
.hero-copy {
  position: absolute;
  top: clamp(72px, 11vh, 120px);
  left: 0;
  right: 0;
  z-index: 2; /* above the card: identity never sits underneath it */
  text-align: center;
  padding: 0 24px;
}
.hero-copy .kicker {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ash);
  margin-bottom: 10px;
}
.hero-copy h1 {
  font-size: clamp(34px, 9vw, 46px);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.05;
  color: var(--ink);
}
.hero-copy .role {
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--limestone);
  letter-spacing: 0.02em;
}
/* phones: the card is already on screen, the cue would point at it */
.hero-copy .scroll-cue { display: none; }
/* faint dot-grid sky (Browserbase/Lightdash borrow): parallax drift is
   scroll-linked in dock.js — lags behind the page, dissolves with the hero */
.hero-dots {
  position: absolute;
  inset: -30% 0 0 0;
  background-image: radial-gradient(circle, rgba(35, 38, 51, 0.16) 1.2px, transparent 1.3px);
  background-size: 26px 26px;
  -webkit-mask-image: radial-gradient(120% 90% at 50% 30%, #000 40%, transparent 78%);
  mask-image: radial-gradient(120% 90% at 50% 30%, #000 40%, transparent 78%);
  will-change: transform;
}
/* cursor spotlight removed (e10s02): the mouse-following wash made the
   dots flare on move and the owner disliked it on baseline */
@media (min-width: 1024px) {
  .hero-copy {
    display: block;
    position: absolute;
    top: 17vh;
    left: 0;
    right: 0;
    z-index: 2; /* above the peeking card: the CTA must never be half-blocked */
    text-align: center;
    padding: 0 24px;
  }
  .hero-copy .kicker {
    font-family: var(--mono);
    font-size: 13px;
    color: var(--ash);
    margin-bottom: 14px;
  }
  .hero-copy h1 {
    font-size: clamp(48px, 7vw, 88px);
    font-weight: 600;
    letter-spacing: -0.03em;
    line-height: 1.02;
    color: var(--ink);
    text-wrap: balance;
  }
  .hero-copy .role {
    margin-top: 16px;
    font-family: var(--mono);
    font-size: clamp(14px, 1.3vw, 17px);
    color: var(--limestone);
    letter-spacing: 0.02em;
  }
  .hero-copy .scroll-cue { display: inline-flex; }
}
.chat-col {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px 20px 40px;
  z-index: 1;
  pointer-events: none; /* the rail must never swallow hero clicks —
     only the card itself is interactive, everything else falls through */
}
.chat-card { pointer-events: auto; }
.hero-gap { display: none; }
@media (min-width: 1024px) {
  main.page {
    position: relative;
    display: grid;
    grid-template-columns: var(--rail) minmax(0, 1fr);
    align-items: start;
  }
  .hero-bg {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
  }
  .chat-col {
    position: sticky;
    top: 40px;
    height: 100vh;
    padding: 20px 16px;
  }
  .chat-col .chat-card {
    max-height: 100%;
  }
  .hero-gap { display: block; height: 100vh; }
  .content { position: relative; z-index: 1; }
}

/* e10s04 mobile: the chat fills the entire first screen. The card spans
   from under the compact name to the bottom of the viewport (composer in
   thumb reach). Story sections flow below and appear once the card folds
   away to the avatar. */
@media (max-width: 1023px) {
  .hero-bg { height: auto; overflow: visible; }
  .hero-dots { display: none; }
  .hero-copy { position: static; padding: 14px 20px 0; }
  .hero-copy h1 { font-size: 30px; }
  .hero-copy .kicker { font-size: 11px; margin-bottom: 6px; }
  .hero-copy .role { font-size: 11px; margin-top: 4px; }
  .chat-col {
    position: static;
    /* 172px = sticky brand bar + compact name block; the card then spans
       from under the name to the bottom of the viewport */
    height: calc(100svh - 172px);
    padding: 0 16px 12px;
  }
  .chat-card { height: 100%; min-height: 0; max-height: none; }
  .chat-card .thread { max-height: none; }
  /* owner pass (e10s04): the desktop column inset (96/48/88/72) is tuned
     for the rail layout; phones get a symmetric column, matched selector
     for specificity so the override wins the cascade */
  main.page .content section,
  main.page .content section.await-reveal > .s-inner {
    padding: 64px 24px;
  }
  .xp-logos { flex-wrap: wrap; row-gap: 16px; }
}

/* ---------- avatar launcher + chat sheet (e10s04 pattern A) ---------- */
.chat-fab {
  position: fixed;
  right: 16px;
  bottom: calc(14px + env(safe-area-inset-bottom));
  z-index: 30;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  padding: 0;
  cursor: pointer;
  overflow: hidden;
  background: var(--inset);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.28);
  opacity: 0;
  pointer-events: none; /* dock.js's fold owns visibility; tap only when handed over */
}
.chat-fab img { width: 100%; height: 100%; object-fit: cover; display: block; filter: grayscale(0.25) contrast(1.05); }
.chat-fab::after {
  content: "";
  position: absolute;
  right: 1px;
  bottom: 1px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--online);
  border: 2px solid var(--canvas);
}
.chat-fab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.chat-veil {
  position: fixed;
  inset: 0;
  z-index: 38;
  background: rgba(5, 6, 10, 0.55);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}
.chat-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  height: 88%;
  display: flex;
  flex-direction: column;
  background: var(--canvas);
  border: 1px solid var(--rim);
  border-bottom: none;
  border-radius: 22px 22px 0 0;
  transform: translateY(104%);
  transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
  box-shadow: 0 -18px 60px rgba(0, 0, 0, 0.4);
  padding-bottom: env(safe-area-inset-bottom);
}
body.sheet-open { overflow: hidden; }
body.sheet-open .chat-veil { opacity: 1; pointer-events: auto; }
body.sheet-open .chat-sheet { transform: translateY(0); }
.chat-sheet.dragging { transition: none; }
.sheet-top { display: flex; align-items: center; padding: 8px 16px 0; }
.sheet-grip { flex: 1; display: grid; place-items: center; padding: 8px 0; cursor: grab; touch-action: none; }
.sheet-grip i { width: 40px; height: 4px; border-radius: 2px; background: var(--ash); opacity: 0.45; }
.sheet-close {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--rim);
  background: none;
  color: var(--fog);
  font-size: 14px;
  cursor: pointer;
}
.sheet-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.chat-sheet .chat-card {
  flex: 1;
  min-height: 0;
  height: auto;
  max-height: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
}

/* pattern A landing: the arrived card turns into the avatar (face fades in
   over the dissolved chat UI) while staying the visible tap target */
.chat-card.landed > *:not(.fold-avatar) { opacity: 0; transition: opacity 0.3s ease; }
.chat-card.landed .fold-avatar {
  opacity: 1;
  transition: opacity 0.35s ease 0.1s;
  /* card is drawn unsquashed then scaled: widen the bg by the same factor so
     the landed face keeps its proportions (matches object-fit: cover) */
  background-size: 100% calc(100% / var(--avatar-aspect, 0.8275));
}
.fold-avatar {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: url('/assets/images/avatar.jpg');
  background-size: cover;
  background-position: center;
  filter: grayscale(0.25) contrast(1.05);
  opacity: 0;
  pointer-events: none;
}
.fold-avatar::after {
  content: "";
  position: absolute;
  right: 2%;
  bottom: 2%;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--online);
  border: 2px solid var(--canvas);
}

/* desktop keeps the chat docked and visible: none of this exists there */
@media (min-width: 1024px) { .chat-fab, .chat-veil, .chat-sheet { display: none; } }

/* e10s07 email offer: the clone drops a plain Email me button into the
   thread when the visitor wants to reach the human */
.email-row { padding: 2px 0 2px 44px; }
.email-cta {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font);
  font-size: 13px;
  font-weight: 500;
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--rim);
  border-radius: 8px;
  padding: 7px 13px;
  cursor: pointer;
  text-decoration: none;
}
.email-cta:hover { border-color: var(--accent); }
.email-cta svg { width: 14px; height: 14px; flex: none; }

/* e10s04 owner pass: touch ergonomics. 16px composer kills the iOS focus
   zoom; 44px tap floors on the small controls; arrows carry the affordance
   where hover does not exist. */
@media (pointer: coarse), (max-width: 1023px) {
  .composer textarea { font-size: 16px; }
  .suggest-cap { min-height: 44px; }
  .sug { min-height: 44px; }
  .sug .arr { opacity: 1; }
  #theme-toggle { width: 44px; height: 44px; }
  /* e10s04: in-thread suggestion pills (mobile) — the panel is removed by
     chat.js and the chips live under the greeting, scrolling with the chat */
  .suggest { display: none; }
  .sug-strip { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 0 4px 12px; }
  .sug-strip .sug {
    min-height: 0;
    font-size: 12px;
    color: var(--fog);
    background: rgba(255, 255, 255, 0.045);
    border: 1px solid var(--rim);
    border-radius: 9999px;
    padding: 6px 10px;
    justify-content: flex-start;
  }
  .sug-strip .sug .arr { display: none; }
  .sug-strip .sug:active { background: rgba(255, 255, 255, 0.09); }
  /* compact density applies to the card everywhere on phones (hero card
     included — it is the chat surface before the sheet ever opens) */
  .chat-card .chat-head { padding: 6px 16px 8px; }
  .chat-card .chat-head .avatar { width: 28px; height: 28px; flex: 0 0 28px; }
  .chat-card .chat-head strong { font-size: 13px; }
  .chat-card .chat-head span { font-size: 10px; }
  .chat-card .thread { gap: 8px; padding: 12px 14px; }
  .chat-card .row img.avatar { width: 24px; height: 24px; flex: 0 0 24px; }
  .chat-card .row .bubble { font-size: 13.5px; padding: 8px 11px; border-radius: 9px; }
  .chat-card .composer { padding: 8px 14px 12px; }
  .chat-card .composer textarea { padding: 10px 12px; }
  .chat-card .send { width: 40px; height: 40px; flex: 0 0 40px; }
  /* focus ring stays neutral on touch: the caret and keyboard show focus */
  .composer textarea:focus { border-color: var(--rim); }
  .chat-sheet .send { width: 40px; height: 40px; flex: 0 0 40px; }
}

/* ---------- footer ---------- */
footer {
  max-width: 640px;
  margin: 0 auto;
  padding: 24px 24px 56px;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  border-top: 1px solid var(--rim);
}
footer p, footer a { font-family: var(--mono); font-size: 11px; color: var(--ash); text-decoration: none; }
footer a:hover { color: var(--ink); }

/* ---------- streaming ---------- */
.dots { display: inline-flex; gap: 4px; padding: 4px 2px; }
.dots i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ash);
  animation: blink 1.2s infinite;
}
.dots i:nth-child(2) { animation-delay: 0.2s; }
.dots i:nth-child(3) { animation-delay: 0.4s; }
@keyframes blink { 0%, 60%, 100% { opacity: 0.25; } 30% { opacity: 1; } }
.bubble .sources {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ash);
  letter-spacing: 0.01em;
  margin-bottom: 8px;
}
.caret {
  display: inline-block;
  width: 7px;
  height: 14px;
  background: var(--ink);
  margin-left: 2px;
  vertical-align: -2px;
  animation: caret 1s steps(1) infinite;
}
@keyframes caret { 50% { opacity: 0; } }

/* markdown in assistant bubbles */
.bubble p { margin: 0 0 8px; }
.bubble p:last-child { margin-bottom: 0; }
.bubble ul { margin: 4px 0 8px 18px; }
.bubble code {
  font-family: var(--mono);
  font-size: 12.5px;
  background: var(--surface);
  border: 1px solid var(--rim);
  border-radius: 5px;
  padding: 1px 5px;
}
.bubble pre {
  background: var(--ink);
  color: var(--canvas);
  border-radius: 8px;
  padding: 10px 12px;
  overflow-x: auto;
  margin: 4px 0 8px;
}
.bubble pre code { background: none; border: none; padding: 0; color: inherit; }
.bubble a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }

/* ---------- accessibility ---------- */
.send:focus-visible,
.sug:focus-visible,
.suggest-cap:focus-visible,
.chat-head .avatar:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.composer textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 0;
}

@media (prefers-reduced-motion: reduce) {
  html:not(.motion-on) { scroll-behavior: auto; }
  html:not(.motion-on) .chat-card,
  html:not(.motion-on) .sug-list,
  html:not(.motion-on) .suggest-cap .chev,
  html:not(.motion-on) .send,
  html:not(.motion-on) .chat-sheet,
  html:not(.motion-on) .chat-veil,
  html:not(.motion-on) .avatar-pop,
  html:not(.motion-on) .photo-pop,
  html:not(.motion-on) .photo-pop img { transition: none; animation: none; }
  html:not(.motion-on) .dots i,
  html:not(.motion-on) .caret,
  html:not(.motion-on) .scroll-cue .arrow { animation: none; }
}

/* ---------- responsive ---------- */
@media (max-width: 640px) {
  /* card height is governed by the max-width: 1023px stack rule (e10s04) */
  .composer { padding: 10px 12px 14px; }
  .avatar-pop img { width: min(200px, 80vw); height: auto; max-height: 60vh; }
  .xp { grid-template-columns: 1fr; column-gap: 0; row-gap: 8px; }
  .hb-ph { width: 100%; height: auto; margin-left: 0; }
  .hb-ph-b { width: 100%; margin-left: 0; margin-top: 24px; }
}

/* ---------- avatar popover ---------- */
.avatar-pop {
  position: fixed;
  z-index: 100;
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 12px);
  transition: opacity .22s ease, transform .22s ease, visibility .22s;
}
.avatar-pop.open { opacity: 1; visibility: visible; transform: translate(-50%, 0); }
.avatar-pop img {
  width: 200px;
  height: 200px;
  object-fit: cover;
  border-radius: 12px;
  border: 1px solid var(--rim);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.28);
}

/* photo popover (e10s06): hobbies thumbs float a color preview near the
   click, like the avatar pop — deliberately not a full-screen modal */
.photo-pop {
  position: fixed;
  z-index: 200;
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 0);
  transition: opacity .16s ease, visibility .16s;
}
.photo-pop.open { opacity: 1; visibility: visible; }
.photo-pop.open img {
  animation: photo-in .2s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes photo-in {
  from { opacity: 0; transform: scale(0.9); }
  to { opacity: 1; transform: none; }
}
.photo-pop img {
  display: block;
  max-width: min(320px, 82vw);
  max-height: min(420px, 66vh);
  width: auto;
  height: auto;
  border-radius: 4px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.28);
}
