/* Voice Chat - Full Screen Session */

/* This immersive overlay covers the whole viewport, and it FLIPS WITH THE APP
   THEME: a warm "paper" world in light mode, an evergreen "room at dusk" world
   in dark mode. The brand accents are identical in both — gold = you/the
   counselor, sage = the simulated client, clay = the system thinking, red =
   stop/record. Only the ground, text, and translucent panels flip.

   The flip runs through the --vc-* tokens below, built on the --rvs-* brand
   palette from site.css. Everything past this point references --vc-* (grounds/
   text/panels) or --rvs-* (accents), never a hard-coded color:
     --vc-bg       full overlay background (gradient + glows)
     --vc-fg       primary text color        (ink in light / cream in dark)
     --vc-fg-rgb   ditto, for rgba chrome (ring/mic borders, captions, toggles)
     --vc-veil-rgb translucent panel base     (warm white in light / ink in dark) */
[data-bs-theme="light"] {
    --vc-bg:
        radial-gradient(1100px 700px at 78% -6%, rgba(var(--rvs-gold-rgb), 0.16), transparent 60%),
        radial-gradient(900px 720px at 6% 14%, rgba(var(--rvs-sage-rgb), 0.13), transparent 55%),
        radial-gradient(1200px 900px at 50% 116%, rgba(var(--rvs-clay-rgb), 0.10), transparent 60%),
        linear-gradient(135deg, var(--rvs-paper) 0%, var(--rvs-paper-2) 60%, var(--rvs-sand) 100%);
    --vc-fg: var(--rvs-ink);
    --vc-fg-rgb: var(--rvs-ink-rgb);
    --vc-veil-rgb: var(--rvs-surface-rgb);
}
[data-bs-theme="dark"] {
    /* "Dark academia" night: forest-charcoal ground with soft gold + teal glows. */
    --vc-bg:
        radial-gradient(900px 600px at 80% 6%, rgba(var(--night-gold-rgb), 0.10), transparent 60%),
        radial-gradient(820px 680px at 8% 100%, rgba(var(--night-teal-rgb), 0.10), transparent 55%),
        linear-gradient(135deg, var(--night-bg) 0%, var(--night-surface) 58%, var(--night-bg-deep) 100%);
    --vc-fg: var(--night-text);
    --vc-fg-rgb: var(--night-text-rgb);
    --vc-veil-rgb: var(--night-surface-rgb);
}

/* ── Top bar — call-screen chrome pinned above the hero ─────────────────────
   Left: live dot + elapsed timer (+ the SessionLimit countdown badge when a
   limit applies). Right: the labeled Show/Hide-transcript button. Fixed so it
   never scrolls away with the hero on short viewports. */
.voice-top-bar {
    position: fixed;
    top: 63px; /* clear of the app navbar (~63px tall; the overlay's 46px offset tucks under it) */
    left: 0;
    right: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.8rem 1.25rem;
    z-index: 1001;
    pointer-events: none; /* the bar spans the screen; only its controls are hit-targets */
}

.voice-top-bar > * {
    pointer-events: auto;
}

.voice-timer-group {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.voice-timer-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.9rem;
    border-radius: 999px;
    background: rgba(var(--vc-veil-rgb), 0.7);
    border: 1px solid rgba(var(--vc-fg-rgb), 0.15);
    color: rgba(var(--vc-fg-rgb), 0.9);
    font-size: 0.95rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.voice-timer-badge .live-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--rvs-sage);
    box-shadow: 0 0 6px var(--rvs-sage);
    animation: status-dot-pulse 2s ease-in-out infinite;
}

/* Session time-limit countdown badge wrapper (badge colors come from Bootstrap
   .badge classes; it just sits beside the elapsed timer now). */
.voice-timer-wrap {
    display: inline-flex;
    align-items: center;
}

/* Labeled transcript toggle — replaces the old "Captions" switch. */
.voice-transcript-btn {
    display: inline-flex;
    align-items: center;
    padding: 0.45rem 1.1rem;
    border-radius: 999px;
    border: 1px solid rgba(var(--vc-fg-rgb), 0.25);
    background: rgba(var(--vc-veil-rgb), 0.7);
    color: rgba(var(--vc-fg-rgb), 0.9);
    font-size: 0.92rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s ease;
}

