diff --git a/frontend/src/components/VoicePreview.css b/frontend/src/components/VoicePreview.css index 93ee2427..6560c245 100644 --- a/frontend/src/components/VoicePreview.css +++ b/frontend/src/components/VoicePreview.css @@ -1,63 +1,15 @@ -.voice-preview { - position: fixed; - /* Track the LogsFooter's live height so an expanded/resized footer never - slides underneath the popover (LogsFooter.jsx writes the variable). */ - bottom: calc(var(--logs-footer-height, 28px) + 16px); - right: 16px; - z-index: 900; - width: 320px; - background: var(--chrome-bg); - border: 1px solid var(--chrome-border-strong); - border-radius: 12px; - box-shadow: 0 8px 32px rgba(0,0,0,0.4); - display: flex; - flex-direction: column; - overflow: hidden; - animation: voice-preview-in 0.2s ease-out; -} +/* VoicePreview — all panel chrome converted to Tailwind utilities on + VoicePreview.jsx. Two things stay here as irreducible CSS: + 1. the entrance @keyframes (referenced via animate-[…] on the popover); and + 2. the select/text rules that layer on top of the *unlayered* shared + .input-base — Tailwind utilities live in @layer utilities and would lose + the cascade to .input-base, so these overrides must stay unlayered. */ + @keyframes voice-preview-in { from { opacity: 0; transform: translateY(12px) scale(0.96); } to { opacity: 1; transform: translateY(0) scale(1); } } -.voice-preview__head { - display: flex; - align-items: center; - justify-content: space-between; - padding: 10px 14px; - border-bottom: 1px solid var(--chrome-border); -} -.voice-preview__title { - display: flex; - align-items: center; - gap: 6px; - font-family: var(--font-mono); - font-size: 0.72rem; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.04em; - color: var(--chrome-fg); -} -.voice-preview__close { - background: none; - border: none; - color: var(--chrome-fg-muted); - cursor: pointer; - padding: 4px; - border-radius: 6px; - transition: background 0.15s; -} -.voice-preview__close:hover { - background: var(--chrome-hover-bg); - color: var(--chrome-fg); -} - -.voice-preview__body { - padding: 12px 14px; - display: flex; - flex-direction: column; - gap: 8px; -} .voice-preview__select { font-size: 0.78rem; padding: 6px 8px; @@ -69,19 +21,3 @@ line-height: 1.4; min-height: 48px; } -.voice-preview__audio { - width: 100%; -} - -.voice-preview__foot { - display: flex; - align-items: center; - justify-content: space-between; - padding: 8px 14px 10px; - border-top: 1px solid var(--chrome-border); -} -.voice-preview__hint { - font-family: var(--font-mono); - font-size: 0.65rem; - color: var(--chrome-fg-dim); -} diff --git a/frontend/src/components/VoicePreview.jsx b/frontend/src/components/VoicePreview.jsx index 11e10e6b..a1cf2e8b 100644 --- a/frontend/src/components/VoicePreview.jsx +++ b/frontend/src/components/VoicePreview.jsx @@ -98,14 +98,14 @@ export default function VoicePreview({ if (!open) return null; return ( -
-
- +
+
+ {t('voicePreview.title')}
-
+