/* ==========================================================================
   Components
   ========================================================================== */

/* ---- Icon ------------------------------------------------------------- */

/* Sizing and colour only — each icon declares its own fill/stroke per path,
   because the design mixes filled glyphs with stroked details. */
.icon {
  width: 1.25rem;
  height: 1.25rem;
  flex: 0 0 auto;
}

.icon--sm { width: 1rem; height: 1rem; }
.icon--lg { width: 1.5rem; height: 1.5rem; }
.icon--xl { width: 1.75rem; height: 1.75rem; }

/* Real Figma-exported PNGs, applied as a mask so currentColor still drives
   the fill (needed for theme switching — the same glyph is blue-on-white in
   light mode and white-on-navy in dark mode). See js/icons.js. */
.icon--mask {
  display: inline-block;
  background-color: currentColor;
  -webkit-mask: var(--icon-src) center / contain no-repeat;
  mask: var(--icon-src) center / contain no-repeat;
}

/* Exported per theme with different geometry, so the file (not just the
   colour) swaps. Set here rather than inline so the theme rule can win. */
.icon--chevron-right { --icon-src: url("../img/icons/chevron-right-light.svg"); }
[data-theme="dark"] .icon--chevron-right { --icon-src: url("../img/icons/chevron-right-dark.svg"); }

.icon--chevron-down { --icon-src: url("../img/icons/chevron-down-light.svg"); }
[data-theme="dark"] .icon--chevron-down { --icon-src: url("../img/icons/chevron-down-dark.svg"); }

img.icon {
  object-fit: contain;
}

/* ---- Header ----------------------------------------------------------- */

.header {
  position: sticky;
  top: 0;
  z-index: 20;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--header-h);
  padding: 0.6rem var(--gutter);   /* design: header band ~44px */
  background: var(--bg);
}

.header__brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);   /* bold at 25.8px reproduces the 87.5px wordmark */
  letter-spacing: -0.02em;
  line-height: 1;
}

.header__mascot {
  width: auto;
  height: 1.53rem;   /* design: 24.5px tall */
  object-fit: contain;
}

.header__actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  justify-self: end;
}

/* Circular icon button (back, agent) */
.icon-btn {
  display: grid;
  place-items: center;
  width: 1.78rem;   /* design: 28.5px */
  height: 1.78rem;
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--accent);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease),
    background var(--dur) var(--ease);
  border: 1px solid transparent;
}

[data-theme="dark"] .icon-btn {
  background: transparent;
  border-color: var(--border-strong);
  box-shadow: none;
  color: var(--text);
}

.icon-btn:active { transform: scale(0.94); }

/* The back control is exported as a complete button per theme (circle, border
   and chevron baked in), like the theme toggle — so the artwork IS the button
   and it carries no child glyph.
   Its viewBox was re-cropped to the visible circle: Figma pads the box
   downward only (feOffset dy=4 for the shadow), which left the artwork sitting
   4.2px above its own box centre and knocked it out of line with the other
   header controls. The shadow is re-applied below as a CSS filter, which does
   not affect layout. Same treatment on .theme-toggle. */
.icon-btn--art {
  width: 1.78rem;   /* same 28.5px as the other header buttons */
  height: 1.78rem;
  background: center / contain no-repeat url("../img/icons/back-light.svg");
  box-shadow: none;
  filter: drop-shadow(0 2px 2px rgba(16, 33, 71, 0.06));
}

[data-theme="dark"] .icon-btn--art {
  background-image: url("../img/icons/back-dark.svg");
  border: 0;
  filter: none;
}

/* ---- Theme toggle ----------------------------------------------------- */

/* The Figma export ships the toggle as one complete component per state
   (button_light.svg / button_darkmode.svg) — pill, border, knob, both glyphs
   and drop shadow all baked in. So the whole control is that artwork, swapped
   by theme, rather than a pill assembled in CSS around separate moon/sun
   glyphs. The two buttons sit transparently on top purely for hit-testing and
   keyboard/AT access.
   The 67x38 viewBox includes the shadow's bleed; the pill inside it is 59px,
   which is the width the design calls for. */
