/* HeyHi design system: the AI widget in the corner of every page (shared/_assistant, assistant_controller.js).
 * A launcher, and a panel holding one conversation with HeyHi AI, by text or by voice. Both are white sheets cast as
 * menus are (--shadow-pop), hairline-ruled and near-monochrome, with amber for the call and our AI's name in amber
 * ink; the panel's title is the serif, and its metadata (how to reach it, the call's state and time, "Call started")
 * is the mono. The panel and the nudge open from @starting-style, as menus do. The controller adds the messages,
 * events and notices, tucks the launcher away (.is-tucked) while a page's own opening call is in view, and toggles the
 * call bar's [data-state], .is-speaking and --mic-level. */

/* ---------- Launcher: a white pill in the corner, which closes the widget while it's open ---------- */
/* Above the panel's layer, so the panel's shadow doesn't fall on it */
.assistant-launcher {
  position: fixed; right: max(20px, env(safe-area-inset-right, 0px)); bottom: max(20px, env(safe-area-inset-bottom, 0px)); z-index: 61;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px; height: 52px; padding: 0 20px 0 6px;
  border: 0; border-radius: var(--radius-round); background: var(--c-white); color: var(--c-ink); box-shadow: var(--shadow-pop);
  font-family: var(--font-text); font-size: var(--text-small); font-weight: 600; letter-spacing: -0.005em; white-space: nowrap; cursor: pointer;
  transition: transform var(--dur-ui) var(--ease-out), opacity var(--dur-ui) var(--ease-out), visibility var(--dur-ui), background-color var(--dur-fast);
}
.assistant-launcher:hover { transform: translateY(-1px); }
/* The call's own mark: our AI's mark, or the phone, on an amber disc, as an incoming call's card shows it */
.assistant-launcher-icon {
  display: grid; place-items: center; width: 40px; height: 40px; flex: none; border-radius: 50%;
  background: var(--amber); color: var(--c-ink); transition: background-color var(--dur-fast);
}
.assistant-launcher:hover .assistant-launcher-icon { background: var(--amber-hover); }
.assistant-launcher-icon .icon { width: 18px; height: 18px; }
.assistant-launcher-icon .mark { width: 20px; }
/* Open, it's a round button that closes the widget */
.assistant-launcher[aria-expanded="true"] { width: 52px; padding: 0; }
.assistant-launcher[aria-expanded="true"] .assistant-launcher-icon { background: transparent; }
.assistant-launcher[aria-expanded="true"]:hover { background: var(--c-paper); }
.assistant-launcher-close, .assistant-launcher[aria-expanded="true"] :is(.assistant-launcher-open, .assistant-launcher-label) { display: none; }
.assistant-launcher[aria-expanded="true"] .assistant-launcher-close { display: block; width: 22px; height: 22px; }
/* Out of sight while the page's own call is in view, unless it's the button that closes the open widget */
.assistant-launcher.is-tucked:not([aria-expanded="true"]) { opacity: 0; visibility: hidden; transform: translateY(16px); }

/* A nudge above the launcher, once a visit, on screens with room for it */
.assistant-teaser {
  position: fixed; right: max(20px, env(safe-area-inset-right, 0px)); bottom: calc(max(20px, env(safe-area-inset-bottom, 0px)) + 64px); z-index: 45;
  display: flex; align-items: center; max-width: 18rem; border-radius: var(--radius-md) var(--radius-md) var(--radius-sm) var(--radius-md);
  background: var(--c-white); color: var(--c-ink); box-shadow: var(--shadow-pop);
  transform-origin: 100% 100%;
  transition: opacity var(--dur-ui) var(--ease-out), transform var(--dur-ui) var(--ease-out);
}
@starting-style {
  .assistant-teaser { opacity: 0; transform: translateY(6px) scale(0.985); }
}
.assistant-teaser-text {
  padding: 12px 4px 12px 16px; border: 0; background: none; color: inherit; cursor: pointer;
  font-size: var(--text-ui); font-weight: 500; line-height: 1.4; text-align: left; text-wrap: balance;
}
.assistant-teaser-close {
  display: grid; place-items: center; flex: none; width: 34px; height: 34px; margin-right: 6px; padding: 0;
  border: 0; border-radius: 50%; background: none; color: var(--ink-mute); cursor: pointer; transition: background-color var(--dur-fast), color var(--dur-fast);
}
.assistant-teaser-close:hover { background: var(--c-paper); color: var(--ink); }
.assistant-teaser-close .icon { width: 15px; height: 15px; }

