/* ============================================================================
   Emily — site-guide widget
   Tokens from tbg.css only. No :root overrides, no new palette.
   Navy / electric / cyan. NO --emerald (it reads as a status-green in a UI
   surface and belongs to Aperture), NO --amber.
   ---------------------------------------------------------------------------- */

.emily {
  position: fixed;
  right: 20px; bottom: 20px;
  z-index: var(--z-widget);          /* 90 — always BELOW the contact modal at 100 */
  display: flex; flex-direction: column; align-items: flex-end; gap: 12px;
}

/* ---------- ORB ---------- */
.emily__orb {
  position: relative;
  width: 56px; height: 56px;
  border-radius: 50%;
  border: 1px solid var(--tint-cyan-50);
  background: radial-gradient(circle at 38% 34%, var(--tint-cyan-22), var(--void-3) 72%);
  box-shadow: var(--shadow-md);
  display: grid; place-items: center;
  padding: 0;
  transition: transform var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.emily__orb:hover { transform: translateY(-2px); border-color: var(--cyan); }
.emily__orb-core {
  width: 20px; height: 20px; border-radius: 50%;
  background: radial-gradient(circle, var(--cyan-2), var(--electric));
  box-shadow: var(--shadow-glow-cyan);
}
.emily__orb-ring {
  position: absolute; inset: -5px;
  border-radius: 50%;
  border: 1px solid var(--tint-cyan-22);
  animation: emily-breathe 3s ease-in-out infinite;
}
@keyframes emily-breathe {
  0%, 100% { opacity: .55; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.06); }
}
.emily__orb-cap {
  position: absolute; right: calc(100% + 10px); top: 50%;
  transform: translateY(-50%);
  white-space: nowrap;
  font-family: var(--f-mono); font-size: 11px;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-2);
  background: var(--void-2);
  border: 1px solid var(--rule-strong);
  border-radius: 999px;
  padding: 6px 12px;
  opacity: 0;
  animation: emily-cap-in var(--dur-med) var(--ease-out-soft) 2.4s forwards;
}
@keyframes emily-cap-in { to { opacity: 1; } }
.emily[data-open="true"] .emily__orb-cap { display: none; }
.emily[data-open="true"] .emily__orb-ring { animation: none; opacity: 1; border-color: var(--cyan); }

/* ---------- PANEL ---------- */
.emily__panel {
  width: 360px; max-width: calc(100vw - 40px);
  background: var(--void-2);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  display: flex; flex-direction: column;
  order: -1;                          /* panel sits ABOVE the orb */
}
.emily__panel[hidden] { display: none; }

.emily__panel-head {
  display: flex; align-items: center; gap: 8px;
  padding: 14px 14px 12px 18px;
  border-bottom: 1px solid var(--rule);
}
.emily__panel-titles { flex: 1 1 auto; min-width: 0; }
.emily__panel-title { font-size: 15px; font-weight: 500; color: var(--ink); letter-spacing: -.01em; }
.emily__panel-sub {
  font-family: var(--f-mono); font-size: 10.5px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ink-4);
  margin-top: 2px;
}
.emily__icon-btn {
  width: 30px; height: 30px; flex: 0 0 auto;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  color: var(--ink-3);
  display: grid; place-items: center;
  font-size: 12px; line-height: 1;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.emily__icon-btn:hover { border-color: var(--rule-strong); color: var(--ink); }

/* ---------- VIDEO / POSTER ---------- */
.emily__video-wrap {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--void);
  border-bottom: 1px solid var(--rule);
}
.emily__video { width: 100%; height: 100%; object-fit: cover; display: block; }
.emily__video-fallback {
  position: absolute; inset: 0;
  display: none; place-items: center;
  background:
    radial-gradient(ellipse 60% 70% at 50% 55%, var(--tint-cyan-16), transparent 70%),
    var(--void);
}
.emily__fallback-orb {
  width: 46px; height: 46px; border-radius: 50%;
  background: radial-gradient(circle at 40% 36%, var(--cyan-2), var(--electric));
  box-shadow: var(--shadow-glow-cyan);
  animation: emily-breathe 3s ease-in-out infinite;
}
/* text-only mode: no clip file yet, or playback refused. Fully functional. */
.emily[data-video="off"] .emily__video { display: none; }
.emily[data-video="off"] .emily__video-fallback { display: grid; }

/* ---------- CAPTIONS (always on — never a toggle) ---------- */
.emily__captions {
  padding: 14px 18px;
  font-size: 15px; line-height: 1.5;
  color: var(--ink);
  min-height: 62px;
  border-bottom: 1px solid var(--rule);
}
.emily__captions[data-partial="true"] { color: var(--ink-3); font-style: italic; }
.emily__captions:empty::before { content: '…'; color: var(--ink-4); }