.theme-toggle {
  position: relative;
  display: flex;
  align-items: stretch;
  /* viewBox re-cropped to the visible pill (see .icon-btn--art), so these are
     now the pill's real dimensions: 58.98 x 27.5 -> design's 59px wide. */
  width: 3.6875rem;   /* 59px */
  height: 1.72rem;    /* 27.5px, preserving the 2.145 aspect */
  flex: 0 0 auto;
  background: center / contain no-repeat url("../img/icons/toggle-light.svg");
  filter: drop-shadow(0 2px 2px rgba(16, 33, 71, 0.06));
}

[data-theme="dark"] .theme-toggle {
  background-image: url("../img/icons/toggle-dark.svg");
  filter: none;
}

/* Left half = moon, right half = sun, matching the artwork. */
.theme-toggle__opt {
  flex: 1;
  border-radius: var(--r-pill);
  cursor: pointer;
}

/* ---- Greeting --------------------------------------------------------- */

/* No mode pill to share the row with any more — the title/subtitle just
   stack, full width. */
.greeting {
  display: flex;
  flex-direction: column;
  padding-block: 1.2rem 0;   /* design: title glyph top at 74px */
}

.greeting__title {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-h1);
  font-weight: var(--fw-bold);
  letter-spacing: -0.02em;
  line-height: 1;   /* frames stack title and subtitle tightly */
  white-space: nowrap;
}

.greeting__wave {
  display: inline-block;
  font-size: 1.25rem;
  transform-origin: 70% 70%;
  animation: wave 2.6s var(--ease) infinite;
}

@keyframes wave {
  0%, 60%, 100% { transform: rotate(0deg); }
  10%, 30% { transform: rotate(14deg); }
  20%, 40% { transform: rotate(-8deg); }
}

.greeting__sub {
  color: var(--text-muted);
  font-size: 0.75rem;   /* design: 12px (string width 167px)  */
  line-height: 1.1;
  margin-top: 0;   /* design: 29.5px from title glyph top to subtitle glyph top */
}

/* ---- Hero avatar -------------------------------------------------------- */

/* The hold-to-talk orb. Square source art, swapped per theme (unlike the
   penguin mascot, the sphere render genuinely differs between light/dark).
   It's a <button>: reset the native chrome, then lay the artwork on with the
   same `background` shorthand the mascot used. touch-action/user-select are
   disabled so a press-and-hold on mobile doesn't scroll the page or pop a
   text-selection/callout menu instead of starting the recording. */
/* The artwork is a centred circle filling ~74% of the square canvas; the
   remaining ~26% is a soft translucent halo. That matters for two reasons:
   the box must be sized ~1.35x the sphere you actually want to see, and a
   dark `drop-shadow` smears that halo into a grey smudge on the near-white
   light background. So the glow below is tinted to the orb's own violet/blue
   instead — it reads as emitted light rather than dirt. */
.hero-avatar {
  position: relative;
  /* The 30vh term only bites on short viewports, where it keeps the orb from
     pushing the Popular Questions list off the fold; on a normal phone the
     15.5rem cap wins and the size is unchanged. */
  width: min(64vw, 15.5rem, 30vh);
  aspect-ratio: 1 / 1;
  margin: 0 auto;
  display: block;
  appearance: none;
  -webkit-appearance: none;
  background: center / contain no-repeat url("../img/orb-light.webp");
  border: none;
  padding: 0;
  cursor: pointer;
  /* A press-and-hold must not scroll the page, select the artwork, or raise
     iOS's callout menu — any of those steal the gesture mid-recording. */
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  filter: drop-shadow(0 10px 26px rgba(124, 92, 255, 0.28));
  animation: mascot-float 7s ease-in-out infinite;
  transition: transform var(--dur-fast) var(--ease), filter var(--dur) var(--ease);
}