.voice-transcript-btn:hover:not(:disabled) {
    background: rgba(var(--vc-fg-rgb), 0.12);
    border-color: rgba(var(--vc-fg-rgb), 0.4);
}

.voice-transcript-btn.open {
    background: var(--rvs-gold);
    border-color: var(--rvs-gold);
    color: var(--rvs-ink);
}

.voice-transcript-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.voice-session-notice {
    max-width: 520px;
    margin: 0 auto 1rem;
    text-align: center;
}

.voice-session-overlay {
    position: fixed;
    top: 46px;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 1000;
    /* Width of the Captions ("Live Transcript") side panel — shared with the panel
       itself and the .has-transcript reservations below so they never drift. */
    --vc-transcript-w: 350px;
    /* Ground flips with the app theme (paper in light, evergreen dusk in dark) — see --vc-bg above. */
    background: var(--vc-bg);
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Center the hero when it fits; "safe" falls back to top-alignment (instead of clipping
       the top out of reach) when the viewport is too short, and overflow-y lets it scroll.
       The fallback `center` covers the rare browser without the safe keyword (degrades to
       top-aligned, still no overlap). */
    justify-content: center;
    justify-content: safe center;
    color: var(--vc-fg);
    overflow-x: hidden;
    overflow-y: auto;
    /* The control section flows right after the hero (it is NOT pinned to the viewport
       bottom), so the hero + controls center together as one group and the controls sit
       directly under the status/phase labels. Just a little breathing room at the end. */
    padding-bottom: 1.5rem;
    /* The fixed top bar (timer + transcript toggle) is out of flow — reserve its height
       (it bottoms out ~63px into the overlay's box) for the safe-center fallback on
       short viewports. */
    padding-top: 80px;
}

/* Captions ("Live Transcript") panel open: reserve the panel's width on the right
   so the hero (avatar → name → status → caption) and the fixed control bar shift
   left into the remaining space instead of being overlapped by the fixed panel,
   which used to hover on top on narrower viewports. box-sizing:border-box (Bootstrap
   global) keeps the padding inside the 100% width, so no horizontal overflow.
   Scoped to the same widths where the panel is actually a right-side panel — below
   769px it relocates to the bottom (see the mobile block), so no horizontal reserve. */
@media (min-width: 769px) {
    .voice-session-overlay.has-transcript {
        padding-right: var(--vc-transcript-w);
    }

    /* The top bar is position:fixed (out of the overlay's flow), so its right edge
       must be pulled in explicitly — the overlay's padding doesn't reach it. (The
       control section is in-flow and follows the overlay's padding on its own.) */
    .voice-session-overlay.has-transcript .voice-top-bar {
        right: var(--vc-transcript-w);
    }
}

/* Demo-session farewell — replaces the graded summary for public-demo users. Reuses the
   themed .voice-session-overlay ground; no fixed control bar here, so drop the reserved
   bottom padding and just center the card. The CTA breaks out of the embed (target="_top"). */
.voice-session-overlay.demo-thanks {
    justify-content: center;
    justify-content: safe center;
    padding: 2rem 1.5rem;
    text-align: center;
}

.demo-thanks-card {
    max-width: 620px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

.demo-thanks-check {
    font-size: 3.2rem;
    line-height: 1;
    color: var(--rvs-sage);
}

.demo-thanks-title {
    font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.3rem);
    font-weight: 600;
    margin: 0;
    color: var(--vc-fg);
}

.demo-thanks-lead {
    font-size: 1.15rem;
    line-height: 1.55;
    margin: 0;
    color: rgba(var(--vc-fg-rgb), 0.92);
}

.demo-thanks-sub {
    font-size: 1rem;
    line-height: 1.55;
    margin: 0;
    color: rgba(var(--vc-fg-rgb), 0.72);
}