/* ---------- CHIPS ---------- */
.emily__chip-row {
  display: flex; gap: 8px;
  padding: 12px 18px;
  overflow-x: auto; scrollbar-width: none;
  border-bottom: 1px solid var(--rule);
}
.emily__chip-row::-webkit-scrollbar { display: none; }
.emily__chip-row[hidden] { display: none; }
.emily-chip {
  flex: 0 0 auto;
  padding: 7px 14px;
  background: transparent;
  border: 1px solid var(--rule-strong);
  border-radius: 999px;
  font-size: 12.5px; color: var(--ink-2);
  white-space: nowrap;
  transition: all var(--dur-fast) var(--ease);
}
.emily-chip:hover { border-color: var(--electric); background: var(--tint-electric-08); color: var(--ink); }

/* ---------- FOOT ---------- */
.emily__panel-foot { display: flex; align-items: center; gap: 8px; padding: 12px 14px 14px 18px; }
.emily__form { flex: 1 1 auto; display: flex; gap: 6px; min-width: 0; }
.emily__input {
  flex: 1 1 auto; min-width: 0;
  background: var(--void-3);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  padding: 9px 12px;
  color: var(--ink);
  font-family: var(--f-body); font-size: 13.5px;
}
.emily__input:focus { outline: none; border-color: var(--electric); box-shadow: 0 0 0 3px var(--tint-electric-16); }
.emily__send, .emily__mic {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  color: var(--ink-3);
  display: grid; place-items: center;
  font-size: 13px;
  transition: all var(--dur-fast) var(--ease);
}
.emily__send:hover, .emily__mic:hover { border-color: var(--electric); color: var(--ink); }
.emily__mic[aria-pressed="true"] { border-color: var(--cyan); color: var(--cyan); box-shadow: 0 0 0 3px var(--tint-cyan-16); }
.emily__mic[hidden] { display: none; }
.emily__handoff {
  flex: 0 0 auto;
  background: transparent;
  border: 0;
  color: var(--ink-4);
  font-size: 11.5px;
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: 0 2px;
}
.emily__handoff:hover { color: var(--cyan); }

/* state cue that is NOT colour — a11y */
.emily[data-mode="listening"]   .emily__panel-sub::before,
.emily[data-mode="near-miss"]   .emily__panel-sub::before,
.emily[data-mode="no-match"]    .emily__panel-sub::before,
.emily[data-mode="handoff"]     .emily__panel-sub::before { margin-right: 6px; }
.emily[data-mode="listening"] .emily__panel-sub::before { content: '●'; color: var(--cyan); }
.emily[data-mode="near-miss"] .emily__panel-sub::before,
.emily[data-mode="no-match"]  .emily__panel-sub::before { content: '?'; }
.emily[data-mode="handoff"]   .emily__panel-sub::before { content: '→'; }

/* ---------- MOBILE — bottom sheet ---------- */
@media (max-width: 819px) {
  /* 88px keeps a full orb clear of a browser bottom bar and of any
     page-bottom Contact CTA */
  .emily { right: 16px; bottom: 88px; }
  .emily__panel {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    width: 100vw; max-width: 100vw;
    height: 78dvh;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    border-left: 0; border-right: 0; border-bottom: 0;
  }
  .emily__video-wrap { flex: 0 0 auto; }
  .emily__captions { flex: 1 1 auto; overflow-y: auto; }
}
@media (max-width: 480px) {
  .emily__chip-row { flex-wrap: wrap; overflow-x: visible; }
}

/* ---------- REDUCED MOTION ---------- */
@media (prefers-reduced-motion: reduce) {
  .emily__orb-ring, .emily__fallback-orb { animation: none; opacity: 1; transform: none; }
  .emily__orb-cap { animation: none; opacity: 1; }
  .emily__orb:hover { transform: none; }
}

/* ---------- FORCED COLORS ---------- */
@media (forced-colors: active) {
  .emily__panel, .emily__orb, .emily-chip { border-color: currentColor; }
}

/* ============================================================================
   P5 — AMBASSADOR UPGRADE (2026-09-03)
   Guided tour, boardroom demo, and the avatar presentation that replaces the
   placeholder orb. Class names are Simon's registry (P2c §11.2) verbatim.
   Tokens only — nothing below introduces a colour, radius, shadow or duration
   that tbg.css does not already define. Navy / electric / cyan. No gold.
   Every rule here is ADDITIVE: no shipped selector above is redefined.
   ---------------------------------------------------------------------------- */

