/* ==========================================================================
   Expanded conversation mode — the large immersive window that appears to
   grow out of the compact monitor. Reuses the site's existing menu-panel
   tokens (tokens.css) rather than inventing a new palette, so it reads as
   the same dark-violet surface language as the rest of the chat card.
   ========================================================================== */

/* --- Trigger + always-measurable frame, positioned over the monitor ---- */

.hero-chat__screen-frame {
  position: absolute;
  top: 24.973%;
  left: 32.237%;
  width: 40.550%;
  height: 41.233%;
  /* Never steals a click from the screen itself (scroll, citation links) —
     only the button inside opts back in. */
  pointer-events: none;
  z-index: 3;
  /* Real bug found via testing (screenshot from a real phone): the
     expand/discussion buttons' own cqw-based sizing (see
     .hero-chat__expand-btn below) used to measure against
     .hero-chat__image's full width — but that's the whole desk-photo
     card, not the monitor screen these buttons actually sit over, which
     is only ~40% of it (see the width above). On a small card the
     buttons stayed proportionate to the CARD but ended up looking huge
     next to the much-smaller monitor/avatar they're anchored to.
     Establishing the container here instead means cqw now tracks this
     frame's own real rendered width — the thing the buttons are actually
     scaled relative to. */
  container-type: inline-size;
  /* Hidden until the avatar's own CRT power-on reveal (.is-on, toggled
     by hero-avatar.js alongside the canvas's is-ready, or by
     hero-chat.js's safety backstop on a load failure) — the expand/
     discussion icons over an empty, not-yet-revealed screen would be
     controls for nothing. Stays in the DOM and stays measurable
     (opacity, not display) the whole time either way — see the comment
     above this element in index.njk about why that matters. Delayed to
     1.05s so the icons only fade in once the vertical opening has
     essentially finished (per design direction: "uniquement lorsque
     l'image est presque totalement ouverte") rather than popping in
     alongside the very first spark. The canvas's own vertical opening
     runs 0.85–1.2s, so 1.15s lands right as it's nearly done, finishing
     visible by 1.45s — the same moment the whole overlay sequence ends. */
  opacity: 0;
  transition: opacity 0.3s ease 1.15s;
}

.hero-chat__screen-frame.is-on {
  opacity: 1;
}

.hero-chat__screen-frame:not(.is-on) .hero-chat__expand-btn {
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .hero-chat__screen-frame {
    transition: none;
  }
}

.hero-chat__expand-btn {
  /* Real bug found via testing: fixed at 44px regardless of how big the
     monitor screen these buttons sit over (.hero-chat__screen-frame,
     container-type set there) actually renders — proportionally huge on
     a small card's tiny monitor, proportionally tiny on a large one.
     cqw tracks the screen-frame's own real rendered width instead (same
     technique already used for .hero-chat__terminal's text), clamped
     between a floor that still reads clearly on the smallest phone card
     and the original 44px as a ceiling so it never grows past its old
     size on a big screen. Values recalibrated against real measured
     screen-frame widths (~115px on a phone card up to ~345px on an
     ultrawide desktop one) after the first version — tuned against the
     whole card instead of this frame — still measured out to a
     proportionally huge icon on a real phone screenshot. */
  --expand-btn-size: clamp(24px, 21cqw, 44px);
  pointer-events: auto;
  position: absolute;
  top: 0;
  right: 0;
  width: var(--expand-btn-size);
  height: var(--expand-btn-size);
  display: grid;
  place-items: center;
  border: 0;
  background: transparent;
  cursor: pointer;
  color: rgba(238, 241, 248, 0.72);
}

.hero-chat__expand-btn::before {
  content: "";
  position: absolute;
  inset: 16%;
  border-radius: 50%;
  background: rgba(10, 8, 16, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.14);
  backdrop-filter: blur(4px);
  opacity: 0.55;
  transition: opacity 0.18s ease, background 0.18s ease;
}

/* Invisible hit-slop: below the 44px floor this button used to sit at,
   the VISUAL circle shrinks with the card (::before above), but the
   actual tap target never should — this pseudo-element extends the real
   tap target a little past the button's own rendered size, exactly like
   the settings panel's own close/back buttons (hero.css). Sized relative
   to --expand-btn-size (+8px in each dimension) rather than a fixed
   44x44 — real bug found via testing: this button and
   --discussion sit only 8px apart (see .hero-chat__expand-btn--discussion
   below), so a FIXED 44px slop centered on each started overlapping the
   other's the smaller --expand-btn-size got, meaning a tap right between
   them could land on the wrong one. +8px on each side exactly meets the
   other button's own slop at the midpoint of that 8px gap — never
   overlapping, whatever size the buttons currently are. */
.hero-chat__expand-btn::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: calc(var(--expand-btn-size) + 8px);
  height: calc(var(--expand-btn-size) + 8px);
  transform: translate(-50%, -50%);
}

.hero-chat__expand-btn svg {
  position: relative;
  width: 36%;
  height: 36%;
}

.hero-chat__image:hover .hero-chat__expand-btn::before,
.hero-chat__expand-btn:hover::before,
.hero-chat__expand-btn:focus-visible::before {
  opacity: 1;
  background: rgba(184, 107, 248, 0.28);
}

@media (hover: none) {
  .hero-chat__expand-btn::before {
    opacity: 0.9;
  }
}

.hero-chat__expand-btn:focus-visible {
  outline: 2px solid #b86bf8;
  outline-offset: -2px;
  border-radius: 50%;
}

@media (max-width: 639px) {
  .hero-chat__expand-btn {
    top: -6px;
    right: -6px;
  }
}

/* Second entry point directly below the expand button — same circular
   language, same size (--expand-btn-size, matching .hero-chat__expand-btn
   exactly since it's the same element/variable, no longer a smaller
   variant), opens straight into the expanded view with the discussion
   panel already showing. Offset is relative to the expand button's own
   (now responsive) size + a fixed gap, rather than a fixed 52px, so the
   two stay evenly spaced at every card size instead of drifting apart or
   overlapping as --expand-btn-size shrinks/grows. */
