/* QEVYO Voice — scène vocale de COACH, extraite de qevyo-app@a96a25b0b39a60dcb603f4fb6943f1a67639c4d3 (app/brand-theme.css, app/components/coach/voice-stage.css). Ne pas modifier : réextraire. */
:root{--q-voice-halo-core:color-mix(in oklab,var(--q-gold) 46%,transparent);--q-voice-halo-edge:color-mix(in oklab,var(--q-gold) 14%,transparent);--q-voice-ring:color-mix(in oklab,var(--q-gold) 45%,transparent);--q-voice-ring-tick:color-mix(in oklab,var(--q-gold) 75%,transparent);--q-voice-portrait-line:color-mix(in oklab,var(--q-gold) 85%,transparent);--q-voice-light:color-mix(in oklab,var(--q-gold) 16%,transparent);--q-voice-line:color-mix(in oklab,var(--q-on-dark) 30%,transparent);--q-voice-line-strong:color-mix(in oklab,var(--q-on-dark) 40%,transparent);--q-voice-track:color-mix(in oklab,var(--q-on-dark) 22%,transparent);--q-voice-scrim:color-mix(in oklab,var(--q-night) 74%,transparent);--q-voice-shadow:0 30px 80px -30px rgb(0 0 0 / 55%);--q-voice-portrait-shadow:0 18px 38px -14px rgb(0 0 0 / 60%);--q-voice-ring-mask:radial-gradient(circle,transparent 65%,rgb(0 0 0) 66%,rgb(0 0 0) 70%,transparent 71%);}
/* L6 Voice — the immersive vocal training (app/components/coach/voice-session.tsx): its own surface, staged above
   COACH's thread (which stays calm, thread.css). Design System tokens only. */
/* L6 Voice — the immersive stage (a modal <dialog>): the avatar the agent chose at the centre, one state at a time,
   the microphone obvious, « Terminer l'entraînement et analyser » secondary. QEVYO's palette only (deep green, ivory,
   gold, soft light). The avatar lives with the voice: --q-voice-energy (GPT-Live's output, 0..1) and --q-mic-energy
   (the agent's microphone) are written ~30 times a second by lib/qevyo/voice/audio-reactivity.ts; without Web Audio,
   [data-voice-reactive=fallback] pulses deterministically. Reduced motion: no scale, no wave, only the state's light. */
