Spaces:
Sleeping
Sleeping
fix(frontend): enable stable click interactions in text input mode by adding pointer-events auto
6f4651f | <html lang="zh-TW"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <meta http-equiv="Content-Security-Policy" | |
| content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: https://accounts.google.com https://www.gstatic.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; connect-src 'self' ws: wss: https://accounts.google.com; img-src 'self' data: https: blob:; media-src 'self' blob: data:; frame-src https://accounts.google.com; base-uri 'self';"> | |
| <title>Bloom Ware 語音沉浸式 - 光暈花瓣版</title> | |
| <link rel="icon" href="/login/icon.svg" type="image/svg+xml"> | |
| <link | |
| href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" | |
| rel="stylesheet"> | |
| <style> | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| body { | |
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; | |
| background: #F5F1ED; | |
| color: #1A1A1A; | |
| overflow: hidden; | |
| -webkit-font-smoothing: antialiased; | |
| /* 2025 最佳實踐:多層 fallback 確保相容性 */ | |
| height: 100vh; | |
| /* fallback 1: 傳統瀏覽器 */ | |
| height: 100svh; | |
| /* fallback 2: 小視窗高度 */ | |
| height: 100dvh; | |
| /* 主要方案: 動態視窗高度(iframe 最佳) */ | |
| /* 針對 WebKit 瀏覽器的額外修正 */ | |
| height: -webkit-fill-available; | |
| } | |
| /* === 控制面板 === */ | |
| .control-panel { | |
| position: fixed; | |
| top: 20px; | |
| left: 20px; | |
| z-index: 200; | |
| background: rgba(255, 255, 255, 0.95); | |
| border: 1px solid rgba(0, 0, 0, 0.08); | |
| border-radius: 16px; | |
| padding: 24px; | |
| backdrop-filter: blur(20px) saturate(180%); | |
| max-width: 320px; | |
| box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08); | |
| display: none; | |
| /* 隱藏模擬面板 */ | |
| } | |
| .control-panel h3 { | |
| font-size: 13px; | |
| font-weight: 600; | |
| letter-spacing: 0.5px; | |
| color: #1A1A1A; | |
| margin-bottom: 20px; | |
| text-transform: uppercase; | |
| } | |
| .control-group { | |
| margin-bottom: 20px; | |
| } | |
| .control-group label { | |
| display: block; | |
| font-size: 11px; | |
| font-weight: 500; | |
| color: rgba(0, 0, 0, 0.5); | |
| margin-bottom: 8px; | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| } | |
| .btn { | |
| width: 100%; | |
| padding: 12px 16px; | |
| margin-bottom: 8px; | |
| background: #FFFFFF; | |
| border: 1px solid rgba(0, 0, 0, 0.08); | |
| border-radius: 10px; | |
| color: #1A1A1A; | |
| font-family: 'Inter', sans-serif; | |
| font-size: 13px; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); | |
| box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); | |
| } | |
| .btn:hover { | |
| background: #F5F5F5; | |
| border-color: rgba(0, 0, 0, 0.12); | |
| transform: translateY(-1px); | |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); | |
| } | |
| .btn:active { | |
| transform: translateY(0); | |
| box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); | |
| } | |
| select { | |
| width: 100%; | |
| padding: 12px; | |
| background: #FFFFFF; | |
| border: 1px solid rgba(0, 0, 0, 0.08); | |
| border-radius: 10px; | |
| color: #1A1A1A; | |
| font-family: 'Inter', sans-serif; | |
| font-size: 13px; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); | |
| } | |
| select:hover { | |
| background: #F5F5F5; | |
| border-color: rgba(0, 0, 0, 0.12); | |
| } | |
| /* === 沉浸式覆蓋層 === */ | |
| .voice-immersive-overlay { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| width: 100vw; | |
| height: 100dvh; | |
| z-index: 100; | |
| overflow: hidden; | |
| pointer-events: none; | |
| background: #F5F1ED; | |
| } | |
| .voice-center-container { | |
| position: fixed; | |
| top: 33%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| z-index: 50; | |
| pointer-events: none; | |
| /* 容器本身不攔截,讓內部元素自己決定 */ | |
| } | |
| /* === 動態漸變背景(移除光暈,改用極淺色情緒底色)=== */ | |
| .voice-immersive-background { | |
| position: fixed; | |
| /* 改為 fixed 確保覆蓋整個視窗 */ | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| width: 100%; | |
| height: 100%; | |
| opacity: 0; | |
| transition: opacity 1.2s cubic-bezier(0.4, 0, 0.2, 1); | |
| z-index: -1; | |
| /* 改為 -1 確保在最底層 */ | |
| pointer-events: none; | |
| /* 不阻擋其他元素的點擊 */ | |
| } | |
| .voice-immersive-background::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: var(--emotion-bg); | |
| opacity: 0.5; | |
| /* 提高透明度,從 0.15 增加到 0.5 */ | |
| } | |
| .voice-immersive-background.active { | |
| opacity: 1; | |
| } | |
| /* 情緒淺色底色變體 */ | |
| .emotion-neutral { | |
| --emotion-bg: linear-gradient(180deg, #E0F2FE 0%, #F5F1ED 100%); | |
| --petal-color: #FFFFFF; | |
| } | |
| .emotion-happy { | |
| --emotion-bg: linear-gradient(180deg, #FEF3C7 0%, #F5F1ED 100%); | |
| --petal-color: #FFFFFF; | |
| } | |
| .emotion-sad { | |
| --emotion-bg: linear-gradient(180deg, #E0E7FF 0%, #F5F1ED 100%); | |
| --petal-color: #FFFFFF; | |
| } | |
| .emotion-angry { | |
| --emotion-bg: linear-gradient(180deg, #FEE2E2 0%, #F5F1ED 100%); | |
| --petal-color: #FFFFFF; | |
| } | |
| .emotion-fear { | |
| --emotion-bg: linear-gradient(180deg, #EDE9FE 0%, #F5F1ED 100%); | |
| --petal-color: #FFFFFF; | |
| } | |
| .emotion-surprise { | |
| --emotion-bg: linear-gradient(180deg, #FFEDD5 0%, #F5F1ED 100%); | |
| --petal-color: #FFFFFF; | |
| } | |
| /* === 中央容器 === */ | |
| .voice-center-container { | |
| position: relative; | |
| z-index: 10; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 60px; | |
| /* 2026 高信心 3D 核心配置 */ | |
| transform-style: preserve-3d; | |
| perspective: 1200px; | |
| --petal-z-back: -44px; | |
| --petal-z-front: 42px; | |
| } | |
| /* === 波形與麥克風容器 === */ | |
| .voice-waveform-container { | |
| position: relative; | |
| width: 400px; | |
| height: 400px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transform-style: preserve-3d; | |
| } | |
| /* Canvas 波形 */ | |
| #waveform-canvas { | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| opacity: 0.3; | |
| } | |
| /* ========== 多層蓮花設計(Bloom Ware 品牌特色)========== */ | |
| .voice-mic-container { | |
| position: relative; | |
| width: 240px; | |
| height: 240px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| z-index: 20; | |
| pointer-events: auto; | |
| transform-style: preserve-3d; | |
| } | |
| /* 花蕊中心(精緻珍珠球體設計,位於花瓣下方)*/ | |
| .bloom-core { | |
| --core-scale: 1; | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| /* 核心 Z 軸置於 120px,始終位於最頂層 */ | |
| transform: translate(-50%, -50%) translateZ(120px); | |
| width: 32px; | |
| height: 32px; | |
| border-radius: 50%; | |
| background: | |
| radial-gradient(circle at 30% 30%, | |
| #FFFFFF 0%, | |
| #FEF9E7 15%, | |
| #FDEAA8 35%, | |
| #FCD34D 60%, | |
| #F59E0B 85%, | |
| #D97706 100%); | |
| box-shadow: | |
| 0 4px 16px rgba(245, 158, 11, 0.4), | |
| 0 2px 8px rgba(251, 191, 36, 0.3), | |
| inset 0 3px 10px rgba(255, 255, 255, 0.8), | |
| inset 0 -3px 10px rgba(217, 119, 6, 0.35); | |
| animation: speakingCoreBreath 2.4s ease-in-out infinite; | |
| z-index: 3; | |
| } | |
| .voice-mic-container:is(.thinking, .speaking, .recording, .disconnected) .bloom-core { | |
| width: 40px; | |
| height: 40px; | |
| } | |
| /* 花蕊高光(更強烈的玻璃光澤)*/ | |
| .bloom-core::before { | |
| content: ''; | |
| position: absolute; | |
| top: 8%; | |
| left: 10%; | |
| width: 55%; | |
| height: 55%; | |
| border-radius: 50%; | |
| background: | |
| radial-gradient(circle at 35% 35%, | |
| rgba(255, 255, 255, 0.95) 0%, | |
| rgba(255, 255, 255, 0.6) 25%, | |
| rgba(255, 255, 255, 0.2) 50%, | |
| transparent 70%); | |
| filter: blur(1px); | |
| } | |
| /* 花蕊深層陰影(移除綠莖,改為立體陰影)*/ | |
| .bloom-core::after { | |
| content: ''; | |
| position: absolute; | |
| bottom: 5%; | |
| right: 8%; | |
| width: 40%; | |
| height: 40%; | |
| border-radius: 50%; | |
| background: | |
| radial-gradient(circle at 50% 50%, | |
| rgba(217, 119, 6, 0.4) 0%, | |
| rgba(217, 119, 6, 0.2) 50%, | |
| transparent 100%); | |
| filter: blur(2px); | |
| } | |
| @keyframes coreBreath { | |
| 0%, | |
| 100% { | |
| transform: translate(-50%, -50%) translateZ(120px) scale(calc(var(--core-scale) * 1)) rotate(0deg); | |
| box-shadow: | |
| 0 3px 12px rgba(251, 191, 36, 0.3), | |
| 0 1px 4px rgba(251, 191, 36, 0.2), | |
| inset 0 2px 6px rgba(255, 255, 255, 0.6), | |
| inset 0 -2px 6px rgba(245, 158, 11, 0.3); | |
| } | |
| 50% { | |
| transform: translate(-50%, -50%) translateZ(120px) scale(calc(var(--core-scale) * 1.05)) rotate(2deg); | |
| box-shadow: | |
| 0 4px 16px rgba(251, 191, 36, 0.4), | |
| 0 2px 6px rgba(251, 191, 36, 0.3), | |
| inset 0 3px 8px rgba(255, 255, 255, 0.7), | |
| inset 0 -3px 8px rgba(245, 158, 11, 0.4); | |
| } | |
| } | |
| /* 花瓣容器(多層結構,啟用 3D 透視)*/ | |
| .bloom-petals { | |
| position: absolute; | |
| top: -15%; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| transform-style: preserve-3d; | |
| perspective: 1000px; | |
| } | |
| .bloom-petal-group { | |
| position: absolute; | |
| inset: 0; | |
| transform-style: preserve-3d; | |
| pointer-events: none; | |
| } | |
| .bloom-petal-group.upper { | |
| margin-top: -15px; | |
| z-index: 10; | |
| transform: translateZ(0); | |
| } | |
| .bloom-petal-group.lower { | |
| margin-top: 0; | |
| z-index: 30; | |
| transform: translateZ(20px); | |
| } | |
| .bloom-petal { | |
| position: absolute; | |
| width: 65px; | |
| height: 105px; | |
| top: 50%; | |
| left: 50%; | |
| transform-origin: 50% 90%; | |
| transform-style: preserve-3d; | |
| transition: all 1.8s cubic-bezier(0.25, 0.46, 0.45, 0.94); | |
| opacity: 0.8; | |
| z-index: 5; | |
| } | |
| .bloom-petal-group.upper .bloom-petal { | |
| width: 65px; | |
| height: 105px; | |
| z-index: 10; | |
| } | |
| .bloom-petal-group.upper .bloom-petal::before { | |
| background: | |
| radial-gradient(ellipse 80% 60% at 50% 30%, | |
| rgba(252, 252, 252, 1) 0%, | |
| rgba(250, 250, 250, 0.98) 40%, | |
| rgba(245, 246, 248, 0.95) 70%, | |
| rgba(238, 240, 243, 0.9) 100%), | |
| linear-gradient(180deg, | |
| #F8F8F8 0%, | |
| #F4F4F4 30%, | |
| #ECEEF1 70%, | |
| #E4E6E9 100%); | |
| } | |
| .bloom-petal-group.upper .bloom-petal::after { | |
| opacity: 0.8; | |
| background: linear-gradient(180deg, | |
| rgba(0, 0, 0, 0.15) 0%, | |
| rgba(0, 0, 0, 0.08) 50%, | |
| transparent 100%); | |
| } | |
| .bloom-petal-group.lower .bloom-petal { | |
| width: 58px; | |
| height: 98px; | |
| z-index: 20; | |
| } | |
| .bloom-petal-group.lower .bloom-petal::after { | |
| opacity: 0.75; | |
| background: linear-gradient(180deg, | |
| rgba(0, 0, 0, 0.12) 0%, | |
| rgba(0, 0, 0, 0.06) 50%, | |
| transparent 100%); | |
| } | |
| .bloom-petal-group.lower .bloom-petal::before { | |
| background: | |
| radial-gradient(ellipse 80% 60% at 50% 30%, | |
| rgba(255, 255, 255, 0.98) 0%, | |
| rgba(255, 255, 255, 0.96) 40%, | |
| rgba(249, 250, 251, 0.92) 70%, | |
| rgba(243, 244, 246, 0.85) 100%), | |
| linear-gradient(180deg, | |
| rgba(255, 255, 255, 0.95) 0%, | |
| rgba(254, 254, 254, 0.92) 30%, | |
| rgba(249, 250, 251, 0.88) 70%, | |
| rgba(243, 244, 246, 0.85) 100%); | |
| clip-path: path('M 29 5 Q 34 0, 39 5 Q 49 20, 54 50 Q 57 75, 49 92 Q 44 98, 29 98 Q 21 98, 16 92 Q 8 75, 11 50 Q 16 20, 26 5'); | |
| } | |
| .bloom-petal::before { | |
| content: ''; | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| background: | |
| radial-gradient(ellipse 80% 60% at 50% 30%, | |
| rgba(255, 255, 255, 1) 0%, | |
| rgba(255, 255, 255, 0.98) 40%, | |
| rgba(249, 250, 251, 0.95) 70%, | |
| rgba(243, 244, 246, 0.9) 100%), | |
| linear-gradient(180deg, | |
| #FFFFFF 0%, | |
| #FEFEFE 30%, | |
| #F9FAFB 70%, | |
| #F3F4F6 100%); | |
| clip-path: path('M 30 5 Q 35 0, 40 5 Q 50 20, 55 50 Q 58 75, 50 92 Q 45 98, 30 98 Q 22 98, 17 92 Q 9 75, 12 50 Q 17 20, 27 5'); | |
| box-shadow: | |
| 0 6px 20px rgba(0, 0, 0, 0.15), | |
| inset -3px 4px 10px rgba(0, 0, 0, 0.08), | |
| inset 3px -4px 12px rgba(255, 255, 255, 0.95), | |
| inset 0 -2px 6px rgba(0, 0, 0, 0.04); | |
| transition: all 0.8s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| border: 1px solid rgba(0, 0, 0, 0.06); | |
| filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.08)); | |
| } | |
| .bloom-petal::after { | |
| content: ''; | |
| position: absolute; | |
| top: 5%; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 1.5px; | |
| height: 75%; | |
| background: linear-gradient(180deg, | |
| rgba(0, 0, 0, 0.08) 0%, | |
| rgba(0, 0, 0, 0.04) 50%, | |
| transparent 100%); | |
| border-radius: 1px; | |
| opacity: 0.6; | |
| filter: blur(0.3px); | |
| } | |
| .bloom-petal { | |
| opacity: 0.9; | |
| } | |
| .bloom-petal-group.upper .bloom-petal:nth-child(1) { --rotate: 0deg; transform: translate(-50%, -50%) rotateZ(0deg) rotateX(0deg) translateY(-15px) scale(0.6); animation: petalBloom 1.6s ease-in-out infinite 0s; z-index: 11; } | |
| .bloom-petal-group.upper .bloom-petal:nth-child(2) { --rotate: 45deg; transform: translate(-50%, -50%) rotateZ(45deg) rotateX(0deg) translateY(-15px) scale(0.6); animation: petalBloom 1.6s ease-in-out infinite 0.2s; z-index: 9; } | |
| .bloom-petal-group.upper .bloom-petal:nth-child(3) { --rotate: 90deg; transform: translate(-50%, -50%) rotateZ(90deg) rotateX(0deg) translateY(-15px) scale(0.6); animation: petalBloom 1.6s ease-in-out infinite 0.4s; z-index: 7; } | |
| .bloom-petal-group.upper .bloom-petal:nth-child(4) { --rotate: 135deg; transform: translate(-50%, -50%) rotateZ(135deg) rotateX(0deg) translateY(-15px) scale(0.6); animation: petalBloom 1.6s ease-in-out infinite 0.6s; z-index: 5; } | |
| .bloom-petal-group.upper .bloom-petal:nth-child(5) { --rotate: 180deg; transform: translate(-50%, -50%) rotateZ(180deg) rotateX(0deg) translateY(-15px) scale(0.6); animation: petalBloom 1.6s ease-in-out infinite 0.8s; z-index: 3; } | |
| .bloom-petal-group.upper .bloom-petal:nth-child(6) { --rotate: 225deg; transform: translate(-50%, -50%) rotateZ(225deg) rotateX(0deg) translateY(-15px) scale(0.6); animation: petalBloom 1.6s ease-in-out infinite 1s; z-index: 5; } | |
| .bloom-petal-group.upper .bloom-petal:nth-child(7) { --rotate: 270deg; transform: translate(-50%, -50%) rotateZ(270deg) rotateX(0deg) translateY(-15px) scale(0.6); animation: petalBloom 1.6s ease-in-out infinite 1.2s; z-index: 7; } | |
| .bloom-petal-group.upper .bloom-petal:nth-child(8) { --rotate: 315deg; transform: translate(-50%, -50%) rotateZ(315deg) rotateX(0deg) translateY(-15px) scale(0.6); animation: petalBloom 1.6s ease-in-out infinite 1.4s; z-index: 9; } | |
| .bloom-petal-group.lower .bloom-petal:nth-child(1) { --rotate-inner: 0deg; transform: translate(-50%, -50%) rotateZ(0deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); animation: petalBloomInner 1.6s ease-in-out infinite 0.1s; z-index: 21; } | |
| .bloom-petal-group.lower .bloom-petal:nth-child(2) { --rotate-inner: 45deg; transform: translate(-50%, -50%) rotateZ(45deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); animation: petalBloomInner 1.6s ease-in-out infinite 0.3s; z-index: 19; } | |
| .bloom-petal-group.lower .bloom-petal:nth-child(3) { --rotate-inner: 90deg; transform: translate(-50%, -50%) rotateZ(90deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); animation: petalBloomInner 1.6s ease-in-out infinite 0.5s; z-index: 17; } | |
| .bloom-petal-group.lower .bloom-petal:nth-child(4) { --rotate-inner: 135deg; transform: translate(-50%, -50%) rotateZ(135deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); animation: petalBloomInner 1.6s ease-in-out infinite 0.7s; z-index: 15; } | |
| .bloom-petal-group.lower .bloom-petal:nth-child(5) { --rotate-inner: 180deg; transform: translate(-50%, -50%) rotateZ(180deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); animation: petalBloomInner 1.6s ease-in-out infinite 0.9s; z-index: 13; } | |
| .bloom-petal-group.lower .bloom-petal:nth-child(6) { --rotate-inner: 225deg; transform: translate(-50%, -50%) rotateZ(225deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); animation: petalBloomInner 1.6s ease-in-out infinite 1.1s; z-index: 15; } | |
| .bloom-petal-group.lower .bloom-petal:nth-child(7) { --rotate-inner: 270deg; transform: translate(-50%, -50%) rotateZ(270deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); animation: petalBloomInner 1.6s ease-in-out infinite 1.3s; z-index: 17; } | |
| .bloom-petal-group.lower .bloom-petal:nth-child(8) { --rotate-inner: 315deg; transform: translate(-50%, -50%) rotateZ(315deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); animation: petalBloomInner 1.6s ease-in-out infinite 1.5s; z-index: 19; } | |
| .voice-mic-container.thinking .bloom-petal { | |
| opacity: 1; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.upper .bloom-petal:nth-child(1) { | |
| transform: translate(-50%, -50%) rotateZ(0deg) rotateX(70deg) translateY(-5px) scale(0.9); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.upper .bloom-petal:nth-child(2) { | |
| transform: translate(-50%, -50%) rotateZ(45deg) rotateX(70deg) translateY(-5px) scale(0.9); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.upper .bloom-petal:nth-child(3) { | |
| transform: translate(-50%, -50%) rotateZ(90deg) rotateX(70deg) translateY(-5px) scale(0.9); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.upper .bloom-petal:nth-child(4) { | |
| transform: translate(-50%, -50%) rotateZ(135deg) rotateX(70deg) translateY(-5px) scale(0.9); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.upper .bloom-petal:nth-child(5) { | |
| transform: translate(-50%, -50%) rotateZ(180deg) rotateX(70deg) translateY(-5px) scale(0.9); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.upper .bloom-petal:nth-child(6) { | |
| transform: translate(-50%, -50%) rotateZ(225deg) rotateX(70deg) translateY(-5px) scale(0.9); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.upper .bloom-petal:nth-child(7) { | |
| transform: translate(-50%, -50%) rotateZ(270deg) rotateX(70deg) translateY(-5px) scale(0.9); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.upper .bloom-petal:nth-child(8) { | |
| transform: translate(-50%, -50%) rotateZ(315deg) rotateX(70deg) translateY(-5px) scale(0.9); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.lower .bloom-petal:nth-child(1) { | |
| transform: translate(-50%, -50%) rotateZ(0deg) rotateX(60deg) rotateZ(20deg) translateY(-12px) scale(0.85); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.lower .bloom-petal:nth-child(2) { | |
| transform: translate(-50%, -50%) rotateZ(45deg) rotateX(60deg) rotateZ(20deg) translateY(-12px) scale(0.85); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.lower .bloom-petal:nth-child(3) { | |
| transform: translate(-50%, -50%) rotateZ(90deg) rotateX(60deg) rotateZ(20deg) translateY(-12px) scale(0.85); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.lower .bloom-petal:nth-child(4) { | |
| transform: translate(-50%, -50%) rotateZ(135deg) rotateX(60deg) rotateZ(20deg) translateY(-12px) scale(0.85); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.lower .bloom-petal:nth-child(5) { | |
| transform: translate(-50%, -50%) rotateZ(180deg) rotateX(60deg) rotateZ(20deg) translateY(-12px) scale(0.85); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.lower .bloom-petal:nth-child(6) { | |
| transform: translate(-50%, -50%) rotateZ(225deg) rotateX(60deg) rotateZ(20deg) translateY(-12px) scale(0.85); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.lower .bloom-petal:nth-child(7) { | |
| transform: translate(-50%, -50%) rotateZ(270deg) rotateX(60deg) rotateZ(20deg) translateY(-12px) scale(0.85); | |
| animation: none; | |
| } | |
| .voice-mic-container.thinking .bloom-petal-group.lower .bloom-petal:nth-child(8) { | |
| transform: translate(-50%, -50%) rotateZ(315deg) rotateX(60deg) rotateZ(20deg) translateY(-12px) scale(0.85); | |
| animation: none; | |
| } | |
| @keyframes petalBloom { | |
| 0%, | |
| 100% { | |
| transform: translate(-50%, -50%) rotateZ(calc(var(--rotate) + 0deg)) translateY(-30px) scale(1); | |
| } | |
| 50% { | |
| transform: translate(-50%, -50%) rotateZ(calc(var(--rotate) + 1.5deg)) translateY(-33px) scale(1.04); | |
| } | |
| } | |
| @keyframes petalBloomInner { | |
| 0%, | |
| 100% { | |
| transform: translate(-50%, -50%) rotateZ(calc(var(--rotate-inner) + 0deg)) rotateX(15deg) rotateZ(20deg) translateY(-22px) translateZ(10px) scale(1); | |
| } | |
| 50% { | |
| transform: translate(-50%, -50%) rotateZ(calc(var(--rotate-inner) - 1deg)) rotateX(18deg) rotateZ(22deg) translateY(-25px) translateZ(12px) scale(1.03); | |
| } | |
| } | |
| .voice-mic-container.thinking .bloom-petal::before { | |
| box-shadow: | |
| 0 6px 24px rgba(0, 0, 0, 0.16), | |
| inset -2px 3px 8px rgba(0, 0, 0, 0.08), | |
| inset 2px -3px 10px rgba(255, 255, 255, 0.95); | |
| } | |
| .voice-mic-container.disconnected .bloom-petal { | |
| opacity: 1; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.upper .bloom-petal:nth-child(1) { | |
| --rotate-disc: 0deg; | |
| animation: petalDisconnect 1.6s ease-in-out infinite 0s; | |
| z-index: 10; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.upper .bloom-petal:nth-child(2) { | |
| --rotate-disc: 45deg; | |
| animation: petalDisconnect 1.6s ease-in-out infinite 0.2s; | |
| z-index: 8; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.upper .bloom-petal:nth-child(3) { | |
| --rotate-disc: 90deg; | |
| animation: petalDisconnect 1.6s ease-in-out infinite 0.4s; | |
| z-index: 6; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.upper .bloom-petal:nth-child(4) { | |
| --rotate-disc: 135deg; | |
| animation: petalDisconnect 1.6s ease-in-out infinite 0.6s; | |
| z-index: 4; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.upper .bloom-petal:nth-child(5) { | |
| --rotate-disc: 180deg; | |
| animation: petalDisconnect 1.6s ease-in-out infinite 0.8s; | |
| z-index: 2; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.upper .bloom-petal:nth-child(6) { | |
| --rotate-disc: 225deg; | |
| animation: petalDisconnect 1.6s ease-in-out infinite 1s; | |
| z-index: 4; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.upper .bloom-petal:nth-child(7) { | |
| --rotate-disc: 270deg; | |
| animation: petalDisconnect 1.6s ease-in-out infinite 1.2s; | |
| z-index: 6; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.upper .bloom-petal:nth-child(8) { | |
| --rotate-disc: 315deg; | |
| animation: petalDisconnect 1.6s ease-in-out infinite 1.4s; | |
| z-index: 8; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.lower .bloom-petal:nth-child(1) { | |
| --rotate-disc-inner: 67.5deg; | |
| animation: petalDisconnectInner 1.6s ease-in-out infinite 0.1s; | |
| z-index: 11; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.lower .bloom-petal:nth-child(2) { | |
| --rotate-disc-inner: 112.5deg; | |
| animation: petalDisconnectInner 1.6s ease-in-out infinite 0.3s; | |
| z-index: 9; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.lower .bloom-petal:nth-child(3) { | |
| --rotate-disc-inner: 157.5deg; | |
| animation: petalDisconnectInner 1.6s ease-in-out infinite 0.5s; | |
| z-index: 7; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.lower .bloom-petal:nth-child(4) { | |
| --rotate-disc-inner: 202.5deg; | |
| animation: petalDisconnectInner 1.6s ease-in-out infinite 0.7s; | |
| z-index: 5; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.lower .bloom-petal:nth-child(5) { | |
| --rotate-disc-inner: 247.5deg; | |
| animation: petalDisconnectInner 1.6s ease-in-out infinite 0.9s; | |
| z-index: 3; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.lower .bloom-petal:nth-child(6) { | |
| --rotate-disc-inner: 292.5deg; | |
| animation: petalDisconnectInner 1.6s ease-in-out infinite 1.1s; | |
| z-index: 5; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.lower .bloom-petal:nth-child(7) { | |
| --rotate-disc-inner: 337.5deg; | |
| animation: petalDisconnectInner 1.6s ease-in-out infinite 1.3s; | |
| z-index: 7; | |
| } | |
| .voice-mic-container.disconnected .bloom-petal-group.lower .bloom-petal:nth-child(8) { | |
| --rotate-disc-inner: 382.5deg; | |
| animation: petalDisconnectInner 1.6s ease-in-out infinite 1.5s; | |
| z-index: 9; | |
| } | |
| @keyframes petalDisconnect { | |
| 0%, | |
| 100% { | |
| transform: translate(-50%, -50%) rotateZ(calc(var(--rotate-disc) + 0deg)) translateY(-30px) scale(1); | |
| } | |
| 50% { | |
| transform: translate(-50%, -50%) rotateZ(calc(var(--rotate-disc) - 3deg)) translateY(-33px) scale(1.04); | |
| } | |
| } | |
| @keyframes petalDisconnectInner { | |
| 0%, | |
| 100% { | |
| transform: translate(-50%, -50%) rotateZ(calc(var(--rotate-disc-inner) + 0deg)) translateY(-15px) scale(1); | |
| } | |
| 50% { | |
| transform: translate(-50%, -50%) rotateZ(calc(var(--rotate-disc-inner) - 2deg)) translateY(-18px) scale(1.03); | |
| } | |
| } | |
| .voice-mic-container.disconnected .bloom-petal::before { | |
| background: linear-gradient(180deg, | |
| #FEE2E2 0%, | |
| #FCA5A5 30%, | |
| #F87171 70%, | |
| #EF4444 100%); | |
| box-shadow: | |
| 0 6px 24px rgba(239, 68, 68, 0.5), | |
| inset -2px 2px 6px rgba(239, 68, 68, 0.35), | |
| inset 2px -2px 6px rgba(255, 255, 255, 0.5); | |
| } | |
| .voice-mic-container.disconnected .bloom-core { | |
| background: linear-gradient(180deg, #FEE2E2 0%, #FCA5A5 50%, #EF4444 100%); | |
| border-color: #EF4444; | |
| box-shadow: | |
| 0 4px 20px rgba(239, 68, 68, 0.4), | |
| inset 0 1px 2px rgba(255, 255, 255, 0.3); | |
| } | |
| .voice-mic-container:hover .bloom-core { | |
| transform: translate(-50%, -50%) translateZ(120px) scale(1.08); | |
| box-shadow: | |
| 0 4px 20px rgba(0, 0, 0, 0.15), | |
| inset 0 1px 3px rgba(255, 255, 255, 0.6); | |
| } | |
| .voice-mic-container.recording .bloom-core { | |
| background: radial-gradient(circle at 35% 35%, | |
| #FEE2E2 0%, | |
| #FCA5A5 25%, | |
| #F87171 55%, | |
| #EF4444 85%, | |
| #DC2626 100%); | |
| border-color: #EF4444; | |
| animation: recordingCoreFlash 1.5s ease-in-out infinite; | |
| } | |
| .voice-mic-container.recording .bloom-petal { | |
| animation: recordingPetalGlow 1.8s ease-in-out infinite; | |
| } | |
| @keyframes recordingCoreFlash { | |
| 0%, | |
| 100% { | |
| transform: translate(-50%, -50%) translateZ(120px) scale(1); | |
| box-shadow: | |
| 0 4px 20px rgba(239, 68, 68, 0.4), | |
| inset 0 1px 2px rgba(255, 255, 255, 0.3); | |
| } | |
| 50% { | |
| transform: translate(-50%, -50%) translateZ(120px) scale(1.15); | |
| box-shadow: | |
| 0 6px 30px rgba(239, 68, 68, 0.6), | |
| inset 0 1px 3px rgba(255, 255, 255, 0.4); | |
| } | |
| } | |
| @keyframes recordingPetalGlow { | |
| 0%, | |
| 100% { | |
| opacity: 0.85; | |
| filter: brightness(1); | |
| } | |
| 50% { | |
| opacity: 1; | |
| filter: brightness(1.08); | |
| } | |
| } | |
| .voice-mic-container.speaking .bloom-petal { | |
| opacity: 1; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.upper .bloom-petal { | |
| animation: none; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.lower .bloom-petal { | |
| animation: none; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.upper .bloom-petal:nth-child(1) { | |
| --rotate: 0deg; | |
| transform: translate(-50%, -50%) rotateZ(0deg) rotateX(0deg) translateY(-15px) scale(0.6); | |
| animation: petalBloom 1.6s ease-in-out infinite 0s; | |
| z-index: 11; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.upper .bloom-petal:nth-child(2) { | |
| --rotate: 45deg; | |
| transform: translate(-50%, -50%) rotateZ(45deg) rotateX(0deg) translateY(-15px) scale(0.6); | |
| animation: petalBloom 1.6s ease-in-out infinite 0.2s; | |
| z-index: 9; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.upper .bloom-petal:nth-child(3) { | |
| --rotate: 90deg; | |
| transform: translate(-50%, -50%) rotateZ(90deg) rotateX(0deg) translateY(-15px) scale(0.6); | |
| animation: petalBloom 1.6s ease-in-out infinite 0.4s; | |
| z-index: 7; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.upper .bloom-petal:nth-child(4) { | |
| --rotate: 135deg; | |
| transform: translate(-50%, -50%) rotateZ(135deg) rotateX(0deg) translateY(-15px) scale(0.6); | |
| animation: petalBloom 1.6s ease-in-out infinite 0.6s; | |
| z-index: 5; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.upper .bloom-petal:nth-child(5) { | |
| --rotate: 180deg; | |
| transform: translate(-50%, -50%) rotateZ(180deg) rotateX(0deg) translateY(-15px) scale(0.6); | |
| animation: petalBloom 1.6s ease-in-out infinite 0.8s; | |
| z-index: 3; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.upper .bloom-petal:nth-child(6) { | |
| --rotate: 225deg; | |
| transform: translate(-50%, -50%) rotateZ(225deg) rotateX(0deg) translateY(-15px) scale(0.6); | |
| animation: petalBloom 1.6s ease-in-out infinite 1s; | |
| z-index: 5; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.upper .bloom-petal:nth-child(7) { | |
| --rotate: 270deg; | |
| transform: translate(-50%, -50%) rotateZ(270deg) rotateX(0deg) translateY(-15px) scale(0.6); | |
| animation: petalBloom 1.6s ease-in-out infinite 1.2s; | |
| z-index: 7; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.upper .bloom-petal:nth-child(8) { | |
| --rotate: 315deg; | |
| transform: translate(-50%, -50%) rotateZ(315deg) rotateX(0deg) translateY(-15px) scale(0.6); | |
| animation: petalBloom 1.6s ease-in-out infinite 1.4s; | |
| z-index: 9; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.lower .bloom-petal:nth-child(1) { | |
| --rotate-inner: 0deg; | |
| transform: translate(-50%, -50%) rotateZ(0deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); | |
| animation: petalBloomInner 1.6s ease-in-out infinite 0.1s; | |
| z-index: 21; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.lower .bloom-petal:nth-child(2) { | |
| --rotate-inner: 45deg; | |
| transform: translate(-50%, -50%) rotateZ(45deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); | |
| animation: petalBloomInner 1.6s ease-in-out infinite 0.3s; | |
| z-index: 19; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.lower .bloom-petal:nth-child(3) { | |
| --rotate-inner: 90deg; | |
| transform: translate(-50%, -50%) rotateZ(90deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); | |
| animation: petalBloomInner 1.6s ease-in-out infinite 0.5s; | |
| z-index: 17; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.lower .bloom-petal:nth-child(4) { | |
| --rotate-inner: 135deg; | |
| transform: translate(-50%, -50%) rotateZ(135deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); | |
| animation: petalBloomInner 1.6s ease-in-out infinite 0.7s; | |
| z-index: 15; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.lower .bloom-petal:nth-child(5) { | |
| --rotate-inner: 180deg; | |
| transform: translate(-50%, -50%) rotateZ(180deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); | |
| animation: petalBloomInner 1.6s ease-in-out infinite 0.9s; | |
| z-index: 13; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.lower .bloom-petal:nth-child(6) { | |
| --rotate-inner: 225deg; | |
| transform: translate(-50%, -50%) rotateZ(225deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); | |
| animation: petalBloomInner 1.6s ease-in-out infinite 1.1s; | |
| z-index: 15; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.lower .bloom-petal:nth-child(7) { | |
| --rotate-inner: 270deg; | |
| transform: translate(-50%, -50%) rotateZ(270deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); | |
| animation: petalBloomInner 1.6s ease-in-out infinite 1.3s; | |
| z-index: 17; | |
| } | |
| .voice-mic-container.speaking .bloom-petal-group.lower .bloom-petal:nth-child(8) { | |
| --rotate-inner: 315deg; | |
| transform: translate(-50%, -50%) rotateZ(315deg) rotateX(15deg) rotateZ(20deg) translateY(-10px) translateZ(10px) scale(0.55); | |
| animation: petalBloomInner 1.6s ease-in-out infinite 1.5s; | |
| z-index: 19; | |
| } | |
| .voice-mic-container.speaking .bloom-petal::before { | |
| box-shadow: | |
| 0 8px 32px rgba(0, 0, 0, 0.18), | |
| inset -2px 3px 8px rgba(0, 0, 0, 0.1), | |
| inset 2px -3px 12px rgba(255, 255, 255, 0.95); | |
| } | |
| .voice-mic-container.speaking .bloom-core { | |
| animation: speakingCoreBreath 2.4s ease-in-out infinite; | |
| transform: translate(-50%, -50%) translateZ(120px); | |
| } | |
| @keyframes speakingCoreBreath { | |
| 0%, | |
| 100% { | |
| transform: translate(-50%, -50%) translateZ(120px) scale(calc(var(--core-scale, 1) * 1)); | |
| } | |
| 50% { | |
| transform: translate(-50%, -50%) translateZ(120px) scale(calc(var(--core-scale, 1) * 1.08)); | |
| } | |
| } | |
| /* === Agent 文字輸出區域(打字機效果)=== */ | |
| .voice-agent-output { | |
| --agent-output-ink: #171717; | |
| --agent-output-muted: rgba(23, 23, 23, 0.58); | |
| --agent-output-line: rgba(23, 23, 23, 0.11); | |
| --agent-output-glow: rgba(48, 71, 94, 0.13); | |
| /* 【關鍵修復】使用固定定位在螢幕底部,避免偏移 */ | |
| position: fixed; | |
| bottom: 120px; | |
| left: 50%; | |
| transform: translateX(-50%) translateY(20px) scale(0.985); | |
| width: clamp(320px, 60vw, 680px); | |
| max-width: calc(100vw - 40px); | |
| min-height: 60px; | |
| max-height: min(30vh, 320px); | |
| padding: 20px 28px; | |
| background: rgba(255, 255, 255, 0.72); | |
| backdrop-filter: blur(20px) saturate(180%); | |
| border: 1px solid rgba(255, 255, 255, 0.4); | |
| border-radius: 20px; | |
| font-size: 16px; | |
| line-height: 1.6; | |
| color: #171717; | |
| box-shadow: 0 12px 40px rgba(0, 0, 0, 0.08); | |
| z-index: 1000; | |
| pointer-events: auto; | |
| transition: all 0.4s cubic-bezier(0.22, 1, 0.36, 1); | |
| display: none; | |
| opacity: 0; | |
| transition: | |
| opacity 260ms ease, | |
| transform 360ms cubic-bezier(0.22, 1, 0.36, 1), | |
| width 240ms ease, | |
| max-height 240ms ease; | |
| overflow-y: auto; | |
| overflow-x: hidden; | |
| -webkit-overflow-scrolling: touch; | |
| scrollbar-gutter: stable; | |
| } | |
| .voice-agent-output.active { | |
| display: block; | |
| opacity: 1; | |
| transform: translateX(-50%) translateY(0) scale(1); | |
| } | |
| .agent-output-shell { | |
| display: grid; | |
| grid-template-columns: 3px minmax(0, 1fr); | |
| gap: 14px; | |
| align-items: start; | |
| animation: agentOutputFlowIn 280ms cubic-bezier(0.22, 1, 0.36, 1); | |
| } | |
| .agent-output-shell::before { | |
| content: ''; | |
| width: 3px; | |
| min-height: 100%; | |
| border-radius: 999px; | |
| background: linear-gradient(180deg, rgba(67, 87, 71, 0.55), rgba(67, 87, 71, 0.08)); | |
| box-shadow: 0 0 18px rgba(67, 87, 71, 0.18); | |
| } | |
| .agent-output-content { | |
| min-width: 0; | |
| } | |
| .voice-agent-output.typing-active .agent-output-content { | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .voice-agent-output.typing-active .agent-output-content p, | |
| .voice-agent-output.typing-active .agent-output-content ul, | |
| .voice-agent-output.typing-active .agent-output-content li, | |
| .voice-agent-output.typing-active .agent-output-content h1, | |
| .voice-agent-output.typing-active .agent-output-content h2, | |
| .voice-agent-output.typing-active .agent-output-content h3 { | |
| display: inline; | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .voice-agent-output.output-mode-processing { | |
| max-height: 200px; | |
| } | |
| .voice-agent-output.output-mode-streaming { | |
| max-height: min(28vh, 280px); | |
| } | |
| .voice-agent-output.output-mode-final { | |
| max-height: min(30vh, 320px); | |
| } | |
| .voice-agent-output h1, | |
| .voice-agent-output h2, | |
| .voice-agent-output h3 { | |
| margin: 0 0 8px; | |
| line-height: 1.25; | |
| font-weight: 700; | |
| } | |
| .voice-agent-output h1 { | |
| font-size: 1.18em; | |
| } | |
| .voice-agent-output h2 { | |
| font-size: 1.1em; | |
| } | |
| .voice-agent-output h3 { | |
| font-size: 1.02em; | |
| } | |
| .voice-agent-output p { | |
| margin: 0 0 10px; | |
| } | |
| .voice-agent-output p:last-child, | |
| .voice-agent-output h1:last-child, | |
| .voice-agent-output h2:last-child, | |
| .voice-agent-output h3:last-child, | |
| .voice-agent-output ul:last-child { | |
| margin-bottom: 0; | |
| } | |
| .agent-output-typewriter-line { | |
| margin: 0; | |
| } | |
| .voice-agent-output p:last-child, | |
| .voice-agent-output ul:last-child, | |
| .voice-agent-output pre:last-child { | |
| margin-bottom: 0; | |
| } | |
| .voice-agent-output ul { | |
| margin: 0 0 8px 1.1em; | |
| padding: 0; | |
| } | |
| .voice-agent-output li { | |
| margin: 2px 0; | |
| } | |
| .voice-agent-output code { | |
| font-family: 'JetBrains Mono', monospace; | |
| font-size: 0.88em; | |
| padding: 1px 5px; | |
| border-radius: 5px; | |
| background: rgba(0, 0, 0, 0.06); | |
| } | |
| .voice-agent-output pre { | |
| margin: 8px 0; | |
| padding: 10px 12px; | |
| border-radius: 10px; | |
| overflow-x: auto; | |
| background: rgba(0, 0, 0, 0.07); | |
| } | |
| .voice-agent-output pre code { | |
| padding: 0; | |
| background: transparent; | |
| } | |
| .voice-agent-output a { | |
| color: #0B5CAD; | |
| text-decoration: none; | |
| border-bottom: 1px solid rgba(11, 92, 173, 0.28); | |
| } | |
| .voice-agent-output.progress-mode { | |
| overflow: hidden; | |
| } | |
| .agent-progress-stack { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| } | |
| .agent-progress-row { | |
| display: grid; | |
| grid-template-columns: 20px 1fr; | |
| align-items: center; | |
| gap: 10px; | |
| color: var(--agent-output-muted); | |
| font-size: 13px; | |
| line-height: 1.45; | |
| animation: agentOutputFlowIn 260ms cubic-bezier(0.22, 1, 0.36, 1); | |
| } | |
| .agent-progress-row.current { | |
| color: var(--agent-output-ink); | |
| font-weight: 600; | |
| } | |
| .agent-progress-dot { | |
| width: 8px; | |
| height: 8px; | |
| justify-self: center; | |
| border-radius: 50%; | |
| background: rgba(23, 23, 23, 0.22); | |
| box-shadow: 0 0 0 5px rgba(23, 23, 23, 0.035); | |
| } | |
| .agent-progress-row.current .agent-progress-dot { | |
| background: #435747; | |
| animation: agentProgressPulse 1.18s ease-in-out infinite; | |
| } | |
| @keyframes agentOutputFlowIn { | |
| from { | |
| opacity: 0; | |
| transform: translateY(8px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| @keyframes agentProgressPulse { | |
| 0%, | |
| 100% { | |
| box-shadow: 0 0 0 4px rgba(67, 87, 71, 0.12); | |
| transform: scale(0.92); | |
| } | |
| 50% { | |
| box-shadow: 0 0 0 9px rgba(67, 87, 71, 0.04); | |
| transform: scale(1.08); | |
| } | |
| } | |
| /* 自訂滾動條樣式 */ | |
| .voice-agent-output::-webkit-scrollbar { | |
| width: 4px; | |
| } | |
| .voice-agent-output::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| .voice-agent-output::-webkit-scrollbar-thumb { | |
| background: rgba(0, 0, 0, 0.15); | |
| border-radius: 2px; | |
| } | |
| /* 打字游標效果 */ | |
| .voice-agent-output.typing-active .typing-cursor { | |
| content: '▋'; | |
| display: inline-block; | |
| animation: typingCursor 0.8s steps(2) infinite; | |
| margin-left: 2px; | |
| color: rgba(0, 0, 0, 0.6); | |
| vertical-align: baseline; | |
| } | |
| @keyframes typingCursor { | |
| 0%, | |
| 50% { | |
| opacity: 1; | |
| } | |
| 51%, | |
| 100% { | |
| opacity: 0; | |
| } | |
| } | |
| @media (prefers-reduced-motion: reduce) { | |
| .voice-agent-output, | |
| .agent-output-shell, | |
| .agent-progress-row, | |
| .agent-progress-row.current .agent-progress-dot, | |
| .voice-agent-output.typing-active .typing-cursor { | |
| animation: none ; | |
| transition: none ; | |
| } | |
| } | |
| /* === 實時字幕 / 文字輸入框 === */ | |
| .voice-transcript { | |
| position: fixed; | |
| bottom: 30px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: auto; | |
| min-width: 140px; | |
| max-width: clamp(300px, 80vw, 800px); | |
| padding: 16px 32px; | |
| background: rgba(255, 255, 255, 0.65); | |
| backdrop-filter: blur(25px) saturate(200%); | |
| border: 1px solid rgba(255, 255, 255, 0.3); | |
| border-radius: 20px; | |
| font-size: 18px; | |
| color: #1A1A1A; | |
| text-align: center; | |
| min-height: 56px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| box-shadow: 0 8px 32px rgba(0, 0, 0, 0.05); | |
| z-index: 1100; | |
| pointer-events: auto; | |
| transition: all 0.4s ease; | |
| } | |
| .voice-transcript.provisional { | |
| color: rgba(0, 0, 0, 0.4); | |
| font-style: italic; | |
| /* 打字狀態:限制一行 */ | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| max-height: calc(1.6em + 48px); | |
| /* 一行文字 + padding */ | |
| } | |
| .voice-transcript.final { | |
| color: #1A1A1A; | |
| border-color: rgba(0, 0, 0, 0.12); | |
| box-shadow: 0 6px 32px rgba(0, 0, 0, 0.12); | |
| } | |
| /* 文字輸入模式 */ | |
| .voice-transcript.text-input-mode { | |
| padding: 0; | |
| min-height: 100px; | |
| max-height: 200px; | |
| overflow: hidden; | |
| } | |
| .voice-transcript.text-input-mode textarea { | |
| width: 100%; | |
| height: 100%; | |
| min-height: 100px; | |
| padding: 24px 32px; | |
| background: transparent; | |
| border: none; | |
| outline: none; | |
| font-size: 18px; | |
| font-weight: 400; | |
| color: #1A1A1A; | |
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; | |
| resize: vertical; | |
| line-height: 1.6; | |
| } | |
| .voice-transcript.text-input-mode textarea::placeholder { | |
| color: rgba(0, 0, 0, 0.4); | |
| font-style: italic; | |
| } | |
| /* === 工具卡片 === */ | |
| #tool-cards-container { | |
| position: fixed; | |
| inset: 0; | |
| z-index: 45; | |
| pointer-events: none; | |
| overflow: hidden; | |
| } | |
| #tool-cards-container .voice-tool-card { | |
| pointer-events: auto; | |
| } | |
| .voice-tool-card { | |
| position: absolute; | |
| padding: 20px 24px; | |
| background: rgba(255, 255, 255, 0.98); | |
| border: 1px solid rgba(15, 23, 42, 0.06); | |
| border-radius: 16px; | |
| backdrop-filter: blur(30px) saturate(180%); | |
| min-width: 280px; | |
| max-width: 360px; | |
| z-index: 40; | |
| box-shadow: | |
| 0 10px 30px rgba(15, 23, 42, 0.08), | |
| 0 2px 10px rgba(15, 23, 42, 0.04), | |
| inset 0 1px 0 rgba(255, 255, 255, 0.7); | |
| animation: cardEnter 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; | |
| } | |
| @keyframes cardEnter { | |
| from { | |
| opacity: 0; | |
| transform: translateY(20px) scale(0.95); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0) scale(1); | |
| } | |
| } | |
| .voice-tool-card.exiting { | |
| animation: cardExit 0.3s ease-out forwards; | |
| } | |
| @keyframes cardExit { | |
| from { | |
| opacity: 1; | |
| transform: scale(1); | |
| } | |
| to { | |
| opacity: 0; | |
| transform: scale(0.95); | |
| } | |
| } | |
| /* 定位變體 */ | |
| .voice-tool-card.pos-top-right { | |
| top: 100px; | |
| right: 100px; | |
| } | |
| .voice-tool-card.pos-top-left { | |
| top: 100px; | |
| left: 100px; | |
| } | |
| .voice-tool-card.pos-bottom-right { | |
| bottom: 100px; | |
| right: 100px; | |
| } | |
| .voice-tool-card.pos-bottom-left { | |
| bottom: 100px; | |
| left: 100px; | |
| } | |
| .voice-tool-card .card-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| margin-bottom: 16px; | |
| padding-bottom: 16px; | |
| border-bottom: 1px solid rgba(15, 23, 42, 0.05); | |
| } | |
| .voice-tool-card .card-icon { | |
| font-size: 28px; | |
| width: 48px; | |
| height: 48px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| background: #F5F5F5; | |
| border-radius: 12px; | |
| } | |
| .voice-tool-card h3 { | |
| font-size: 15px; | |
| font-weight: 600; | |
| color: #1A1A1A; | |
| letter-spacing: -0.3px; | |
| } | |
| .voice-tool-card .card-content { | |
| color: rgba(0, 0, 0, 0.7); | |
| } | |
| .voice-tool-card .data-row { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 10px 0; | |
| border-bottom: 1px solid rgba(15, 23, 42, 0.05); | |
| } | |
| .voice-tool-card .data-row:last-child { | |
| border-bottom: none; | |
| } | |
| .voice-tool-card .data-label { | |
| color: rgba(0, 0, 0, 0.5); | |
| font-size: 13px; | |
| font-weight: 500; | |
| } | |
| .voice-tool-card .data-value { | |
| color: #1A1A1A; | |
| font-size: 15px; | |
| font-weight: 600; | |
| font-family: 'JetBrains Mono', monospace; | |
| } | |
| /* ChatWindow 折疊圖標 */ | |
| .chat-icon { | |
| position: fixed; | |
| /* iframe 環境適配:使用固定值避免 viewport 計算問題 */ | |
| bottom: 40px; | |
| left: 40px; | |
| z-index: 101; | |
| width: 56px; | |
| height: 56px; | |
| background: rgba(255, 255, 255, 0.95); | |
| border: 1px solid rgba(0, 0, 0, 0.08); | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| backdrop-filter: blur(20px); | |
| box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| font-size: 20px; | |
| pointer-events: auto; | |
| } | |
| .chat-icon:hover { | |
| transform: scale(1.1); | |
| background: #FFFFFF; | |
| box-shadow: 0 6px 24px rgba(0, 0, 0, 0.15); | |
| } | |
| /* 退出按鈕 */ | |
| .exit-button { | |
| position: absolute; | |
| /* iframe 環境適配:使用固定值 */ | |
| top: 40px; | |
| right: 40px; | |
| z-index: 50; | |
| padding: 12px 20px; | |
| background: rgba(255, 255, 255, 0.95); | |
| border: 1px solid rgba(0, 0, 0, 0.08); | |
| border-radius: 10px; | |
| color: rgba(0, 0, 0, 0.6); | |
| font-family: 'Inter', sans-serif; | |
| font-size: 13px; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| backdrop-filter: blur(10px); | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); | |
| pointer-events: auto; | |
| } | |
| .exit-button:hover { | |
| background: #FFFFFF; | |
| color: #1A1A1A; | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); | |
| } | |
| /* 情緒標籤 */ | |
| .emotion-indicator { | |
| position: absolute; | |
| /* iframe 環境適配:使用固定值 */ | |
| top: 40px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| z-index: 50; | |
| padding: 10px 20px; | |
| background: rgba(255, 255, 255, 0.95); | |
| border: 1px solid rgba(0, 0, 0, 0.08); | |
| border-radius: 20px; | |
| font-size: 13px; | |
| font-weight: 500; | |
| color: rgba(0, 0, 0, 0.7); | |
| backdrop-filter: blur(20px); | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); | |
| } | |
| /* 狀態指示器 */ | |
| .status-badge { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 6px; | |
| padding: 6px 12px; | |
| background: rgba(34, 197, 94, 0.1); | |
| border: 1px solid rgba(34, 197, 94, 0.2); | |
| border-radius: 8px; | |
| font-size: 11px; | |
| font-weight: 600; | |
| color: #16A34A; | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| margin-top: 12px; | |
| } | |
| .status-badge::before { | |
| content: ''; | |
| width: 6px; | |
| height: 6px; | |
| background: #16A34A; | |
| border-radius: 50%; | |
| animation: blink 2s ease-in-out infinite; | |
| } | |
| @keyframes blink { | |
| 0%, | |
| 100% { | |
| opacity: 1; | |
| } | |
| 50% { | |
| opacity: 0.3; | |
| } | |
| } | |
| /* === 登入覆蓋層(蓮花風格)=== */ | |
| .login-overlay { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100vw; | |
| height: 100vh; | |
| background: linear-gradient(135deg, #E6F7F0 0%, #F5F1ED 100%); | |
| z-index: 9999; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: opacity 0.6s ease, visibility 0.6s ease; | |
| } | |
| .login-overlay.hidden { | |
| opacity: 0; | |
| visibility: hidden; | |
| pointer-events: none; | |
| } | |
| .login-container { | |
| text-align: center; | |
| max-width: 400px; | |
| padding: 48px; | |
| background: rgba(255, 255, 255, 0.95); | |
| border-radius: 32px; | |
| backdrop-filter: blur(20px) saturate(180%); | |
| box-shadow: 0 8px 48px rgba(0, 0, 0, 0.12); | |
| } | |
| .login-lotus { | |
| width: 120px; | |
| height: 120px; | |
| margin: 0 auto 32px; | |
| position: relative; | |
| } | |
| .login-lotus::before { | |
| content: '🪷'; | |
| font-size: 120px; | |
| line-height: 1; | |
| animation: float 3s ease-in-out infinite; | |
| } | |
| @keyframes float { | |
| 0%, | |
| 100% { | |
| transform: translateY(0px); | |
| } | |
| 50% { | |
| transform: translateY(-10px); | |
| } | |
| } | |
| .login-title { | |
| font-size: 28px; | |
| font-weight: 700; | |
| color: #1A1A1A; | |
| margin-bottom: 12px; | |
| letter-spacing: -0.5px; | |
| } | |
| .login-subtitle { | |
| font-size: 15px; | |
| color: rgba(0, 0, 0, 0.5); | |
| margin-bottom: 40px; | |
| line-height: 1.6; | |
| } | |
| .login-button { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 12px; | |
| padding: 16px 32px; | |
| background: #FFFFFF; | |
| border: 1px solid rgba(0, 0, 0, 0.12); | |
| border-radius: 16px; | |
| color: #1A1A1A; | |
| font-family: 'Inter', sans-serif; | |
| font-size: 15px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); | |
| } | |
| .login-button:hover { | |
| background: #F5F5F5; | |
| border-color: rgba(0, 0, 0, 0.18); | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); | |
| } | |
| .login-button:active { | |
| transform: translateY(0); | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); | |
| } | |
| .login-button img { | |
| width: 20px; | |
| height: 20px; | |
| } | |
| /* === 工具抽屜(手機端右側拉出面板)=== */ | |
| .tool-drawer-toggle { | |
| position: fixed; | |
| right: 0; | |
| top: 50%; | |
| transform: translateY(-50%); | |
| z-index: 200; | |
| width: 24px; | |
| height: 60px; | |
| background: rgba(255, 255, 255, 0.6); | |
| border: 1px solid rgba(0, 0, 0, 0.08); | |
| border-right: none; | |
| border-radius: 12px 0 0 12px; | |
| display: none; | |
| /* 預設隱藏,有工具結果時才顯示 */ | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| backdrop-filter: blur(10px); | |
| box-shadow: -2px 0 8px rgba(0, 0, 0, 0.06); | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| .tool-drawer-toggle.visible { | |
| display: flex; | |
| } | |
| .tool-drawer-toggle:hover { | |
| background: rgba(255, 255, 255, 0.9); | |
| width: 28px; | |
| } | |
| .tool-drawer-toggle::before { | |
| content: '‹'; | |
| font-size: 18px; | |
| color: rgba(0, 0, 0, 0.5); | |
| transition: transform 0.3s; | |
| } | |
| .tool-drawer-toggle.open::before { | |
| transform: rotate(180deg); | |
| } | |
| /* 工具抽屜面板 */ | |
| .tool-drawer { | |
| position: fixed; | |
| right: -320px; | |
| top: 0; | |
| width: 320px; | |
| height: 100%; | |
| height: 100dvh; | |
| background: rgba(255, 255, 255, 0.98); | |
| border-left: 1px solid rgba(0, 0, 0, 0.08); | |
| z-index: 199; | |
| backdrop-filter: blur(20px) saturate(180%); | |
| box-shadow: -4px 0 24px rgba(0, 0, 0, 0.1); | |
| transition: right 0.4s cubic-bezier(0.4, 0, 0.2, 1); | |
| display: flex; | |
| flex-direction: column; | |
| overflow: hidden; | |
| } | |
| .tool-drawer.open { | |
| right: 0; | |
| } | |
| .tool-drawer-header { | |
| padding: 20px; | |
| border-bottom: 1px solid rgba(0, 0, 0, 0.06); | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| flex-shrink: 0; | |
| } | |
| .tool-drawer-header h3 { | |
| font-size: 15px; | |
| font-weight: 600; | |
| color: #1A1A1A; | |
| margin: 0; | |
| } | |
| .tool-drawer-close { | |
| width: 32px; | |
| height: 32px; | |
| border: none; | |
| background: rgba(0, 0, 0, 0.05); | |
| border-radius: 8px; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 16px; | |
| color: rgba(0, 0, 0, 0.5); | |
| transition: all 0.2s; | |
| } | |
| .tool-drawer-close:hover { | |
| background: rgba(0, 0, 0, 0.1); | |
| color: rgba(0, 0, 0, 0.8); | |
| } | |
| .tool-drawer-content { | |
| flex: 1; | |
| overflow-y: auto; | |
| overflow-x: hidden; | |
| padding: 16px; | |
| -webkit-overflow-scrolling: touch; | |
| } | |
| /* 抽屜內的工具卡片樣式覆寫 */ | |
| .tool-drawer-content .voice-tool-card { | |
| position: relative; | |
| top: auto; | |
| left: auto; | |
| right: auto; | |
| bottom: auto; | |
| width: 100%; | |
| max-width: none; | |
| min-width: auto; | |
| margin-bottom: 16px; | |
| animation: none; | |
| } | |
| /* 抽屜內滾動條樣式 */ | |
| .tool-drawer-content::-webkit-scrollbar { | |
| width: 3px; | |
| } | |
| .tool-drawer-content::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| .tool-drawer-content::-webkit-scrollbar-thumb { | |
| background: rgba(15, 23, 42, 0.12); | |
| border-radius: 999px; | |
| } | |
| /* 抽屜遮罩層 */ | |
| .tool-drawer-overlay { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: rgba(0, 0, 0, 0.3); | |
| z-index: 198; | |
| opacity: 0; | |
| visibility: hidden; | |
| transition: all 0.3s; | |
| } | |
| .tool-drawer-overlay.visible { | |
| opacity: 1; | |
| visibility: visible; | |
| } | |
| /* === 響應式設計:根據裝置類型切換工具卡片顯示方式 === */ | |
| /* ========== 響應式設計:設備檢測與適配 ========== */ | |
| /* === 1. 手機模式(寬度 <= 480px)=== */ | |
| @media (max-width: 480px) { | |
| #tool-cards-container { | |
| display: none ; | |
| } | |
| .tool-drawer-toggle.visible { | |
| display: flex; | |
| } | |
| .tool-drawer { | |
| display: flex; | |
| } | |
| /* 花朵縮小 */ | |
| .voice-waveform-container { | |
| width: 280px; | |
| height: 280px; | |
| } | |
| .voice-mic-container { | |
| width: 180px; | |
| height: 180px; | |
| } | |
| .bloom-core { | |
| width: 40px; | |
| height: 40px; | |
| --core-scale: 0.8; | |
| } | |
| .bloom-petal:nth-child(-n+8) { | |
| width: 58px; | |
| height: 112px; | |
| } | |
| .bloom-petal:nth-child(n+9) { | |
| width: 46px; | |
| height: 88px; | |
| } | |
| /* 文字輸出區域 */ | |
| .voice-agent-output { | |
| width: calc(100vw - 32px); | |
| max-width: calc(100vw - 32px); | |
| max-height: min(36vh, 300px); | |
| font-size: 14px; | |
| padding: 15px 17px; | |
| } | |
| .agent-output-shell { | |
| grid-template-columns: 2px minmax(0, 1fr); | |
| gap: 11px; | |
| } | |
| } | |
| /* === 2. 平板模式(481px - 1024px)=== */ | |
| @media (min-width: 481px) and (max-width: 1024px) { | |
| #tool-cards-container { | |
| display: none ; | |
| } | |
| .tool-drawer-toggle.visible { | |
| display: flex; | |
| } | |
| .tool-drawer { | |
| display: flex; | |
| } | |
| /* 花朵適中 */ | |
| .voice-waveform-container { | |
| width: 350px; | |
| height: 350px; | |
| } | |
| .voice-mic-container { | |
| width: 210px; | |
| height: 210px; | |
| } | |
| .voice-agent-output { | |
| width: min(78vw, 680px); | |
| max-height: min(32vh, 340px); | |
| } | |
| } | |
| /* === 3. 電腦模式(寬度 > 1024px 且非直立螢幕)=== */ | |
| @media (min-width: 1025px) and (orientation: landscape) { | |
| #tool-cards-container { | |
| display: block; | |
| } | |
| .tool-drawer-toggle { | |
| display: none ; | |
| } | |
| .tool-drawer { | |
| display: none ; | |
| } | |
| .tool-drawer-overlay { | |
| display: none ; | |
| } | |
| .voice-agent-output { | |
| width: clamp(320px, 50vw, 640px); | |
| } | |
| } | |
| /* === 4. 90度橫屏/直立螢幕模式(寬度 < 高度,無論實際寬度)=== */ | |
| /* 這適用於外接顯示器 90 度旋轉的情況 */ | |
| @media (orientation: portrait) and (min-width: 600px) { | |
| /* 使用抽屜模式 */ | |
| #tool-cards-container { | |
| display: none ; | |
| } | |
| .tool-drawer-toggle.visible { | |
| display: flex; | |
| } | |
| .tool-drawer { | |
| display: flex; | |
| } | |
| /* 花朵響應式放大(根據視窗高度)*/ | |
| .voice-waveform-container { | |
| width: min(50vh, 500px); | |
| height: min(50vh, 500px); | |
| } | |
| .voice-mic-container { | |
| width: min(30vh, 300px); | |
| height: min(30vh, 300px); | |
| } | |
| .bloom-core { | |
| width: min(5vh, 45px); | |
| height: min(5vh, 45px); | |
| --core-scale: 1.29; | |
| /* 45/35 = 1.29 (max scale) */ | |
| } | |
| .bloom-petal:nth-child(-n+8) { | |
| width: min(9vh, 94px); | |
| height: min(15vh, 160px); | |
| } | |
| .bloom-petal:nth-child(n+9) { | |
| width: min(7vh, 72px); | |
| height: min(12vh, 122px); | |
| } | |
| /* 文字輸出區域適配 */ | |
| .voice-agent-output { | |
| width: clamp(300px, 72vw, 640px); | |
| max-width: calc(100vw - 32px); | |
| max-height: min(32vh, 380px); | |
| font-size: clamp(14px, 1.6vh, 17px); | |
| } | |
| } | |
| /* === 5. 超寬螢幕(寬度 > 1920px)=== */ | |
| @media (min-width: 1921px) { | |
| .voice-waveform-container { | |
| width: 500px; | |
| height: 500px; | |
| } | |
| .voice-mic-container { | |
| width: 300px; | |
| height: 300px; | |
| } | |
| .bloom-core { | |
| width: 45px; | |
| height: 45px; | |
| --core-scale: 1.29; | |
| /* 45/35 = 1.29 */ | |
| } | |
| .bloom-petal:nth-child(-n+8) { | |
| width: 92px; | |
| height: 154px; | |
| } | |
| .bloom-petal:nth-child(n+9) { | |
| width: 74px; | |
| height: 122px; | |
| } | |
| .voice-agent-output { | |
| width: clamp(480px, 40vw, 640px); | |
| max-height: min(34vh, 460px); | |
| } | |
| } | |
| /* === 6. 強制直立模式(JS 動態添加 class)=== */ | |
| body.portrait-mode #tool-cards-container { | |
| display: none ; | |
| } | |
| body.portrait-mode .tool-drawer-toggle.visible { | |
| display: flex; | |
| } | |
| body.portrait-mode .tool-drawer { | |
| display: flex; | |
| } | |
| body.portrait-mode .voice-waveform-container { | |
| width: min(50vh, 500px); | |
| height: min(50vh, 500px); | |
| } | |
| body.portrait-mode .voice-mic-container { | |
| width: min(30vh, 300px); | |
| height: min(30vh, 300px); | |
| } | |
| body.portrait-mode .bloom-core { | |
| --core-scale: 1.29; | |
| /* 與直立螢幕模式一致 */ | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="control-panel"> | |
| <h3>🎛️ 控制面板</h3> | |
| <div class="control-group"> | |
| <label>情緒切換</label> | |
| <select id="emotion-select"> | |
| <option value="neutral">😐 中性 (預設)</option> | |
| <option value="happy">😊 開心</option> | |
| <option value="sad">😢 悲傷</option> | |
| <option value="angry">😡 生氣</option> | |
| <option value="fear">😨 恐懼</option> | |
| <option value="surprise">😲 驚訝</option> | |
| </select> | |
| </div> | |
| <div class="control-group"> | |
| <label>字幕測試</label> | |
| <button class="btn" id="transcript-provisional">顯示臨時字幕</button> | |
| <button class="btn" id="transcript-final">顯示最終字幕</button> | |
| </div> | |
| <div class="control-group"> | |
| <label>模擬工具調用</label> | |
| <button class="btn" id="simulate-weather">🌤️ 查詢天氣</button> | |
| <button class="btn" id="simulate-news">📰 查詢新聞</button> | |
| <button class="btn" id="simulate-health">❤️ 查詢健康</button> | |
| </div> | |
| <div class="control-group"> | |
| <label>模擬下次輸入</label> | |
| <button class="btn" id="simulate-next-input">🎤 開始新輸入(清除卡片)</button> | |
| </div> | |
| <div class="control-group"> | |
| <label>Agent 狀態</label> | |
| <button class="btn" id="toggle-recording">切換錄音狀態</button> | |
| <button class="btn" id="toggle-thinking">切換思考狀態(順時針)</button> | |
| <button class="btn" id="toggle-speaking">切換回覆狀態(打字機輸出)</button> | |
| <button class="btn" id="toggle-disconnected">切換斷線狀態(逆時針)</button> | |
| </div> | |
| <div class="control-group"> | |
| <label>💡 喚醒詞可行性評估</label> | |
| <div | |
| style="font-size: 11px; line-height: 1.6; color: rgba(0,0,0,0.6); padding: 12px; background: rgba(0,0,0,0.02); border-radius: 8px; border: 1px solid rgba(0,0,0,0.06);"> | |
| <strong style="color: rgba(0,0,0,0.8);">技術限制:</strong><br> | |
| • Web Speech API 不支援持續監聽<br> | |
| • 需要用戶點擊才能啟動麥克風<br> | |
| • 瀏覽器安全政策限制背景錄音<br><br> | |
| <strong style="color: rgba(0,0,0,0.8);">替代方案:</strong><br> | |
| • iOS App 可實現真正喚醒詞<br> | |
| • Web 端改用「按住說話」模式<br> | |
| • 或結合快捷鍵(Space/Ctrl+M) | |
| </div> | |
| </div> | |
| <div class="status-badge"> | |
| Interactive Preview | |
| </div> | |
| </div> | |
| <div class="voice-immersive-overlay"> | |
| <div class="voice-immersive-background emotion-neutral active" id="background"></div> | |
| <div class="emotion-indicator" id="emotion-indicator">當前情緒: 😐 中性</div> | |
| <button class="exit-button" id="logoutBtn">登出</button> | |
| <div class="chat-icon" id="chatIcon" title="切換對話視窗">💬</div> | |
| <div class="voice-center-container"> | |
| <div class="voice-waveform-container"> | |
| <canvas id="waveform-canvas" width="400" height="400"></canvas> | |
| <div class="voice-mic-container" id="mic-container"> | |
| <div class="bloom-core"></div> | |
| <div class="bloom-petals"> | |
| <div class="bloom-petal-group upper" data-petal-layer="upper"> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| </div> | |
| <div class="bloom-petal-group lower" data-petal-layer="lower"> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| <div class="bloom-petal"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="voice-agent-output" id="agent-output" role="status" aria-live="polite" aria-atomic="false"></div> | |
| <div class="voice-transcript provisional" id="transcript"> | |
| 請說話... | |
| </div> | |
| <div id="tool-cards-container"></div> | |
| </div> | |
| <div class="tool-drawer-overlay" id="toolDrawerOverlay"></div> | |
| <div class="tool-drawer-toggle" id="toolDrawerToggle"></div> | |
| <div class="tool-drawer" id="toolDrawer"> | |
| <div class="tool-drawer-header"> | |
| <h3>📊 工具結果</h3> | |
| <button class="tool-drawer-close" id="toolDrawerClose">✕</button> | |
| </div> | |
| <div class="tool-drawer-content" id="toolDrawerContent"> | |
| </div> | |
| </div> | |
| <script src="js/config.js"></script> | |
| <script src="js/ui.js"></script> | |
| <script src="js/tts.js"></script> | |
| <script src="js/tools.js"></script> | |
| <script src="js/agent.js"></script> | |
| <script src="js/canvas.js"></script> | |
| <script src="js/location.js"></script> | |
| <script src="js/websocket.js"></script> | |
| <script src="js/app.js"></script> | |
| <script> | |
| (function () { | |
| function detectScreenOrientation() { | |
| const width = window.innerWidth; | |
| const height = window.innerHeight; | |
| const isPortrait = height > width; | |
| const isLargePortrait = isPortrait && width >= 600; | |
| document.body.classList.remove('mobile-mode', 'tablet-mode', 'desktop-mode', 'portrait-mode'); | |
| if (isLargePortrait) { | |
| document.body.classList.add('portrait-mode'); | |
| // console.log('📱 螢幕模式: 直立螢幕(90度橫屏)', width, 'x', height); | |
| } else if (width <= 480) { | |
| document.body.classList.add('mobile-mode'); | |
| // console.log('📱 螢幕模式: 手機', width, 'x', height); | |
| } else if (width <= 1024) { | |
| document.body.classList.add('tablet-mode'); | |
| // console.log('📱 螢幕模式: 平板', width, 'x', height); | |
| } else { | |
| document.body.classList.add('desktop-mode'); | |
| // console.log('🖥️ 螢幕模式: 桌機/筆電', width, 'x', height); | |
| } | |
| } | |
| detectScreenOrientation(); | |
| window.addEventListener('resize', detectScreenOrientation); | |
| if (screen.orientation) { | |
| screen.orientation.addEventListener('change', detectScreenOrientation); | |
| } | |
| })(); | |
| </script> | |
| </body> | |
| </html> | |