[data-theme="dark"] .hero-avatar {
  background-image: url("../img/orb-dark.webp");
  filter: drop-shadow(0 10px 30px rgba(120, 130, 255, 0.38));
}

.hero-avatar:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
  border-radius: 50%;
}

/* Held: the float stops (it fights the press) and the orb swells slightly
   into a brighter glow, so the gesture reads as "live". */
.hero-avatar--recording {
  animation: none;
  transform: scale(1.06);
  filter: drop-shadow(0 12px 34px rgba(124, 92, 255, 0.55));
}

[data-theme="dark"] .hero-avatar--recording {
  filter: drop-shadow(0 12px 38px rgba(140, 150, 255, 0.65));
}

.hero-avatar--sending {
  animation: none;
  opacity: 0.55;
  cursor: wait;
}

/* ---- Hold-to-record hint ------------------------------------------------ */

.hero-hint {
  margin: var(--sp-4) 0 0;
  text-align: center;
  color: var(--text-muted);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  min-height: 1.25em;   /* reserve the line so swapping text can't shift the orb */
  transition: color var(--dur) var(--ease);
}

.hero-hint--active {
  color: var(--accent);
}

@keyframes mascot-float {
  0%, 100% { transform: translateY(0) scale(1); }
  50% { transform: translateY(-8px) scale(1.02); }
}

/* ---- FAQ list --------------------------------------------------------- */

.faq {
  margin-block: var(--sp-3) var(--sp-6);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  border: 1px solid transparent;
}

[data-theme="dark"] .faq {
  border-color: var(--border);
  box-shadow: none;
}

.faq__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  width: 100%;
  padding: 0.75rem var(--sp-4);   /* design: 45px row height */
  text-align: left;
  color: var(--text);
  font-size: 0.75rem;   /* design: 12px */
  transition: background var(--dur-fast) var(--ease);
}

.faq__item + .faq__item { border-top: 1px solid var(--divider); }
.faq__item:hover { background: var(--accent-softer); }
.faq__item .icon { color: var(--accent); }

[data-theme="dark"] .faq__item .icon { color: var(--text); }

/* ---- Section title ---------------------------------------------------- */

.section-title {
  font-size: var(--fs-h3);
  font-weight: var(--fw-semibold);
  letter-spacing: -0.01em;
  margin-top: var(--sp-4);
}

/* ---- Chat ------------------------------------------------------------- */

.thread {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding-block: var(--sp-5) var(--sp-4);
}

.msg {
  display: flex;
  align-items: flex-end;
  gap: var(--sp-2);
  max-width: 100%;
}

.msg--user { flex-direction: row-reverse; }

.msg__avatar {
  display: grid;
  place-items: center;
  width: 2.875rem;   /* design: 46px */
  height: 2.875rem;
  flex: 0 0 auto;
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--accent);
  box-shadow: var(--shadow-sm);
  align-self: flex-start;
  border: 1px solid transparent;
}

[data-theme="dark"] .msg__avatar {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text);
  box-shadow: none;
}

/* Bot avatar: the penguin mascot in a circular badge, matching the user
   avatar's treatment (a plain circle is the app's established avatar
   language). Unlike the old orb art, the penguin cutout isn't self-framing,
   so — unlike .hero-avatar — this one keeps a background colour + border. */
.msg__avatar--ai {
  width: 2.53rem;   /* design: 40.5px — smaller than the user avatar */
  height: 2.53rem;
  border: 1px solid transparent;
  box-shadow: var(--shadow-sm);
  background: var(--surface) center / 68% no-repeat url("../img/penguin-avatar.webp");
}

/* Must repeat the whole shorthand, not just background-image: the dark
   .msg__avatar rule above sets `background: transparent`, which resets
   size/repeat/position and would tile the asset from its transparent corner
   inside a 40px circle. */
[data-theme="dark"] .msg__avatar--ai {
  border-color: var(--border-strong);
  box-shadow: none;
  background: transparent center / 68% no-repeat url("../img/penguin-avatar.webp");
}