.demo-thanks-btn {
    margin-top: 0.75rem;
    display: inline-flex;
    align-items: center;
    padding: 0.85rem 1.6rem;
    border-radius: 999px;
    background: var(--rvs-gold);
    color: var(--rvs-ink);
    font-weight: 600;
    font-size: 1.05rem;
    text-decoration: none;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.demo-thanks-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(var(--rvs-gold-rgb), 0.4);
    color: var(--rvs-ink);
}

/* "Ask for more sessions" footnote under the CTA */
.demo-thanks-note {
    margin: 1.1rem 0 0;
    font-size: 0.9rem;
    line-height: 1.5;
    color: rgba(var(--vc-fg-rgb), 0.6);
}

.demo-thanks-note a {
    color: var(--rvs-gold);
    text-decoration: underline;
}

/* Startup loader — covers the session overlay until STT is live. Warm evergreen
   translucent veil (brand ink RGB, per the no-hardcoded-color rule) with a blur
   so the avatar reads faintly behind it. Text/spinner inherit the overlay's
   cream color. */
.voice-loading-overlay {
    position: absolute;
    inset: 0;
    z-index: 1200;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--vc-veil-rgb), 0.6);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

.voice-loading-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    text-align: center;
    padding: 2rem 2.5rem;
}

.voice-loading-spinner {
    width: 3rem;
    height: 3rem;
    border-width: 0.3em;
}

.voice-loading-title {
    font-size: 1.5rem;
    font-weight: 600;
}

.voice-loading-sub {
    font-size: 1rem;
    opacity: 0.8;
    max-width: 320px;
}

/* Client Avatar */
.voice-avatar-container {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 0.5rem;
}

.voice-avatar-ring {
    width: 260px;
    height: 260px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 4px solid rgba(var(--vc-fg-rgb), 0.2);
    transition: border-color 0.3s ease;
}

.voice-avatar-ring img {
    width: 240px;
    height: 240px;
    border-radius: 50%;
    object-fit: cover;
}

.voice-avatar-ring .avatar-placeholder {
    width: 240px;
    height: 240px;
    border-radius: 50%;
    background: rgba(var(--vc-fg-rgb), 0.1);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 4rem;
    color: rgba(var(--vc-fg-rgb), 0.5);
}

/* Additional-speaker session: extra sims fanned in an arc above the central ring,
   each just touching it and fully visible. Positions are computed inline (percentage
   of the ring box) so the mobile ring resize keeps the fan aligned. */
.voice-avatar-wrap {
    position: relative;
}

/* Reserve headroom so the fan doesn't overlap whatever sits above the avatar. */
.voice-avatar-wrap.has-fan {
    padding-top: 100px;
}

.voice-avatar-wrap .voice-avatar-ring {
    position: relative;
    z-index: 2;
}

.voice-avatar-extra {
    position: absolute;
    transform: translate(-50%, -50%);
    z-index: 3; /* fully visible above the ring */
    width: 96px;
    height: 96px;
    border-radius: 50%;
    overflow: hidden;
    border: 3px solid rgba(var(--vc-fg-rgb), 0.25);
    background: rgba(var(--vc-fg-rgb), 0.1);
    display: flex;
    align-items: center;
    justify-content: center;
}

.voice-avatar-extra img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.voice-avatar-extra .avatar-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
    color: rgba(var(--vc-fg-rgb), 0.5);
}

/* Group session: all sims the same size, slightly overlapping. */
.voice-avatar-group {
    display: flex;
    align-items: center;
}

.voice-avatar-group .voice-avatar-ring-sm {
    width: 175px;
    height: 175px;
    position: relative;
}

.voice-avatar-group .voice-avatar-ring-sm + .voice-avatar-ring-sm {
    margin-left: -28px;
}

.voice-avatar-group .voice-avatar-ring-sm img,
.voice-avatar-group .voice-avatar-ring-sm .avatar-placeholder {
    width: 160px;
    height: 160px;
    font-size: 2.5rem;
}

.voice-client-name {
    margin-top: 1rem;
    font-size: 1.5rem;
    font-weight: 600;
    text-align: center;
}

.voice-phase-label {
    font-size: 0.9rem;
    color: rgba(var(--vc-fg-rgb), 0.6);
    margin-top: 0.25rem;
}

