/* Private hands-free conversation instrument for the Atlas voice bridge. */ .voice-mode-bar { --voice-accent: 72, 207, 204; --voice-accent-secondary: 76, 164, 205; position: relative; isolation: isolate; box-sizing: border-box; min-height: 106px; padding: 9px 12px 10px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; overflow: hidden; border-bottom: 1px solid rgba(174, 192, 218, 0.1); background: radial-gradient(circle at 50% 38%, rgba(var(--voice-accent), 0.075), transparent 46%), linear-gradient(180deg, rgba(255, 255, 255, 0.025), rgba(4, 8, 18, 0.035)); } .voice-mode-bar::before { content: ""; position: absolute; z-index: -1; top: 0; left: 18%; right: 18%; height: 1px; background: linear-gradient(90deg, transparent, rgba(233, 244, 255, 0.16), transparent); } :root:not(.dark) .voice-mode-bar { border-bottom-color: rgba(38, 55, 78, 0.1); background: radial-gradient(circle at 50% 38%, rgba(var(--voice-accent), 0.09), transparent 48%), linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(226, 232, 240, 0.12)); } .voice-mode-indicator { --voice-ripple-scale: 1.035; --voice-ripple-opacity: 0.3; position: relative; width: 70px; height: 70px; flex: 0 0 70px; border-radius: 50%; transform: translateZ(0); } .voice-mode-indicator.listening { --voice-accent: 69, 218, 207; --voice-accent-secondary: 73, 169, 209; } .voice-mode-indicator.transcribing { --voice-accent: 73, 193, 218; --voice-accent-secondary: 93, 129, 224; } .voice-mode-indicator.thinking { --voice-accent: 135, 111, 244; --voice-accent-secondary: 81, 62, 190; } .voice-mode-indicator.speaking { --voice-accent: 249, 169, 105; --voice-accent-secondary: 236, 112, 137; } .voice-mode-indicator.error { --voice-accent: 235, 135, 88; --voice-accent-secondary: 198, 74, 78; } .voice-instrument-halo, .voice-instrument-ripple, .voice-instrument-orbit, .voice-instrument-core { position: absolute; display: block; box-sizing: border-box; border-radius: 50%; pointer-events: none; } .voice-instrument-halo { inset: 2px; opacity: 0; background: radial-gradient(circle, rgba(var(--voice-accent), 0.2), rgba(var(--voice-accent), 0.05) 43%, transparent 70%); filter: blur(4px); } .voice-instrument-ripple { inset: 3px; opacity: 0; border: 1px solid rgba(var(--voice-accent), 0.56); box-shadow: 0 0 12px rgba(var(--voice-accent), 0.13); } .voice-instrument-orbit { inset: 2px; opacity: 0; border: 1px solid rgba(var(--voice-accent), 0.18); box-shadow: inset 0 0 8px rgba(var(--voice-accent), 0.06), 0 0 11px rgba(var(--voice-accent), 0.07); } .voice-instrument-orbit::before { content: ""; position: absolute; inset: -1px; border-radius: inherit; border-top: 1.5px solid rgba(var(--voice-accent), 0.88); border-right: 1px solid rgba(var(--voice-accent-secondary), 0.35); border-bottom: 1px solid transparent; border-left: 1px solid transparent; } .voice-instrument-orbit::after { content: ""; position: absolute; top: -2px; left: 50%; width: 5px; height: 5px; margin-left: -2.5px; border-radius: 50%; background: rgb(var(--voice-accent)); box-shadow: 0 0 5px rgba(var(--voice-accent), 0.92), 0 0 12px rgba(var(--voice-accent), 0.44); } .voice-instrument-core { inset: 12px; display: grid; place-items: center; color: rgba(242, 250, 255, 0.94); border: 1px solid rgba(238, 247, 255, 0.2); background: radial-gradient(circle at 38% 29%, rgba(255, 255, 255, 0.26), transparent 24%), radial-gradient(circle at 50% 66%, rgba(var(--voice-accent), 0.36), transparent 64%), linear-gradient(145deg, rgba(36, 45, 61, 0.96), rgba(10, 15, 27, 0.98)); box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.22), inset 0 -9px 18px rgba(0, 0, 0, 0.24), 0 4px 13px rgba(0, 0, 0, 0.25), 0 0 17px rgba(var(--voice-accent), 0.17); } :root:not(.dark) .voice-instrument-core { color: rgba(31, 48, 66, 0.9); border-color: rgba(255, 255, 255, 0.82); background: radial-gradient(circle at 38% 29%, rgba(255, 255, 255, 0.96), transparent 27%), radial-gradient(circle at 50% 66%, rgba(var(--voice-accent), 0.2), transparent 65%), linear-gradient(145deg, rgba(248, 250, 251, 0.98), rgba(216, 225, 231, 0.96)); box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.94), inset 0 -8px 17px rgba(64, 84, 100, 0.1), 0 4px 12px rgba(35, 53, 72, 0.15), 0 0 15px rgba(var(--voice-accent), 0.13); } .voice-instrument-symbol { display: block; width: 22px; height: 22px; filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.32)); } .voice-instrument-symbol svg { display: block; width: 100%; height: 100%; } .voice-symbol { display: none; } .voice-mode-indicator.listening .voice-symbol-listening, .voice-mode-indicator.transcribing .voice-symbol-transcribing, .voice-mode-indicator.thinking .voice-symbol-thinking, .voice-mode-indicator.speaking .voice-symbol-speaking, .voice-mode-indicator.error .voice-symbol-error { display: inline; } .voice-mode-indicator.listening .voice-instrument-halo { opacity: 0.62; animation: voice-instrument-breathe 3.8s ease-in-out infinite; } .voice-mode-indicator.listening .voice-instrument-ripple { opacity: var(--voice-ripple-opacity); transform: scale(var(--voice-ripple-scale)); transition: transform 140ms ease-out, opacity 160ms ease-out; } .voice-mode-indicator.transcribing .voice-instrument-orbit { opacity: 0.92; animation: voice-instrument-orbit 3.4s cubic-bezier(0.58, 0.12, 0.42, 0.88) infinite; } .voice-mode-indicator.thinking .voice-instrument-orbit { opacity: 0.96; animation: voice-instrument-orbit 4.6s cubic-bezier(0.58, 0.12, 0.42, 0.88) infinite; } .voice-mode-indicator.thinking .voice-instrument-core { animation: voice-instrument-core-breathe 5.7s ease-in-out infinite; } .voice-mode-indicator.speaking .voice-instrument-orbit { opacity: 0.86; transform: rotate(38deg); } .voice-mode-indicator.speaking.is-playing .voice-instrument-halo { opacity: 0.66; animation: voice-instrument-speaking-pulse 2.15s ease-out infinite; } .voice-mode-indicator.error .voice-instrument-orbit { opacity: 0.9; transform: rotate(-32deg); border-color: rgba(var(--voice-accent), 0.44); } .voice-mode-indicator.error .voice-instrument-core { color: rgba(255, 232, 219, 0.95); box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.2), inset 0 -9px 18px rgba(0, 0, 0, 0.24), 0 4px 13px rgba(0, 0, 0, 0.25), 0 0 12px rgba(var(--voice-accent), 0.17); } .voice-mode-label { position: relative; z-index: 1; min-height: 16px; max-width: min(100%, 34rem); overflow: hidden; color: var(--text, #f4f6fb); font-size: 12px; font-weight: 650; line-height: 1.35; letter-spacing: 0.018em; text-align: center; text-overflow: ellipsis; white-space: nowrap; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.28); } :root:not(.dark) .voice-mode-label { color: #263648; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.8); } @keyframes voice-instrument-breathe { 0%, 100% { opacity: 0.38; transform: scale(0.94); } 50% { opacity: 0.72; transform: scale(1.06); } } @keyframes voice-instrument-orbit { 0% { transform: rotate(0deg); } 50% { transform: rotate(177deg); } 100% { transform: rotate(360deg); } } @keyframes voice-instrument-core-breathe { 0%, 100% { filter: saturate(0.96) brightness(0.98); } 50% { filter: saturate(1.08) brightness(1.06); } } @keyframes voice-instrument-speaking-pulse { 0% { opacity: 0.58; transform: scale(0.88); } 58% { opacity: 0.22; transform: scale(1.12); } 100% { opacity: 0; transform: scale(1.2); } } @media (max-width: 640px) { .voice-mode-bar { min-height: 94px; padding: 7px 10px 8px; gap: 4px; } .voice-mode-indicator { width: 62px; height: 62px; flex-basis: 62px; } .voice-instrument-core { inset: 11px; } .voice-instrument-symbol { width: 20px; height: 20px; } } @media (prefers-reduced-motion: reduce) { .voice-mode-bar *, .voice-mode-bar *::before, .voice-mode-bar *::after { animation: none !important; transition: none !important; } .voice-mode-indicator.listening .voice-instrument-halo { opacity: 0.45; transform: none; } .voice-mode-indicator.listening .voice-instrument-ripple { opacity: 0.34; transform: scale(1.035); } .voice-mode-indicator.transcribing .voice-instrument-orbit, .voice-mode-indicator.thinking .voice-instrument-orbit { transform: rotate(24deg); } .voice-mode-indicator.speaking.is-playing .voice-instrument-halo { opacity: 0.42; transform: scale(1.03); } } /* ── Conversation mode overlay ─────────────────────────────────────────── */ /* Full-viewport hands-free conversation surface. Created lazily by atlas-voice.js on activation and removed on deactivate. The orb breathes in idle listening, follows live microphone energy through --conversation-level, and pulses while Hermes speaks (.is-playing, driven from TTS playback activity). State accents reuse the indicator palette. */ .voice-conversation { --voice-accent: 69, 218, 207; --voice-accent-secondary: 73, 169, 209; --conversation-level: 0; position: fixed; inset: 0; z-index: 420; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 24px; padding: 34px 22px calc(28px + env(safe-area-inset-bottom, 0px)); background: radial-gradient(circle at 50% 30%, rgba(var(--voice-accent), 0.11), transparent 52%), radial-gradient(circle at 22% 92%, rgba(157, 142, 224, 0.07), transparent 44%), linear-gradient(160deg, #0b1120, #070a12 55%, #081018); color: rgba(240, 247, 255, 0.94); } .voice-conversation[data-voice-state="transcribing"] { --voice-accent: 73, 193, 218; --voice-accent-secondary: 93, 129, 224; } .voice-conversation[data-voice-state="thinking"] { --voice-accent: 135, 111, 244; --voice-accent-secondary: 81, 62, 190; } .voice-conversation[data-voice-state="speaking"] { --voice-accent: 249, 169, 105; --voice-accent-secondary: 236, 112, 137; } .voice-conversation[data-voice-state="error"] { --voice-accent: 235, 135, 88; --voice-accent-secondary: 198, 74, 78; } .voice-conversation-orb { position: relative; width: min(46vmin, 220px); height: min(46vmin, 220px); flex: none; } .voice-conversation-orb-halo, .voice-conversation-orb-core, .voice-conversation-orb-ring { position: absolute; inset: 0; display: block; border-radius: 50%; pointer-events: none; } .voice-conversation-orb-halo { background: radial-gradient(circle, rgba(var(--voice-accent), 0.34), rgba(var(--voice-accent-secondary), 0.1) 52%, transparent 74%); filter: blur(10px); opacity: 0.75; transform: scale(calc(1 + (var(--conversation-level) * 0.3))); transition: transform 130ms ease-out; } .voice-conversation-orb-core { inset: 12%; background: radial-gradient(circle at 36% 28%, rgba(255, 255, 255, 0.34), transparent 34%), radial-gradient(circle at 52% 68%, rgba(var(--voice-accent), 0.62), rgba(var(--voice-accent-secondary), 0.4) 62%, transparent 86%), linear-gradient(150deg, rgba(34, 44, 63, 0.95), rgba(9, 13, 24, 0.98)); box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.28), 0 10px 42px rgba(0, 0, 0, 0.45), 0 0 44px rgba(var(--voice-accent), 0.3); transform: scale(calc(1 + (var(--conversation-level) * 0.14))); transition: transform 110ms ease-out; } .voice-conversation-orb-ring { inset: 3%; border: 1.5px solid rgba(var(--voice-accent), 0.4); box-shadow: 0 0 22px rgba(var(--voice-accent), 0.16); opacity: 0.85; } /* FIX 1: the Hermes CHARACTER watermark inside the orb. A pre-processed data URI — the 512px character art, feathered to a circle so its edges fade to transparent (the orb appears to CROP it, with no square box) and luminance- weighted to a warm near-white so the facial features read as light. Painted with mix-blend-mode: screen so the glyph's darks drop away and only the light face features glow over the dark orb. It is a static, centred, inset watermark that scales with the orb (inset-positioned), carries no animation of its own (reduced-motion safe) and stays subtle across every state tint. Inlined as a data URI, so there is no separate static asset to serve. */ .voice-conversation-orb-mark { position: absolute; inset: 16%; pointer-events: none; background-image: url("data:image/png;base64,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"); background-position: center; background-repeat: no-repeat; background-size: contain; mix-blend-mode: screen; opacity: 0.6; transition: opacity 200ms ease-out; } /* Speaking/thinking lift the watermark a touch so it feels alive with the turn, still far below any level that would mask the energy layers. */ .voice-conversation[data-voice-state="speaking"] .voice-conversation-orb-mark, .voice-conversation[data-voice-state="thinking"] .voice-conversation-orb-mark { opacity: 0.72; } .voice-conversation.is-muted .voice-conversation-orb-mark { opacity: 0.4; } /* Idle listening: slow breathing. */ .voice-conversation[data-voice-state="listening"] .voice-conversation-orb-halo { animation: voice-conversation-breathe 4.4s ease-in-out infinite; } /* Transcribing/thinking: the ring sweeps. */ .voice-conversation[data-voice-state="transcribing"] .voice-conversation-orb-ring, .voice-conversation[data-voice-state="thinking"] .voice-conversation-orb-ring { border-top-color: rgba(var(--voice-accent), 0.95); border-right-color: rgba(var(--voice-accent-secondary), 0.4); animation: voice-conversation-sweep 2.6s linear infinite; } /* Hermes speaking: the halo waves outward while playback is live. */ .voice-conversation.is-playing .voice-conversation-orb-halo { animation: voice-conversation-wave 1.9s ease-out infinite; } .voice-conversation.is-playing .voice-conversation-orb-core { animation: voice-conversation-swell 1.9s ease-in-out infinite; } .voice-conversation-state { min-height: 20px; font-size: 15px; font-weight: 650; letter-spacing: 0.02em; text-align: center; color: rgba(238, 246, 255, 0.9); } .voice-conversation-captions { display: flex; flex-direction: column; gap: 10px; width: min(100%, 40rem); min-height: 0; text-align: center; } /* Each caption is its own bounded scroll region: the user transcript and the reply overflow independently, scroll by touch inside the overlay without moving the page behind (overscroll-behavior: contain), stay keyboard scrollable via tabindex, and fade at the top edge so clipped history reads as scrollable. Auto-follow of the streaming tail lives in atlas-voice.js (data-follow, per region). */ .voice-conversation-caption-user, .voice-conversation-caption-assistant { overflow-y: auto; touch-action: pan-y; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; scrollbar-width: thin; -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 18px, #000 100%); mask-image: linear-gradient(180deg, transparent 0, #000 18px, #000 100%); } .voice-conversation-caption-user:focus-visible, .voice-conversation-caption-assistant:focus-visible { outline: 2px solid rgb(var(--voice-accent)); outline-offset: 2px; } .voice-conversation-caption-user { margin: 0; max-height: 22vh; font-size: 14px; line-height: 1.5; color: rgba(178, 196, 214, 0.88); font-style: italic; } .voice-conversation-caption-assistant { margin: 0; max-height: 38vh; font-size: 16px; line-height: 1.6; color: rgba(240, 247, 255, 0.95); } .voice-conversation-controls { display: flex; gap: 14px; margin-top: 6px; } .voice-conversation-controls button { font: inherit; font-size: 13px; font-weight: 600; color: rgba(233, 243, 252, 0.92); background: rgba(255, 255, 255, 0.07); border: 1px solid rgba(var(--voice-accent), 0.36); border-radius: 999px; padding: 10px 18px; cursor: pointer; } .voice-conversation-controls button:hover { background: rgba(255, 255, 255, 0.12); } .voice-conversation-controls button:focus-visible { outline: 2px solid rgb(var(--voice-accent)); outline-offset: 2px; } .voice-conversation.is-muted .voice-conversation-mute { color: #ffd9c7; border-color: rgba(235, 135, 88, 0.6); background: rgba(235, 135, 88, 0.14); } /* FIX 3: unobtrusive language chooser in the top-right corner. A small frosted globe that opens a compact Auto + supported-language menu; selecting forces both the reply voice and the STT hint for the session. */ .voice-conversation-lang { position: absolute; top: calc(16px + env(safe-area-inset-top, 0px)); right: calc(16px + env(safe-area-inset-right, 0px)); z-index: 2; } .voice-conversation-lang-btn { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; color: rgba(226, 238, 250, 0.72); background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(var(--voice-accent), 0.28); border-radius: 50%; cursor: pointer; transition: color 160ms ease, background 160ms ease, border-color 160ms ease; } .voice-conversation-lang-btn:hover { color: rgba(240, 248, 255, 0.95); background: rgba(255, 255, 255, 0.12); } .voice-conversation-lang-btn:focus-visible { outline: 2px solid rgb(var(--voice-accent)); outline-offset: 2px; } /* Forced (non-Auto) language: a small accent dot marks the active override. */ .voice-conversation-lang-btn.is-forced { color: rgb(var(--voice-accent)); border-color: rgba(var(--voice-accent), 0.7); } .voice-conversation-lang-btn.is-forced::after { content: ""; position: absolute; top: 2px; right: 2px; width: 8px; height: 8px; border-radius: 50%; background: rgb(var(--voice-accent)); box-shadow: 0 0 6px rgba(var(--voice-accent), 0.8); } .voice-conversation-lang-menu { position: absolute; top: 46px; right: 0; min-width: 148px; display: flex; flex-direction: column; gap: 2px; padding: 6px; background: rgba(16, 22, 36, 0.96); border: 1px solid rgba(var(--voice-accent), 0.28); border-radius: 14px; box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5); backdrop-filter: blur(8px); } .voice-conversation-lang-menu[hidden] { display: none; } .voice-conversation-lang-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; font: inherit; font-size: 14px; font-weight: 550; text-align: left; color: rgba(231, 241, 251, 0.9); background: transparent; border: 0; border-radius: 9px; padding: 9px 12px; cursor: pointer; } .voice-conversation-lang-item:hover { background: rgba(255, 255, 255, 0.08); } .voice-conversation-lang-item:focus-visible { outline: 2px solid rgb(var(--voice-accent)); outline-offset: -2px; } /* The selected option carries a trailing check. */ .voice-conversation-lang-item[aria-checked="true"] { color: #fff; background: rgba(var(--voice-accent), 0.16); } .voice-conversation-lang-item[aria-checked="true"]::after { content: "✓"; font-size: 13px; color: rgb(var(--voice-accent)); } /* Output-device selector: a twin of the language chooser, seated just left of it in the same corner. Feature-detected and hidden entirely when the browser cannot enumerate/route outputs, so it never appears as a dead control. */ .voice-conversation-out { position: absolute; top: calc(16px + env(safe-area-inset-top, 0px)); right: calc(64px + env(safe-area-inset-right, 0px)); z-index: 2; } .voice-conversation-out-btn { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; color: rgba(226, 238, 250, 0.72); background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(var(--voice-accent), 0.28); border-radius: 50%; cursor: pointer; transition: color 160ms ease, background 160ms ease, border-color 160ms ease; } .voice-conversation-out-btn:hover { color: rgba(240, 248, 255, 0.95); background: rgba(255, 255, 255, 0.12); } .voice-conversation-out-btn:focus-visible { outline: 2px solid rgb(var(--voice-accent)); outline-offset: 2px; } /* A non-default output device is marked with the same accent dot. */ .voice-conversation-out-btn.is-forced { color: rgb(var(--voice-accent)); border-color: rgba(var(--voice-accent), 0.7); } .voice-conversation-out-btn.is-forced::after { content: ""; position: absolute; top: 2px; right: 2px; width: 8px; height: 8px; border-radius: 50%; background: rgb(var(--voice-accent)); box-shadow: 0 0 6px rgba(var(--voice-accent), 0.8); } .voice-conversation-out-menu { position: absolute; top: 46px; right: 0; min-width: 180px; max-width: 260px; display: flex; flex-direction: column; gap: 2px; padding: 6px; background: rgba(16, 22, 36, 0.96); border: 1px solid rgba(var(--voice-accent), 0.28); border-radius: 14px; box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5); backdrop-filter: blur(8px); } .voice-conversation-out-menu[hidden] { display: none; } .voice-conversation-out-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; font: inherit; font-size: 14px; font-weight: 550; text-align: left; color: rgba(231, 241, 251, 0.9); background: transparent; border: 0; border-radius: 9px; padding: 9px 12px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .voice-conversation-out-item:hover { background: rgba(255, 255, 255, 0.08); } .voice-conversation-out-item:focus-visible { outline: 2px solid rgb(var(--voice-accent)); outline-offset: -2px; } .voice-conversation-out-item[aria-checked="true"] { color: #fff; background: rgba(var(--voice-accent), 0.16); } .voice-conversation-out-item[aria-checked="true"]::after { content: "✓"; font-size: 13px; color: rgb(var(--voice-accent)); } .voice-conversation.is-muted .voice-conversation-orb-halo, .voice-conversation.is-muted .voice-conversation-orb-core { animation: none; transform: none; filter: blur(10px) saturate(0.4); } .voice-conversation.is-muted .voice-conversation-orb-core { filter: saturate(0.35) brightness(0.8); } /* FIX 4: "working…" affordance. Armed by atlas-voice.js (.is-awaiting) only after the model has been Thinking a beat with no reply text yet, so dead time reads as alive. A slow orb shimmer plus animated dots trailing the state caption — cheap, CSS-only, and fully suppressed under reduced motion by the blanket rule below. */ .voice-conversation.is-awaiting .voice-conversation-orb-halo { animation: voice-conversation-await-shimmer 2.6s ease-in-out infinite; } .voice-conversation.is-awaiting .voice-conversation-state::after { content: ""; display: inline-block; width: 1.4em; margin-left: 0.15em; text-align: left; vertical-align: bottom; animation: voice-conversation-await-dots 1.4s steps(4, end) infinite; } @keyframes voice-conversation-await-shimmer { 0%, 100% { opacity: 0.6; filter: blur(10px); } 50% { opacity: 0.92; filter: blur(13px); } } @keyframes voice-conversation-await-dots { 0% { content: ""; } 25% { content: "·"; } 50% { content: "··"; } 75% { content: "···"; } 100% { content: ""; } } @keyframes voice-conversation-breathe { 0%, 100% { opacity: 0.55; transform: scale(calc(0.96 + (var(--conversation-level) * 0.3))); } 50% { opacity: 0.85; transform: scale(calc(1.05 + (var(--conversation-level) * 0.3))); } } @keyframes voice-conversation-sweep { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes voice-conversation-wave { 0% { opacity: 0.8; transform: scale(0.96); } 55% { opacity: 0.5; transform: scale(1.12); } 100% { opacity: 0.75; transform: scale(0.98); } } @keyframes voice-conversation-swell { 0%, 100% { transform: scale(0.99); } 50% { transform: scale(1.05); } } @media (max-width: 640px) { .voice-conversation { gap: 18px; } .voice-conversation-caption-user { max-height: 24vh; } .voice-conversation-caption-assistant { max-height: 34vh; } } /* Reduced motion: static orb states — the accent color and the state caption still communicate every phase without animation or level-driven motion. */ @media (prefers-reduced-motion: reduce) { .voice-conversation *, .voice-conversation *::before, .voice-conversation *::after { animation: none !important; transition: none !important; } .voice-conversation-orb-halo, .voice-conversation-orb-core { transform: none !important; } }