.hero-chat__expand-btn--discussion {
  top: calc(var(--expand-btn-size) + 8px);
}

@media (max-width: 639px) {
  .hero-chat__expand-btn--discussion {
    top: calc(var(--expand-btn-size) + 2px);
    right: -6px;
  }
}

.hero-chat__expand-hint {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  max-width: 180px;
  padding: 6px 10px;
  border-radius: 8px;
  background: rgba(10, 8, 16, 0.85);
  border: 1px solid rgba(184, 107, 248, 0.3);
  color: rgba(238, 241, 248, 0.85);
  font-family: var(--font-satoshi);
  font-size: 11px;
  line-height: 1.35;
  pointer-events: none;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.25s ease, transform 0.25s ease;
}

.hero-chat__expand-hint.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.hero-chat__expand-hint[hidden] {
  display: none;
}

/* --- The modal stage -----------------------------------------------------
   Was previously a full "monitor" hardware assembly (shell + bezel + chin
   with logo/LED + neck + base + a gradient signature ring) — removed per
   explicit direction: it read as heavy/gimmicky, not like a real premium
   product. Now just the application itself, in a normal rounded panel —
   small corner radius, no chrome, no framing pretending to be a physical
   screen. The FLIP-from-the-compact-screen open/close animation is
   unchanged; only what it animates TO changed. `monitor-assembly`/
   `monitor-shell` class names and data-attributes are kept as-is (they're
   only ever used as internal hooks by hero-chat-expanded.js, never
   visible), so none of the FLIP/JS logic needed to change. -------------- */

.hero-chat__expanded {
  --hc-x-w: min(84vw, 1400px);
  --hc-x-h: min(86vh, 900px);
  --hc-x-radius: 16px;
  --hc-x-bubble-max: 70%;
  /* The conversation column's own reading width — adaptive up to
     820-1100px per spec on a wide enough window, never the full window
     width even on an ultra-wide monitor (which would make lines
     uncomfortably long). No hard minimum here on purpose: the shell
     itself can be narrower than 820px at some breakpoints (tablet), and
     a forced minimum would overflow it horizontally — min(92%, ...)
     shrinks gracefully with the shell instead. */
  --hc-x-content-max: min(92%, clamp(820px, 62vw, 1100px));
  /* The composer deliberately gets its OWN, much wider max-width than the
     thread's reading-width cap above — real gap found via testing: they
     used to share --hc-x-content-max, leaving large empty margins on
     both sides of the composer on a wide desktop window even though nothing
     about a single-line input needs the same narrow measure a paragraph
     of prose does. */
  --hc-x-composer-max: 1200px;
  --hc-x-vv-h: 100dvh;
  --hc-x-vv-top: 0px;
  position: fixed;
  inset: 0;
  /* Above .site-header (hero.css: z-index 998/999) and everything else on
     the page — confirmed necessary directly: without this the header's
     own nav bar visually painted over the modal and intercepted clicks
     meant for the close button despite sitting behind it in the DOM. */
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hero-chat__expanded[hidden] {
  display: none;
}

.hero-chat__expanded-scrim {
  position: absolute;
  inset: 0;
  /* Deeper black/aubergine + a real 10-16px blur (was 3px, read as a thin
     haze rather than the site genuinely receding behind glass) — the rest
     of the page must still be visible, just clearly behind this window. */
  background: radial-gradient(120% 100% at 50% 0%, rgba(20, 8, 28, 0.78), rgba(4, 2, 8, 0.88));
  backdrop-filter: blur(13px) saturate(0.85);
  opacity: 0;
}

.hero-chat__expanded-ghost {
  position: fixed;
  background: linear-gradient(150deg, #201f28, #0a090d);
  border: 1px solid rgba(120, 150, 255, 0.22);
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.5);
  pointer-events: none;
  z-index: 2;
}

.hero-chat__expanded-ghost[hidden] {
  display: none;
}

/* --- Monitor assembly ---------------------------------------------------
   A plain flex column: shell (bezel+chin) stacked above neck, stacked
   above base. Centering the WHOLE assembly (not just the shell) in the
   flex stage is what naturally leaves the shell sitting a little above
   true viewport center once the foot's own height is added underneath
   it — no manual vertical offset math needed. */
.hero-chat__monitor-assembly {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  z-index: 3;
}

/* A soft ambient halo behind the whole assembly, plus a faint colored
   reflection pooling low and wide (as if the monitor's own light were
   catching the desk under it) — never a hard neon ring, just enough to
   separate the monitor from the blurred site behind it. */
.hero-chat__monitor-assembly::before {
  content: "";
  position: absolute;
  inset: -10% -8%;
  background:
    radial-gradient(58% 50% at 50% 34%, rgba(140, 110, 255, 0.17), rgba(120, 150, 255, 0) 70%),
    radial-gradient(70% 30% at 50% 96%, rgba(168, 102, 240, 0.1), rgba(168, 102, 240, 0) 75%);
  filter: blur(32px);
  pointer-events: none;
  z-index: -1;
}

.hero-chat__monitor-shell {
  position: relative;
  width: var(--hc-x-w);
  height: var(--hc-x-h);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  border-radius: var(--hc-x-radius);
  border: 1px solid rgba(255, 255, 255, 0.09);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5), 0 8px 24px rgba(0, 0, 0, 0.35);
  overflow: hidden;
  opacity: 0;
}

/* The dalle itself — recessed one layer inside the bezel's own padding,
   a distinct (slightly less rounded) radius from the shell's outer one
   so it visibly reads as "set into" the bezel rather than flush with it.
   Near-black with a faint violet cast, a soft top vignette (like a real
   panel's own backlight falloff), an inner rim glow, and its own inset
   shadow for depth — never the site's shared dropdown-menu tokens. */