/* State indicator animations — gold = you (listening), clay = thinking,
   sage = the client (speaking). */
.voice-avatar-ring.state-listening {
    border-color: var(--rvs-gold);
    box-shadow: 0 0 0 0 rgba(var(--rvs-gold-rgb), 0.4);
    animation: pulse-gold 2s infinite;
}

.voice-avatar-ring.state-processing {
    border-color: var(--rvs-clay);
    box-shadow: 0 0 0 0 rgba(var(--rvs-clay-rgb), 0.4);
    animation: pulse-clay 1.5s infinite;
}

.voice-avatar-ring.state-speaking {
    border-color: var(--rvs-sage);
    box-shadow: 0 0 0 0 rgba(var(--rvs-sage-rgb), 0.4);
    animation: pulse-sage 1.8s infinite;
}

@keyframes pulse-gold {
    0% { box-shadow: 0 0 0 0 rgba(var(--rvs-gold-rgb), 0.5); }
    70% { box-shadow: 0 0 0 20px rgba(var(--rvs-gold-rgb), 0); }
    100% { box-shadow: 0 0 0 0 rgba(var(--rvs-gold-rgb), 0); }
}

@keyframes pulse-clay {
    0% { box-shadow: 0 0 0 0 rgba(var(--rvs-clay-rgb), 0.5); }
    70% { box-shadow: 0 0 0 20px rgba(var(--rvs-clay-rgb), 0); }
    100% { box-shadow: 0 0 0 0 rgba(var(--rvs-clay-rgb), 0); }
}

@keyframes pulse-sage {
    0% { box-shadow: 0 0 0 0 rgba(var(--rvs-sage-rgb), 0.5); }
    70% { box-shadow: 0 0 0 20px rgba(var(--rvs-sage-rgb), 0); }
    100% { box-shadow: 0 0 0 0 rgba(var(--rvs-sage-rgb), 0); }
}

/* Status label — explicit indicator of session state, sitting directly under the
   client's name so "who" and "what's happening" read as one line. Always visible:
   even the idle states have words now ("Muted" / "Your turn"), so the user can
   always tell whether they're being heard. Color shifts with state to make
   "Listening" unmistakable. */
.voice-status-label {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 1rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    padding: 0.45rem 1.1rem;
    border-radius: 999px;
    background: rgba(var(--vc-veil-rgb), 0.7);
    border: 1px solid rgba(var(--vc-fg-rgb), 0.18);
    color: rgba(var(--vc-fg-rgb), 0.92);
    min-height: 2.25rem;
    margin-top: 0.6rem;
    box-shadow: 0 2px 8px rgba(var(--vc-veil-rgb), 0.35);
    position: static;
    flex-shrink: 0;
}

/* Idle states (Muted / Your turn / Paused / Session ended) keep the neutral veil;
   the dot stops pulsing so "nothing is being heard" is visually quiet. */
.voice-status-label.is-idle .status-dot,
.voice-status-label.is-paused .status-dot,
.voice-status-label.is-ended .status-dot {
    animation: none;
    opacity: 0.45;
    box-shadow: none;
}

.voice-status-label.is-listening {
    background: var(--rvs-gold);
    border-color: var(--rvs-gold);
    color: var(--rvs-ink);
}

.voice-status-label.is-processing {
    background: var(--rvs-clay);
    border-color: var(--rvs-clay);
    color: var(--rvs-ink);
}

.voice-status-label.is-speaking {
    background: var(--rvs-sage);
    border-color: var(--rvs-sage);
    color: var(--rvs-ink);
}

.voice-status-label .status-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 8px currentColor;
    animation: status-dot-pulse 1.1s ease-in-out infinite;
}

@keyframes status-dot-pulse {
    0%, 100% { opacity: 0.55; transform: scale(0.85); }
    50% { opacity: 1; transform: scale(1.2); }
}

/* "Thinking" ellipsis inside the status label. */
.voice-status-label .thinking-dots {
    display: inline-flex;
    gap: 3px;
}

