/* Element Education voice agent widget.
   Design system: The Exploded View. See DESIGN.md in the site repo.
   Flat sheet, hairline rules, hard squares, no shadow except the focus ring. */

/* ---------- LAUNCHER ----------
   A hard rectangle pinned bottom right. Graphite, not Vermilion: the One
   Signal Rule allows one primary action per viewport and the page already
   spends it on the booking CTA. Graphite reads as an instrument attached to
   the page rather than a second competing offer. */

.eev-launcher {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  z-index: 9998;
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 3rem;
  padding: 0.875rem 1.25rem;
  background: #14181C;
  color: #F2F5F7;
  border: 1px solid #14181C;
  border-radius: 2px;
  font-family: 'Unbounded', system-ui, sans-serif;
  font-weight: 600;
  font-size: 0.875rem;
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: background-color 120ms cubic-bezier(0.2, 0, 0.1, 1);
}
.eev-launcher:hover { background: #0A63C9; border-color: #0A63C9; }
.eev-launcher:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px #F2F5F7, 0 0 0 4px #0A63C9;
}
.eev-launcher svg { width: 1.125rem; height: 1.125rem; flex: none; }

/* No paper offset here. The launcher is position:fixed with a z-index, which
   makes it its own stacking context, so a z-index:-1 pseudo-element paints
   above the element's own background instead of behind it and washes the fill
   out. The offset belongs on the panel, which is not a stacking context. */

.eev-launcher[hidden] { display: none; }

@media (max-width: 600px) {
  /* The label stays on small screens. An unlabelled speech-bubble icon is a
     guess: it could be feedback, support, or a comment thread. The button is
     the only invitation to talk to Keel, so it says so at every width. */
  .eev-launcher { right: 1rem; bottom: 1rem; padding: 0.8125rem 1rem; }
  .eev-launcher span { font-size: 0.875rem; }
}

/* Narrowest phones. The label still wins over the icon, which drops out rather
   than squeezing the words it exists to support. */
@media (max-width: 360px) {
  .eev-launcher { right: 0.75rem; bottom: 0.75rem; padding: 0.75rem 0.875rem; gap: 0.5rem; }
  .eev-launcher svg { display: none; }
}

/* ---------- MODAL ----------
   Flat scrim, never a backdrop blur: the system bans glassmorphism outright.
   The panel gets a 1px Graphite outline and the paper offset for depth. */

.eev-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(20, 24, 28, 0.55);
}
.eev-overlay[hidden] { display: none; }

.eev-overlay .eev { width: 100%; max-width: 36rem; max-height: 100%; display: flex; flex-direction: column; }
.eev-overlay .eev-body { overflow-y: auto; }

.eev-close {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  margin: -0.75rem -0.75rem -0.75rem 0;
  background: none;
  border: 0;
  color: #5A6672;
  cursor: pointer;
}
.eev-close:hover { color: #14181C; }
.eev-close svg { width: 1rem; height: 1rem; }

@media (max-width: 600px) {
  /* A full height sheet panel, matching the site's mobile nav pattern. */
  .eev-overlay { padding: 0; align-items: stretch; }
  .eev-overlay .eev { max-width: none; max-height: none; height: 100%; border: 0; }
  .eev-overlay .eev::after { display: none; }
}

.eev {
  --eev-sheet: #F2F5F7;
  --eev-sunk: #E7ECF0;
  --eev-graphite: #14181C;
  --eev-graphite-soft: #5A6672;
  --eev-rule: #C3CDD6;
  --eev-signal: #0A63C9;
  --eev-sky: #54B8EE;
  --eev-revision: #C9331B;
  --eev-shipped: #0A7A4D;
  --eev-ease: cubic-bezier(0.2, 0, 0.1, 1);

  position: relative;
  max-width: 34rem;
  background: var(--eev-sheet);
  border: 1px solid var(--eev-graphite);
  color: var(--eev-graphite);
  font-family: 'DM Sans', system-ui, sans-serif;
  font-size: 1rem;
  line-height: 1.6;
}

/* Depth is a second sheet of paper behind, never a shadow. */
.eev::after {
  content: '';
  position: absolute;
  inset: 4px -4px -4px 4px;
  background: var(--eev-sunk);
  z-index: -1;
  pointer-events: none;
}

.eev *,
.eev *::before,
.eev *::after { box-sizing: border-box; }

.eev :focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--eev-sheet), 0 0 0 4px var(--eev-signal);
}

/* ---------- TITLE BLOCK ---------- */

.eev-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--eev-graphite);
}

.eev-label {
  font-size: 0.6875rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--eev-graphite-soft);
}

.eev-head .eev-label:first-child { color: var(--eev-graphite); }

/* ---------- BODY ---------- */