/* Back-to-top shares the corner, so it steps aside while the nudge or the widget is showing */
.assistant-teaser:not([hidden]) ~ .back-to-top,
.assistant-panel:not([hidden]) ~ .back-to-top { visibility: hidden; opacity: 0; }

/* ---------- Panel: the whole screen on phones, so the conversation has room ---------- */
/* There it acts as a popup: the controller makes the page behind it inert and puts focus inside it */
.assistant-panel {
  position: fixed; inset: 0; z-index: 60;
  display: flex; flex-direction: column;
  background: var(--c-white); color: var(--ink); font-size: var(--text-small);
  transition: opacity var(--dur-ui) var(--ease-out), transform var(--dur-ui) var(--ease-out), display var(--dur-ui) allow-discrete;
}
@starting-style {
  .assistant-panel { opacity: 0; transform: translateY(8px); }
}
/* Closing, it eases away quicker than it came */
.assistant-panel[hidden] {
  opacity: 0; transform: translateY(6px); pointer-events: none;
  transition-duration: var(--dur-fast); transition-timing-function: var(--ease-in);
}
/* It takes focus as a whole when there's no message box to start in; its title is read out, and no ring is drawn
   around the window itself */
.assistant-panel:focus { outline: none; }
@media (max-width: 35.99em) {
  html.assistant-open { overflow: hidden; }
  .assistant-launcher[aria-expanded="true"] { display: none; }
}

/* From 36em, a card above the launcher, short enough to stay clear of the header */
@media (min-width: 36em) {
  .assistant-panel {
    inset: auto max(20px, env(safe-area-inset-right, 0px)) calc(max(20px, env(safe-area-inset-bottom, 0px)) + 64px) auto;
    width: min(400px, calc(100vw - 40px));
    height: min(640px, calc(100dvh - var(--header-h) - 100px)); max-height: min(640px, calc(100dvh - var(--header-h) - 100px));
    border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-pop);
    transform-origin: 100% 100%;
  }
  @starting-style {
    .assistant-panel { opacity: 0; transform: translateY(8px) scale(0.985); }
  }
  .assistant-panel[hidden] { transform: translateY(6px) scale(0.99); }
}

/* Its head, as a product card's: who's answering, and how */
.assistant-header {
  display: flex; flex: none; align-items: center; gap: 12px; min-height: 64px;
  padding: max(12px, env(safe-area-inset-top, 0px)) 10px 12px 16px; border-bottom: 1px solid var(--line);
}
.assistant-avatar { display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: 50%; background: var(--amber); color: var(--c-ink); }
.assistant-avatar .mark { width: 19px; }
.assistant-heading { display: grid; gap: 3px; min-width: 0; }
.assistant-title { font-family: var(--font-display); font-size: 20px; font-weight: 400; letter-spacing: -0.012em; line-height: 1.1; }
/* How to reach it, as metadata, beside a live dot */
.assistant-subtitle {
  display: flex; align-items: center; gap: 8px; white-space: nowrap;
  font-family: var(--font-mono); font-size: 11px; font-weight: 500; line-height: 1.3; letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--ink-mute);
}
/* Live, as a product's status shows it: a solid amber dot that breathes */
.assistant-online { position: relative; width: 7px; height: 7px; flex: none; border-radius: 50%; background: var(--amber); }
.assistant-online::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--amber);
  animation: status-breathe 2.4s var(--ease-in-out) infinite;
}