.voice-status-label .thinking-dots > span {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: currentColor;
    animation: thinking-blink 1.2s ease-in-out infinite;
}

.voice-status-label .thinking-dots > span:nth-child(2) { animation-delay: 0.2s; }
.voice-status-label .thinking-dots > span:nth-child(3) { animation-delay: 0.4s; }

@keyframes thinking-blink {
    0%, 80%, 100% { opacity: 0.25; }
    40% { opacity: 1; }
}

/* Control section — call-screen layout: a labeled Mute · mic · End row with
   the listening-mode selector beneath it. In normal flow directly after the
   hero (NOT pinned to the viewport bottom), so with the live caption gone the
   controls ride up right under the status/phase labels and the whole call
   screen centers as one group. The row is a three-column grid so the mic wrap
   stays exactly centered even as the side controls change width. */
.voice-control-bar {
    width: 100%;
    margin-top: 1rem;
    padding: 0 2rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    flex-shrink: 0;
}

.voice-controls-row {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    column-gap: 2.5rem;
    width: 100%;
    max-width: 640px;
}

/* Side controls hug the center column rather than the screen edges, so
   they stay visually grouped with the mic on wide screens. */
.voice-controls-row > .voice-side-ctl:first-child { justify-self: end; }
.voice-controls-row > .voice-main-ctl { justify-self: center; }
.voice-controls-row > .voice-side-ctl:last-child { justify-self: start; }

/* Every control stacks over its own label, like a phone's call screen. */
.voice-side-ctl {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
}

.voice-main-ctl {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.voice-ctl-label {
    font-size: 0.85rem;
    color: rgba(var(--vc-fg-rgb), 0.75);
    text-align: center;
    white-space: nowrap;
}

/* Sits fully BELOW the mic wrap — the waveform ring can swell to the canvas
   edge, so the label must never reach into the wrap box or the ring draws
   through it. The wrap sizes are trimmed per tier to keep the gap modest. */
.voice-main-label {
    font-weight: 600;
    color: rgba(var(--vc-fg-rgb), 0.9);
    margin-top: 0.1rem;
}

/* Mute — neutral secondary control (matches the End button's dimensions). */
.voice-mute-btn {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    border: 2px solid rgba(var(--vc-fg-rgb), 0.3);
    background: transparent;
    color: rgba(var(--vc-fg-rgb), 0.85);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.2rem;
    cursor: pointer;
    transition: all 0.2s ease;
}

.voice-mute-btn:hover:not(:disabled) {
    background: rgba(var(--vc-fg-rgb), 0.12);
    border-color: rgba(var(--vc-fg-rgb), 0.5);
}

.voice-mute-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* Muted = filled, inverted — unmissable "you are not being heard". */
.voice-mute-btn.is-muted {
    background: rgba(var(--vc-fg-rgb), 0.85);
    border-color: rgba(var(--vc-fg-rgb), 0.85);
    color: rgba(var(--vc-veil-rgb), 1);
}

/* Listening-mode selector: Auto | Tap to talk segmented control + hint line. */
.voice-mode-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.9rem;
    flex-wrap: wrap;
    max-width: 640px;
}

.voice-mode-seg {
    display: inline-flex;
    border: 1px solid rgba(var(--vc-fg-rgb), 0.25);
    border-radius: 999px;
    overflow: hidden;
    flex-shrink: 0;
}

.voice-mode-seg .seg-opt {
    border: none;
    background: transparent;
    color: rgba(var(--vc-fg-rgb), 0.75);
    font-size: 0.88rem;
    font-weight: 600;
    padding: 0.35rem 1rem;
    cursor: pointer;
    white-space: nowrap;
    transition: all 0.15s ease;
}

.voice-mode-seg .seg-opt:hover:not(.active) {
    background: rgba(var(--vc-fg-rgb), 0.1);
}

.voice-mode-seg .seg-opt.active {
    background: var(--rvs-gold);
    color: var(--rvs-ink);
}

.voice-mode-hint {
    font-size: 0.82rem;
    color: rgba(var(--vc-fg-rgb), 0.6);
    max-width: 340px;
    line-height: 1.35;
}