.bubble {
  max-width: 72%;   /* design: 242.5px bot bubble on a 335px row */
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-lg);
  background: var(--bubble-bot);
  box-shadow: var(--shadow-card);
  font-size: 0.76rem;   /* design: 12.2px (measured string width) */
  line-height: var(--lh-body);
  overflow-wrap: anywhere;
}

[data-theme="dark"] .bubble { box-shadow: none; }

.msg--user .bubble {
  background: var(--bubble-user);
  border-bottom-right-radius: var(--r-sm);
}

.msg--bot .bubble {
  border-bottom-left-radius: var(--r-sm);
}

.bubble p + p { margin-top: var(--sp-3); }
.bubble ul { margin: var(--sp-2) 0; padding-left: 1.1rem; }
.bubble li { margin-block: 0.15rem; }
.bubble h5, .bubble h6 {
  margin: var(--sp-3) 0 var(--sp-1);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
}
.bubble a { text-decoration: underline; }

/* Suggestion chips */
.chips {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;   /* design: 14.5px */
  /* Chips align with the bot bubble rather than running to the gutter. */
  padding-left: calc(2.53rem + var(--sp-3));
  padding-right: 2.4rem;
}

.chip {
  width: 100%;
  padding: var(--sp-3);   /* design: 12px inset keeps the label on one line */
  border-radius: var(--r-md);
  background: var(--chip-bg);
  border: 1px solid var(--border);
  color: var(--text);
  text-align: left;
  font-size: 0.75rem;   /* design: 11.9px */
  transition: transform var(--dur-fast) var(--ease), border-color var(--dur) var(--ease);
}

.chip:hover { border-color: var(--accent); }
.chip:active { transform: scale(0.99); }

/* Typing indicator */
.typing {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: var(--sp-4);
}

.typing__dot {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--text-subtle);
  animation: typing 1.3s var(--ease) infinite;
}

.typing__dot:nth-child(2) { animation-delay: 0.16s; }
.typing__dot:nth-child(3) { animation-delay: 0.32s; }

@keyframes typing {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}

/* ---- Voice note ------------------------------------------------------- */

.voicenote {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 13rem;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-lg);
  background: var(--bubble-user);
  box-shadow: var(--shadow-card);
}

[data-theme="dark"] .voicenote { box-shadow: none; }

.voicenote__time {
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.voicenote__wave {
  flex: 1;
  height: 1.75rem;
  cursor: pointer;
}

.voicenote__play {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  flex: 0 0 auto;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: #FFFFFF;
  transition: transform var(--dur-fast) var(--ease);
}

.voicenote__play:active { transform: scale(0.92); }

/* ---- Recording controls ----------------------------------------------- */

/* Cancel | elapsed | Pause-Resume. The elapsed time used to be appended to the
   Pause button's own label, which made the button width jump every tick and
   hid what the control actually did. */
.reccontrols {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--sp-3);
  padding-block: var(--sp-3);
}

.reccontrols__time {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  font-variant-numeric: tabular-nums;   /* stop the digits jittering per tick */
  text-align: center;
}

/* A paused take shouldn't look live. */
.reccontrols__time--paused {
  opacity: 0.6;
}

.btn {
  min-height: 3rem;
  padding-inline: var(--sp-5);
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  transition: transform var(--dur-fast) var(--ease);
}

.btn:active { transform: scale(0.97); }

.btn--ghost {
  background: var(--surface);
  color: var(--accent);
  box-shadow: var(--shadow-card);
}

[data-theme="dark"] .btn--ghost {
  background: #FFFFFF;
  color: #0A66D6;
  box-shadow: none;
}

.btn--soft {
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid transparent;
}

[data-theme="dark"] .btn--soft {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border);
}

/* ---- Composer --------------------------------------------------------- */

.composer {
  position: sticky;
  bottom: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-2) var(--gutter) var(--sp-4);
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-4);
  /* The frames draw a generously rounded field with a hairline outline. */
  border-radius: var(--r-xl);
  border: 1px solid var(--border);
  background: var(--input-bg);
  box-shadow: var(--shadow-sm);
}

