/* ===== Hero chat =====
   The ask-about-Cris field under the headline, and the conversation zone it
   opens ABOVE itself.

   Written on SEMANTIC tokens (--surface-raised, --text-primary) for colour
   and on the dedicated --chat-* and --hero-* proportion tokens (tokens.css,
   "Hero + AI-chat field") for size and timing. Fonts and palette are the
   site's; only the measurements are the mock's.

   THE RULE THIS SECTION FOLLOWS (spec 30 Oct):
     • the field never moves, the headline never moves, the page never scrolls;
     • the conversation lives in a FIXED, INVISIBLE zone of its own, pinned
       just above the field, scrolling inside itself;
     • on the first question the headline simply dissolves in place.

   That is why the zone is `position: absolute`: taken out of flow, it can open
   over the space the (now faded) headline occupied without pushing the field
   down or growing the section. hero-chat.js holds the scrolling + reveal. */

/* --- the Hero is a bottom-anchored column ----------------------------
   headline on top, field at the bottom (`justify-content: flex-end`), the
   gap between them the idle headline→field distance. The thread is absolute,
   so these two are the only flow children and the field sits against the
   section's padding-bottom. The section is pinned to 100vh with overflow
   hidden in sections/hero.css — a conversation changes nothing about the
   section's box, so nothing below the Hero moves either. */
.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: var(--hero-title-gap);
  /* No --header-h reserve any more (spec part 2): the header has no bar, just
     a fixed logo in the corner, so the Hero no longer holds space for it. This
     is only a floor for a tall stack anyway — the headline rests at the bottom
     (flex-end). The chat zone still clears the logo via --header-h on its own. */
  padding-top: var(--space-8);
  padding-bottom: var(--hero-field-bottom);
  padding-inline: var(--space-5);
}

.hero-chat {
  /* positioned + stacked ABOVE the fidget canvas (inset:0 at
     --z-hero-fidget), or the canvas would swallow every tap on the field.
     `position: relative` is also the anchor the absolute thread resolves
     against. Its width is the one the zone shares — see --chat-field-width. */
  position: relative;
  z-index: var(--z-hero-controls);
  width: 100%;
  max-width: var(--chat-field-width);
}

/* --- the conversation zone -------------------------------------------
   Fixed height, pinned so its bottom edge sits one gap above the field, the
   same width and edges as the field (left/right: 0 inside the shared-width
   parent). Invisible: no background, border or shadow — only the messages
   show, over the dot-grid. Scrolls inside itself; the page stays put. */
.hero-chat__thread {
  position: absolute;
  left: 0;
  right: 0;
  /* Runs from just under the header down to just above the field — height is
     the span between the two, NOT a fixed number, so the logo and controls up
     top always stay clear whatever the viewport. Both edges are expressed
     against this absolute box's parent (.hero-chat, which sits at the field):
       • bottom — one gap above the field (100% of .hero-chat = the field);
       • top — back up to the header line. The field's top in the viewport is
         (100vh − field-bottom − field-height), so the offset from there up to
         --header-h works out to the calc below. */
  bottom: calc(100% + var(--chat-zone-gap));
  top: calc(var(--header-h) - 100vh + var(--hero-field-bottom) + var(--chat-field-height));
  display: flex;
  flex-direction: column;
  gap: var(--chat-turn-gap);
  overflow-y: auto;
  /* a scroll gesture inside the zone must not bubble out and move the page */
  overscroll-behavior: contain;
  /* the zone is invisible furniture — hide its scrollbar too */
  scrollbar-width: none;
}
.hero-chat__thread::-webkit-scrollbar { display: none; }
/* empty until the first question — and an empty absolute box would still sit
   over the field catching nothing, so drop it out entirely until it has turns */
.hero-chat__thread:empty { display: none; }

/* Old turns dissolve at the TOP as soon as they stop fitting (there is always
   content hidden above once the zone is scrolled down). A bottom fade by the
   field is added ONLY while the visitor has scrolled up off the latest turn.
   mask-image fades the zone's OWN pixels — the text — to transparent, so the
   dot-grid behind stays fully visible; it is never a page-coloured plate laid
   over the content. hero-chat.js toggles the two classes from scrollTop. */
.hero-chat__thread.has-top-fade {
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--chat-mask-top));
          mask-image: linear-gradient(to bottom, transparent, #000 var(--chat-mask-top));
}
.hero-chat__thread.has-bottom-fade:not(.has-top-fade) {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - var(--chat-mask-bottom)), transparent);
          mask-image: linear-gradient(to bottom, #000 calc(100% - var(--chat-mask-bottom)), transparent);
}
.hero-chat__thread.has-top-fade.has-bottom-fade {
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--chat-mask-top), #000 calc(100% - var(--chat-mask-bottom)), transparent);
          mask-image: linear-gradient(to bottom, transparent, #000 var(--chat-mask-top), #000 calc(100% - var(--chat-mask-bottom)), transparent);
}