/* Pause/resume button — gold (brand "hold"); same dimensions as end button so the pair is balanced */
.voice-pause-btn {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    border: 2px solid var(--rvs-gold);
    background: transparent;
    color: var(--rvs-gold);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    cursor: pointer;
    transition: all 0.2s ease;
}

.voice-pause-btn:hover:not(:disabled) {
    background: var(--rvs-gold);
    color: var(--rvs-ink);
}

.voice-pause-btn:disabled {
    opacity: 0.5;
    cursor: wait;
}

.voice-pause-btn.is-paused {
    background: var(--rvs-gold);
    color: var(--rvs-ink);
}

/* Mic button */
.voice-mic-btn {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    border: 3px solid rgba(var(--vc-fg-rgb), 0.3);
    background: rgba(var(--vc-fg-rgb), 0.1);
    color: var(--vc-fg);
    font-size: 1.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s ease;
}

.voice-mic-btn:hover {
    background: rgba(var(--vc-fg-rgb), 0.2);
    border-color: rgba(var(--vc-fg-rgb), 0.5);
}

/* Active = recording: danger red, the conventional "live mic" signal.
   Icon stays light on the red fill in both themes. */
.voice-mic-btn.active {
    background: var(--bs-danger);
    border-color: var(--bs-danger);
    color: var(--rvs-cream);
}

/* The mic button sits inside a wrapper so a sibling canvas can render
   a live waveform ring around it without affecting layout. */
.voice-mic-wrap {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Sized to fit the mic button + its waveform ring (the ring draws out to the
       canvas edge at peak level) while keeping the label below at a modest gap. */
    width: 144px;
    height: 144px;
}

.voice-mic-wrap .voice-mic-btn {
    position: relative;
    z-index: 1;
}

.voice-mic-viz {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.2s ease;
}

.voice-mic-viz.active {
    opacity: 1;
}

/* End session button — danger red (destructive). */
.voice-end-btn {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    border: 2px solid var(--bs-danger);
    background: transparent;
    color: var(--bs-danger);
    font-size: 1.2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s ease;
}

.voice-end-btn:hover {
    background: var(--bs-danger);
    color: var(--rvs-cream);
}

/* Live transcript panel — a side panel on desktop, a full-screen sheet on mobile
   (see the mobile media query). Starts below the app navbar (~63px) — the navbar
   is z-index 1030, so anything under it is unreachable. */
.voice-transcript-panel {
    position: fixed;
    top: 63px;
    right: 0;
    bottom: 0;
    width: var(--vc-transcript-w);
    background: rgba(var(--vc-veil-rgb), 0.78);
    z-index: 1002;
    display: flex;
    flex-direction: column;
    border-left: 1px solid rgba(var(--vc-fg-rgb), 0.1);
}

.voice-transcript-header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1rem 1.25rem;
    border-bottom: 1px solid rgba(var(--vc-fg-rgb), 0.1);
    font-weight: 600;
    font-size: 0.95rem;
    color: rgba(var(--vc-fg-rgb), 0.9);
}

.voice-transcript-header .transcript-title {
    flex: 1;
}

/* Live status echo — only meaningful on the mobile sheet, where the transcript
   covers the call screen. Hidden while the panel sits beside the live call. */
.voice-transcript-header .transcript-live-status {
    display: none;
    font-size: 0.82rem;
    font-weight: 500;
    color: rgba(var(--vc-fg-rgb), 0.6);
    white-space: nowrap;
}

.voice-transcript-header .transcript-close-btn {
    border: none;
    background: transparent;
    color: rgba(var(--vc-fg-rgb), 0.6);
    font-size: 1rem;
    cursor: pointer;
    padding: 0.25rem 0.4rem;
    border-radius: 6px;
}

.voice-transcript-header .transcript-close-btn:hover {
    background: rgba(var(--vc-fg-rgb), 0.1);
    color: rgba(var(--vc-fg-rgb), 0.9);
}

/* "Back to call" — the mobile sheet's exit; hidden on desktop where the call
   stays visible beside the panel. */