[data-theme="dark"] .composer {
  box-shadow: none;
}

.composer__input {
  flex: 1;
  min-width: 0;
  max-height: 6rem;
  border: 0;
  background: transparent;
  resize: none;
  font-size: var(--fs-sm);   /* design: 14px */
  line-height: 1.4;
  padding-block: 0.75rem;
}

.composer__input::placeholder { color: var(--text-placeholder); }
.composer__input:focus { outline: none; }

.composer__btn {
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  flex: 0 0 auto;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent);
  transition: transform var(--dur-fast) var(--ease), background var(--dur) var(--ease);
}

[data-theme="dark"] .composer__btn {
  background: var(--surface);
  color: var(--text);
}

.composer__btn:active { transform: scale(0.92); }
.composer__btn[disabled] { opacity: 0.45; pointer-events: none; }

.composer__btn--recording {
  background: var(--accent);
  color: #FFFFFF;
  animation: pulse 1.4s var(--ease) infinite;
}

@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(0, 128, 255, 0.45); }
  70% { box-shadow: 0 0 0 0.6rem rgba(0, 128, 255, 0); }
}

/* ---- Modal ------------------------------------------------------------ */

.modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  /* A closed <dialog> must stay display:none, or it covers the viewport and
     swallows every click on the page behind it. Only lay it out when [open]. */
  display: none;
  place-items: center;
  padding: var(--gutter);
  border: 0;
  background: transparent;
  max-width: none;
  max-height: none;
  width: 100%;
  height: 100%;
}

.modal[open] {
  display: grid;
}

.modal::backdrop {
  background: var(--scrim);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.modal__card {
  width: min(21rem, 100%);
  padding: var(--sp-6) var(--sp-5) var(--sp-5);
  border-radius: var(--r-xl);
  background: var(--bg-elevated);
  box-shadow: var(--shadow-modal);
  text-align: center;
  animation: modal-in var(--dur-slow) var(--ease-out);
}

@keyframes modal-in {
  from { opacity: 0; transform: translateY(12px) scale(0.97); }
  to { opacity: 1; transform: none; }
}

/* whatsapp.svg carries its own green disc, so this wrapper must NOT paint a
   second circle behind it or the badge doubles up. It does need a white disc
   though: the handset inside the mark is a knockout (transparent), which
   reads white on the light card but would show navy through on dark. The
   radial stop sits just inside the mark's own edge so no white rim shows. */
.modal__icon {
  display: grid;
  place-items: center;
  width: 4.25rem;
  height: 4.25rem;
  margin: 0 auto var(--sp-4);
  background: #FFFFFF;
  border-radius: var(--r-pill);
}

.modal__icon .icon {
  width: 100%;
  height: 100%;
}

.modal__title {
  font-size: var(--fs-h3);
  font-weight: var(--fw-bold);
  margin-bottom: var(--sp-1);
}

.modal__text {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  margin-bottom: var(--sp-5);
}

.modal__actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
}

/* Tighter than the default button padding so two-word labels stay on one line. */
.modal__actions .btn {
  padding-inline: var(--sp-3);
  white-space: nowrap;
}

.modal__input {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  background: var(--input-bg);
  color: var(--text);
  font: inherit;
  font-size: 1.25rem;
  letter-spacing: .5em;
  text-align: center;
}

.modal__input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.modal__error {
  min-height: 1.25rem;
  margin: 0;
  color: #b42318;
  font-size: var(--fs-label);
}

/* ---- Toast ------------------------------------------------------------ */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--composer-h) + var(--sp-4));
  transform: translate(-50%, 1rem);
  z-index: 70;
  max-width: min(22rem, calc(100vw - 2rem));
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--text);
  color: var(--bg);
  font-size: var(--fs-sm);
  box-shadow: var(--shadow-modal);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease-out);
}

.toast[data-visible="true"] {
  opacity: 1;
  transform: translate(-50%, 0);
}