/* --- the question bubble ---------------------------------------------
   Right-aligned plate. A full capsule — --radius-pill on all four corners, the
   same chip radius the rest of the site uses (no tail, no avatar, no colour —
   the side it sits on is the whole of "this one is mine"), no shadow, 14×20
   padding. The plate says "this is what the visitor pasted in"; the answer
   below has none, because it is the page talking about itself. */
.hero-chat__q {
  align-self: flex-end;
  max-width: 85%;
  padding: var(--chat-q-pad-y) var(--chat-q-pad-x);
  border-radius: var(--radius-pill);
  background: var(--surface-raised);
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  color: var(--text-primary);
}

/* --- the answer -------------------------------------------------------
   No plate, no edge: prose set straight on the page, left-aligned, at a
   readable measure (~84% of the zone) and a looser leading than the UI text. */
.hero-chat__a {
  align-self: flex-start;
  max-width: var(--chat-a-width);
  font-size: var(--chat-a-size);
  line-height: var(--chat-a-leading);
  color: var(--text-primary);
}
.hero-chat__a--error { color: var(--text-secondary); }

/* The answer types itself in a word at a time: each word fades up, staggered.
   hero-chat.js wraps every word in a .word and sets its animation-delay from
   --chat-word-step; the per-word fade duration is --chat-word-dur here. Under
   reduced motion the JS renders the plain string instead, so nothing staggers
   and reset.css's duration clamp has nothing to act on. */
@keyframes hero-chat-word-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.hero-chat__a .word {
  opacity: 0;
  animation: hero-chat-word-in var(--chat-word-dur) var(--ease-out) both;
}

/* the question bubble still fades up as a whole as it arrives */
@keyframes hero-chat-in {
  from { opacity: 0; translate: 0 var(--space-2); }
  to   { opacity: 1; translate: 0 0; }
}
.hero-chat__q { animation: hero-chat-in var(--motion-enter) both; }

/* --- the field -------------------------------------------------------- */
.hero-chat__form {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--chat-field-gap);
  min-height: var(--chat-field-height);
  padding: 0 var(--chat-field-pad-r) 0 var(--chat-field-pad-l);
  border: 0;                     /* no rule — the surface is the shape */
  border-radius: var(--radius-full);
  background: var(--surface-raised);
  box-shadow: var(--chat-field-shadow);
  transition: box-shadow var(--motion-hover), background var(--motion-hover);
}
.hero-chat__form:focus-within { box-shadow: var(--chat-field-shadow), var(--chat-field-focus); }

/* --- the Sparkles mark + its spin -------------------------------------
   SWAP POINT. To change the mark, replace the <svg> inside
   <span class="hero-chat__icon"> in index.html; the box is sized here and the
   artwork only fills it. `currentColor` themes it.

   The spin: four quarter turns, 90, 180, 270, 360, with a hold after each,
   forever. The star's points are not identical, so 90° is not the same pose
   as 0° and a reset there shows; only the full turn closes the loop.
   Timings come from the two tokens; see the note on them in tokens.css. */
.hero-chat__icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: var(--chat-field-icon);
  height: var(--chat-field-icon);
  color: var(--text-secondary);
}
.hero-chat__icon svg {
  width: 100%;
  height: 100%;
  display: block;
  transform-origin: center;
  animation: hero-sparkle-spin
             calc((var(--sparkle-spin-duration) + var(--sparkle-spin-pause)) * 4)
             ease-in-out infinite;
}
@keyframes hero-sparkle-spin {
  0%    { transform: rotate(0deg); }
  12.5% { transform: rotate(90deg); }
  25%   { transform: rotate(90deg); }
  37.5% { transform: rotate(180deg); }
  50%   { transform: rotate(180deg); }
  62.5% { transform: rotate(270deg); }
  75%   { transform: rotate(270deg); }
  87.5% { transform: rotate(360deg); }
  100%  { transform: rotate(360deg); }
}
/* While the field is focused the star finishes its current quarter turn and
   freezes there (hero-chat.js drives the finish and the return to the loop). */
.hero-chat__icon.is-settled svg { animation: none; }
@media (prefers-reduced-motion: reduce) {
  .hero-chat__icon svg { animation: none; transform: none; }
}

/* --- the input and its ghost placeholder ------------------------------
   The real <input> carries NO placeholder attribute. ::placeholder cannot be
   animated, so the idle prompt ("Ask about Cris…") and the questions that
   rotate in after it are a separate element laid over the input, which is
   kept transparent-backgrounded on top so the caret and real typing win. */