.q-vs-dialog{box-sizing:border-box;inline-size:min(560px,calc(100% - 32px));max-inline-size:none;max-block-size:calc(100dvh - 32px);margin:auto;padding:0;border:0;border-radius:var(--q-radius-large);background:transparent;color:var(--q-on-dark);overflow:visible}
.q-vs-dialog::backdrop{background:var(--q-voice-scrim);backdrop-filter:blur(6px)}
.q-vs{--e:var(--q-voice-energy,0);--m:var(--q-mic-energy,0);box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:var(--q-space-4);min-block-size:min(680px,calc(100dvh - 32px));max-block-size:calc(100dvh - 32px);padding:var(--q-space-5) var(--q-space-5) var(--q-space-6);border-radius:inherit;background:radial-gradient(120% 64% at 50% 36%,var(--q-voice-light) 0,transparent 62%),var(--q-deep-wash);box-shadow:var(--q-voice-shadow);overflow:hidden auto;overflow-wrap:anywhere}
.q-vs__top{display:flex;align-items:center;justify-content:space-between;gap:var(--q-space-3);inline-size:100%;min-inline-size:0}
.q-vs__eyebrow{margin:0;color:var(--q-on-dark-secondary);font-size:var(--q-caption);letter-spacing:.08em;text-transform:uppercase}
.q-vs__thread{display:inline-flex;flex:none;align-items:center;gap:6px;min-block-size:var(--q-tap);padding:0 var(--q-space-4);border:1px solid var(--q-voice-line);border-radius:var(--q-radius-pill);background:transparent;color:var(--q-on-dark);font:var(--q-weight-medium) var(--q-body-small)/1 var(--q-font-body);cursor:pointer}
.q-vs__presence{position:relative;flex:none;inline-size:min(62vw,264px);aspect-ratio:1;margin-block-start:var(--q-space-4)}
.q-vs__ring,.q-vs__halo,.q-vs__portrait{position:absolute;border-radius:50%}
.q-vs__ring{inset:0;border:1px solid var(--q-voice-ring);opacity:.5}
.q-vs__halo{inset:6%;background:radial-gradient(circle,var(--q-voice-halo-core) 0,var(--q-voice-halo-edge) 56%,transparent 72%);opacity:.35}
.q-vs__portrait{inset:17%;overflow:hidden;border:2px solid var(--q-voice-portrait-line);background:var(--q-brand-deep-end);box-shadow:var(--q-voice-portrait-shadow)}
.q-vs__portrait svg{display:block;inline-size:100%;block-size:100%}
/* Robot: a more geometric, precise signal — still warm (gold), never cyberpunk. */
.q-vs[data-avatar=robot] .q-vs__portrait{border-radius:30%}
.q-vs[data-avatar=robot] .q-vs__ring{border:0;background:repeating-conic-gradient(var(--q-voice-ring-tick) 0 1.4deg,transparent 1.4deg 7.5deg);-webkit-mask:var(--q-voice-ring-mask);mask:var(--q-voice-ring-mask)}
.q-vs__state{min-block-size:4.6em;text-align:center}
.q-vs__label{margin:0;color:var(--q-ivory);font:var(--q-weight-medium) clamp(1.5rem,5.4vw,2rem)/1.2 var(--q-font-display);letter-spacing:-.01em}
.q-vs__hint{margin:var(--q-space-2) 0 0;color:var(--q-on-dark-secondary);font-size:var(--q-body-small)}
.q-vs__mic{display:inline-flex;align-items:center;gap:var(--q-space-2);min-block-size:var(--q-tap);margin:0;padding:0 var(--q-space-4) 0 var(--q-space-2);border:1px solid var(--q-gold);border-radius:var(--q-radius-pill);background:var(--q-voice-light);color:var(--q-ivory);font-weight:var(--q-weight-strong)}
.q-vs__mic-icon{display:grid;place-items:center;inline-size:30px;block-size:30px;border-radius:50%;background:var(--q-gold);color:var(--q-night)}
.q-vs__mic-level{inline-size:40px;block-size:4px;border-radius:2px;background:linear-gradient(90deg,var(--q-gold) calc(var(--m) * 100%),var(--q-voice-track) 0)}
/* QEVYO's words (the framing, the feedback): readable, never required (the voice says them). */
.q-vs__words{box-sizing:border-box;flex-shrink:0;inline-size:100%;max-inline-size:460px;max-block-size:min(30dvh,240px);overflow:auto;padding:var(--q-space-4);border:1px solid var(--q-voice-line);border-radius:var(--q-radius);background:var(--q-selected-dark);color:var(--q-ivory);font:var(--q-weight-regular) var(--q-body-small)/1.55 var(--q-font-body)}
.q-vs__words p{margin:0}
.q-vs__words:focus-visible{outline:3px solid var(--q-focus-on-dark);outline-offset:2px}
/* « Entraîne-moi sur une objection »: the choice (one objection of the strategy, or the agent's own). */
.q-vs__choose{display:flex;flex-direction:column;align-items:stretch;gap:var(--q-space-3);inline-size:100%;max-inline-size:480px;margin-block-start:var(--q-space-4);text-align:start}
.q-vs__choose .q-vs__label,.q-vs__choose .q-vs__hint{text-align:center}
.q-vs__options{display:grid;gap:var(--q-space-2);margin:0;padding:0;border:0;min-inline-size:0}
.q-vs__option{display:flex;align-items:center;gap:var(--q-space-3);min-block-size:var(--q-tap);padding:var(--q-space-3) var(--q-space-4);border:1px solid var(--q-voice-line);border-radius:var(--q-radius);background:var(--q-selected-dark);color:var(--q-ivory);font:var(--q-weight-medium) var(--q-body-small)/1.4 var(--q-font-body);cursor:pointer}
.q-vs__option:has(input:checked){border-color:var(--q-gold)}
.q-vs__option input{flex:none;inline-size:20px;block-size:20px;margin:0;accent-color:var(--q-gold)}
.q-vs__option:has(input:focus-visible){outline:3px solid var(--q-focus-on-dark);outline-offset:2px}
.q-vs__own-label{color:var(--q-on-dark-secondary);font-size:var(--q-body-small)}
.q-vs__own{box-sizing:border-box;inline-size:100%;min-block-size:var(--q-tap);padding:0 var(--q-space-4);border:1px solid var(--q-voice-line-strong);border-radius:var(--q-radius);background:transparent;color:var(--q-ivory);font:var(--q-weight-regular) var(--q-body)/1.4 var(--q-font-body)}
.q-vs__own:focus-visible{outline:3px solid var(--q-focus-on-dark);outline-offset:2px}
.q-vs__primary:disabled{opacity:.5;cursor:default}
/* « Analyser » before any answer: said plainly, the trial goes on. */
.q-vs__notice{max-inline-size:460px;margin:0;padding:var(--q-space-3) var(--q-space-4);border:1px solid var(--q-gold);border-radius:var(--q-radius);color:var(--q-ivory);font-size:var(--q-body-small);text-align:center}
.q-vs__actions{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--q-space-3);inline-size:100%;margin-block-start:auto}
.q-vs__primary,.q-vs__secondary{min-block-size:var(--q-tap);max-inline-size:100%;padding:var(--q-space-2) var(--q-space-5);border-radius:var(--q-radius-pill);font:var(--q-weight-strong) var(--q-body-small)/1.25 var(--q-font-body);cursor:pointer}
.q-vs__primary{border:0;background:var(--q-gold);color:var(--q-night)}
.q-vs__secondary{border:1px solid var(--q-voice-line-strong);background:transparent;color:var(--q-on-dark)}
.q-vs button:focus-visible{outline:3px solid var(--q-focus-on-dark);outline-offset:2px}
.q-vs__disclosure{margin:0;color:var(--q-on-dark-secondary);font-size:var(--q-caption);text-align:center}
/* The states (motion allowed): READY breathes very lightly; LISTENING breathes slowly (the ring follows the
   microphone, subtly); THINKING gathers slowly towards the centre; SPEAKING follows QEVYO's voice; ANALYZING is slow
   again; FEEDBACK is calm (a small echo of the voice). Never a spinner. */
