/** * VoiceCloneModal 样式 — V21 设计系统 * CSS 变量统一,与配音库 / 我的音色页面风格一致 * 命名规范:xx-vcmodal-* */ @import "../../styles/global.css"; /* ── 弹窗内容区 ───────────────────────────────────────────── */ .xx-vcmodal-body { display: flex; flex-direction: column; gap: var(--space-md); padding: var(--space-sm) 0; } /* ── 字段容器 ─────────────────────────────────────────────── */ .xx-vcmodal-field { display: flex; flex-direction: column; gap: var(--space-sm); } .xx-vcmodal-label { font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--text-primary); letter-spacing: var(--letter-spacing-wide); } /* ── 输入框 ───────────────────────────────────────────────── */ .xx-vcmodal-input { width: 100%; height: 40px; padding: 0 var(--space-md); border: 1px solid var(--border-color); border-radius: var(--radius-sm); background: var(--bg-primary); font-size: var(--font-size-base); color: var(--text-primary); outline: none; transition: border-color 0.2s ease, box-shadow 0.2s ease; } .xx-vcmodal-input::placeholder { color: var(--text-tertiary); } .xx-vcmodal-input:focus { border-color: var(--color-primary-400); box-shadow: 0 0 0 3px var(--color-primary-100); } /* ── 上传区域 ─────────────────────────────────────────────── */ .xx-vcmodal-upload-zone { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-sm); padding: var(--space-lg) var(--space-md); border: 2px dashed var(--border-color); border-radius: var(--radius-md); background: var(--bg-secondary); cursor: pointer; transition: border-color 0.2s ease, background 0.2s ease; } .xx-vcmodal-upload-zone:hover { border-color: var(--color-primary-300); background: var(--color-primary-50); } .xx-vcmodal-upload-zone--active { border-color: var(--color-primary-500); background: var(--color-primary-100); } .xx-vcmodal-upload-zone--has-file { border-style: solid; border-color: var(--color-primary-400); background: var(--color-primary-50); } .xx-vcmodal-upload-icon { font-size: 32px; line-height: 1; } .xx-vcmodal-upload-title { margin: 0; font-size: var(--font-size-base); font-weight: var(--font-weight-medium); color: var(--text-primary); text-align: center; word-break: break-all; } .xx-vcmodal-upload-hint { margin: 0; font-size: var(--font-size-sm); color: var(--text-secondary); text-align: center; } /* ── 分隔线 ───────────────────────────────────────────────── */ .xx-vcmodal-divider { display: flex; align-items: center; gap: var(--space-md); margin: var(--space-xs) 0; } .xx-vcmodal-divider-line { flex: 1; height: 1px; background: var(--border-color); } .xx-vcmodal-divider-text { font-size: var(--font-size-sm); color: var(--text-tertiary); font-weight: var(--font-weight-medium); } /* ── 录制区域 ─────────────────────────────────────────────── */ .xx-vcmodal-record-area { display: flex; align-items: center; gap: var(--space-md); padding: var(--space-md); border: 1px solid var(--border-color); border-radius: var(--radius-sm); background: var(--bg-secondary); } .xx-vcmodal-record-info { flex: 1; display: flex; flex-direction: column; gap: var(--space-xs); } .xx-vcmodal-record-hint { margin: 0; font-size: var(--font-size-sm); color: var(--text-secondary); } /* 录制波形动画 */ .xx-vcmodal-record-wave { display: flex; align-items: flex-end; gap: 3px; height: 20px; } .xx-vcmodal-record-wave-bar { width: 3px; background: var(--color-primary-500); border-radius: var(--radius-full); animation: vcmodal-wave 0.8s ease-in-out infinite alternate; } .xx-vcmodal-record-wave-bar:nth-child(1) { height: 40%; animation-delay: 0s; } .xx-vcmodal-record-wave-bar:nth-child(2) { height: 70%; animation-delay: 0.15s; } .xx-vcmodal-record-wave-bar:nth-child(3) { height: 100%; animation-delay: 0.3s; } .xx-vcmodal-record-wave-bar:nth-child(4) { height: 60%; animation-delay: 0.45s; } .xx-vcmodal-record-wave-bar:nth-child(5) { height: 30%; animation-delay: 0.6s; } @keyframes vcmodal-wave { from { transform: scaleY(0.4); } to { transform: scaleY(1); } } /* 录制按钮 */ .xx-vcmodal-record-btn { width: 48px; height: 48px; border: none; border-radius: var(--radius-full); background: var(--bg-primary); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); font-size: 20px; cursor: pointer; transition: background 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease; display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .xx-vcmodal-record-btn:hover { background: var(--color-primary-50); transform: scale(1.05); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); } .xx-vcmodal-record-btn--recording { background: var(--error-color); color: var(--text-inverse); animation: vcmodal-pulse 1.2s ease-in-out infinite; } .xx-vcmodal-record-btn--recording:hover { background: var(--error-hover); } @keyframes vcmodal-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); } 50% { box-shadow: 0 0 0 8px rgba(239, 68, 68, 0); } } /* ── 提示 ─────────────────────────────────────────────────── */ .xx-vcmodal-tip { display: flex; align-items: flex-start; gap: var(--space-sm); padding: var(--space-sm) var(--space-md); border-radius: var(--radius-xs); background: var(--info-soft); border: 1px solid var(--info-border); font-size: var(--font-size-sm); color: var(--text-secondary); line-height: var(--line-height-base); } .xx-vcmodal-tip-icon { flex-shrink: 0; font-size: var(--font-size-base); } /* ── 底部按钮 ─────────────────────────────────────────────── */ .xx-vcmodal-footer { display: flex; justify-content: flex-end; gap: var(--space-sm); padding-top: var(--space-sm); border-top: 1px solid var(--border-light); } /* ── 进度阶段通用 ─────────────────────────────────────────── */ .xx-vcmodal-progress-body { display: flex; flex-direction: column; align-items: center; gap: var(--space-xl); padding: var(--space-lg) 0 var(--space-md); } /* ── 步骤指示器 ───────────────────────────────────────────── */ .xx-vcmodal-steps { display: flex; align-items: center; gap: 0; width: 100%; max-width: 360px; } .xx-vcmodal-step { display: flex; flex-direction: column; align-items: center; gap: var(--space-xs); flex: 1; position: relative; } .xx-vcmodal-step-icon { width: 40px; height: 40px; border-radius: var(--radius-full); background: var(--bg-tertiary); border: 2px solid var(--border-color); display: flex; align-items: center; justify-content: center; font-size: 16px; color: var(--text-tertiary); transition: all 0.3s ease; } .xx-vcmodal-step--active .xx-vcmodal-step-icon { background: var(--color-primary-50); border-color: var(--color-primary-500); color: var(--color-primary-600); box-shadow: 0 0 0 4px var(--color-primary-100); } .xx-vcmodal-step--done .xx-vcmodal-step-icon { background: var(--color-secondary-50); border-color: var(--color-secondary-500); color: var(--color-secondary-600); } .xx-vcmodal-step-label { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); color: var(--text-tertiary); transition: color 0.3s ease; } .xx-vcmodal-step--active .xx-vcmodal-step-label { color: var(--color-primary-600); font-weight: var(--font-weight-semibold); } .xx-vcmodal-step--done .xx-vcmodal-step-label { color: var(--color-secondary-600); } /* 步骤连接线 */ .xx-vcmodal-step-connector { flex: 0 0 40px; height: 2px; background: var(--border-color); margin-bottom: 20px; transition: background 0.3s ease; } .xx-vcmodal-step-connector--done { background: var(--color-secondary-400); } /* ── 进度信息 ─────────────────────────────────────────────── */ .xx-vcmodal-progress-info { display: flex; flex-direction: column; align-items: center; gap: var(--space-sm); text-align: center; } /* 加载动画 */ .xx-vcmodal-progress-spinner { width: 48px; height: 48px; border: 3px solid var(--color-primary-100); border-top-color: var(--color-primary-500); border-radius: var(--radius-full); animation: vcmodal-spin 0.8s linear infinite; } .xx-vcmodal-progress-spinner--cloning { border-color: var(--color-secondary-100); border-top-color: var(--color-secondary-500); } @keyframes vcmodal-spin { to { transform: rotate(360deg); } } .xx-vcmodal-progress-text { margin: 0; font-size: var(--font-size-md); font-weight: var(--font-weight-semibold); color: var(--text-primary); } .xx-vcmodal-progress-sub { margin: 0; font-size: var(--font-size-sm); color: var(--text-secondary); } /* ── 完成阶段 ─────────────────────────────────────────────── */ .xx-vcmodal-success { display: flex; flex-direction: column; align-items: center; gap: var(--space-sm); text-align: center; } .xx-vcmodal-success-icon { font-size: 48px; line-height: 1; animation: vcmodal-bounce 0.6s ease-out; } @keyframes vcmodal-bounce { 0% { transform: scale(0); opacity: 0; } 60% { transform: scale(1.2); opacity: 1; } 100% { transform: scale(1); } } .xx-vcmodal-success-title { margin: 0; font-size: var(--font-size-lg); font-weight: var(--font-weight-bold); color: var(--text-primary); } .xx-vcmodal-success-desc { margin: 0; font-size: var(--font-size-sm); color: var(--text-secondary); max-width: 280px; line-height: var(--line-height-relaxed); } /* ── 响应式 ───────────────────────────────────────────────── */ @media (max-width: 768px) { .xx-vcmodal-body { gap: var(--space-sm); } .xx-vcmodal-upload-zone { padding: var(--space-md) var(--space-sm); } .xx-vcmodal-record-area { flex-direction: column; align-items: stretch; text-align: center; } .xx-vcmodal-record-btn { align-self: center; } .xx-vcmodal-steps { max-width: 280px; } .xx-vcmodal-step-connector { flex: 0 0 24px; } .xx-vcmodal-footer { flex-direction: column-reverse; } .xx-vcmodal-footer > * { width: 100%; } } @media (max-width: 480px) { .xx-vcmodal-step-icon { width: 32px; height: 32px; font-size: 13px; } .xx-vcmodal-step-connector { flex: 0 0 16px; margin-bottom: 16px; } .xx-vcmodal-progress-spinner { width: 36px; height: 36px; } .xx-vcmodal-success-icon { font-size: 36px; } }