/* Calling HeyHi Voice from the head, the way a messaging app offers a call */
.assistant-header .assistant-call-button { flex: none; margin-left: auto; --btn-h: 36px; padding: 0 14px; font-size: var(--text-ui); }
.assistant-header .assistant-call-button .icon { width: 15px; height: 15px; }
.assistant-close {
  display: grid; place-items: center; flex: none; width: 36px; height: 36px; margin-left: auto; padding: 0;
  border: 0; border-radius: 50%; background: transparent; color: var(--ink-soft); cursor: pointer; transition: background-color var(--dur-fast), color var(--dur-fast);
}
.assistant-close:hover { background: var(--c-paper); color: var(--ink); }
.assistant-close .icon { width: 18px; height: 18px; }
.assistant-call-button:not([hidden]) + .assistant-close { margin-left: 0; }

/* ---------- The conversation, with the suggestions under the greeting until it starts ---------- */
.assistant-thread {
  display: flex; flex: 1; flex-direction: column; gap: var(--space-5); min-height: 0; padding: 20px 18px 18px;
  overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent;
}
.assistant-messages { list-style: none; display: flex; flex-direction: column; gap: var(--space-4); }
.assistant-message { max-width: 100%; font-size: var(--text-small); line-height: 1.55; overflow-wrap: anywhere; }
/* Our AI's words stand on the card, as a call card's lines do; the visitor's sit in a warm panel on the right */
.assistant-message--assistant { align-self: stretch; color: var(--ink); }
.assistant-message--user {
  align-self: flex-end; max-width: 86%; padding: 9px 14px; white-space: pre-wrap;
  border-radius: var(--radius-md) var(--radius-md) var(--radius-sm) var(--radius-md); background: var(--c-panel);
}
/* An answer that couldn't come, as a highlighted row */
.assistant-message--error { padding: 10px 14px; border-radius: var(--radius-md); background: var(--amber-soft); }
.assistant-message :is(p, ul, ol) { margin: 0 0 8px; }
.assistant-message > :last-child { margin-bottom: 0; }
.assistant-message :is(ul, ol) { padding-left: 20px; }
.assistant-message li + li { margin-top: 4px; }
.assistant-message li::marker { color: var(--ink-mute); }
.assistant-message strong { font-weight: 600; }
.assistant-message .text-link { text-underline-offset: 3px; }

/* A call's transcript says who spoke, as a call card does: our AI's name in amber ink */
.assistant-speaker, .assistant-message--user.assistant-message--voice::before {
  display: block; margin-bottom: 2px; font-size: var(--text-caption); font-weight: 600; line-height: 1.4; color: var(--amber-ink);
}
.assistant-message--user.assistant-message--voice::before { content: "You"; color: var(--ink-mute); }

/* "Call started" and "Call ended", as a rule across the conversation */
.assistant-event {
  display: flex; align-items: center; gap: var(--space-3); margin-block: 2px; white-space: nowrap;
  font-family: var(--font-mono); font-size: 11px; font-weight: 500; line-height: 1.4; letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--ink-mute); font-variant-numeric: tabular-nums;
}
.assistant-event::before, .assistant-event::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* Why a call couldn't start, or ended early */
.assistant-notice { align-self: center; max-width: 92%; font-size: var(--text-ui); line-height: 1.5; text-align: center; text-wrap: balance; color: var(--ink-soft); }
.assistant-notice .text-link { text-underline-offset: 3px; }

/* Until the first words of an answer arrive */
.assistant-typing { display: inline-flex; gap: 4px; padding-block: 8px; vertical-align: middle; }
.assistant-typing span { width: 6px; height: 6px; border-radius: 50%; background: var(--ink-mute); animation: assistant-typing 1.2s ease-in-out infinite; }
.assistant-typing span:nth-child(2) { animation-delay: 0.15s; }
.assistant-typing span:nth-child(3) { animation-delay: 0.3s; }

