Files
voicepaste/web/style.css

235 lines
5.1 KiB
CSS

@import "tailwindcss";
/* ─── Design Tokens ─── */
@theme {
--color-bg: #08080d;
--color-surface: #111117;
--color-surface-hover: #17171e;
--color-surface-active: #1c1c25;
--color-edge: #1e1e2a;
--color-edge-active: #2c2c3e;
--color-fg: #eaeaef;
--color-fg-secondary: #9e9eb5;
--color-fg-dim: #5a5a6e;
--color-accent: #6366f1;
--color-accent-hover: #818cf8;
--color-danger: #f43f5e;
--color-success: #34d399;
--radius-card: 14px;
}
/* ─── Base ─── */
@layer base {
html,
body {
font-family:
"SF Pro Display", -apple-system, BlinkMacSystemFont, "PingFang SC",
"Hiragino Sans GB", "Microsoft YaHei", sans-serif;
-webkit-font-smoothing: antialiased;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
}
body::after {
content: "";
@apply fixed pointer-events-none z-0;
top: -30%;
left: 50%;
transform: translateX(-50%);
width: 600px;
height: 600px;
background: radial-gradient(
circle,
rgba(99, 102, 241, 0.04) 0%,
transparent 70%
);
}
}
/* ─── App Container (safe-area padding) ─── */
#app {
padding: calc(16px + env(safe-area-inset-top, 0px)) 20px
calc(16px + env(safe-area-inset-bottom, 0px));
}
/* ─── Connection Status States ─── */
.status.connected {
@apply border-success/15;
}
.status.connected .dot {
@apply bg-success;
box-shadow: 0 0 6px rgba(52, 211, 153, 0.5);
}
.status.disconnected .dot {
@apply bg-danger;
box-shadow: 0 0 6px rgba(244, 63, 94, 0.4);
}
.status.connecting .dot {
@apply bg-accent;
animation: pulse 1.4s ease-in-out infinite;
}
/* ─── Preview Active State ─── */
.preview-box.active {
border-color: rgba(99, 102, 241, 0.4);
box-shadow:
0 0 0 1px rgba(99, 102, 241, 0.2),
0 4px 24px -4px rgba(99, 102, 241, 0.15);
background: linear-gradient(
180deg,
rgba(99, 102, 241, 0.03) 0%,
var(--color-surface) 100%
);
}
/* ─── Placeholder Text ─── */
#preview-text.placeholder {
@apply text-fg-dim;
}
/* ─── Mic Button ─── */
#mic-btn {
background: linear-gradient(
145deg,
var(--color-surface-hover),
var(--color-surface)
);
box-shadow:
0 2px 12px rgba(0, 0, 0, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.04);
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
#mic-btn:disabled {
@apply opacity-30 cursor-not-allowed;
}
#mic-btn:not(:disabled):active,
#mic-btn.recording {
@apply bg-accent border-accent-hover text-white;
transform: scale(1.06);
box-shadow:
0 0 32px rgba(99, 102, 241, 0.35),
0 0 80px rgba(99, 102, 241, 0.2);
}
#mic-btn.recording {
animation: mic-breathe 1.8s ease-in-out infinite;
}
/* ─── Wave Rings ─── */
#mic-btn.recording + .mic-rings .ring {
animation: ring-expand 2.4s cubic-bezier(0.2, 0, 0.2, 1) infinite;
}
#mic-btn.recording + .mic-rings .ring:nth-child(2) {
animation-delay: 0.8s;
}
#mic-btn.recording + .mic-rings .ring:nth-child(3) {
animation-delay: 1.6s;
}
/* ─── History Items (dynamically created) ─── */
#history-list li {
@apply bg-surface border border-edge rounded-card cursor-pointer flex items-start gap-3 transition-all duration-150;
padding: 14px 16px;
margin-bottom: 8px;
font-size: 14px;
line-height: 1.5;
animation: slide-up 0.35s cubic-bezier(0.16, 1, 0.3, 1) both;
animation-delay: calc(var(--i, 0) * 40ms);
}
#history-list li:active {
@apply bg-surface-active border-edge-active;
transform: scale(0.985);
}
#history-list li .hist-text {
@apply flex-1 break-words;
}
#history-list li .hist-time {
@apply text-fg-dim whitespace-nowrap shrink-0;
font-size: 11px;
padding-top: 2px;
font-variant-numeric: tabular-nums;
}
/* ─── Text Button Active State ─── */
.text-btn:active {
@apply text-danger;
background: rgba(244, 63, 94, 0.08);
}
/* ─── Scrollbar ─── */
.preview-box::-webkit-scrollbar,
#history-list::-webkit-scrollbar {
width: 3px;
}
.preview-box::-webkit-scrollbar-track,
#history-list::-webkit-scrollbar-track {
background: transparent;
}
.preview-box::-webkit-scrollbar-thumb,
#history-list::-webkit-scrollbar-thumb {
@apply bg-edge;
border-radius: 3px;
}
/* ─── Toast ─── */
.toast {
bottom: calc(80px + env(safe-area-inset-bottom, 0px));
transform: translateX(-50%) translateY(8px);
background: rgba(28, 28, 37, 0.85);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.toast.show {
@apply opacity-100;
transform: translateX(-50%) translateY(0);
}
/* ─── Keyframes ─── */
@keyframes pulse {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.3;
}
}
@keyframes mic-breathe {
0%,
100% {
box-shadow:
0 0 32px rgba(99, 102, 241, 0.35),
0 0 80px rgba(99, 102, 241, 0.2);
}
50% {
box-shadow:
0 0 48px rgba(99, 102, 241, 0.35),
0 0 120px rgba(99, 102, 241, 0.2),
0 0 200px rgba(99, 102, 241, 0.08);
}
}
@keyframes ring-expand {
0% {
transform: scale(1);
opacity: 0.35;
}
100% {
transform: scale(2);
opacity: 0;
}
}
@keyframes slide-up {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}