/* ---------- VIDEO HOOD — still + video + vignette in one stacking context ---- */
.emily__video-hood {
  position: relative;
  aspect-ratio: 4 / 5;
  background: var(--void);
  border-bottom: 1px solid var(--rule);
  overflow: hidden;
}
/* The hood owns the aspect now; the shipped wrap fills it rather than
   imposing a second, conflicting ratio. */
.emily__video-hood .emily__video-wrap {
  position: absolute; inset: 0;
  aspect-ratio: auto;
  border-bottom: 0;
  background: transparent;
}
.emily__still {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  opacity: 1;
  transition: opacity var(--dur-med) var(--ease-out-soft);
}
/* She is speaking: the video is the presentation, the still steps behind it. */
.emily[data-vstate="speaking"] .emily__still { opacity: 0; }

.emily__video-vignette {
  position: absolute; inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 40px var(--tint-cyan-16);
  transition: box-shadow var(--dur-med) var(--ease);
}
.emily[data-vstate="speaking"]  .emily__video-vignette { box-shadow: inset 0 0 40px var(--tint-cyan-08); }
.emily[data-vstate="listening"] .emily__video-vignette { box-shadow: inset 0 0 44px var(--tint-cyan-22); }
.emily[data-vstate="thinking"]  .emily__video-vignette { box-shadow: inset 0 0 40px var(--tint-electric-16); }

/* ---------- CAPTION CUES ---------- */
/* Weight only — never a colour change, so the highlight survives forced
   colours and does not cost contrast. */
.emily__cue { transition: opacity var(--dur-fast) var(--ease); opacity: .68; }
.emily__cue--active { opacity: 1; font-weight: 500; }

/* ---------- CHIPS AT THE LARGER SCALE ---------- */
.emily-chip--primary {
  border-color: var(--electric);
  background: var(--tint-electric-08);
  color: var(--ink);
}
.emily-chip--primary:hover { background: var(--tint-electric-16); border-color: var(--electric-2); }
.emily__chip-row--overflow {
  -webkit-mask-image: linear-gradient(to right, #000 88%, transparent 100%);
          mask-image: linear-gradient(to right, #000 88%, transparent 100%);
}

/* ---------- TOUR BAR ---------- */
.emily__tour-bar {
  padding: 10px 18px 8px;
  border-bottom: 1px solid var(--rule);
  background: var(--void-3);
}
.emily__tour-bar[hidden] { display: none; }
.emily__tour-dots { display: flex; gap: 5px; align-items: center; }
.emily__tour-dot {
  width: 100%; height: 3px;
  flex: 1 1 auto;
  border-radius: 999px;
  background: var(--rule-strong);
  transition: background var(--dur-fast) var(--ease);
}
.emily__tour-dot--visited { background: var(--tint-cyan-50); }
.emily__tour-dot--current { background: var(--cyan); box-shadow: var(--shadow-glow-cyan); }
.emily__tour-label {
  margin-top: 7px;
  font-family: var(--f-mono); font-size: 10.5px;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-4);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ---------- TOUR CONTROLS (mutually exclusive with the chip row) ---------- */
.emily__tour-controls {
  display: flex; gap: 8px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--rule);
}
.emily__tour-controls[hidden] { display: none; }
.emily__tour-btn {
  flex: 1 1 auto;
  padding: 8px 10px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  color: var(--ink-3);
  font-family: var(--f-mono); font-size: 11px;
  letter-spacing: .12em; text-transform: uppercase;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.emily__tour-btn:hover { border-color: var(--electric); color: var(--ink); }

/* ---------- PAGE-LEVEL STOP RIBBON ---------- */
.emily__stop-ribbon {
  position: absolute; left: 0; top: 0;
  display: flex; align-items: center; gap: 10px;
  padding: 6px 12px 6px 0;
  pointer-events: none;
  animation: emily-ribbon-in var(--dur-med) var(--ease-out-soft);
}
.emily__stop-ribbon-mark {
  width: 3px; height: 22px;
  border-radius: 999px;
  background: var(--cyan);
  box-shadow: var(--shadow-glow-cyan);
}
.emily__stop-ribbon-label {
  font-family: var(--f-mono); font-size: 10px;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--cyan);
}
@keyframes emily-ribbon-in { from { opacity: 0; } to { opacity: 1; } }

/* ---------- BOARDROOM DEMO TETHER (boardroom.html only) ---------- */
.emily__demo-tether {
  position: fixed;
  right: 46px; bottom: 96px;
  width: 1px; height: 22vh;
  z-index: var(--z-widget);
  pointer-events: none;
  background: linear-gradient(to top, var(--cyan), transparent);
  opacity: .55;
  animation: emily-tether-in var(--dur-slow) var(--ease-out-soft);
}
@keyframes emily-tether-in { from { opacity: 0; } to { opacity: .55; } }

/* ---------- PANEL SIZE VARIANTS ---------- */
.emily--tour .emily__panel,
.emily--demo .emily__panel { width: 384px; }
.emily--watch .emily__panel { width: 480px; }
/* The demo narrates a console that sits to the right; she moves left so she is
   not standing on top of the thing she is describing. */
@media (min-width: 1100px) {
  .emily--demo { right: auto; left: 20px; align-items: flex-start; }
  .emily--demo .emily__demo-tether { right: auto; left: 46px; }
}

/* ---------- MOBILE ---------- */
@media (max-width: 819px) {
  /* A 4:5 portrait plus a tour bar plus controls does not fit a phone
     alongside the caption; cap the hood so the caption keeps the room. */
  .emily__video-hood { aspect-ratio: 5 / 4; max-height: 34dvh; }
  .emily--demo { right: 16px; left: auto; align-items: flex-end; }
  .emily__demo-tether { display: none; }
  .emily__tour-label { font-size: 10px; }
}

/* ---------- REDUCED MOTION ---------- */
@media (prefers-reduced-motion: reduce) {
  .emily__still,
  .emily__video-vignette,
  .emily__cue { transition: none; }
  .emily__stop-ribbon,
  .emily__demo-tether { animation: none; }
}

/* ---------- FORCED COLORS ---------- */
@media (forced-colors: active) {
  .emily__tour-btn,
  .emily__video-hood { border-color: currentColor; }
  .emily__tour-dot--current { background: Highlight; }
  .emily__stop-ribbon-mark { background: Highlight; }
  .emily__cue--active { font-weight: 700; }
}

/* ---------- DOCK (the default corner presentation) ---------- */
.emily--dock .emily__panel { width: 384px; }

/* ---------- OPEN / CLOSE TRANSITION ----------
   Transient only: emily.js removes this class within --dur-med, so a panel can
   never be left mid-fade by a later state change. */
.emily--transitioning .emily__panel {
  animation: emily-panel-in var(--dur-med) var(--ease-out-soft);
}
@keyframes emily-panel-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .emily--transitioning .emily__panel { animation: none; }
}