/* "Midnight" surface — real bug found via testing: a flat near-black fill
   read as an "immense surface noire presque vide" the instant the thread
   had few/no messages, since nothing in the background itself gave any
   sense of depth. Five layers, back to front: a fine dot/constellation
   grid (barely-there, never competing with text contrast), a soft violet
   halo pooling behind where the conversation actually sits, a corner
   vignette, the base near-black-violet gradient, and (via ::before,
   z-index below the real content) an ultra-low-opacity grain texture —
   all of it decorative, none of it ever reduces bubble/text contrast. */
.hero-chat__expanded-window {
  position: relative;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  display: grid;
  grid-template-rows: auto 1fr auto;
  border-radius: inherit;
  background:
    radial-gradient(1px 1px at 20px 20px, rgba(255, 255, 255, 0.045) 1px, transparent 1.5px),
    radial-gradient(1px 1px at 20px 20px, rgba(255, 255, 255, 0.045) 1px, transparent 1.5px),
    radial-gradient(46% 40% at 50% 30%, rgba(90, 80, 150, 0.15), rgba(90, 80, 150, 0) 68%),
    radial-gradient(120% 85% at 50% -8%, rgba(70, 60, 110, 0.16), rgba(70, 60, 110, 0) 55%),
    radial-gradient(140% 110% at 50% 50%, transparent 55%, rgba(0, 0, 0, 0.32) 100%),
    linear-gradient(175deg, #08070e 0%, #0d0916 46%, #07070c 100%);
  background-size: 44px 44px, 44px 44px, 100% 100%, 100% 100%, 100% 100%, 100% 100%;
  background-position: 0 0, 22px 22px, 0 0, 0 0, 0 0, 0 0;
  box-shadow:
    inset 0 0 0 1px rgba(130, 170, 255, 0.14),
    inset 0 2px 22px rgba(0, 0, 0, 0.65),
    inset 0 0 40px rgba(0, 0, 0, 0.35);
  overflow: hidden;
  opacity: 0;
}

.hero-chat__expanded-window::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, rgba(255, 255, 255, 0.035) 0%, rgba(255, 255, 255, 0) 20%, rgba(255, 255, 255, 0) 82%, rgba(140, 170, 255, 0.03) 100%);
  pointer-events: none;
  /* Behind the real header/thread/composer content (all normal-flow,
     non-positioned grid children — this only needs to sit above the
     window's own background, never above the UI itself). */
  z-index: -1;
}

/* --- Header -------------------------------------------------------------- */

.hero-chat__expanded-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 14px;
  /* Real bug found via testing at 375px: as a grid row inside
     .hero-chat__expanded-window, this defaults to min-width:auto like any
     grid/flex item — which blocks it from ever shrinking below its
     content's own natural width, silently overflowing the shell (which
     clips via overflow:hidden) and cutting the collapse button off past
     the visible edge entirely, invisible with no visual warning. min-
     width:0 is what actually lets it respect the grid track's real
     available width so its own flex children (identity text, min-width:0
     + ellipsis below) can do their job shrinking first. */
  min-width: 0;
  /* Finer, more like a monitor's own OSD strip than an app title bar —
     the 44px action buttons still fit with real breathing room (they
     center within the row via align-items, never forcing the header
     itself to grow to their size). */
  height: 54px;
  flex-shrink: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  background: transparent;
}

.hero-chat__expanded-identity {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.hero-chat__expanded-identity-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

/* Mini avatar badge — the site's own brand mark, standing in for "Avatar
   de Yacine" the way a small profile picture would in any chat header.
   The existing online status-dot (hero.css) is repositioned to overlap
   its bottom-right corner instead of floating alone before the text. */
.hero-chat__expanded-badge {
  position: relative;
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  overflow: visible;
}

.hero-chat__expanded-badge img {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.12);
}

.hero-chat__expanded-badge .hero-chat__status-dot {
  position: absolute;
  right: -1px;
  bottom: -1px;
  /* Matches .hero-chat__expanded-window's own dark background (the
     header itself is transparent) so the dot reads as cut into the
     badge rather than floating over it. */
  box-shadow: 0 0 0 2px #0a0810, 0 0 6px #2ecc71;
}