/* Questions to start with, as a list ruled like a card's rows */
.assistant-suggestions { display: grid; border-top: 1px solid var(--line); }
.assistant-suggestion {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); width: 100%; min-height: 48px; padding: 12px 2px;
  border: 0; border-bottom: 1px solid var(--line); background: none; color: var(--ink); cursor: pointer;
  font-size: var(--text-small); font-weight: 500; line-height: 1.35; text-align: left;
}
.assistant-suggestion .icon { width: 16px; height: 16px; color: var(--ink-mute); transition: transform var(--dur-ui) var(--ease-out), color var(--dur-fast); }
.assistant-suggestion:hover .icon { transform: translateX(3px); color: var(--ink); }
/* Inside the row, which the thread's scrolling would otherwise clip */
.assistant-suggestion:focus-visible { outline-offset: -2px; }

/* ---------- The message box, the call's controls in its place, or the line to call ---------- */
.assistant-footer { flex: none; padding: 12px 12px max(12px, env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--line); }
/* Nothing to show until a call starts */
.assistant-footer:not(:has(> :not([hidden]))) { display: none; }
/* One box, with Send inside it, edged as the contact form's fields are (--field-line, 3:1); focus darkens its edge and lays
   the amber wash around it */
.assistant-form {
  display: flex; align-items: flex-end; gap: var(--space-2); padding: 4px 4px 4px 16px;
  border: 1px solid var(--field-line); border-radius: var(--radius-xl); background: var(--c-white);
  transition: border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.assistant-form:hover { border-color: var(--ink-mute); }
.assistant-form:focus-within { border-color: var(--ink); box-shadow: 0 0 0 3px var(--amber-soft); }
/* 16px text, so phones don't zoom in on it */
.assistant-input {
  flex: 1; min-width: 0; min-height: 40px; max-height: 128px; padding: 9px 0;
  border: 0; background: none; color: var(--ink); font-size: 16px; line-height: 1.35; resize: none;
}
.assistant-input::placeholder { color: var(--ink-mute); }
.assistant-input:focus { outline: none; }
.assistant-send {
  display: grid; place-items: center; flex: none; width: 40px; height: 40px; padding: 0;
  border: 0; border-radius: 50%; background: var(--amber); color: var(--c-ink); cursor: pointer; transition: background-color var(--dur-fast), color var(--dur-fast);
}
.assistant-send:hover:not(:disabled) { background: var(--amber-hover); }
.assistant-send:disabled { background: var(--c-panel); color: var(--ink-mute); cursor: default; }
.assistant-send .icon { width: 18px; height: 18px; transform: rotate(-90deg); }

/* On a call: who's talking, how long is left, and the button to hang up */
.assistant-callbar { display: flex; align-items: center; gap: 12px; min-height: 48px; padding-left: 2px; }
.assistant-call-info { flex: 1; min-width: 0; }
.assistant-call-name { font-weight: 600; line-height: 1.3; }
.assistant-call-status {
  font-family: var(--font-mono); font-size: 11px; font-weight: 500; line-height: 1.5; letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--ink-mute); font-variant-numeric: tabular-nums;
}
.assistant-callbar[data-state="live"] .assistant-call-status { color: var(--amber-ink); }
.assistant-call-timer { color: var(--ink-mute); }
.assistant-call-timer:not(:empty)::before { content: " · "; }
.assistant-hangup { flex: none; }
/* The handset, put down */
.assistant-hangup .icon { transform: rotate(135deg); }

/* The call's mark: breathing while the call connects, rippling while HeyHi Voice speaks; its bars follow the visitor's
   voice */