.voice-transcript-header .transcript-back-btn {
    display: none;
    align-items: center;
    border: none;
    border-radius: 999px;
    padding: 0.4rem 1rem;
    background: var(--rvs-gold);
    color: var(--rvs-ink);
    font-size: 0.88rem;
    font-weight: 600;
    cursor: pointer;
}

/* Chat-style bubbles: you on the right, the client on the left, so speaker
   attribution is readable at a glance. */
.voice-transcript-messages {
    flex: 1;
    overflow-y: auto;
    padding: 1rem 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
}

.voice-transcript-msg {
    padding: 0.5rem 0.75rem;
    border-radius: 8px;
    font-size: 0.85rem;
    line-height: 1.4;
    max-width: 92%;
    flex-shrink: 0;
}

/* You (the counselor) = gold, right-aligned; the simulated client = sage, left. */
.voice-transcript-msg.user-msg {
    background: rgba(var(--rvs-gold-rgb), 0.15);
    border-right: 3px solid var(--rvs-gold);
    align-self: flex-end;
}

.voice-transcript-msg.ai-msg {
    background: rgba(var(--rvs-sage-rgb), 0.15);
    border-left: 3px solid var(--rvs-sage);
    align-self: flex-start;
}

/* In-progress speech — faded until STT commits it as a real message. */
.voice-transcript-msg.pending {
    opacity: 0.65;
}

.voice-transcript-msg.pending .msg-text {
    font-style: italic;
}

.voice-transcript-msg .msg-role {
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 0.25rem;
}

.voice-transcript-msg .msg-time {
    font-size: 0.7rem;
    color: rgba(var(--vc-fg-rgb), 0.4);
    float: right;
}

.voice-transcript-msg .msg-text {
    color: rgba(var(--vc-fg-rgb), 0.85);
}

/* Multi-speaker: per-speaker name colors in the live transcript (speaker-0 = primary) */
.voice-transcript-msg .msg-text .speaker-name {
    color: var(--bs-primary);
}

.voice-transcript-msg .msg-text .speaker-name.speaker-1 {
    color: var(--bs-info);
}

.voice-transcript-msg .msg-text .speaker-name.speaker-2 {
    color: var(--bs-success);
}

.voice-transcript-msg .msg-text .speaker-name.speaker-3 {
    color: var(--bs-warning);
}

/* Responsive */
@media (max-width: 768px) {
    .voice-avatar-ring {
        width: 200px;
        height: 200px;
    }

    .voice-avatar-ring img,
    .voice-avatar-ring .avatar-placeholder {
        width: 180px;
        height: 180px;
    }

    .voice-avatar-group .voice-avatar-ring-sm {
        width: 120px;
        height: 120px;
    }

    .voice-avatar-group .voice-avatar-ring-sm + .voice-avatar-ring-sm {
        margin-left: -20px;
    }

    .voice-avatar-group .voice-avatar-ring-sm img,
    .voice-avatar-group .voice-avatar-ring-sm .avatar-placeholder {
        width: 108px;
        height: 108px;
        font-size: 1.75rem;
    }

    .voice-avatar-extra {
        width: 64px;
        height: 64px;
    }

    .voice-avatar-wrap.has-fan {
        padding-top: 70px;
    }

    .voice-client-name {
        font-size: 1.25rem;
    }

    /* The transcript becomes a full-screen sheet over the call screen (the call keeps
       running underneath): full-bleed, above the control/top bars, with a "Back to call"
       button and the live status echoed in its header. */
    .voice-transcript-panel {
        top: 63px; /* below the app navbar, which stays above (z 1030) */
        left: 0;
        right: 0;
        bottom: 0;
        width: 100%;
        border-left: none;
        z-index: 1003;
        background: rgba(var(--vc-veil-rgb), 0.97);
    }

    .voice-transcript-header .transcript-back-btn {
        display: inline-flex;
    }

    .voice-transcript-header .transcript-close-btn {
        display: none;
    }

    .voice-transcript-header .transcript-live-status {
        display: inline;
    }

    /* Collapse the control section: tighter padding + a smaller mic wrap,
       smaller side buttons, and a tighter mode row. */
    .voice-control-bar {
        margin-top: 0.75rem;
        padding: 0 1rem;
        gap: 0.2rem;
    }

    .voice-controls-row {
        column-gap: 1rem;
    }

    .voice-mic-btn {
        width: 56px;
        height: 56px;
        font-size: 1.25rem;
    }

    .voice-mic-wrap {
        width: 112px;
        height: 112px;
    }

    .voice-mute-btn,
    .voice-end-btn,
    .voice-pause-btn {
        width: 44px;
        height: 44px;
        font-size: 1rem;
    }

    .voice-ctl-label {
        font-size: 0.78rem;
    }

    .voice-mode-hint {
        font-size: 0.76rem;
        max-width: 300px;
    }

    .voice-top-bar {
        padding: 0.8rem 0.75rem;
    }

    .voice-session-overlay {
        padding-top: 74px;
    }
}