.hero-chat__field {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;                  /* or a long word would push the pill wide */
  display: flex;
  align-items: center;
}

.hero-chat__input {
  width: 100%;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: var(--text-md);     /* 16px — also stops iOS zoom-on-focus */
  line-height: var(--leading-normal);
  color: var(--text-primary);
}
.hero-chat__input:focus { outline: none; }
.hero-chat__input:disabled { color: var(--text-secondary); }

/* "Ask something else…" — the real placeholder once a conversation has
   started (hero-chat.js writes it). Same muted token as the sparkle and arrow
   either side of it; browsers add their own opacity to ::placeholder, set
   here so it does not compound. */
.hero-chat__input::placeholder {
  color: var(--text-secondary);
  opacity: .55;
}

.hero-chat__ghost {
  position: absolute;
  inset: 0;
  /* GRID so a leaving line and an arriving line can share one cell (grid-area
     below) — as flex items they would sit side by side. */
  display: grid;
  align-items: center;
  overflow: hidden;              /* the outgoing line leaves through the top */
  pointer-events: none;          /* clicks belong to the input underneath */
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
  opacity: .55;                  /* the idle prompt reads as placeholder, muted */
}
.hero-chat__ghost-line {
  grid-area: 1 / 1;              /* every line in the same cell = stacked */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: translate var(--chat-line-in) var(--chat-line-ease) var(--chat-line-delay),
              opacity var(--chat-line-in) var(--chat-line-ease) var(--chat-line-delay);
}
.hero-chat__ghost-line.is-out {
  translate: 0 calc(var(--chat-line-shift) * -1);
  opacity: 0;
  transition: translate var(--chat-line-out) var(--chat-line-ease),
              opacity var(--chat-line-out) var(--chat-line-ease);
}
.hero-chat__ghost-line.is-in { translate: 0 var(--chat-line-shift); opacity: 0; }

/* --- the send button -------------------------------------------------- */
.hero-chat__send {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: var(--chat-field-send);
  height: var(--chat-field-send);
  border: 0;
  border-radius: var(--radius-full);
  background: none;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color var(--motion-hover), background var(--motion-hover);
}
.hero-chat__send svg { width: var(--chat-field-arrow); height: var(--chat-field-arrow); }
.hero-chat__send:hover:not(:disabled),
.hero-chat__send:focus-visible:not(:disabled) {
  color: var(--text-primary);
  background: var(--surface-page);
}
.hero-chat__send:disabled { opacity: .4; cursor: default; }

/* --- "typing…" --------------------------------------------------------
   Three bare dots where the answer's first line will be — on the line, in the
   text colour, no plate. */
.hero-chat__typing {
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: var(--space-1);
  /* match an answer's first-line height so the reply lands where the dots were */
  min-height: calc(var(--chat-a-size) * var(--chat-a-leading));
}
.hero-chat__typing span {
  width: var(--space-2);
  height: var(--space-2);
  border-radius: var(--radius-full);
  background: var(--text-secondary);
  animation: hero-chat-blink 1.2s infinite ease-in-out both;
}
.hero-chat__typing span:nth-child(2) { animation-delay: .15s; }
.hero-chat__typing span:nth-child(3) { animation-delay: .3s; }
@keyframes hero-chat-blink {
  0%, 80%, 100% { opacity: .25; }
  40%           { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-chat__typing span { animation: none; opacity: .5; }
}

/* --- out of messages --------------------------------------------------
   The conversation's last screen: hand the visitor to Cris herself. Lives in
   the zone like any other turn — no plate, the zone is invisible around it. */
.hero-chat__spent {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  padding-block: var(--space-6);
  text-align: center;
  animation: hero-chat-in var(--motion-enter) both;
}
.hero-chat__spent-text {
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
}
.hero-chat__contacts {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* the pills are .pill-link from pill-bar.css — the footer's contact component */

.hero-chat.is-spent .hero-chat__form { opacity: .5; }

/* --- small screens ----------------------------------------------------
   The zone cannot be a flat 544px tall on a short phone — cap it to the room
   above the field, and sit the field a little higher so the headline (more
   lines here) clears the header. The dock/width rules come later in the spec. */
@media (max-width: 768px) {
  .hero {
    /* the field sits a little higher on a phone — the headline is more lines
       here; the chat zone's top/bottom calc picks this up automatically */
    --hero-field-bottom: 37vh;
    padding-inline: var(--space-4);
    gap: var(--space-8);
  }
  .hero-chat__form {
    padding-left: var(--space-4);
    font-size: var(--text-md);   /* 16px keeps iOS Safari from zooming on focus */
  }
}
