/* Animations + visual tweaks that don't fit cleanly in utility classes.
   Brand-specific bits (colours, fonts, radii) live in the brand visual
   manifest (data/brand_visuals/<id>/visual.json) and are applied at boot
   by app.js — see applyBrand(). Everything below is brand-agnostic. */

/* ---- Sensible fallbacks until /api/brand resolves -------------------- */
[data-theme="light"] {
  --color-primary: #502314;
  --color-primary-content: #f5ebdc;
  --color-base-100: #fffaf2;
  --color-base-200: #faf3e8;
  --color-base-300: #efe1cc;
  --color-base-content: #502314;
  --color-success: #198737;
  --color-success-content: #f5ebdc;
  --color-warning: #e0a82e;
  --color-warning-content: #2c170d;
  --color-error: #d62300;
  --color-error-content: #f5ebdc;
  --radius-box: 12px;
  --radius-field: 12px;
  --radius-selector: 9999px;
}

/* ---- bk.fr-flavoured polish for the BK brands ------------------------
   Scoped on data-brand so other brands keep their own chrome. Mirrors
   burgerking.fr's signature touches: uppercase tracked CTA labels,
   flat cream cards with hairline borders, tight type rhythm. The
   selector ^="bk_" sweeps both bk_germany and bk_poland. */
[data-brand^="bk_"] {
  /* Tighter button radius (bk.fr uses ~4px for contained CTAs). */
  --radius-field: 6px;
}
[data-brand^="bk_"] .btn {
  font-family: var(--font-display, inherit);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  box-shadow: none;
}
[data-brand^="bk_"] .btn-primary:hover {
  background-color: color-mix(in oklab, var(--color-primary) 85%, black);
}
[data-brand^="bk_"] #zone-basket .rounded-box {
  box-shadow: none;
}
/* Cream "paper" cart entries on the dark-brown basket — give them the
   subtlest divider instead of a heavy border. bk.fr leans hard on this
   look on its cart sidebar. */
[data-brand^="bk_"] #basket-cart .rounded-box {
  border-color: var(--color-base-300);
}
/* Total label / amount: bigger, brown, tabular. */
[data-brand^="bk_"] #cart-total-label {
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: color-mix(in oklab, var(--color-base-content) 65%, transparent);
}
[data-brand^="bk_"] #cart-total {
  font-family: var(--font-display, inherit);
  font-variant-numeric: tabular-nums;
  color: var(--color-primary);
}
/* Welcome headline + reply headline: display-font weight bump for that
   chunky bk.fr poster vibe. */
[data-brand^="bk_"] #welcome-headline,
[data-brand^="bk_"] #reply-headline {
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* ---- State-zone colours, driven by [data-state] on #app -------------- */
/* Defaults set by HTML are neutral grey; these override per state. */
#app[data-state="listening"] #zone-state {
  background-color: var(--color-success);
  color: var(--color-success-content);
}
#app[data-state="confirming"] #zone-state {
  background-color: var(--color-warning);
  color: var(--color-warning-content);
}
#app[data-state="thinking"] #zone-state {
  background-color: var(--color-error);
  color: var(--color-error-content);
}
/* Payment emitted — mic still open (customer can still add) but the
   strip flips to a distinct purple "at pay window" badge. */
#app[data-state="paying"] #zone-state {
  background-color: var(--color-primary);
  color: var(--color-primary-content);
  filter: brightness(0.85);
}

/* ---- CONFIRMING — grace-window bar, shrinks left→right ----------------
   The animation runs while we're in `confirming`. Duration matches the
   Deepgram eager-EOT → final window observed in production (~1.5s p90).
   When `is_turn_resumed` arrives we exit the state and the bar resets.
   When `is_final` arrives we exit too — backend truth, not a timer. */
#app[data-state="confirming"] #zone-state {
  position: relative;
  background-color: var(--color-warning);
}
#app[data-state="confirming"] #zone-state::after {
  content: "";
  position: absolute;
  inset: 0;
  background-color: color-mix(in oklab, var(--color-warning) 60%, black);
  transform-origin: right;
  animation: grace-shrink 1.5s linear forwards;
  z-index: 0;
  pointer-events: none;
}
@keyframes grace-shrink {
  from { transform: scaleX(1); }
  to   { transform: scaleX(0); }
}

/* ---- THINKING — cascade pills ---------------------------------------- */
#app[data-state="thinking"] #thinking-cascade { display: flex; }
.cascade-pill {
  width: 5rem;
  height: 0.55rem;
  border-radius: 9999px;
  border: 1.5px solid color-mix(in oklab, var(--color-error-content) 50%, transparent);
  background-color: transparent;
}
.cascade-pill-tried {
  border-color: color-mix(in oklab, var(--color-error-content) 35%, transparent);
}
.cascade-pill-matched {
  border-color: transparent;
  background-color: var(--color-success);
  animation: pill-pulse 0.9s ease-in-out infinite alternate;
}
@keyframes pill-pulse {
  from { opacity: 0.55; }
  to   { opacity: 1; }
}

/* ---- Basket "just added" flash --------------------------------------- */
.cart-entry-just-added {
  border-color: var(--color-success) !important;
  box-shadow: 0 0 0 1px var(--color-success) inset;
  animation: just-added-fade 2.6s ease-out forwards;
}
@keyframes just-added-fade {
  0%   { background-color: color-mix(in oklab, var(--color-success) 18%, transparent); }
  60%  { background-color: color-mix(in oklab, var(--color-success) 10%, transparent); }
  100% { background-color: transparent; }
}

/* ---- Live transcript caret tick during LISTENING --------------------- */
#app[data-state="listening"] #state-transcript::after {
  content: "▍";
  margin-left: 0.25rem;
  animation: caret-blink 1s steps(2) infinite;
}
@keyframes caret-blink {
  50% { opacity: 0; }
}

/* ---- Connection dot --------------------------------------------------- */
#conn-dot.live {
  background-color: var(--color-success);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-success) 30%, transparent);
}