.hero-chat__expanded-title {
  font-family: var(--font-satoshi);
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hero-chat__expanded-subtitle {
  font-family: var(--font-satoshi);
  font-size: 11px;
  color: rgba(238, 241, 248, 0.42);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hero-chat__expanded-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
}

.hero-chat__expanded-action {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border: none;
  background: transparent;
  border-radius: 50%;
  color: rgba(238, 241, 248, 0.72);
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease;
}

.hero-chat__expanded-action:hover {
  background: rgba(184, 107, 248, 0.16);
  color: #d9b8ff;
}

.hero-chat__expanded-action:focus-visible {
  outline: 2px solid #b86bf8;
  outline-offset: -2px;
}

/* The discussion toggle carries a visible label (unlike the icon-only
   settings/collapse buttons) — it's the one control that changes what's
   on screen in a way worth naming, not just window chrome. Real bug found
   via testing: it inherited `display:grid;place-items:center` from the
   base .hero-chat__expanded-action rule above, which — with two children
   (icon + label) and no explicit grid-template — auto-placed them on
   separate implicit ROWS (grid-auto-flow's default), stacking the icon
   above the label instead of putting them side by side. Explicit
   `display:inline-flex` + `flex-direction:row` overrides that. */
.hero-chat__expanded-action--discussion {
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  width: auto;
  height: 40px;
  padding: 0 16px 0 13px;
  gap: 7px;
  border-radius: 999px;
  border: 1px solid rgba(184, 107, 248, 0.22);
  background: rgba(184, 107, 248, 0.08);
  font-family: var(--font-satoshi);
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.hero-chat__expanded-action--discussion svg {
  flex-shrink: 0;
}

.hero-chat__expanded-action--discussion:hover {
  background: linear-gradient(120deg, rgba(63, 123, 248, 0.28), rgba(168, 102, 240, 0.28), rgba(248, 107, 184, 0.24));
  border-color: rgba(217, 184, 255, 0.5);
  color: #fff;
}

.hero-chat__expanded-action--discussion[aria-expanded="true"] {
  background: linear-gradient(120deg, rgba(63, 123, 248, 0.32), rgba(168, 102, 240, 0.32), rgba(248, 107, 184, 0.26));
  border-color: rgba(217, 184, 255, 0.55);
  color: #fff;
}

/* Icon-only fallback — only at the one breakpoint where the full pill
   genuinely doesn't fit next to the settings/collapse buttons in the
   header's own available width (measured against the real 320px case,
   see the resize test matrix), never a default. */
@media (max-width: 360px) {
  .hero-chat__expanded-action--discussion .hero-chat__expanded-action-label {
    display: none;
  }
  .hero-chat__expanded-action--discussion {
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 50%;
  }
}

/* --- Body: avatar stage + floating zoom controls + a thread panel -------
   The body is a real flex row: on desktop the panel is a genuine flex
   sibling with an animated WIDTH (not a transform overlay), so opening it
   actually shrinks the avatar stage's own box — the ResizeObserver in
   hero-avatar.js (see hero-avatar.js's `applyResize`) picks up every
   intermediate frame of that width transition and keeps the renderer/
   camera in sync with it continuously, which is what makes the avatar
   recenter smoothly in the remaining space instead of staying centered
   on the old, wider box or jumping. On mobile there isn't room for a real
   side-by-side split, so the panel reverts to a full-width overlay there
   (see the max-width:699px rules below) and the avatar stage keeps its
   full box the whole time. ------------------------------------------- */

.hero-chat__expanded-body {
  position: relative;
  display: flex;
  flex-direction: row;
  min-height: 0;
  overflow: hidden;
}

/* Receives the same <canvas> physically moved from the compact screen
   (hero-chat.js/hero-chat-expanded.js) — now the primary content of the
   expanded view (full body, avatar-only by default, matching the
   reference project's own look), not a strip above a text thread any
   more. Same sunset wallpaper as the IAcine avatar project's own index.css
   body background — this is the one place in the app meant to feel like
   an actual "stage", not app chrome. flex:1 + min-width:0 is what lets
   this box genuinely shrink when the thread panel takes real flex width
   next to it (min-width:0 overrides a flex item's default min-width:auto,
   which would otherwise refuse to shrink past the avatar canvas's own
   intrinsic size). */
.hero-chat__expanded-avatar-stage {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  background: linear-gradient(19deg, #ff7e5f 0%, #feb47b 50%, #6a3093 100%);
  /* Contains the floor grid's tilted plane below — a sibling element
     (.hero-chat__expanded-zoom) sits outside this box entirely, so this
     never risks clipping the floating zoom controls. */
  overflow: hidden;
}

/* The flat, tilted CSS floor grid that used to live here is gone —
   replaced by a real Three.js floor plane in the scene itself
   (hero-avatar.js's createFloorGrid), which the SAME canvas already
   shows since it's the one physically moved into this stage. It orbits
   with the camera and reads correctly from below, unlike this overlay
   ever could. */

.hero-chat__expanded-avatar-stage .hero-chat__avatar-canvas {
  /* Static positioning + pointer-events here always apply once the canvas
     is physically moved into this stage. Opacity is deliberately NOT
     force-set to 1 here — the compact screen's own is-ready gate
     (hero.css) still applies even inside the expanded stage, so a T-pose/
     A-pose can't flash here either in the (rare) case the modal is opened
     before the GLB has finished loading. Cursor hints at the drag-to-
     look-around interaction (OrbitControls, see hero-avatar.js). */
  position: static;
  pointer-events: auto;
  cursor: grab;
}

.hero-chat__expanded-avatar-stage .hero-chat__avatar-canvas.is-ready {
  opacity: 1;
}

.hero-chat__expanded-avatar-stage .hero-chat__avatar-canvas:active {
  cursor: grabbing;
}

/* Floating zoom controls — same spirit/position as the reference
   project's own right-edge buttons. */
.hero-chat__expanded-zoom {
  position: absolute;
  right: 16px;
  bottom: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 2;
  opacity: 1;
  pointer-events: auto;
  transition: opacity 0.2s ease;
}

/* Hidden while the discussion panel is open — it's anchored to the same
   right edge and would otherwise sit underneath (or, on mobile where the
   panel is a full overlay, visually behind) the panel. */
.hero-chat__expanded[data-discussion-open] .hero-chat__expanded-zoom {
  opacity: 0;
  pointer-events: none;
}

.hero-chat__expanded-zoom-btn {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(18, 16, 28, 0.72);
  backdrop-filter: blur(6px);
  color: rgba(238, 241, 248, 0.85);
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, transform 0.18s ease;
}

.hero-chat__expanded-zoom-btn:hover {
  background: rgba(184, 107, 248, 0.28);
  color: #fff;
  transform: scale(1.06);
}

.hero-chat__expanded-zoom-btn:focus-visible {
  outline: 2px solid #b86bf8;
  outline-offset: 2px;
}

/* --- Mood-trigger emojis --------------------------------------------------
   Opposite corner from the zoom control, same glass-pill visual language.
   Hidden with the discussion panel open for the same reason as the zoom
   control (anchored to an edge the panel would cover). */
.hero-chat__expanded-moods {
  position: absolute;
  left: 16px;
  bottom: 16px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  opacity: 1;
  pointer-events: auto;
  transition: opacity 0.2s ease;
}

.hero-chat__expanded[data-discussion-open] .hero-chat__expanded-moods {
  opacity: 0;
  pointer-events: none;
}

.hero-chat__expanded-moods-hint {
  margin: 0 0 0 4px;
  font-family: var(--font-satoshi);
  font-size: 11px;
  font-style: italic;
  color: rgba(238, 241, 248, 0.55);
  white-space: nowrap;
}

.hero-chat__expanded-moods-row {
  display: flex;
  flex-wrap: wrap;
  max-width: min(280px, 70vw);
  gap: 6px;
  padding: 6px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(18, 16, 28, 0.72);
  backdrop-filter: blur(6px);
}

/* Text pills now (explicit direction, replacing the single-emoji circle
   glyphs — see the njk comment above this markup): width is auto/
   content-driven instead of a fixed 30x30 circle, since "Effrayé" needs
   more room than a single character ever did. */
.hero-chat__expanded-mood-btn {
  height: 26px;
  padding: 0 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  border-radius: 9999px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.04);
  color: rgba(238, 241, 248, 0.85);
  font-family: var(--font-satoshi);
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}

.hero-chat__expanded-mood-btn:hover {
  background: rgba(184, 107, 248, 0.28);
  border-color: rgba(184, 107, 248, 0.5);
  transform: scale(1.05);
}

.hero-chat__expanded-mood-btn:focus-visible {
  outline: 2px solid #b86bf8;
  outline-offset: 2px;
}

@media (max-width: 640px) {
  /* Not enough width for both the hint and 8 buttons plus the zoom
     control without crowding the avatar itself — the hint is the least
     essential part, the buttons stay. */
  .hero-chat__expanded-moods-hint {
    display: none;
  }
  .hero-chat__expanded-mood-btn {
    height: 24px;
    padding: 0 8px;
    font-size: 10.5px;
  }
}

/* --- Thread panel ---------------------------------------------------------
   Toggled by the header's "Afficher la discussion" button; never visible
   by default. Below 700px there isn't room for a real side-by-side split,
   so it's a full-width overlay that slides in over the avatar (transform,
   the avatar stage's own box never changes size on mobile). From 700px up
   it's a genuine flex sibling of the avatar stage with an ANIMATED WIDTH
   (~28-32% of the body, clamped to a comfortable reading range) — a real
   layout change, not a transform, which is what makes the avatar stage's
   box actually shrink and the ResizeObserver-driven recenter (see
   hero-avatar.js) kick in smoothly frame by frame as it opens/closes. */

.hero-chat__expanded-thread-panel {
  position: absolute;
  inset: 0 0 0 auto;
  width: 100%;
  display: flex;
  flex-direction: column;
  background: rgba(10, 9, 16, 0.88);
  backdrop-filter: blur(18px) saturate(1.1);
  border-left: 1px solid rgba(130, 170, 255, 0.14);
  box-shadow: -24px 0 50px rgba(0, 0, 0, 0.4);
  transform: translateX(100%);
  transition: transform 0.32s cubic-bezier(0.22, 0.61, 0.36, 1);
  z-index: 3;
}

.hero-chat__expanded[data-discussion-open] .hero-chat__expanded-thread-panel {
  transform: translateX(0);
}

@media (min-width: 700px) {
  .hero-chat__expanded-thread-panel {
    position: relative;
    inset: auto;
    flex: 0 0 0%;
    width: auto;
    min-width: 0;
    overflow: hidden;
    transform: none;
    box-shadow: none;
    opacity: 0;
    transition: flex-basis 0.4s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.4s ease;
  }

  .hero-chat__expanded[data-discussion-open] .hero-chat__expanded-thread-panel {
    flex-basis: clamp(300px, 30%, 460px);
    opacity: 1;
  }

  /* The panel's own inner content needs a stable width to lay out/animate
     text-wrap against, independent of the flex-basis transition's
     in-between values — pinned to the fully-open target width so the
     thread never visibly reflows mid-transition, only fades/reveals. */
  .hero-chat__expanded-thread-panel > * {
    width: clamp(300px, 30vw, 460px);
    flex-shrink: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-chat__expanded-thread-panel {
    transition: none;
  }
}

/* --- Thread -------------------------------------------------------------- */

.hero-chat__expanded-thread {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-behavior: smooth;
  padding: 20px 16px;
  /* justify-content:center only actually does anything while the thread
     is shorter than its container (i.e. just the empty state) — once
     real messages push .hero-chat__expanded-thread-inner past the
     available height, centering has nothing left to center and this is
     a no-op; scrolling still works normally. This is what moves the new
     empty state to the true visual middle of the dalle instead of
     pinned to the top of a mostly-empty screen. */
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.hero-chat__expanded-thread:focus-visible {
  outline: none;
}

.hero-chat__expanded-thread-inner {
  max-width: var(--hc-x-content-max);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.hero-chat__expanded-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 40px 20px;
  text-align: center;
}

.hero-chat__expanded-empty[hidden] {
  display: none;
}

.hero-chat__expanded-empty-icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin-bottom: 6px;
  border-radius: 50%;
  color: #a9c2ff;
  background: radial-gradient(circle, rgba(63, 123, 248, 0.16), rgba(168, 102, 240, 0.05) 65%, transparent 78%);
  box-shadow: 0 0 30px rgba(120, 130, 255, 0.14);
}

.hero-chat__expanded-empty-title {
  font-family: var(--font-satoshi);
  font-size: 16px;
  font-weight: 700;
  color: rgba(238, 241, 248, 0.9);
  margin: 0;
}

.hero-chat__expanded-empty-detail {
  font-family: var(--font-satoshi);
  font-size: 12.5px;
  color: rgba(238, 241, 248, 0.5);
  margin: 4px 0 0;
  max-width: 42ch;
}

.hero-chat__expanded-empty-suggestions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 18px;
  max-width: 460px;
}

.hero-chat__expanded-empty-suggestion {
  font-family: var(--font-satoshi);
  font-size: 12.5px;
  font-weight: 600;
  color: rgba(220, 226, 245, 0.82);
  padding: 9px 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease;
}

.hero-chat__expanded-empty-suggestion:hover {
  background: rgba(120, 130, 255, 0.1);
  border-color: rgba(120, 130, 255, 0.35);
  transform: translateY(-1px);
}

.hero-chat__expanded-empty-suggestion:focus-visible {
  outline: 2px solid #b86bf8;
  outline-offset: 2px;
}

.hero-chat__expanded-date-sep {
  align-self: center;
  font-family: var(--font-satoshi);
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: rgba(238, 241, 248, 0.35);
  margin: 8px 0 -2px;
}

/* --- Bubbles --------------------------------------------------------- */

.hero-chat__expanded-msg {
  display: flex;
  flex-direction: column;
  max-width: var(--hc-x-bubble-max);
}

.hero-chat__expanded-msg--user {
  align-self: flex-end;
  align-items: flex-end;
}

.hero-chat__expanded-msg--assistant {
  align-self: flex-start;
  align-items: flex-start;
}

.hero-chat__expanded-bubble {
  border-radius: 16px;
  padding: 11px 15px;
  font-family: var(--font-satoshi);
  font-size: clamp(13.5px, 1vw, 15px);
  line-height: 1.58;
  word-wrap: break-word;
  overflow-wrap: anywhere;
}

.hero-chat__expanded-msg--user .hero-chat__expanded-bubble {
  background: linear-gradient(270.04deg, #3f7bf8 0.04%, #b86bf8 99.96%);
  color: #fff;
  border-bottom-right-radius: 4px;
  /* A real but restrained glow — never a hard neon edge. */
  box-shadow: 0 4px 18px rgba(120, 100, 240, 0.28), 0 1px 0 rgba(255, 255, 255, 0.12) inset;
}

.hero-chat__expanded-msg--assistant .hero-chat__expanded-bubble {
  position: relative;
  background: linear-gradient(165deg, rgba(255, 255, 255, 0.055), rgba(255, 255, 255, 0.025));
  border: 1px solid rgba(120, 170, 255, 0.22);
  color: rgba(238, 241, 248, 0.92);
  border-bottom-left-radius: 4px;
  /* A soft ambient glow instead of the removed vertical brand bar — no
     border-left, no pseudo-element, no extra left margin/padding. */
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.22), 0 0 26px rgba(120, 170, 255, 0.06);
  transition: border-color 0.18s ease, background 0.18s ease;
}

.hero-chat__expanded-msg--assistant .hero-chat__expanded-bubble:hover {
  border-color: rgba(120, 170, 255, 0.34);
  background: linear-gradient(165deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.03));
}

.hero-chat__expanded-msg--assistant.is-failed .hero-chat__expanded-bubble {
  border-color: rgba(255, 95, 86, 0.35);
  background: rgba(255, 95, 86, 0.08);
  color: #ffb3ac;
}

.hero-chat__expanded-bubble p {
  margin: 0 0 8px;
}

.hero-chat__expanded-bubble p:last-child {
  margin-bottom: 0;
}

.hero-chat__expanded-bubble ul,
.hero-chat__expanded-bubble ol {
  margin: 0 0 8px;
  padding-left: 20px;
}

.hero-chat__expanded-bubble a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.hero-chat__expanded-bubble code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
  background: rgba(0, 0, 0, 0.25);
  padding: 1px 5px;
  border-radius: 4px;
}

