@tailwind base; @tailwind components; @tailwind utilities; /* ── 自托管 Web 字体(OFL 许可,latin 子集,public/fonts/)── 取代原先 fonts.googleapis.com 的渲染阻塞外链:自托管服务常部署在 无法访问 Google 的网络,外链会拖住首屏渲染直到超时。 */ @font-face { font-family: 'Geist'; font-style: normal; font-weight: 300; font-display: swap; src: url('/fonts/geist-300.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { font-family: 'Geist'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/geist-400.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { font-family: 'Geist'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/geist-500.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { font-family: 'Geist'; font-style: normal; font-weight: 600; font-display: swap; src: url('/fonts/geist-600.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { font-family: 'Geist'; font-style: normal; font-weight: 700; font-display: swap; src: url('/fonts/geist-700.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/jetbrainsmono-400.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/jetbrainsmono-500.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url('/fonts/jetbrainsmono-600.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } html, body, #root { height: 100%; } :root { --app-bg: #f9fafb; --app-panel: #ffffff; --app-panel-soft: #f9fafb; --app-header-bg: rgba(255, 255, 255, 0.82); --app-control-bg: rgba(249, 250, 251, 0.72); --app-hover: #f3f4f6; --app-active-bg: #111827; --app-active-text: #ffffff; --app-active-icon: #c9954a; --app-command-bg: #111827; --app-command-text: #ffffff; --app-tooltip-bg: #111827; --app-tooltip-text: #ffffff; --app-brand-soft: rgba(255, 248, 231, 0.9); --app-brand-text: #9a6a1e; --app-brand-border: rgba(234, 214, 182, 0.9); --app-brand-emphasis: rgba(201, 149, 74, 0.18); --app-danger-soft: rgba(254, 242, 242, 0.9); --app-text: #111827; --app-subtle: #374151; --app-muted: #6b7280; --app-border: rgba(229, 231, 235, 0.82); --app-shadow: rgba(17, 24, 39, 0.08); --app-hero-bg: radial-gradient(circle at 80% 20%, rgba(212, 175, 55, 0.22), transparent 34%), linear-gradient(135deg, #fff7ed, #f8fafc 52%, #eef2ff); --app-hero-overlay: linear-gradient(90deg, #ffffff 0%, rgba(255,255,255,0.96) 37%, rgba(255,255,255,0.62) 68%, rgba(255,255,255,0.2) 100%); --app-hero-fade: linear-gradient(to top, #ffffff, transparent); --app-poster-shell: #ffffff; --app-poster-empty: linear-gradient(135deg, #f9fafb, #fff7ed); } :root[data-theme='dark'] { --app-bg: #070a0f; --app-panel: #0f141d; --app-panel-soft: #111827; --app-header-bg: rgba(15, 20, 29, 0.86); --app-control-bg: rgba(17, 24, 39, 0.72); --app-hover: #1f2937; --app-active-bg: #1f2937; --app-active-text: #f9fafb; --app-active-icon: #e3b56d; --app-command-bg: #f9fafb; --app-command-text: #0b1018; --app-tooltip-bg: #f9fafb; --app-tooltip-text: #0b1018; --app-brand-soft: rgba(201, 149, 74, 0.14); --app-brand-text: #e3b56d; --app-brand-border: rgba(201, 149, 74, 0.34); --app-brand-emphasis: rgba(201, 149, 74, 0.18); --app-danger-soft: rgba(127, 29, 29, 0.22); --app-text: #f9fafb; --app-subtle: #d1d5db; --app-muted: #9ca3af; --app-border: rgba(55, 65, 81, 0.82); --app-shadow: rgba(0, 0, 0, 0.45); --app-hero-bg: radial-gradient(circle at 78% 18%, rgba(201, 149, 74, 0.18), transparent 34%), linear-gradient(135deg, #0b1018, #101826 54%, #171f2d); --app-hero-overlay: linear-gradient(90deg, rgba(7,10,15,0.98) 0%, rgba(15,20,29,0.92) 42%, rgba(15,20,29,0.62) 70%, rgba(15,20,29,0.24) 100%); --app-hero-fade: linear-gradient(to top, #0f141d, transparent); --app-poster-shell: #141b26; --app-poster-empty: linear-gradient(135deg, #111827, #1f2937); } body { background-color: var(--app-bg); color: var(--app-text); margin: 0; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /* ─── Selection ─── */ ::selection { background: rgba(201, 149, 74, 0.2); color: var(--app-text); } /* ─── Focus Ring ─── */ *:focus-visible { outline: 2px solid #c9954a; outline-offset: 2px; border-radius: 6px; } /* ─── Scrollbar ─── */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: #e5e7eb; border-radius: 999px; } ::-webkit-scrollbar-thumb:hover { background: #c9954a; } :root[data-theme='dark'] ::-webkit-scrollbar-thumb { background: #374151; } :root[data-theme='dark'] .bg-white, :root[data-theme='dark'] .bg-gray-50, :root[data-theme='dark'] .bg-gray-50\/50, :root[data-theme='dark'] .bg-gray-50\/60, :root[data-theme='dark'] .bg-gray-50\/70, :root[data-theme='dark'] .bg-gray-50\/80, :root[data-theme='dark'] .bg-gray-50\/90, :root[data-theme='dark'] .bg-white\/50, :root[data-theme='dark'] .bg-white\/60, :root[data-theme='dark'] .bg-white\/70, :root[data-theme='dark'] .bg-white\/75, :root[data-theme='dark'] .bg-white\/80, :root[data-theme='dark'] .bg-white\/82, :root[data-theme='dark'] .bg-white\/85, :root[data-theme='dark'] .bg-white\/90, :root[data-theme='dark'] .bg-white\/95 { background-color: var(--app-panel) !important; } :root[data-theme='dark'] .bg-gray-100, :root[data-theme='dark'] .bg-gray-100\/50, :root[data-theme='dark'] .bg-gray-100\/60, :root[data-theme='dark'] .bg-gray-100\/70, :root[data-theme='dark'] .bg-gray-100\/80 { background-color: var(--app-hover) !important; } :root[data-theme='dark'] .bg-brand-50, :root[data-theme='dark'] .bg-primary-400\/10, :root[data-theme='dark'] .bg-primary-400\/15, :root[data-theme='dark'] .bg-primary-400\/20, :root[data-theme='dark'] .bg-sand-50, :root[data-theme='dark'] .bg-amber-50, :root[data-theme='dark'] .bg-yellow-50, :root[data-theme='dark'] .bg-emerald-50, :root[data-theme='dark'] .bg-green-50, :root[data-theme='dark'] .bg-red-50 { background-color: var(--app-control-bg) !important; } :root[data-theme='dark'] .bg-\[\#f9fafb\] { background-color: var(--app-bg) !important; } :root[data-theme='dark'] .hover\:bg-gray-50:hover, :root[data-theme='dark'] .hover\:bg-gray-50\/50:hover, :root[data-theme='dark'] .hover\:bg-gray-100:hover, :root[data-theme='dark'] .hover\:bg-brand-50:hover, :root[data-theme='dark'] .hover\:bg-primary-400\/10:hover, :root[data-theme='dark'] .hover\:bg-red-100:hover { background-color: var(--app-hover) !important; } :root[data-theme='dark'] .text-gray-900, :root[data-theme='dark'] .text-gray-950, :root[data-theme='dark'] .text-\[\#111827\], :root[data-theme='dark'] .text-ink-600, :root[data-theme='dark'] .text-ink-500, :root[data-theme='dark'] .text-ink-400, :root[data-theme='dark'] .text-ink-300, :root[data-theme='dark'] .text-ink-200, :root[data-theme='dark'] .text-ink-100 { color: var(--app-text) !important; } :root[data-theme='dark'] .text-gray-700, :root[data-theme='dark'] .text-gray-600, :root[data-theme='dark'] .text-gray-500, :root[data-theme='dark'] .text-ink-50, :root[data-theme='dark'] .text-sand-500 { color: var(--app-muted) !important; } :root[data-theme='dark'] .border-gray-100, :root[data-theme='dark'] .border-gray-200, :root[data-theme='dark'] .border-gray-200\/50, :root[data-theme='dark'] .border-gray-200\/60, :root[data-theme='dark'] .border-gray-200\/80, :root[data-theme='dark'] .border-gray-200\/90, :root[data-theme='dark'] .border-gray-300 { border-color: var(--app-border) !important; } :root[data-theme='dark'] .shadow-xl, :root[data-theme='dark'] .shadow-2xl, :root[data-theme='dark'] .shadow-md, :root[data-theme='dark'] .shadow-sm { box-shadow: 0 18px 50px var(--app-shadow) !important; } :root[data-theme='dark'] input, :root[data-theme='dark'] select, :root[data-theme='dark'] textarea { color: var(--app-text) !important; background-color: var(--app-panel-soft) !important; border-color: var(--app-border) !important; } :root[data-theme='dark'] input::placeholder, :root[data-theme='dark'] textarea::placeholder { color: #6b7280; } .scrollbar-hide { -ms-overflow-style: none; scrollbar-width: none; } .scrollbar-hide::-webkit-scrollbar { display: none; } /* ── 播放器底部动作面板的高度上限 ── 手机上按视口高度算(86%),老浏览器不认识 dvh 时退回 vh,避免面板 在 flex 容器里被内容撑出屏幕。 */ .player-sheet-height { max-height: 86vh; max-height: 86dvh; } /* ─── Reduced Motion ─── */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } } @layer components { .theme-hero-bg { background: var(--app-hero-bg); } .theme-hero-overlay { background: var(--app-hero-overlay); } .theme-hero-fade { background: var(--app-hero-fade); } /* ── Unified Swiss-Editorial Cards ── */ .card { @apply rounded-2xl bg-white border border-gray-200/80 shadow-[0_1px_3px_rgba(0,0,0,0.01),0_1px_2px_rgba(0,0,0,0.015)] p-4 sm:p-6; } .card-hover { @apply card transition-all duration-300 ease-out hover:border-gray-300 hover:shadow-[0_12px_32px_rgba(17,24,39,0.04),0_4px_12px_rgba(17,24,39,0.01)] hover:-translate-y-1; } .card-elevated { @apply card shadow-[0_20px_40px_rgba(17,24,39,0.05),0_1px_3px_rgba(17,24,39,0.01)]; } /* ── Glassmorphic Bright Panels ── */ .glass-panel { @apply rounded-2xl bg-white border border-gray-200 shadow-sm p-4 sm:p-6; } .glass-card { @apply rounded-2xl bg-white border border-gray-200 shadow-sm p-4 sm:p-6; } .glass-card-elevated { @apply rounded-2xl bg-white border border-gray-200 shadow-md p-4 sm:p-6; } /* ── Input Fields Redesign ── */ .input-field { @apply w-full rounded-xl border border-gray-200 bg-gray-50/50 px-4 py-3 text-sm text-gray-900 placeholder:text-gray-400 outline-none transition-all duration-300 ease-out focus:border-brand-500 focus:bg-white focus:ring-4 focus:ring-brand-100/50; } .input-label { @apply block mb-1.5 text-xs font-bold uppercase tracking-widest text-gray-500; } /* ── Premium Editorial Buttons Redesign ── */ .btn-primary { @apply inline-flex items-center justify-center gap-2 rounded-xl bg-[#111827] px-5 py-3 text-sm font-bold text-white transition-all duration-300 ease-out shadow-sm hover:bg-[#1f2937] hover:-translate-y-0.5 active:translate-y-0 active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-40 disabled:translate-y-0; } .btn-ghost { @apply inline-flex items-center justify-center gap-2 rounded-xl px-4 py-2.5 text-sm font-semibold text-gray-600 transition-all duration-200 ease-out hover:bg-gray-100 hover:text-gray-900 active:scale-[0.98]; } .btn-outline { @apply inline-flex items-center justify-center gap-2 rounded-xl border border-gray-200/90 bg-white px-4 py-2.5 text-sm font-bold text-gray-700 transition-all duration-300 ease-out shadow-sm hover:border-gray-300 hover:text-gray-900 hover:shadow-md hover:-translate-y-0.5 active:translate-y-0 active:scale-[0.98]; } /* ── Badges Redesign ── */ .badge { @apply inline-flex items-center rounded-full px-3 py-1 text-2xs font-bold uppercase tracking-wider; } .badge-brand { @apply badge bg-brand-50 text-brand-700 border border-brand-100/30; } .badge-sage { @apply badge bg-sage-50 text-sage-700 border border-sage-100/30; } .badge-neutral { @apply badge bg-gray-100 text-gray-600 border border-gray-200/50; } /* ── Page Headings ── */ .page-heading { @apply font-display text-2xl font-extrabold tracking-tight text-gray-900 sm:text-3xl; } .page-subtitle { @apply mt-1 text-sm text-gray-500; } /* ── Mobile Data Tables ── */ .table-scroll { @apply overflow-x-auto overscroll-x-contain; -webkit-overflow-scrolling: touch; } .data-table { @apply w-full text-left text-sm border-collapse; } .data-table thead { @apply border-b border-gray-200 bg-gray-50/70; } .data-table th { @apply px-5 py-4 text-xs font-bold uppercase tracking-wider text-gray-500 whitespace-nowrap; } .data-table td { @apply px-5 py-4 text-gray-700 border-b border-gray-100 max-w-xs truncate; } .data-table tbody tr { @apply transition-colors hover:bg-gray-50/50; } /* ── Dividers ── */ .divider { @apply border-t border-gray-200/80; } /* ── Backward Compatibility ── */ .surface-card { @apply card; } .surface-card-elevated { @apply card-elevated; } .field-input { @apply input-field; } .field-label { @apply input-label; } .amber-btn { @apply btn-outline; } .amber-btn--solid { @apply btn-primary; } .amber-btn--ghost { @apply btn-ghost; } .neon-button { @apply btn-outline; } .input-base { @apply input-field; } .warm-divider { @apply divider; } } .episode-artwork-toggle { background-color: var(--app-panel); border-color: var(--app-border); color: var(--app-subtle); } .episode-artwork-toggle--on, .episode-artwork-toggle[data-state='on'] { background-color: var(--app-brand-soft) !important; border-color: var(--app-brand-border) !important; color: var(--app-brand-text) !important; } .episode-artwork-toggle__icon, .episode-artwork-toggle__state { background-color: var(--app-panel-soft); color: var(--app-muted); } .episode-artwork-toggle--on .episode-artwork-toggle__icon, .episode-artwork-toggle--on .episode-artwork-toggle__state, .episode-artwork-toggle[data-state='on'] .episode-artwork-toggle__icon, .episode-artwork-toggle[data-state='on'] .episode-artwork-toggle__state { background-color: var(--app-brand-emphasis) !important; color: var(--app-brand-text) !important; } /* ── 播放器字幕(WebVTT )── 彻底去除浏览器 User Agent 默认的半透明黑底背景框,使用文字阴影保证亮暗画面下的可读性。 */ ::cue, video::cue, ::cue(*), video::cue(*) { background: transparent !important; background-color: transparent !important; color: #ffffff !important; font-family: "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif !important; font-weight: 500 !important; line-height: 1.35 !important; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.95), 0 0 8px rgba(0, 0, 0, 0.8), 0 0 16px rgba(0, 0, 0, 0.6) !important; } /* ── Entrance animations (replaces framer-motion on the critical shell) ── */ @keyframes overlay-in { from { opacity: 0; } to { opacity: 1; } } @keyframes drawer-in { from { transform: translateX(-100%); } to { transform: translateX(0); } } @keyframes page-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } } @keyframes accordion-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } } @keyframes fade-slide-in { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: translateX(0); } } @keyframes menu-in { from { opacity: 0; transform: translateY(10px) scale(0.95); } to { opacity: 1; transform: translateY(0) scale(1); } } .animate-overlay-in { animation: overlay-in 0.15s ease-out both; } .animate-drawer-in { animation: drawer-in 0.22s ease-out both; } /* 播放完成后不能保留 transform,否则长页面会成为 fixed 弹框的包含块。 */ .animate-page-in { animation: page-in 0.25s ease-out backwards; } .animate-accordion-in { animation: accordion-in 0.18s ease-out both; } .animate-fade-slide-in { animation: fade-slide-in 0.2s ease-out both; } .animate-menu-in { animation: menu-in 0.15s ease-out both; } @media (prefers-reduced-motion: reduce) { .animate-overlay-in, .animate-drawer-in, .animate-page-in, .animate-accordion-in, .animate-fade-slide-in, .animate-menu-in { animation: none !important; } } @keyframes pulse-soft { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } } @keyframes hero-in { from { opacity: 0; transform: scale(1.08); } to { opacity: 0.38; transform: scale(1.02); } } @keyframes title-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } .animate-pulse-soft { animation: pulse-soft 1.5s ease-in-out infinite; } .animate-hero-in { animation: hero-in 0.8s ease-out both; } .animate-title-in { animation: title-in 0.3s ease-out both; } @media (prefers-reduced-motion: reduce) { .animate-pulse-soft, .animate-hero-in, .animate-title-in { animation: none !important; } }