.eev-body { padding: 1.25rem; }

.eev-title {
  font-family: 'Unbounded', system-ui, sans-serif;
  font-weight: 600;
  font-size: 1.0625rem;
  line-height: 1.3;
  letter-spacing: -0.01em;
  margin-bottom: 0.5rem;
}

.eev-intro {
  color: var(--eev-graphite-soft);
  max-width: 46ch;
  margin-bottom: 1.25rem;
}


/* ---------- CONTROLS ---------- */

.eev-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
}

.eev-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding: 0.875rem 1.5rem;
  border: 1px solid transparent;
  border-radius: 2px;
  font-family: 'Unbounded', system-ui, sans-serif;
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: background-color 120ms var(--eev-ease), color 120ms var(--eev-ease);
}

.eev-btn-primary { background: var(--eev-revision); color: var(--eev-sheet); }
.eev-btn-primary:hover:not(:disabled) { background: var(--eev-graphite); }

.eev-btn-secondary {
  background: var(--eev-sheet);
  border-color: var(--eev-graphite);
  color: var(--eev-graphite);
}
.eev-btn-secondary:hover:not(:disabled) { background: var(--eev-sunk); }

.eev-btn:disabled { opacity: 0.45; cursor: not-allowed; }

.eev-btn svg { width: 1.125rem; height: 1.125rem; flex: none; }

.eev-link {
  color: var(--eev-signal);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  cursor: pointer;
  min-height: 2.75rem;
}
.eev-link:hover { text-decoration-thickness: 2px; }

/* ---------- VOICE STAGE ----------
   An oscilloscope trace, not a glowing orb. Hard rectangular bars on a centre
   axis, driven by real amplitude from the microphone and from Keel's playback,
   so the movement is a readout of something rather than decoration.

   Graphite bars are the visitor speaking. Signal Blue bars are Keel speaking.
   That is the only thing distinguishing the two directions and it is enough. */

.eev-stage {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.75rem 0 1.25rem;
  border-bottom: 1px solid var(--eev-rule);
  margin-bottom: 1.25rem;
}
.eev-stage[hidden] { display: none; }

.eev-scope {
  display: block;
  width: 100%;
  height: 13rem;
}
/* `display: block` above beats the [hidden] attribute, so the 2D fallback has
   to be hidden explicitly once WebGL takes over. Without this both canvases
   render and you get two orbs. */
.eev-scope[hidden] { display: none; }

.eev-stage-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.eev-stage-state { display: flex; align-items: center; gap: 0.5rem; }

/* A hard square that fills in to mark the live state. No pulsing dot. */
.eev-stage-mark {
  width: 0.5rem;
  height: 0.5rem;
  border: 1px solid var(--eev-graphite-soft);
  flex: none;
}
.eev-stage[data-mode='listening'] .eev-stage-mark { background: var(--eev-graphite); border-color: var(--eev-graphite); }
.eev-stage[data-mode='waiting'] .eev-stage-mark { background: transparent; border-color: var(--eev-graphite-soft); }
.eev-stage[data-mode='speaking']  .eev-stage-mark { background: var(--eev-signal); border-color: var(--eev-signal); }

.eev-stage[data-mode='speaking'] .eev-stage-state .eev-label { color: var(--eev-signal); }

@media (prefers-reduced-motion: reduce) {
  /* The state label and the filled mark still carry the information. The
     recorder holds at a flat datum instead of running. */
  .eev-scope { opacity: 0.55; }
}

/* ---------- STATUS ---------- */

.eev-status {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 1.5rem;
  margin-top: 1rem;
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--eev-graphite-soft);
}

@media (prefers-reduced-motion: reduce) {
  .eev-btn { transition: none; }
}

/* ---------- TRANSCRIPT ----------
   Reads as a conversation, not a table of records: the exchange is the main
   thing on the sheet and it grows downward toward the input. It stays inside the
   system by using the leader-line idiom instead of chat bubbles, which are
   pills, which the system bans outright. The speaker is carried by the rule on
   the left, not by a rounded container. */

.eev-transcript {
  margin-bottom: 1.25rem;
  max-height: 26rem;
  overflow-y: auto;
  scroll-behavior: smooth;
}

.eev-turn {
  padding: 0.125rem 0 0.125rem 0.875rem;
  margin-bottom: 1rem;
  border-left: 2px solid var(--eev-rule);
}

/* The agent speaks on the structural axis. The visitor is a quieter mark
   beside it, indented so the alternation is legible at a glance. */
.eev-turn[data-role='agent'] { border-left-color: var(--eev-signal); }
.eev-turn[data-role='you'] {
  border-left-color: var(--eev-rule);
  margin-left: 2rem;
  color: var(--eev-graphite-soft);
}