/* A collapsible section INSIDE the bubble, not loose chips floating
   below it — collapsed by default, a real toggle with a rotating
   chevron, one row per document (already deduped/page-merged
   server-side by groupCitations()). */
.hero-chat__expanded-citations {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.hero-chat__expanded-citations-toggle {
  display: flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-satoshi);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: rgba(169, 194, 255, 0.75);
  background: none;
  border: none;
  padding: 2px 0;
  min-height: 30px;
  cursor: pointer;
}

.hero-chat__expanded-citations-toggle:hover {
  color: rgba(200, 215, 255, 0.95);
}

.hero-chat__expanded-citations-chevron {
  transition: transform 0.18s ease;
}

.hero-chat__expanded-citations-toggle[aria-expanded="true"] .hero-chat__expanded-citations-chevron {
  transform: rotate(180deg);
}

.hero-chat__expanded-citations-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}

.hero-chat__expanded-citations-list[hidden] {
  display: none;
}

.hero-chat__expanded-citation-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 9px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.07);
}

.hero-chat__expanded-citation-icon {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 22px;
  height: 26px;
  border-radius: 4px;
  background: rgba(120, 150, 255, 0.12);
  font-size: 6.5px;
  font-weight: 800;
  color: #a9c2ff;
}

.hero-chat__expanded-citation-meta {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1;
}