.assistant-orb { position: relative; display: grid; flex: none; place-items: center; width: 44px; height: 44px; }
.assistant-orb-core {
  position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 2px; width: 100%; height: 100%;
  border-radius: 50%; background: var(--amber);
}
.assistant-orb-core span { width: 3px; height: calc(4px + 16px * var(--mic-level, 0) * var(--bar, 1)); border-radius: 2px; background: var(--ink); transition: height 0.08s linear; }
.assistant-orb-core span:nth-child(1), .assistant-orb-core span:nth-child(5) { --bar: 0.45; }
.assistant-orb-core span:nth-child(2), .assistant-orb-core span:nth-child(4) { --bar: 0.75; }
.assistant-orb-ring { position: absolute; inset: 0; border: 1.5px solid var(--amber); border-radius: 50%; opacity: 0; }
.assistant-callbar[data-state="connecting"] .assistant-orb-core { animation: assistant-breathe 1.2s ease-in-out infinite; }
.assistant-callbar.is-speaking .assistant-orb-ring { animation: assistant-ripple 1.6s ease-out infinite; }
.assistant-callbar.is-speaking .assistant-orb-ring + .assistant-orb-ring { animation-delay: 0.8s; }
/* While HeyHi Voice speaks, the bars move with it instead */
.assistant-callbar.is-speaking .assistant-orb-core span { animation: assistant-equalize 0.8s ease-in-out infinite alternate; }
.assistant-callbar.is-speaking .assistant-orb-core span:nth-child(2) { animation-delay: -0.5s; }
.assistant-callbar.is-speaking .assistant-orb-core span:nth-child(3) { animation-delay: -0.2s; }
.assistant-callbar.is-speaking .assistant-orb-core span:nth-child(4) { animation-delay: -0.65s; }
.assistant-callbar.is-speaking .assistant-orb-core span:nth-child(5) { animation-delay: -0.35s; }

@keyframes assistant-typing { 0%, 60%, 100% { opacity: 0.35; transform: none; } 30% { opacity: 1; transform: translateY(-3px); } }
@keyframes assistant-ripple { from { opacity: 0.9; transform: scale(1); } to { opacity: 0; transform: scale(1.55); } }
@keyframes assistant-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.06); } }
@keyframes assistant-equalize { from { height: 4px; } to { height: calc(6px + 14px * var(--bar, 1)); } }

/* ---------- Fitting around the page ---------- */
/* Without chat there's only the welcome and the call, so the card is only as tall as they are, until a call's
   transcript fills it */
@media (min-width: 36em) {
  .assistant-panel--call-only { height: auto; }
}
/* On phones the launcher is just its disc, so it covers as little of the page as it can; its words stay for screen
   readers, as its name */
@media (max-width: 35.99em) {
  .assistant-launcher { width: 52px; padding: 0; }
  .assistant-launcher-label {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }

  /* Without chat, a sheet from the bottom of the screen over the dimmed page, rather than a screen with one line on it */
  .assistant-panel--call-only {
    inset: auto 0 0; max-height: calc(100dvh - var(--header-h)); border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    box-shadow: var(--shadow-pop);
  }
  @starting-style {
    .assistant-panel--call-only { opacity: 1; transform: translateY(100%); }
  }
  .assistant-panel--call-only[hidden] { opacity: 1; transform: translateY(100%); transition-duration: var(--dur-ui); }
  .assistant-panel--call-only .assistant-header { padding-top: 12px; }
  body:has(> .assistant-panel--call-only:not([hidden]))::after {
    content: ""; position: fixed; inset: 0; z-index: 55; background: color-mix(in srgb, var(--c-night) 44%, transparent);
    animation: assistant-fade var(--dur-ui) var(--ease-out);
  }
}
@keyframes assistant-fade { from { opacity: 0; } }
/* The open menu sheet has the screen to itself */
html.menu-open .assistant-launcher,
html.menu-open .assistant-teaser { display: none; }