.eev-turn .eev-label { display: block; margin-bottom: 0.25rem; }
.eev-turn[data-role='agent'] .eev-label { color: var(--eev-signal); }
.eev-turn p { margin: 0; max-width: 58ch; }
.eev-turn:last-child { margin-bottom: 0; }

/* Working indicator. Three marks, one leader line, no bouncing dots. Motion is
   a single opacity fade so it costs nothing and stops under reduced motion. */
.eev-working {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  padding-left: 0.875rem;
  border-left: 2px solid var(--eev-signal);
  min-height: 1.5rem;
}
.eev-working i {
  width: 4px;
  height: 4px;
  background: var(--eev-signal);
  animation: eev-pulse 1.2s var(--eev-ease) infinite;
}
.eev-working i:nth-child(2) { animation-delay: 0.15s; }
.eev-working i:nth-child(3) { animation-delay: 0.3s; }

@keyframes eev-pulse {
  0%, 100% { opacity: 0.2; }
  50%      { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .eev-working i { animation: none; opacity: 0.6; }
  .eev-transcript { scroll-behavior: auto; }
}

/* ---------- PARTS LEDGER ----------
   Demoted to a progress strip in the title block. It is the instrument reading,
   not the conversation, so it belongs at the edge of the sheet rather than
   underneath the dialogue competing with it. */

.eev-ledger { display: flex; gap: 1rem; align-items: center; }

.eev-ledger-row { display: flex; align-items: center; gap: 0.375rem; }

.eev-chip {
  width: 1.125rem;
  height: 1.125rem;
  display: grid;
  place-items: center;
  background: var(--eev-rule);
  color: var(--eev-sheet);
  font-family: 'Unbounded', system-ui, sans-serif;
  font-weight: 600;
  font-size: 0.625rem;
  transition: background-color 150ms var(--eev-ease);
}
.eev-ledger-row[data-state='met'] .eev-chip { background: var(--eev-shipped); }
.eev-ledger-row[data-state='unmet'] .eev-chip { background: var(--eev-revision); }

.eev-ledger-name {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--eev-graphite-soft);
}
.eev-ledger-row[data-state='met'] .eev-ledger-name { color: var(--eev-graphite); }
.eev-ledger-name small { display: none; }
.eev-state { display: none; }

@media (prefers-reduced-motion: reduce) {
  .eev-chip { transition: none; }
}

@media (max-width: 600px) {
  .eev-ledger { gap: 0.625rem; }
  .eev-ledger-name { letter-spacing: 0.08em; }
}

/* ---------- OUTCOME ---------- */

.eev-outcome {
  margin-top: 1.25rem;
  padding: 1.25rem;
  background: var(--eev-sunk);
  border: 1px solid var(--eev-graphite);
}
.eev-outcome .eev-label { display: block; margin-bottom: 0.5rem; }
.eev-outcome p { margin: 0 0 1rem; max-width: 52ch; }

.eev-error {
  margin-top: 1rem;
  padding: 0.75rem 1rem;
  border-left: 2px solid var(--eev-revision);
  background: var(--eev-sunk);
  font-size: 0.875rem;
}

/* ---------- COMPOSE ----------
   A real writing area, not a one line field. People describe an app idea in a
   couple of sentences, and a single-line input tells them not to. */

.eev-compose { display: block; width: 100%; }
.eev-compose label { display: block; }
.eev-compose .eev-label { display: block; margin-bottom: 0.375rem; }

.eev-input {
  display: block;
  width: 100%;
  min-height: 5.25rem;
  max-height: 12rem;
  padding: 0.75rem 0.875rem;
  background: var(--eev-sheet);
  border: 1px solid var(--eev-rule);
  border-bottom-width: 2px;
  border-radius: 2px;
  font: inherit;
  line-height: 1.5;
  color: var(--eev-graphite);
  resize: none;
  overflow-y: auto;
}
.eev-input::placeholder { color: var(--eev-graphite-soft); }
.eev-input:focus {
  outline: none;
  border-color: var(--eev-graphite);
  border-bottom-color: var(--eev-signal);
}
.eev-compose label:focus-within .eev-label { color: var(--eev-signal); }

.eev-compose-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.75rem;
}
.eev-hint {
  font-size: 0.75rem;
  color: var(--eev-graphite-soft);
}
@media (max-width: 600px) {
  .eev-hint { display: none; }
  .eev-compose-actions .eev-btn { width: 100%; justify-content: center; }
}

.eev-vh {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@media (max-width: 600px) {
  .eev-body { padding: 1rem; }
  .eev-head { padding: 0.75rem 1rem; }
  .eev-controls { flex-direction: column; align-items: stretch; }
  .eev-btn { justify-content: center; }
}