.hero-chat__expanded-citation-name {
  font-size: 11.5px;
  font-weight: 600;
  color: rgba(238, 241, 248, 0.85);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hero-chat__expanded-citation-loc {
  font-size: 10px;
  color: rgba(238, 241, 248, 0.45);
}

.hero-chat__expanded-citation-reactivate {
  flex-shrink: 0;
  font-family: var(--font-satoshi);
  font-size: 10px;
  font-weight: 700;
  padding: 4px 9px;
  min-height: 30px;
  border-radius: 999px;
  border: 1px solid rgba(120, 150, 255, 0.28);
  background: rgba(120, 150, 255, 0.08);
  color: #a9c2ff;
  cursor: pointer;
  white-space: nowrap;
}

.hero-chat__expanded-citation-reactivate:hover {
  background: rgba(120, 150, 255, 0.16);
}

/* --- Thinking bubble (mirrors the compact screen's own orbit) -------- */

.hero-chat__expanded-thinking {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-self: flex-start;
  max-width: var(--hc-x-bubble-max);
  padding: 12px 15px;
  border-radius: 16px;
  border-bottom-left-radius: 4px;
  background: linear-gradient(165deg, rgba(255, 255, 255, 0.055), rgba(255, 255, 255, 0.025));
  border: 1px solid rgba(120, 170, 255, 0.22);
}

.hero-chat__expanded-thinking-header {
  display: flex;
  align-items: center;
  gap: 10px;
}

.hero-chat__expanded-thinking-title {
  font-family: var(--font-satoshi);
  font-size: 13px;
  font-weight: 700;
  color: rgba(238, 241, 248, 0.9);
}

/* Second pass (explicit direction: "le timer est pas bon... au centre,
   un truc stylé, là c'est moche" — the pill counted down correctly but
   read as a small number stuck in a corner of the header, not a real
   timer). Its own centered row now (.hero-chat__expanded-thinking-ring-row,
   hero-chat-expanded.js), holding a real draining ring — an SVG circle
   whose stroke-dashoffset empties clockwise over the same 30s
   (updateThinkingRing), with the remaining-seconds number centered
   inside it via absolute positioning over the SVG. */
.hero-chat__expanded-thinking-ring-row {
  display: flex;
  justify-content: center;
  padding: 4px 0 2px;
}

.hero-chat__thinking-ring {
  position: relative;
  display: inline-flex;
  width: 56px;
  height: 56px;
}

.hero-chat__thinking-ring-svg {
  width: 100%;
  height: 100%;
  /* Start the drain at 12 o'clock, not 3 o'clock (SVG circles start
     their path at 0deg = 3 o'clock by default). */
  transform: rotate(-90deg);
}

.hero-chat__thinking-ring-track,
.hero-chat__thinking-ring-fill {
  fill: none;
  stroke-width: 3;
}

.hero-chat__thinking-ring-track {
  stroke: rgba(255, 255, 255, 0.12);
}

.hero-chat__thinking-ring-fill {
  stroke: rgba(184, 107, 248, 0.9);
  stroke-linecap: round;
  transition: stroke-dashoffset 1s linear;
}

.hero-chat__thinking-ring-value {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-satoshi);
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: rgba(238, 241, 248, 0.92);
}