@media (prefers-reduced-motion:no-preference){
 .q-vs[data-voice-stage=connecting] .q-vs__halo{animation:q-vs-breathe 5.2s ease-in-out infinite}
 .q-vs[data-voice-stage=listening] .q-vs__halo{opacity:.45;animation:q-vs-breathe 4.4s ease-in-out infinite}
 .q-vs[data-voice-stage=listening] .q-vs__ring{opacity:calc(.45 + var(--m) * .35);transform:scale(calc(1 + var(--m) * .025));transition:transform 120ms linear,opacity 120ms linear}
 .q-vs:is([data-voice-stage=processing],[data-voice-stage=preparing]) .q-vs__ring{animation:q-vs-gather 3.8s ease-in-out infinite}
 .q-vs:is([data-voice-stage=processing],[data-voice-stage=preparing]) .q-vs__halo{opacity:.3}
 .q-vs[data-voice-stage=analyzing] .q-vs__ring{animation:q-vs-gather 4.8s ease-in-out infinite}
 .q-vs[data-voice-stage=analyzing] .q-vs__halo{opacity:.3}
 .q-vs[data-voice-stage=speaking] .q-vs__portrait{transform:scale(calc(1 + var(--e) * .035));box-shadow:var(--q-voice-portrait-shadow),0 0 calc(var(--e) * 36px) var(--q-voice-ring);transition:transform 90ms linear,box-shadow 90ms linear}
 .q-vs[data-voice-stage=speaking] .q-vs__halo{opacity:calc(.42 + var(--e) * .55);transform:scale(calc(1 + var(--e) * .14));transition:transform 90ms linear,opacity 90ms linear}
 .q-vs[data-voice-stage=speaking] .q-vs__ring{opacity:calc(.35 + var(--e) * .5);transform:scale(calc(1.01 + var(--e) * .06));transition:transform 90ms linear,opacity 90ms linear}
 /* QEVYO the coach speaking (framing, feedback): the same voice-driven halo, calmer than the seller's. */
 .q-vs:is([data-voice-stage=framing],[data-voice-stage=feedback]) .q-vs__halo{opacity:calc(.42 + var(--e) * .4);transform:scale(calc(1 + var(--e) * .08));transition:transform 110ms linear,opacity 110ms linear}
 .q-vs:is([data-voice-stage=framing],[data-voice-stage=feedback]) .q-vs__portrait{transform:scale(calc(1 + var(--e) * .02));transition:transform 110ms linear}
 .q-vs[data-voice-stage=ready] .q-vs__halo{opacity:.4;animation:q-vs-breathe 5.2s ease-in-out infinite}
 .q-vs[data-voice-reactive=fallback]:is([data-voice-stage=speaking],[data-voice-stage=framing],[data-voice-stage=feedback]) .q-vs__halo{animation:q-vs-pulse 1.8s ease-in-out infinite}
}
@keyframes q-vs-breathe{50%{transform:scale(1.04);opacity:.55}}
@keyframes q-vs-gather{0%,100%{transform:scale(1.04);opacity:.25}50%{transform:scale(.95);opacity:.65}}
@keyframes q-vs-pulse{50%{transform:scale(1.08);opacity:.72}}
@media (prefers-reduced-motion:reduce){
 .q-vs__ring,.q-vs__halo,.q-vs__portrait{animation:none;transition:none;transform:none}
 .q-vs[data-voice-stage=listening] .q-vs__halo{opacity:.5}
 .q-vs:is([data-voice-stage=processing],[data-voice-stage=preparing],[data-voice-stage=analyzing]) .q-vs__halo{opacity:.22}
 .q-vs[data-voice-stage=speaking] :is(.q-vs__halo,.q-vs__ring){opacity:.9}
 .q-vs:is([data-voice-stage=framing],[data-voice-stage=feedback]) .q-vs__halo{opacity:.6}
}
/* Mobile: the whole screen — avatar, state, microphone, end; nothing else. */
@media (max-width:640px){
 .q-vs-dialog{inline-size:100%;block-size:100dvh;max-block-size:100dvh;margin:0;border-radius:0}
 .q-vs{min-block-size:100dvh;max-block-size:100dvh;padding:max(var(--q-space-4),env(safe-area-inset-top)) var(--q-space-4) max(var(--q-space-5),env(safe-area-inset-bottom))}
 .q-vs__actions > *{flex:1 1 100%}
}