/* ============================================================================
   FRAMING FIX — 2026-09-03 (Joe: "she gets cutoff at the top ... make it all
   fit properly in the window ... maybe show less of Emily's lower body")
   TWO causes, both real, both fixed here. Additive only — nothing above is
   redefined, and tbg.css is untouched.

   CAUSE 1 — the panel had NO height bound on desktop. Hood 4:5 at 360px wide
   is 450px, plus head + captions + chips + foot is ~665px of panel. The panel
   is bottom-anchored, so on a short window it grew off the TOP of the viewport
   and the first thing clipped was her head.

   CAUSE 2 — the clips are 1536x1024 LANDSCAPE, framed head-to-waist with only
   ~4% headroom above her hair. Any centred crop therefore eats her scalp
   before it eats anything else. The media is now TOP-ANCHORED, so every crop
   is taken off the BOTTOM. Her head can no longer be cut, at any window size.
   ---------------------------------------------------------------------------- */

/* --- 2 — top-anchored, oversized. Applies at every width. -------------------
   width:150% zooms past `cover` into a real head-and-shoulders (a plain cover
   fit cannot crop tighter than the source framing, which is head-to-waist).
   Chosen by rendering the 1.3x / 1.5x / 1.8x crops from a real clip frame and
   comparing them; 1.5x keeps visible headroom, 1.8x did not. */
.emily__video-hood .emily__video,
.emily__video-hood .emily__still {
  position: absolute;
  top: 0; left: 50%;
  width: 150%;
  height: auto;
  min-height: 100%;
  transform: translateX(-50%);
  object-fit: cover;
  object-position: 50% 0;
}

/* --- 1 — desktop: bind the panel to the window and let the caption yield. --- */
@media (min-width: 820px) {
  /* orb 56 + gap 12 + bottom 20 = 88 of furniture, plus a 32px top margin. */
  .emily__panel { max-height: calc(100dvh - 120px); }

  /* 3:2 returns ~210px to the panel vs the old 4:5. The hood may shrink as a
     last resort — and because the media is top-anchored, shrinking it only
     ever trims her torso. */
  .emily__video-hood { aspect-ratio: 3 / 2; max-height: 32dvh; flex: 0 1 auto; min-height: 120px; }

  /* The captions are what gives way when the window is short, not the video. */
  .emily__captions { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
}