.hero-chat__expanded-thinking-detail {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 11px;
  color: rgba(238, 241, 248, 0.5);
}

/* Every real phase the backend is rotating through, shown at once — the
   current one lit up, earlier ones dimmed to read as "already passed
   through" without claiming a literal, sequential completion the backend
   doesn't actually report (it's an honest rotation, not real progress
   tracking — see hero-chat.js's own phase-cycling comment). */
.hero-chat__expanded-thinking-steps {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding-left: 34px;
}

.hero-chat__expanded-thinking-step {
  font-family: var(--font-satoshi);
  font-size: 11px;
  color: rgba(238, 241, 248, 0.32);
  transition: color 0.25s ease;
}

.hero-chat__expanded-thinking-step.is-done {
  color: rgba(238, 241, 248, 0.48);
}

.hero-chat__expanded-thinking-step.is-active {
  color: #a9c2ff;
  font-weight: 600;
}

.hero-chat__expanded-thinking-step.is-active::before {
  content: "› ";
}

/* --- Document event cards --------------------------------------------- */

/* A real technical card, not a text tag: icon | name+status | actions,
   a compact "system panel" surface. Green border/glow is reserved for
   the genuinely active document only (--active modifier) — a merely
   "ready" document stays neutral until actually selected, so "ready" and
   "the one RAG will use" read as two different, honestly distinct
   things. */
.hero-chat__expanded-doc-card {
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: var(--hc-x-bubble-max);
  padding: 9px 10px 9px 12px;
  border-radius: 12px;
  background: linear-gradient(165deg, rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0.02));
  border: 1px solid rgba(255, 255, 255, 0.1);
  font-family: var(--font-satoshi);
  font-size: 12.5px;
  color: rgba(238, 241, 248, 0.85);
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

.hero-chat__expanded-doc-card--active {
  border-color: rgba(61, 220, 132, 0.4);
  box-shadow: 0 0 0 1px rgba(61, 220, 132, 0.12), 0 0 20px rgba(61, 220, 132, 0.08);
}

.hero-chat__expanded-doc-card--rejected {
  border-color: rgba(255, 95, 86, 0.3);
  background: rgba(255, 95, 86, 0.06);
  color: #ffb3ac;
}

.hero-chat__expanded-doc-card--deleted {
  color: rgba(238, 241, 248, 0.4);
  font-style: italic;
}

.hero-chat__expanded-doc-icon {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 30px;
  height: 34px;
  border-radius: 5px;
  background: rgba(120, 150, 255, 0.12);
  border: 1px solid rgba(120, 150, 255, 0.22);
  font-size: 8px;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: #a9c2ff;
}

.hero-chat__expanded-doc-card--rejected .hero-chat__expanded-doc-icon {
  background: rgba(255, 95, 86, 0.12);
  border-color: rgba(255, 95, 86, 0.25);
  color: #ffb3ac;
}

.hero-chat__expanded-doc-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.hero-chat__expanded-doc-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 220px;
}

.hero-chat__expanded-doc-status {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
  font-size: 10.5px;
  font-weight: 600;
  color: rgba(238, 241, 248, 0.55);
}

.hero-chat__expanded-doc-dot {
  width: 6px;
  height: 6px;
  flex-shrink: 0;
  border-radius: 50%;
  box-shadow: 0 0 4px 1px currentColor;
}

.hero-chat__expanded-doc-actions {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 2px;
  margin-left: auto;
}

.hero-chat__expanded-doc-select {
  flex-shrink: 0;
  font-family: var(--font-satoshi);
  font-size: 10.5px;
  font-weight: 700;
  padding: 5px 10px;
  min-height: 30px;
  border-radius: 999px;
  border: 1px solid rgba(61, 220, 132, 0.3);
  background: rgba(61, 220, 132, 0.08);
  color: #a8f0b8;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.hero-chat__expanded-doc-card--active .hero-chat__expanded-doc-select {
  background: rgba(61, 220, 132, 0.2);
  border-color: rgba(61, 220, 132, 0.5);
}

.hero-chat__expanded-doc-select:hover {
  background: rgba(61, 220, 132, 0.16);
}

.hero-chat__expanded-doc-remove {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  min-width: 44px;
  min-height: 44px;
  margin: -9px -6px -9px 0;
  border: none;
  background: transparent;
  color: rgba(238, 241, 248, 0.45);
  cursor: pointer;
  border-radius: 999px;
  transition: color 0.15s ease, background 0.15s ease;
}

.hero-chat__expanded-doc-remove:hover,
.hero-chat__expanded-doc-remove:focus-visible {
  color: #ffb3ac;
  background: rgba(255, 95, 86, 0.12);
}

.hero-chat__expanded-doc-remove:disabled {
  opacity: 0.4;
  cursor: default;
}

/* --- Jump-to-bottom pill ---------------------------------------------- */