/* Short viewports (landscape phones, small/embedded desktop windows, captions sidebar
   squeezing height). The base rule already prevents overlap (safe-center + reserved bar
   padding); these tiers just progressively shrink the avatar + mic so the hero stays
   compact and rarely needs to scroll, and trim the reserved space as the bar shrinks. */
@media (max-height: 720px) {
    .voice-avatar-container {
        margin-bottom: 0.25rem;
    }

    .voice-avatar-ring {
        width: 190px;
        height: 190px;
    }

    .voice-avatar-ring img,
    .voice-avatar-ring .avatar-placeholder {
        width: 172px;
        height: 172px;
    }

    /* Less headroom for the additional-speaker fan since the ring (and fan) are smaller. */
    .voice-avatar-wrap.has-fan {
        padding-top: 66px;
    }

    .voice-status-label {
        margin-top: 0.4rem;
    }

    /* Collapse the control section on short viewports too: shrink the mic wrap
       (which sets the controls row's height) and tighten its top margin. */
    .voice-control-bar {
        margin-top: 0.5rem;
        gap: 0.2rem;
    }

    .voice-mic-wrap {
        width: 112px;
        height: 112px;
    }

    .voice-mic-btn {
        width: 56px;
        height: 56px;
        font-size: 1.25rem;
    }

    .voice-top-bar {
        padding: 0.5rem 1rem;
    }

    .voice-session-overlay {
        padding-top: 72px;
    }
}

@media (max-height: 590px) {
    .voice-avatar-container {
        margin-bottom: -0.5rem;
    }

    .voice-avatar-ring {
        width: 124px;
        height: 124px;
        border-width: 3px;
    }

    .voice-avatar-ring img,
    .voice-avatar-ring .avatar-placeholder {
        width: 110px;
        height: 110px;
    }

    .voice-avatar-wrap.has-fan {
        padding-top: 44px;
    }

    .voice-client-name {
        font-size: 1.15rem;
    }

    .voice-status-label {
        margin-top: 0.3rem;
        padding: 0.3rem 0.9rem;
        font-size: 0.9rem;
    }

    .voice-mic-wrap {
        width: 96px;
        height: 96px;
    }

    .voice-mic-btn {
        width: 48px;
        height: 48px;
        font-size: 1.1rem;
    }

    .voice-main-label {
        font-size: 0.75rem;
    }

    .voice-control-bar {
        margin-top: 0.35rem;
        gap: 0.15rem;
    }

    .voice-mute-btn,
    .voice-end-btn,
    .voice-pause-btn {
        width: 42px;
        height: 42px;
        font-size: 0.9rem;
    }

    .voice-ctl-label {
        font-size: 0.72rem;
    }

    /* The mode explainer is the first thing to go when height is scarce —
       the segmented control still names both modes. */
    .voice-mode-hint {
        display: none;
    }

    .voice-mode-seg .seg-opt {
        font-size: 0.8rem;
        padding: 0.25rem 0.85rem;
    }

    .voice-top-bar {
        padding: 0.4rem 0.75rem;
    }

    .voice-timer-badge,
    .voice-transcript-btn {
        font-size: 0.82rem;
        padding: 0.3rem 0.8rem;
    }

    .voice-session-overlay {
        padding-top: 64px;
    }
}
