/*!
 * Ally chat app — styles.
 *
 * Every colour and the typeface come from the --ally-* custom properties the
 * server writes into :root from widget.theme, so a rebrand is a database edit
 * rather than a deploy. Light theme only: this renders inside the firm's own
 * white site, and a dark variant that only sometimes matches the host page
 * looks broken rather than adaptive.
 *
 * Contrast: text on --ally-primary is white by default. If the configured
 * primary is light enough that white would fail WCAG AA, embed.js sets
 * data-on-primary="dark" on <html> after a luminance check and the rules below
 * flip to near-black. The check happens in JS because CSS cannot read the
 * luminance of a custom property.
 */

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

html, body {
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background: var(--ally-bg, #fff);
  color: var(--ally-text, #1c2533);
  font-family: var(--ally-font, system-ui, -apple-system, "Segoe UI", sans-serif);
  -webkit-text-size-adjust: 100%;
}

/* --ally-vh is set by embed.js from visualViewport when this document is the
   top-level page (standalone /s/ page): iOS does not shrink the layout
   viewport for the keyboard, so 100% would leave the composer under it. */
#app { display: flex; flex-direction: column; height: var(--ally-vh, 100%); min-height: 0; }

/* ── Header ──────────────────────────────────────────────────────────────── */

/* Two rows, never one.
   Four language pills and an identity block do not fit on one line at 390px:
   they used to collide with the name and push the header over the transcript.
   Row 1 is identity + close, row 2 is a horizontally scrollable language
   strip. Total height stays under 110px so the first bubble is always
   visible above the composer. */

.ally-header {
  flex: 0 0 auto;
  background: var(--ally-primary, #1e3a5f);
  color: #fff;
  padding-top: env(safe-area-inset-top, 0px);
}
:root[data-on-primary="dark"] .ally-header { color: #0f172a; }

/* ── Standalone page (/s/<slug>) ─────────────────────────────────────────────
   Session 4: the page used to be a bare transcript with no identity and
   full-width bubbles. It now wears the embed's header (minus the close
   button — there is nothing to close) in a centred 680px column, with the
   firm's address as a footer on desktop. At phone width it is exactly the
   embed's full-screen layout. */
.ally-mode-page .ally-close { display: none; }
.ally-footer { display: none; }
@media (min-width: 640px) {
  body.ally-mode-page { background: var(--ally-surface, #f4f6f9); }
  .ally-mode-page #app {
    max-width: 680px; margin: 0 auto; background: var(--ally-bg, #fff);
    border-left: 1px solid rgba(0, 0, 0, .06); border-right: 1px solid rgba(0, 0, 0, .06);
    box-shadow: 0 0 40px rgba(15, 23, 42, .06);
  }
  .ally-mode-page .ally-footer:not(:empty) {
    display: block; flex: 0 0 auto; padding: 10px 16px 14px; text-align: center;
    font-size: 13px; line-height: 1.5; color: var(--ally-text, #1c2533); opacity: .7;
    border-top: 1px solid rgba(0, 0, 0, .06);
  }
}

.ally-headrow {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
}

.ally-avatar {
  width: 36px; height: 36px; border-radius: 50%;
  background: rgba(255, 255, 255, .22);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 16px; flex: 0 0 auto;
  background-size: cover; background-position: center;
}
:root[data-on-primary="dark"] .ally-avatar { background: rgba(15, 23, 42, .12); }

/* min-width:0 is what lets the ellipsis work — without it the flex item
   refuses to shrink below its text and pushes the close button off-screen. */
.ally-id { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.ally-name {
  font-weight: 600; font-size: 16px; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ally-firm {
  font-size: 13px; opacity: .8; line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Scrolls sideways rather than wrapping: a wrapped second row of pills would
   push the header past its budget on the narrowest phones, and four
   languages will become five. The scrollbar is hidden because a visible one
   inside a 90px header reads as damage. */
.ally-langs {
  display: flex;
  gap: 6px;
  padding: 0 12px 10px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  overscroll-behavior-x: contain;
}
.ally-langs::-webkit-scrollbar { display: none; }
/* A single-language widget renders no pills; without this the empty strip
   still claims its bottom padding and the header carries 10px of nothing. */
.ally-langs:empty { display: none; }

.ally-pill {
  flex: 0 0 auto;
  white-space: nowrap;
  scroll-snap-align: start;
  border: 0; border-radius: 999px;
  min-height: 32px; padding: 0 12px;
  background: rgba(255, 255, 255, .14); color: #fff;
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.ally-pill[aria-pressed="true"] { background: #fff; color: var(--ally-primary, #1e3a5f); }
:root[data-on-primary="dark"] .ally-pill { background: rgba(15, 23, 42, .1); color: #0f172a; }
:root[data-on-primary="dark"] .ally-pill[aria-pressed="true"] { background: #0f172a; color: #fff; }

.ally-close {
  border: 0; background: transparent; color: inherit; cursor: pointer;
  width: 36px; height: 36px; border-radius: 50%; font-size: 20px; line-height: 1;
  flex: 0 0 auto;
}
.ally-close:hover { background: rgba(255, 255, 255, .16); }
/* Nothing to close: an inline embed is part of the host page, and in page
   mode the whole header is gone already. */
.ally-mode-inline .ally-close { display: none; }

/* ── Progress ────────────────────────────────────────────────────────────────
   No numbers and no phase names. The staff app shows neither, for the same
   reason: the tree holds every case path and one screening walks one of them,
   so any count would be a number the visitor could not act on.               */

.ally-progress { height: 3px; background: rgba(0, 0, 0, .08); flex: 0 0 auto; }
.ally-progress > i {
  display: block; height: 100%; width: 0%;
  background: var(--ally-accent, #C9A84C);
  transition: width .35s ease;
}
@media (prefers-reduced-motion: reduce) { .ally-progress > i { transition: none; } }

/* ── Transcript ──────────────────────────────────────────────────────────── */

/* min-height:0 is the whole fix for the clipped transcript: a flex child
   defaults to min-height:auto, which refuses to shrink below its content, so
   the list grew past the viewport and pushed the composer off the bottom
   instead of scrolling inside itself. */
.ally-log {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  padding: 16px 12px 8px; display: flex; flex-direction: column; gap: 6px;
  overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
}

.ally-row { display: flex; }
.ally-row.bot { justify-content: flex-start; }
.ally-row.visitor { justify-content: flex-end; }

/* 6px between consecutive bubbles from the same speaker, 14px when the
   speaker changes — the gap is what makes a transcript readable as a
   conversation rather than a list. */
.ally-row.bot + .ally-row.visitor,
.ally-row.visitor + .ally-row.bot { margin-top: 8px; }

.ally-bubble {
  max-width: 84%;
  padding: 10px 14px;
  border-radius: var(--ally-radius, 12px);
  line-height: 1.45;
  font-size: 15px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.bot .ally-bubble { background: var(--ally-surface, #f4f6f9); color: var(--ally-text, #1c2533); border-bottom-left-radius: 6px; }
.visitor .ally-bubble { background: var(--ally-primary, #1e3a5f); color: #fff; border-bottom-right-radius: 6px; }
:root[data-on-primary="dark"] .visitor .ally-bubble { color: #0f172a; }

.ally-helper { display: block; margin-top: 6px; font-size: 13px; opacity: .75; }

.ally-typing { display: inline-flex; gap: 4px; align-items: center; padding: 4px 2px; }
.ally-typing i {
  width: 7px; height: 7px; border-radius: 50%; background: currentColor; opacity: .45;
  animation: ally-blink 1.1s infinite ease-in-out;
}
.ally-typing i:nth-child(2) { animation-delay: .18s; }
.ally-typing i:nth-child(3) { animation-delay: .36s; }
@keyframes ally-blink { 0%, 80%, 100% { opacity: .25; } 40% { opacity: .9; } }
@media (prefers-reduced-motion: reduce) { .ally-typing i { animation: none; } }

/* ── Outcome card ────────────────────────────────────────────────────────── */

.ally-outcome {
  background: var(--ally-surface, #f4f6f9);
  border: 1px solid rgba(0, 0, 0, .08);
  border-radius: var(--ally-radius, 12px);
  padding: 16px; max-width: 100%;
}
.ally-outcome h2 { margin: 0 0 8px; font-size: 17px; line-height: 1.35; }
.ally-outcome p { margin: 0 0 12px; font-size: 15px; line-height: 1.55; }
.ally-outcome .ally-foot { margin: 12px 0 0; font-size: 13px; opacity: .7; line-height: 1.5; }
.ally-call {
  display: block; text-align: center; text-decoration: none; font-weight: 700; font-size: 16px;
  background: var(--ally-primary, #1e3a5f); color: #fff;
  border-radius: var(--ally-radius, 12px); padding: 14px 16px; min-height: 48px;
}
:root[data-on-primary="dark"] .ally-call { color: #0f172a; }

/* ── Composer ────────────────────────────────────────────────────────────── */

/* position:static is deliberate and load-bearing. Nothing in this app is
   absolutely or fixed-positioned: the column is a real flex layout, so the
   composer cannot float over the last message and the iOS keyboard cannot
   strand it behind the fold. */
.ally-composer {
  flex: 0 0 auto; position: static;
  border-top: 1px solid rgba(0, 0, 0, .06);
  padding: 10px 12px; padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  background: var(--ally-bg, #fff); display: flex; flex-direction: column;
}

/* Chips sit at the TOP of the composer, not in the transcript, so the answer
   buttons can never be scrolled out of reach. A long checklist scrolls within
   its own 40vh rather than eating the conversation. */
.ally-chips {
  display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px;
  max-height: 40vh; overflow-y: auto; overscroll-behavior: contain;
}
.ally-chips:empty { margin-bottom: 0; }
.ally-chip {
  min-height: 44px; padding: 10px 14px; font: inherit; font-size: 15px; font-weight: 600;
  border-radius: var(--ally-radius, 12px);
  border: 2px solid var(--ally-primary, #1e3a5f);
  background: #fff; color: var(--ally-primary, #1e3a5f);
  cursor: pointer; text-align: left; flex: 0 1 auto; max-width: 100%;
  overflow-wrap: anywhere;
}
.ally-chip:hover { background: var(--ally-surface, #f4f6f9); }
.ally-chip[aria-pressed="true"] { background: var(--ally-primary, #1e3a5f); color: #fff; }
:root[data-on-primary="dark"] .ally-chip[aria-pressed="true"] { color: #0f172a; }
.ally-chip.primary { background: var(--ally-primary, #1e3a5f); color: #fff; border-color: var(--ally-primary, #1e3a5f); }
:root[data-on-primary="dark"] .ally-chip.primary { color: #0f172a; }
.ally-chip.quiet {
  border: 0; background: transparent; color: var(--ally-text, #1c2533);
  opacity: .72; font-weight: 600; text-decoration: underline; padding: 10px 6px;
}
.ally-chip:disabled { opacity: .4; cursor: default; }

.ally-textrow { display: flex; gap: 8px; align-items: center; }
.ally-secondary:not(:empty) { margin-top: 8px; }
.ally-slot:not(:empty) { margin-bottom: 8px; }
.ally-input {
  flex: 1 1 auto; min-width: 0; min-height: 44px;
  /* 16px exactly: anything smaller makes iOS Safari zoom the page on focus. */
  font: inherit; font-size: 16px;
  padding: 10px 12px; border-radius: var(--ally-radius, 12px);
  border: 1px solid rgba(0, 0, 0, .18); background: #fff; color: var(--ally-text, #1c2533);
}
.ally-input:disabled { background: var(--ally-surface, #f4f6f9); opacity: .7; }
.ally-send {
  flex: 0 0 auto; min-height: 44px; padding: 10px 16px; border: 0;
  border-radius: var(--ally-radius, 12px);
  background: var(--ally-primary, #1e3a5f); color: #fff;
  font: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
}
:root[data-on-primary="dark"] .ally-send { color: #0f172a; }
.ally-send:disabled { opacity: .45; cursor: default; }

/* Story mode: the same field, sized for a paragraph rather than a line.
   It grows with what is typed and stops at six rows, after which it scrolls —
   a box that keeps growing pushes the Send button off a phone screen. */
.ally-story {
  flex: 1 1 auto; min-width: 0;
  font: inherit; font-size: 16px; line-height: 1.5;
  padding: 10px 12px; border-radius: var(--ally-radius, 12px);
  border: 1px solid rgba(0, 0, 0, .18); background: #fff; color: var(--ally-text, #1c2533);
  resize: none; overflow-y: auto; min-height: 88px; max-height: 168px;
}
.ally-story:disabled { background: var(--ally-surface, #f4f6f9); opacity: .7; }
/* Send sits at the bottom of a tall box rather than floating at its middle. */
.ally-textrow.story { align-items: flex-end; }

.ally-secondary { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.ally-link {
  border: 0; background: transparent; padding: 8px 4px; min-height: 40px;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--ally-text, #1c2533);
  opacity: .7; text-decoration: underline; cursor: pointer;
}
.ally-link:hover { opacity: 1; }

.ally-slot { display: flex; justify-content: center; }
.ally-error { font-size: 14px; line-height: 1.5; color: #b91c1c; }

/* ── Talk to a person ────────────────────────────────────────────────────────
   Deliberately small and outlined: it must be findable at every step without
   ever competing with the answer the visitor is being asked for. It is the
   only control that never disappears while the offer stands.               */

.ally-actions { display: flex; justify-content: flex-end; margin-bottom: 8px; }
.ally-actions[hidden] { display: none; }

.ally-talk {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 32px; padding: 0 12px;
  border: 1px solid var(--ally-primary, #1e3a5f);
  border-radius: 999px; background: transparent;
  color: var(--ally-primary, #1e3a5f);
  font: inherit; font-size: 13px; font-weight: 600;
  cursor: pointer; white-space: nowrap; flex: 0 0 auto;
}
.ally-talk[hidden] { display: none; }
.ally-talk svg { width: 14px; height: 14px; fill: currentColor; flex: 0 0 auto; }
.ally-talk:hover { background: var(--ally-surface, #f4f6f9); }

/* In the header the background IS the primary colour, so an outline in that
   colour would be invisible. Borrow the header's own text colour instead. */
.ally-headrow .ally-talk {
  border-color: currentColor; color: inherit; margin-right: 2px;
}
.ally-headrow .ally-talk:hover { background: rgba(255, 255, 255, .16); }
:root[data-on-primary="dark"] .ally-headrow .ally-talk:hover { background: rgba(15, 23, 42, .1); }

/* Said once, just after we have a way to reach them. */
.ally-hint {
  margin-top: 8px; font-size: 13px; line-height: 1.45;
  /* .72, not .6: at .6 this was 4.19:1 on white, under AA. */
  color: var(--ally-text, #1c2533); opacity: .72;
}
.ally-hint[hidden] { display: none; }

/* ── System lines ────────────────────────────────────────────────────────────
   A step that did not land is a quiet aside, not a bot message and not a
   screen: it must never read as Ally having said something.               */

.ally-system {
  align-self: center; max-width: 92%; text-align: center;
  font-size: 13px; line-height: 1.5;
  color: var(--ally-text, #1c2533); opacity: .65;
}
.ally-system-btn {
  display: inline-flex; align-items: center; gap: 6px;
  border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 13px; color: inherit;
  padding: 6px 4px; min-height: 32px; text-decoration: underline;
}
.ally-retry { font-size: 14px; text-decoration: none; }

/* ── Focus (WCAG 2.2: 2.4.7 visible, 1.4.11 ≥ 3:1) ───────────────────────────
   Two tones, because no single colour clears 3:1 everywhere: the Brooks gold
   accent is 2.3:1 on white, and the AI-bert accent IS the header colour
   (1:1). So the ring is the accent outline with a primary-coloured ring
   inside it — one of the two always contrasts — and inside the header,
   where the background is the primary, it turns white. */
:focus-visible {
  outline: 2px solid var(--ally-accent, #C9A84C); outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--ally-primary, #1e3a5f);
}
.ally-header :focus-visible { outline-color: #fff; box-shadow: 0 0 0 2px var(--ally-primary, #1e3a5f); }
:root[data-on-primary="dark"] .ally-header :focus-visible { outline-color: #0f172a; }

/* Landscape phones: keep content clear of the notch and the rounded corners. */
.ally-log, .ally-composer {
  padding-left: max(12px, env(safe-area-inset-left, 0px));
  padding-right: max(12px, env(safe-area-inset-right, 0px));
}
.ally-outcome { scroll-margin-bottom: env(safe-area-inset-bottom, 0px); }


@media (max-width: 380px) {
  .ally-bubble, .ally-chip { font-size: 14px; }
  .ally-log { padding-top: 12px; padding-bottom: 8px; }
  .ally-headrow { padding: 8px 10px; }
  .ally-langs { padding: 0 10px 8px; }
}