.hero-chat__expanded-jump {
  position: absolute;
  left: 50%;
  bottom: 96px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid rgba(184, 107, 248, 0.35);
  background: rgba(20, 16, 30, 0.92);
  color: #fff;
  font-family: var(--font-satoshi);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.35);
  z-index: 4;
}

.hero-chat__expanded-jump[hidden] {
  display: none;
}

/* --- Composer slot ----------------------------------------------------- */

/* The composer as the dalle's own "command dock" — a soft upward shadow
   separating it from the thread above (instead of a flat, uniform-black
   strip merging into the rest of the screen), a slightly richer surface,
   and a hairline top edge that picks up a touch of the brand gradient
   rather than plain white. */
.hero-chat__expanded-composer-slot {
  position: relative;
  flex-shrink: 0;
  padding: 14px 16px calc(14px + env(safe-area-inset-bottom));
  background: linear-gradient(180deg, rgba(20, 16, 30, 0.4), rgba(10, 8, 16, 0.62) 40%);
  box-shadow: 0 -18px 30px -14px rgba(0, 0, 0, 0.35);
}

.hero-chat__expanded-composer-slot::before {
  content: "";
  position: absolute;
  top: 0;
  left: 16px;
  right: 16px;
  height: 1px;
  background: linear-gradient(90deg, rgba(63, 123, 248, 0.28), rgba(168, 102, 240, 0.22) 55%, rgba(248, 107, 184, 0.14));
}

.hero-chat__expanded-composer-slot > .hero-chat__stack {
  max-width: var(--hc-x-composer-max);
  margin-inline: auto;
}

/* The composer's own document-chip strip is deliberately never removed or
 * duplicated in JS — it's the same live DOM hero-chat-documents.js already
 * owns — but the thread already shows the exact same information
 * chronologically (a live scan card while pending, a permanent compact
 * card once settled), so showing both here would read as a real
 * duplicate. CSS-only, visual-only: the strip and its state stay fully
 * intact underneath for when the composer moves back to the compact card.
 */
.hero-chat__expanded-composer-slot [data-chat-documents] {
  display: none;
}

/* --- Blocked-close nudge (accidental scrim-click guard) ---------------- */

@keyframes hero-x-nudge {
  0%,
  100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-4px);
  }
  75% {
    transform: translateX(4px);
  }
}

.hero-chat__monitor-shell.is-blocked {
  animation: hero-x-nudge 0.24s ease;
}

/* --- Turnstile-required inline notice (composer slot, never preventive) */

.hero-chat__expanded-turnstile-notice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
  padding: 8px 12px;
  border-radius: 10px;
  background: rgba(255, 195, 107, 0.1);
  border: 1px solid rgba(255, 195, 107, 0.3);
  font-family: var(--font-satoshi);
  font-size: 12px;
  color: rgba(255, 214, 148, 0.92);
}

.hero-chat__expanded-turnstile-notice button {
  font-family: var(--font-satoshi);
  font-size: 11.5px;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  background: transparent;
  color: #fff;
  cursor: pointer;
  flex-shrink: 0;
}

/* --- Responsive breakpoints -------------------------------------------- */

@media (max-width: 429px) {
  .hero-chat__monitor-assembly {
    width: 100%;
    height: var(--hc-x-vv-h, 100dvh);
  }
  .hero-chat__monitor-shell {
    width: 100%;
    height: 100%;
    border-radius: 0;
  }
  .hero-chat__expanded-window {
    padding-top: env(safe-area-inset-top);
  }
  .hero-chat__expanded-header {
    padding-inline: max(12px, env(safe-area-inset-left)) max(12px, env(safe-area-inset-right));
  }
  .hero-chat__expanded-jump {
    bottom: 92px;
  }
}

@media (min-width: 430px) and (max-width: 767px) {
  .hero-chat__monitor-assembly {
    width: calc(100% - 12px);
    height: calc(var(--hc-x-vv-h, 100dvh) - 12px);
  }
  .hero-chat__monitor-shell {
    width: 100%;
    height: 100%;
    --hc-x-radius: 16px;
  }
}

/* >=768px: the foot (neck+base) is genuinely part of the composition, so
   the shell's own share of the viewport shrinks a little at each step up
   to leave it real room underneath — plain vw/vh percentages here would
   either crowd the foot out (too tall a shell) or make the whole monitor
   look tiny (too conservative), so each range is tuned against a real
   screenshot at its own representative resolution (768 tablet, 1366x768
   / 1440x900 laptop, 1920x1080, 2560x1440), not a single formula scaled
   blindly across all of them. */
/* Taller than before across the board — the expanded view's primary
   content is now a full-body avatar (head to toe), which needs real
   vertical room, not the more modest height a text-only thread was fine
   with. */
@media (min-width: 768px) {
  .hero-chat__expanded {
    --hc-x-w: min(94vw, 900px);
    --hc-x-h: min(84dvh, 820px);
  }
  .hero-chat__expanded-bubble {
    font-size: 14px;
  }
}

@media (min-width: 1024px) {
  .hero-chat__expanded {
    --hc-x-w: min(92vw, 1360px);
    --hc-x-h: min(86dvh, 880px);
    --hc-x-bubble-max: 74%;
  }
}

@media (min-width: 1440px) {
  .hero-chat__expanded {
    --hc-x-w: min(90vw, 1560px);
    --hc-x-h: min(88dvh, 960px);
    --hc-x-bubble-max: 70%;
  }
}

@media (min-width: 1920px) {
  .hero-chat__expanded {
    --hc-x-w: min(88vw, 1900px);
    --hc-x-h: min(88dvh, 1100px);
  }
}

/* A short laptop viewport (1366x768 being the canonical case) needs the
   shell's height budget cut further regardless of width, or it pushes
   against the bottom edge — a pure width breakpoint can't see this, only
   a height-keyed one can. */
@media (min-width: 768px) and (max-height: 820px) {
  .hero-chat__expanded {
    --hc-x-h: min(76dvh, 680px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-chat__monitor-shell.is-blocked {
    animation: none;
  }
}
