Files
rootandClaude Opus 5.5 c9b4ceb301 fix(web): 控制台界面细节与 uhd_web 控件规范对齐
- 顶栏搜索移进右侧玻璃胶囊;输入框改淡玻璃(边线 0.46 → 0.16,悬停加深,聚焦 / 出错保留光晕)
- 新增 SegmentedControl(滑动 seg-thumb),替换站点、下载、订阅、文件、智能体列表及对话框里的实心选中块;Tabs 改为同一枚滑块
- 开关型按钮统一 outline + aria-pressed 选中外观;页头 / 工具栏次操作描边、图标钮描边圆;文件排序改 Select;下载总速度加标签
- 分页一页放得下时只留总数、空列表不渲染、按容器宽度收起按钮
- 运行状态存储区重排;智能体列表页与会话页共用外壳路由,标题与左栏不再重挂载
- 站点卡片「⋯」不再单独换行;设置导航、状态计数、多选条件改玻璃选中态

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
2026-10-08 12:02:48 +08:00

1783 lines
69 KiB
CSS

@import "tailwindcss";
@import "tw-animate-css";
@import "./shadcn-tailwind.css";
/* ───────────────────────── Tailwind configuration ───────────────────────── */
@custom-variant dark (&:is(.dark *), &:is([data-force-dark] *));
/* 悬停只给真鼠标:触屏(含被报告成鼠标的车机)点按后不留悬停态。覆盖 Tailwind 内置的 hover,group-hover / peer-hover 一并跟随 */
@custom-variant hover {
@media (hover: hover) {
&:not(:where([data-input="touch"] *)):hover {
@slot;
}
}
}
/* 触屏:系统报告粗指针,或 <html data-input="touch">(特斯拉车机等报告成鼠标的触屏,见 input-modality.ts) */
@custom-variant touch {
@media (pointer: coarse) {
@slot;
}
&:where([data-input="touch"] *) {
@slot;
}
}
@theme {
--font-sans:
"Inter Tight Variable", "Inter Tight", "SF Pro Display", "PingFang SC",
"Microsoft YaHei", sans-serif;
--font-display:
"Space Grotesk Variable", "Space Grotesk", "Inter Tight Variable",
"SF Pro Display", sans-serif;
--color-ink-950: #040507;
--color-ink-900: #080b12;
--color-ink-800: #141925;
--color-ink-700: #202637;
--color-bone-50: #fbfaf7;
--color-bone-100: #f1eee7;
--color-bone-200: #dcd5c8;
--color-bone-300: #bdb4a5;
--color-bone-400: #918879;
--color-bone-500: #6f675c;
--color-gold-100: #fff0c4;
--color-gold-200: #f7d98d;
--color-gold-300: #e6b85c;
--color-gold-400: #d49a4a;
--color-gold-500: #af7133;
--tracking-hero: 0;
--shadow-card: 0 18px 40px -24px rgba(0, 0, 0, 0.9);
--shadow-card-hover: 0 26px 54px -24px rgba(0, 0, 0, 1);
--animate-fade-in: fade-in 520ms ease-out both;
/* backwards 而不是 both:动画播完要撤掉。透明度动画一直挂着时,Chromium 把这个元素当成背景根,
里面的玻璃 / 磨砂只能采样到它自己,菜单就不糊了(账户菜单、播放器菜单都踩过) */
--animate-pg-pop: pg-pop 200ms var(--ease-pop) backwards;
/* 播放器加载提示的滚动字幕:新一行从下方滚入,上一行向上滚出 */
--animate-ticker-in: ticker-in 360ms var(--ease-standard) both;
--animate-ticker-out: ticker-out 360ms var(--ease-standard) both;
--animate-blur-in: blur-in 560ms var(--ease-pop) backwards;
--animate-hero-fade: hero-fade 740ms ease-out both;
--animate-ken-burns: ken-burns 14s ease-out both;
/* ─── 字号阶梯(见 docs/features/design-tokens.md)──────────────────────
只定字号不定行高,行为等同原来的 text-[Npx];自带行高的 text-xs / text-sm 继续用。
组件按角色引用,不写像素。正文阶:10 / 11 / 12 / 13 / 14 / 15 / 16 / 17。 */
--text-micro: 10px;
--text-label: 11px;
--text-meta: 12px;
--text-caption: 13px;
--text-body: 14px;
--text-control: 15px;
--text-lead: 16px;
--text-lead-lg: 17px;
/* 标题阶:18 / 20 / 22 / 24 / 26 / 28 / 30 / 32 / 34 / 42 / 44 / 52 / 56(现状值逐档保留,收敛另议) */
--text-title-xs: 18px;
--text-title-sm: 20px;
--text-title: 22px;
--text-title-lg: 24px;
--text-headline-xs: 26px;
--text-headline-sm: 28px;
--text-headline: 30px;
--text-headline-lg: 32px;
--text-display-xs: 34px;
--text-display-sm: 42px;
--text-display: 44px;
--text-display-lg: 52px;
--text-display-xl: 56px;
/* 流式标题:每处 clamp 原值保留,按用途命名;要不要收成三档是设计决定 */
--text-hero-stream: clamp(32px, 9vw, 46px);
--text-hero-stream-sm: clamp(40px, 7.5vw, 72px);
--text-hero-stream-md: clamp(44px, 7.5vw, 88px);
--text-detail-title: clamp(32px, 8vw, 82px);
--text-notfound-code: clamp(7rem, 18vw, 11rem);
--text-pricing-hero: clamp(2rem, 4.4vw, 4rem);
--text-pricing-title: clamp(1.6rem, 2.4vw, 2.2rem);
--text-landing-hero: clamp(2.1rem, 4.1vw, 3.9rem);
--text-landing-platforms-title: clamp(1.8rem, 3.4vw, 2.8rem);
--text-landing-immersive-title: clamp(2.25rem, 4.8vw, 5.4rem);
--text-landing-service-hero: clamp(2rem, 4.4vw, 4.4rem);
--text-landing-service-title: clamp(1.6rem, 2.4vw, 2.4rem);
--text-landing-service-title-lg: clamp(1.6rem, 2.6vw, 2.6rem);
--text-landing-service-sub: clamp(1.5rem, 2vw, 2rem);
/* ─── 缓动(见 docs/features/design-tokens.md)。standard 是绝大多数过渡;spring 给
滑块 / 按压回弹;sheet 给抽屉;pop 给弹层出现。组件用 ease-standard 等,不写 bezier */
--ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
--ease-spring-soft: cubic-bezier(0.34, 1.2, 0.64, 1);
--ease-sheet: cubic-bezier(0.32, 0.72, 0, 1);
--ease-pop: cubic-bezier(0.22, 1, 0.36, 1);
}
/* 过渡时长四档 + 两档特例。Tailwind 没有时长的主题命名空间,用 @utility 定义,
写法与内置 duration-N 完全一致(同时设 --tw-duration,tw-animate 的 animate-in 也读它)。 */
:root {
--duration-micro: 150ms;
--duration-base: 200ms;
--duration-layout: 300ms;
--duration-slow: 500ms;
--duration-hero: 700ms;
--duration-cinematic: 1000ms;
}
/* 横向滚动容器会连带裁掉纵向溢出(overflow-x:auto 时 overflow-y 不能是 visible),
里面胶囊、分段滑块的阴影与描边会被切成直边。四周向外借 12px 再用内边距还回来,
布局位置不变,阴影有地方画。放胶囊的横向滚动容器一律加它 */
@utility scroll-bleed {
margin: -0.75rem;
padding: 0.75rem;
}
/* 横滚标签条右端淡出:手机上分类标签滚到排序按钮跟前不再被硬切,也提示还能往右滑 */
@utility scroll-fade-end {
-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
}
@utility duration-micro { --tw-duration: var(--duration-micro); transition-duration: var(--duration-micro); }
@utility duration-base { --tw-duration: var(--duration-base); transition-duration: var(--duration-base); }
@utility duration-layout { --tw-duration: var(--duration-layout); transition-duration: var(--duration-layout); }
@utility duration-slow { --tw-duration: var(--duration-slow); transition-duration: var(--duration-slow); }
@utility duration-hero { --tw-duration: var(--duration-hero); transition-duration: var(--duration-hero); }
@utility duration-cinematic { --tw-duration: var(--duration-cinematic); transition-duration: var(--duration-cinematic); }
@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--radius-2xl: calc(var(--radius) + 8px);
--radius-3xl: calc(var(--radius) + 12px);
--radius-4xl: calc(var(--radius) + 16px);
/* 角色型圆角:tight 给徽章 / 骨架屏这类小件(原来的裸 rounded),drawer 给手机端底部抽屉顶角,
slab 给门户大卡。控件 md、输入与小按钮 lg、卡片 xl、面板 2xl、抽屉与大卡 3xl、药丸 full,
那些沿用 Tailwind 名,值随 --radius 一起缩放。 */
--radius-tight: 0.25rem;
--radius-drawer: 28px;
--radius-slab: 2.5rem;
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-success: var(--success);
--color-success-foreground: var(--success-foreground);
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
/* ─── 主题 token(见 docs/features/design-tokens.md)───────────────────
组件只许用这些语义名,不许直接写 bone / ink / gold 原色、十六进制、rgba 或
white/black 透明度。值在下方各壳的 token 块里定义,主题包只覆盖值。 */
/* 文字层级(随日夜翻转) */
--color-content-strong: var(--content-strong);
--color-content: var(--content);
--color-content-secondary: var(--content-secondary);
--color-content-tertiary: var(--content-tertiary);
--color-content-muted: var(--content-muted);
--color-content-faint: var(--content-faint);
/* 面(随日夜翻转):页面底、普通面、抬起的卡、更高一层 */
--color-canvas: var(--canvas);
--color-surface: var(--surface);
--color-surface-raised: var(--surface-raised);
--color-surface-high: var(--surface-high);
/* 品牌色族(门户 = 墨水蓝族,流媒体 = 金,动漫版 = 品牌色) */
--color-brand-soft: var(--brand-soft);
--color-brand-light: var(--brand-light);
--color-brand: var(--brand);
--color-brand-strong: var(--brand-strong);
--color-brand-deep: var(--brand-deep);
/* 透明"洗"层的底色:hover / 按压 / 分隔线等半透明层写成 `bg-wash/[0.07]`,透明度留在
调用处,底色随日夜翻转(暗底白洗,亮底黑洗)。 */
--color-wash: var(--wash);
/* 压在视频 / 海报上的东西:不随日夜翻转,画面永远是暗的 */
--color-on-media-strong: var(--on-media-strong);
--color-on-media: var(--on-media);
--color-on-media-secondary: var(--on-media-secondary);
--color-on-media-tertiary: var(--on-media-tertiary);
--color-on-media-muted: var(--on-media-muted);
--color-on-media-faint: var(--on-media-faint);
--color-on-media-wash: var(--on-media-wash);
/* 压暗画面的遮罩底色(黑),透明度留在调用处 */
--color-scrim: var(--scrim);
}
/* ─────────────────────────── Semantic tokens ─────────────────────────── */
:root {
--radius: 0.85rem;
color-scheme: light;
/* Core surfaces */
--background: oklch(0.985 0.002 260);
--foreground: oklch(0.18 0.006 260);
--card: oklch(1 0 0 / 90%);
--card-solid: oklch(1 0 0);
--card-foreground: var(--foreground);
--popover: oklch(1 0 0);
--popover-foreground: var(--foreground);
/* Actions and states */
/* 无彩主色(2026-09-26 拍板):日间是墨,夜间是白,和落地页的白色胶囊按钮同一个语言;
彩色只来自海报、剧照等内容,状态提示用下面的 success / warning / destructive */
--primary: oklch(0.2 0.006 260);
--primary-foreground: oklch(0.99 0.002 260);
--secondary: oklch(0.95 0.003 260);
--secondary-foreground: oklch(0.26 0.006 260);
--muted: oklch(0.955 0.003 260);
--muted-foreground: oklch(0.47 0.008 260);
--accent: oklch(0.935 0.004 260);
--accent-foreground: oklch(0.2 0.006 260);
--destructive: oklch(0.54 0.2 25);
--destructive-foreground: oklch(0.99 0.005 25);
/* 状态色:只用于状态提示,饱和度压低 */
--success: oklch(0.52 0.1 155);
--success-foreground: oklch(0.99 0.002 260);
--warning: oklch(0.6 0.12 70);
--warning-foreground: oklch(0.99 0.002 260);
/* Controls */
--border: oklch(0.88 0.003 260 / 85%);
--input: oklch(0.93 0.003 260);
--ring: var(--primary);
/* App shell */
--sidebar: oklch(0.975 0.002 260);
--sidebar-foreground: var(--foreground);
--sidebar-primary: var(--primary);
--sidebar-primary-foreground: var(--primary-foreground);
--sidebar-accent: oklch(0.93 0.003 260);
--sidebar-accent-foreground: var(--foreground);
--sidebar-border: var(--border);
--sidebar-ring: var(--primary);
--shell-border: color-mix(in oklch, var(--border) 86%, transparent);
--shell-hover: color-mix(in oklch, var(--accent) 68%, transparent);
--shell-subtle: color-mix(in oklch, var(--muted) 72%, transparent);
/* 主题 token:浅色门户。文字层级从 foreground 往淡推,面从 background 往上抬 */
--content-strong: oklch(0.13 0.006 260);
--content: var(--foreground);
--content-secondary: oklch(0.32 0.006 260);
--content-tertiary: var(--muted-foreground);
--content-muted: oklch(0.58 0.006 260);
--content-faint: oklch(0.7 0.005 260);
--canvas: var(--background);
--surface: oklch(0.98 0.002 260);
--surface-raised: var(--card-solid);
--surface-high: oklch(0.955 0.003 260);
--brand-soft: oklch(0.93 0.003 260);
--brand-light: oklch(0.45 0.006 260);
--brand: var(--primary);
--brand-strong: oklch(0.1 0.004 260);
--brand-deep: oklch(0.05 0.002 260);
--wash: #000000;
/* on-media 不分日夜:与流媒体壳的暗色文字层级同值(bone 阶) */
--on-media-strong: #fbfaf7;
--on-media: #f1eee7;
--on-media-secondary: #dcd5c8;
--on-media-tertiary: #bdb4a5;
--on-media-muted: #918879;
--on-media-faint: #6f675c;
--on-media-wash: #ffffff;
--scrim: #000000;
/* ─── 材质参数(见 docs/features/interface-materials.md)────────────────────
一个材质 = 一份固定配方(底色 / 光泽 / 模糊 / 边 / 内高光 / 内暗线 / 外投影 / 辉光)+ 这里的参数。
class 只引用参数;浅色 / 深色 / 流媒体壳的差别只改参数,不再各自重写声明。
值与参数化前逐字相同。`--pg-surface-alpha` 是唯一给组件用的公开旋钮。 */
/* surface:贴边控制条 / header */
--mat-surface-rgb: 12, 13, 17;
--mat-surface-blur: blur(24px) saturate(160%);
--mat-surface-hairline: rgba(255, 255, 255, 0.08);
--mat-surface-highlight: rgba(255, 255, 255, 0.07);
--mat-surface-solid: rgba(12, 13, 17, 0.92);
/* pill:药丸 HUD */
--mat-pill-bg: rgba(16, 17, 23, 0.58);
--mat-pill-sheen: linear-gradient(180deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.04) 40%, rgba(255, 255, 255, 0) 70%);
--mat-pill-blur: blur(16px) saturate(160%);
--mat-pill-border: rgba(255, 255, 255, 0.06);
--mat-pill-highlight: rgba(255, 255, 255, 0.34);
--mat-pill-edge: rgba(0, 0, 0, 0.4);
--mat-pill-shade: rgba(255, 255, 255, 0.1);
--mat-pill-shadow: 0 2px 6px -2px rgba(0, 0, 0, 0.2), 0 12px 32px -14px rgba(0, 0, 0, 0.42);
--mat-pill-solid: rgba(16, 17, 23, 0.88);
/* slab:门户外层内容卡(浅色值;深色在 .dark 块) */
--mat-slab-bg: linear-gradient(155deg, rgba(255, 255, 255, 0.74) 0%, rgba(255, 255, 255, 0.58) 40%, rgba(255, 255, 255, 0.52) 100%);
--mat-slab-border: rgba(255, 255, 255, 0.3);
--mat-slab-blur: blur(20px) saturate(160%);
/* 内容卡的边与全站玻璃同一套:左上亮、右下弱的 1px 边光 + 外侧 1px 暗线;面本身不变 */
--mat-slab-shadow: inset 1px 1px 0 -0.25px rgba(255, 255, 255, 0.95), inset -1px -1px 0 -0.25px rgba(255, 255, 255, 0.45), 0 0 0 1px rgba(20, 22, 28, 0.07), 0 1px 2px rgba(20, 22, 28, 0.05), 0 12px 28px -18px rgba(20, 22, 28, 0.16);
/* 满高工作面板(文件管理的目录树 + 主面板)的实底与粘性表头:两块共用,背后的光斑不再让一块比另一块亮 */
--mat-slab-base: color-mix(in oklab, var(--background) 35%, transparent);
--mat-slab-head: color-mix(in oklab, var(--background) 25%, white);
--mat-slab-reflection: linear-gradient(105deg, transparent 0%, rgba(255, 255, 255, 0.14) 36%, rgba(255, 255, 255, 0.3) 44%, rgba(255, 255, 255, 0.07) 51%, transparent 62%);
--mat-spotlight: rgba(255, 255, 255, 0.6);
/* 卡片投影:日间轻,夜间沿用 @theme 里的深投影 */
--shadow-card: 0 1px 2px rgba(20, 22, 28, 0.06), 0 14px 32px -18px rgba(20, 22, 28, 0.28);
--shadow-card-hover: 0 1px 2px rgba(20, 22, 28, 0.08), 0 20px 40px -20px rgba(20, 22, 28, 0.34);
--mat-leak-opacity: 0.3;
--mat-leak-blend: multiply;
/* chrome:门户侧栏 / 顶栏 */
--mat-chrome-bg: rgba(255, 255, 255, 0.52);
--mat-chrome-blur: blur(24px) saturate(160%);
--mat-chrome-border: color-mix(in oklch, var(--primary) 11%, transparent);
--mat-chrome-shadow: 0 8px 24px -20px rgba(20, 22, 28, 0.25);
/* 竖直侧栏的边:内侧细亮边 + 外侧细暗线 + 很淡的投影,与玻璃同一套,不画硬分隔线 */
--mat-chrome-side-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.9), 1px 0 0 rgba(20, 22, 28, 0.06), 10px 0 28px -22px rgba(20, 22, 28, 0.2);
--mat-chrome-solid: rgba(255, 255, 255, 0.95);
/* float:门户小型悬浮面板。SEARCH-4(2026-09-30)起不透明实底 = popover token,不做背景模糊:
半透明弹层压在资源列表上文字看不清(用户反馈) */
--mat-float-bg: var(--popover);
--mat-float-blur: none;
--mat-float-border: rgba(255, 255, 255, 0.3);
/* 边与全站玻璃同一套(uhd_web 2026-10-07):左上亮、右下弱的 1px 边光 + 外侧 1px 暗线。底仍是 SEARCH-4 的实底 */
--mat-float-shadow: inset 1px 1px 0 -0.25px rgba(255, 255, 255, 0.95), inset -1px -1px 0 -0.25px rgba(255, 255, 255, 0.5), 0 0 0 1px rgba(20, 22, 28, 0.08), 0 2px 6px -2px rgba(20, 22, 28, 0.08), 0 20px 40px -20px rgba(20, 22, 28, 0.2);
--mat-float-solid: rgb(251, 251, 252);
/* 对话框 / 抽屉的底:uhd_web 的菜单是通透玻璃、对话框才换实底;本项目菜单本来就是实底(SEARCH-4),两者同值,留着这一层供换皮 */
--mat-float-modal-bg: var(--popover);
/* 胶囊按钮:主操作是有填充的薄玻璃,次操作只描边。日夜对称——夜间白色薄玻璃配白字,
日间墨色薄玻璃配深字;不做实心黑 / 实心白 */
--mat-pill-primary-bg: linear-gradient(180deg, rgba(20, 22, 28, 0.02), rgba(20, 22, 28, 0.05));
--mat-pill-primary-bg-hover: linear-gradient(180deg, rgba(20, 22, 28, 0.04), rgba(20, 22, 28, 0.08));
--mat-pill-primary-fg: var(--content-strong);
--mat-pill-primary-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 1px 2px rgba(20, 22, 28, 0.06);
/* 主按钮的棱镜环(方案 A):亮度、彩度、环与内光的强度 */
--prism-l: 0.66;
--prism-c: 0.15;
--prism-ring: 1;
--prism-glow: 0.14;
/* 选中态(分页当前页、角标、选中的选项):静态半透明 + 稍深描边,不转动、不实心 */
--mat-pill-selected-bg: rgba(20, 22, 28, 0.08);
--mat-pill-selected-border: rgba(20, 22, 28, 0.22);
--mat-pill-secondary-bg: rgba(20, 22, 28, 0.03);
--mat-pill-secondary-bg-hover: rgba(20, 22, 28, 0.07);
--mat-pill-secondary-border: rgba(20, 22, 28, 0.12);
/* lens:液态玻璃小控件(次按钮、图标键;主按钮只用 edge / sheen)。meniscus 的 lens 档:
本体几乎透明,靠左上亮右下暗的 1px 边光(内阴影)和外侧 1px 暗线成形 */
--mat-lens-fill: rgba(255, 255, 255, 0.08);
--mat-lens-fill-hover: rgba(255, 255, 255, 0.3);
--mat-lens-rim: inset 1px 1px 0 -0.25px rgba(255, 255, 255, 0.95), inset -1px -1px 0 -0.25px rgba(255, 255, 255, 0.55), inset 0 0 0 1px rgba(255, 255, 255, 0.25);
--mat-lens-edge: 0 0 0 1px rgba(20, 22, 28, 0.1);
--mat-lens-sheen: inset 1px 1px 0 -0.5px rgba(255, 255, 255, 0.7);
--mat-lens-shadow: 0 6px 16px -10px rgba(20, 22, 28, 0.28);
--mat-lens-blur: blur(2px) saturate(160%);
/* field:输入框 / 下拉选择的触发器,与按钮同一套边光;底比按钮实一点,保证字和占位符好读 */
/* 输入框是淡玻璃:半透明白底 + 细边 + 上沿内高光(2026-10-08 调轻:0.46 的边在控制台的筛选条、搜索框里读成一圈黑框);
聚焦 / 展开时边线加深并带光晕,出错时红线,这两种状态仍要一眼看得出 */
--mat-field-bg: rgba(255, 255, 255, 0.5);
--mat-field-edge: rgba(20, 22, 28, 0.16);
--mat-field-edge-focus: rgba(20, 22, 28, 0.5);
--mat-field-edge-hover: rgba(20, 22, 28, 0.28);
/* 登录页的表单卡片:实在的底,先把卡片和页面分开 */
--mat-auth-card-bg: rgba(255, 255, 255, 0.84);
--mat-field-ring: rgba(20, 22, 28, 0.08);
--mat-field-highlight: rgba(255, 255, 255, 0.7);
/* 小玻璃圆片的烟色玻璃:白色图标坐在上面。日间烟墨、夜间淡白;压在图片上的恒用 media 档 */
--mat-chip-glass: rgba(20, 22, 28, 0.56);
/* media-hero:详情页头图。剧照铺在内容区顶部、渐隐到页面底色;左侧文字区压近乎不透明的底色,右侧露出剧照。
窄屏海报与文字上下排,改为自上而下压底色 */
--mat-hero-image-opacity: 1;
--mat-hero-scrim-side: linear-gradient(90deg, var(--background) 0%, color-mix(in oklab, var(--background) 96%, transparent) 38%, color-mix(in oklab, var(--background) 82%, transparent) 55%, color-mix(in oklab, var(--background) 40%, transparent) 72%, transparent 92%);
--mat-hero-scrim-stack: linear-gradient(180deg, color-mix(in oklab, var(--background) 30%, transparent) 0%, color-mix(in oklab, var(--background) 72%, transparent) 45%, color-mix(in oklab, var(--background) 92%, transparent) 75%, var(--background) 100%);
/* 分段控件的滑块(侧栏当前项、SegmentedTabs):日间是托起的白片,夜间是薄白玻璃 */
--mat-seg-thumb-bg: rgba(255, 255, 255, 0.62);
--mat-seg-thumb-border: transparent;
--mat-seg-thumb-shadow: inset 1px 1px 0 -0.25px rgba(255, 255, 255, 1), inset -1px -1px 0 -0.25px rgba(255, 255, 255, 0.6), 0 0 0 1px rgba(20, 22, 28, 0.08), 0 3px 12px -3px rgba(20, 22, 28, 0.18);
/* Scrollbars */
--scrollbar-thumb: color-mix(
in oklch,
var(--muted-foreground) 26%,
transparent
);
--scrollbar-thumb-hover: color-mix(
in oklch,
var(--muted-foreground) 42%,
transparent
);
--scrollbar-thumb-active: color-mix(
in oklch,
var(--muted-foreground) 58%,
transparent
);
}
.dark,
:root:has([data-force-dark]) {
color-scheme: dark;
--background: oklch(0.15 0.004 265);
--foreground: oklch(0.96 0.003 260);
--card: oklch(0.21 0.004 265 / 88%);
--card-solid: oklch(0.21 0.004 265);
--card-foreground: var(--foreground);
--popover: oklch(0.2 0.004 265);
--popover-foreground: var(--foreground);
/* 深色档主色是白(见 :root 处注释) */
--primary: oklch(0.97 0.002 260);
--primary-foreground: oklch(0.16 0.004 265);
--secondary: oklch(0.27 0.004 265);
--secondary-foreground: var(--foreground);
--muted: oklch(0.26 0.004 265);
--muted-foreground: oklch(0.7 0.004 260);
--accent: oklch(0.29 0.004 265);
--accent-foreground: var(--foreground);
--destructive: oklch(0.7 0.15 25);
--destructive-foreground: oklch(0.16 0.004 265);
--success: oklch(0.78 0.1 158);
--success-foreground: oklch(0.2 0.03 158);
--warning: oklch(0.82 0.1 78);
--warning-foreground: oklch(0.22 0.03 78);
--border: oklch(0.36 0.004 265 / 70%);
--input: oklch(0.3 0.004 265);
--ring: var(--primary);
--sidebar: oklch(0.17 0.004 265);
--sidebar-foreground: var(--foreground);
--sidebar-primary: var(--primary);
--sidebar-primary-foreground: var(--primary-foreground);
--sidebar-accent: oklch(0.27 0.004 265);
--sidebar-accent-foreground: var(--foreground);
--sidebar-border: var(--border);
--sidebar-ring: var(--primary);
--shell-border: rgba(255, 255, 255, 0.08);
--shell-hover: rgba(255, 255, 255, 0.08);
--shell-subtle: rgba(255, 255, 255, 0.05);
/* 主题 token:深色门户 */
--content-strong: oklch(0.99 0.002 260);
--content: var(--foreground);
--content-secondary: oklch(0.85 0.004 260);
--content-tertiary: var(--muted-foreground);
--content-muted: oklch(0.58 0.004 260);
--content-faint: oklch(0.46 0.004 260);
--canvas: var(--background);
--surface: oklch(0.18 0.004 265);
--surface-raised: var(--card-solid);
--surface-high: oklch(0.26 0.004 265);
--brand-soft: oklch(0.27 0.004 265);
--brand-light: oklch(1 0 0);
--brand: var(--primary);
--brand-strong: oklch(0.88 0.003 260);
--brand-deep: oklch(0.78 0.003 260);
--wash: #ffffff;
/* 材质参数:深色门户 */
--mat-slab-bg: linear-gradient(155deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.04) 30%, rgba(255, 255, 255, 0.03) 75%, rgba(255, 255, 255, 0.04) 100%);
--mat-slab-border: rgba(255, 255, 255, 0.04);
--mat-slab-shadow: inset 1px 1px 0 -0.25px rgba(255, 255, 255, 0.22), inset -1px -1px 0 -0.25px rgba(255, 255, 255, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.2), 0 12px 28px -18px rgba(0, 0, 0, 0.4);
--mat-slab-base: color-mix(in oklab, var(--background) 78%, transparent);
--mat-slab-head: color-mix(in oklab, var(--background) 94%, white);
--mat-slab-reflection: linear-gradient(105deg, transparent 0%, rgba(255, 255, 255, 0.006) 36%, rgba(255, 255, 255, 0.013) 44%, rgba(255, 255, 255, 0.003) 51%, transparent 62%);
--mat-spotlight: rgba(255, 255, 255, 0.07);
--shadow-card: 0 18px 40px -24px rgba(0, 0, 0, 0.9);
--shadow-card-hover: 0 26px 54px -24px rgba(0, 0, 0, 1);
--mat-leak-opacity: 0.3;
--mat-leak-blend: normal;
--mat-chrome-bg: color-mix(in oklch, var(--card-solid) 48%, transparent);
--mat-chrome-border: color-mix(in oklch, var(--primary) 13%, transparent);
--mat-chrome-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
--mat-chrome-side-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.08), 1px 0 0 rgba(0, 0, 0, 0.45), 10px 0 28px -22px rgba(0, 0, 0, 0.55);
--mat-chrome-solid: rgba(12, 13, 17, 0.92);
--mat-float-bg: linear-gradient(180deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0) 40%), var(--popover);
--mat-float-solid: rgb(22, 23, 27);
--mat-float-modal-bg: linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0) 40%), var(--popover);
--mat-float-blur: none;
--mat-float-border: rgba(255, 255, 255, 0.06);
/* 胶囊按钮:夜间主操作是白色玻璃 */
--mat-pill-primary-bg: rgba(255, 255, 255, 0.05);
--mat-pill-primary-bg-hover: rgba(255, 255, 255, 0.09);
--mat-pill-primary-fg: #ffffff;
--mat-pill-primary-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), 0 1px 2px rgba(0, 0, 0, 0.2);
--prism-l: 0.82;
--prism-c: 0.13;
--prism-ring: 1;
--prism-glow: 0.2;
--mat-pill-selected-bg: rgba(255, 255, 255, 0.12);
--mat-pill-selected-border: rgba(0, 0, 0, 0.45);
--mat-pill-secondary-bg: rgba(255, 255, 255, 0.04);
--mat-pill-secondary-bg-hover: rgba(255, 255, 255, 0.1);
--mat-pill-secondary-border: rgba(255, 255, 255, 0.15);
--mat-lens-fill: rgba(0, 0, 0, 0.14);
--mat-lens-fill-hover: rgba(255, 255, 255, 0.08);
--mat-lens-rim: inset 1px 1px 0 -0.25px rgba(255, 255, 255, 0.42), inset -1px -1px 0 -0.25px rgba(255, 255, 255, 0.16), inset 0 0 0 1px rgba(255, 255, 255, 0.06);
--mat-lens-edge: 0 0 0 1px rgba(0, 0, 0, 0.35);
--mat-lens-sheen: inset 1px 1px 0 -0.5px rgba(255, 255, 255, 0.28);
--mat-lens-shadow: 0 6px 16px -10px rgba(0, 0, 0, 0.55);
/* 夜间:底比卡片略亮,外线是浅色细线(黑线压在深色卡片上看不见) */
--mat-field-bg: rgba(255, 255, 255, 0.05);
--mat-field-edge: rgba(255, 255, 255, 0.16);
--mat-field-edge-focus: rgba(255, 255, 255, 0.5);
--mat-field-edge-hover: rgba(255, 255, 255, 0.28);
--mat-auth-card-bg: rgba(26, 27, 32, 0.74);
--mat-field-ring: rgba(255, 255, 255, 0.07);
--mat-field-highlight: rgba(255, 255, 255, 0.04);
--mat-chip-glass: rgba(255, 255, 255, 0.12);
--mat-hero-image-opacity: 0.85;
--mat-hero-scrim-side: linear-gradient(90deg, var(--background) 0%, color-mix(in oklab, var(--background) 94%, transparent) 38%, color-mix(in oklab, var(--background) 78%, transparent) 55%, color-mix(in oklab, var(--background) 36%, transparent) 72%, transparent 92%);
--mat-hero-scrim-stack: linear-gradient(180deg, color-mix(in oklab, var(--background) 30%, transparent) 0%, color-mix(in oklab, var(--background) 72%, transparent) 45%, color-mix(in oklab, var(--background) 92%, transparent) 75%, var(--background) 100%);
--mat-seg-thumb-bg: rgba(255, 255, 255, 0.08);
--mat-seg-thumb-border: transparent;
--mat-seg-thumb-shadow: inset 1px 1px 0 -0.25px rgba(255, 255, 255, 0.42), inset -1px -1px 0 -0.25px rgba(255, 255, 255, 0.14), 0 0 0 1px rgba(0, 0, 0, 0.35), 0 4px 18px -6px rgba(0, 0, 0, 0.4);
--mat-float-shadow: inset 1px 1px 0 -0.25px rgba(255, 255, 255, 0.32), inset -1px -1px 0 -0.25px rgba(255, 255, 255, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.45), 0 2px 6px -2px rgba(0, 0, 0, 0.22), 0 18px 40px -20px rgba(0, 0, 0, 0.4);
}
/* ───────────────────────────── Base styles ───────────────────────────── */
@layer base {
* {
@apply border-border outline-ring/50;
}
html,
body {
min-height: 100%;
}
/* Light app shell */
body {
@apply bg-background text-foreground antialiased;
background-image: linear-gradient(180deg, oklch(1 0 0), oklch(0.97 0.002 260));
}
/* Dark app shell, including fixed-dark public and stream routes */
.dark body,
:root:has([data-force-dark]) body {
background-image: linear-gradient(180deg, oklch(0.16 0.004 265), oklch(0.12 0.004 265));
}
/* 流媒体壳:html / body 整块铺成壳的 canvas,不用上面门户的渐变底。
桌面上永远看不到 body,但手机上地址栏收起、橡皮筋回弹、内容不够一屏、崩溃页这些
"壳没铺满"的时刻会把 body 露出来。夜间 html 也一并铺:iOS 回弹露出来的是 html 不是 body。 */
:root.dark:has([data-stream-shell]),
:root:has([data-stream-shell="play"]) {
background: var(--canvas);
}
:root.dark:has([data-stream-shell]) body,
:root:has([data-stream-shell="play"]) body,
:root:not(.dark):has([data-stream-shell="page"]) body {
background-image: none;
background-color: var(--canvas);
}
/* 触屏点按时不要系统自带的半透明高亮(Android 是一层蓝灰),按压反馈由
卡片 / 按钮自己的 active:scale 给。该属性可继承,挂在壳上即可。 */
[data-stream-shell] {
-webkit-tap-highlight-color: transparent;
}
a {
@apply transition-colors;
}
}
/* ────────────────────────────── Utilities ────────────────────────────── */
@layer utilities {
/* Typography */
.font-display {
font-family: var(--font-display);
letter-spacing: 0.01em;
}
/* Scrolling */
.no-scrollbar {
scrollbar-width: none;
}
.no-scrollbar::-webkit-scrollbar {
display: none;
}
:root:has(.app-scrollbars),
:root:has(.app-scrollbars) *:not(.no-scrollbar):not(.scrollbar-none) {
scrollbar-color: var(--scrollbar-thumb) transparent;
scrollbar-width: thin;
}
:root:has(.app-scrollbars)
*:not(.no-scrollbar):not(.scrollbar-none):hover {
scrollbar-color: var(--scrollbar-thumb-hover) transparent;
}
:root:has(.app-scrollbars)::-webkit-scrollbar,
:root:has(.app-scrollbars)
*:not(.no-scrollbar):not(.scrollbar-none)::-webkit-scrollbar {
width: 6px;
height: 6px;
}
:root:has(.app-scrollbars)::-webkit-scrollbar-track,
:root:has(.app-scrollbars)
*:not(.no-scrollbar):not(.scrollbar-none)::-webkit-scrollbar-track {
background: transparent;
}
:root:has(.app-scrollbars)::-webkit-scrollbar-thumb,
:root:has(.app-scrollbars)
*:not(.no-scrollbar):not(.scrollbar-none)::-webkit-scrollbar-thumb {
min-height: 36px;
border: 1px solid transparent;
border-radius: 999px;
background-color: var(--scrollbar-thumb);
background-clip: padding-box;
}
:root:has(.app-scrollbars)
*:not(.no-scrollbar):not(.scrollbar-none):hover::-webkit-scrollbar-thumb {
background-color: var(--scrollbar-thumb-hover);
}
:root:has(.app-scrollbars)::-webkit-scrollbar-thumb:hover,
:root:has(.app-scrollbars)
*:not(.no-scrollbar):not(.scrollbar-none)::-webkit-scrollbar-thumb:hover {
background-color: var(--scrollbar-thumb-active);
}
/* Player controls */
.volume-slider {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: 4px;
border-radius: 999px;
outline: none;
cursor: pointer;
background: linear-gradient(
to right,
rgba(255, 255, 255, 0.9) 0%,
rgba(255, 255, 255, 0.9) var(--val, 100%),
rgba(255, 255, 255, 0.12) var(--val, 100%),
rgba(255, 255, 255, 0.12) 100%
);
}
.volume-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 13px;
height: 13px;
border-radius: 50%;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
cursor: pointer;
border: 0;
}
.volume-slider::-moz-range-thumb {
width: 13px;
height: 13px;
border-radius: 50%;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
cursor: pointer;
border: 0;
}
/* App shell backgrounds */
/* 门户 shell 背景光斑(user/unsubscribe 共用)。2026-09-26 主色改为无彩后,光斑也去掉色相,
只留明暗层次:日间顶部一层柔和的白与一抹极淡的灰,夜间顶部一抹微光。
玻璃卡背后要有明暗变化才读得出是玻璃,不能是一整块平涂。 */
/* 门户页背景:无彩的明暗光斑铺满整页;棱镜漏光是单独一层(.prism-leak)。
卡片是磨砂面,背景只需给它柔和的明暗与淡彩,不需要纹理 */
.bg-page-glow {
background:
radial-gradient(ellipse 60% 50% at 12% 4%, rgba(20, 22, 28, 0.09) 0%, transparent 70%),
radial-gradient(ellipse 45% 40% at 88% 18%, rgba(255, 255, 255, 0.9) 0%, transparent 70%),
radial-gradient(ellipse 50% 45% at 70% 62%, rgba(20, 22, 28, 0.07) 0%, transparent 70%),
radial-gradient(ellipse 45% 40% at 20% 88%, rgba(20, 22, 28, 0.06) 0%, transparent 70%),
linear-gradient(180deg, rgba(255, 255, 255, 0.42), rgba(246, 246, 248, 0.72));
}
/* 棱镜漏光(全站,落地页与播放页除外):左上角斜进来一束已分好色的光,大幅虚化、只占
一角,与落地页的棱镜叙事呼应;卡片压在上面时透出淡彩。日间用 multiply 叠在浅底上,
避免发灰;浓度见 --mat-leak-opacity。由 <PrismLeak /> 渲染,固定在视口上 */
.prism-leak {
position: fixed;
inset: -10%;
pointer-events: none;
background: linear-gradient(
118deg,
transparent 6%,
oklch(0.75 0.15 25) 13%,
oklch(0.8 0.14 65) 17%,
oklch(0.87 0.14 100) 21%,
oklch(0.8 0.14 150) 25%,
oklch(0.78 0.12 205) 29%,
oklch(0.68 0.15 265) 33%,
oklch(0.62 0.16 305) 37%,
transparent 44%
);
filter: blur(48px);
opacity: var(--mat-leak-opacity);
mix-blend-mode: var(--mat-leak-blend);
-webkit-mask-image: radial-gradient(ellipse 75% 70% at 8% 0%, #000 0%, rgba(0, 0, 0, 0.5) 45%, transparent 78%);
mask-image: radial-gradient(ellipse 75% 70% at 8% 0%, #000 0%, rgba(0, 0, 0, 0.5) 45%, transparent 78%);
}
.dark .bg-page-glow,
[data-force-dark] .bg-page-glow {
background:
radial-gradient(ellipse 60% 50% at 12% 4%, rgba(255, 255, 255, 0.075) 0%, transparent 70%),
radial-gradient(ellipse 45% 40% at 88% 22%, rgba(255, 255, 255, 0.05) 0%, transparent 70%),
radial-gradient(ellipse 50% 45% at 68% 64%, rgba(255, 255, 255, 0.055) 0%, transparent 70%),
radial-gradient(ellipse 45% 40% at 18% 90%, rgba(255, 255, 255, 0.04) 0%, transparent 70%),
linear-gradient(180deg, rgba(16, 17, 20, 0.76), rgba(17, 18, 21, 0.86));
}
}
/* ───────────────────────────── Components ───────────────────────────── */
@layer components {
/* Player subtitles */
[data-subtitles-hidden] .ASS-box {
display: none !important;
}
.ASS-box {
transition: transform 200ms ease;
}
/* 抬多少由 Player 按字幕层与控件常驻面的实际重叠量写进 --uhd-sub-lift(负值 px);
量不到时退回固定 5.5rem(约等于控件常驻面高度)。 */
[data-controls-visible] .ASS-box {
transform: translate3d(0, var(--uhd-sub-lift, -5.5rem), 0);
}
.ASS-box .ASS-dialogue [data-text] {
paint-order: stroke fill;
-webkit-text-stroke: 1.5px rgba(0, 0, 0, 0.95);
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}
/* 字幕字号档位:Player 在根节点上写 --uhd-sub-scale(见 subtitleScale.ts),
在 ass.js 自己算出的字号上再乘一个倍率。ass.js 的样式表是不分层的
(#ASS-global-style),这里在 @layer 里按普通优先级会输给它,所以三条都加
!important —— 分层内的 !important 高于未分层的普通声明。只动字号 / 行高 /
字距,定位与描边仍由 ass.js 的 --ass-scale 控制。 */
.ASS-box .ASS-dialogue [data-text] {
font-size: calc(var(--ass-scale) * var(--ass-real-fs) * var(--uhd-sub-scale, 1) * 1px) !important;
line-height: calc(var(--ass-scale) * var(--ass-tag-fs) * var(--uhd-sub-scale, 1) * 1px) !important;
letter-spacing: calc(var(--ass-scale) * var(--ass-tag-fsp) * var(--uhd-sub-scale, 1) * 1px) !important;
}
/* ─── 玻璃三档 tokens(全站 dark chrome 统一配方)──────────────────
配方来源是 btn-glass 的语言 + Glass UI 的思路:① 底色不透明度压到
0.55~0.70,blur 真正透出后面的内容才有玻璃感(旧 .glass/.glass-panel
的 0.86+ 基本是实心板,已删除并全量迁移);② inset 顶部高光,玻璃
上沿"接光"。边框与投影一并收进 class,组件侧不再各写各的。
使用范围:播放器全部浮层 + 媒体区 header/筛选栏/弹层/卡片徽章。 */
/* 两族分治(2026-08-01 实测校准):
- 贴边 chrome(header/筛选栏/播放器底栏)= pg-surface,融入页面:
只有 blur + 底色,不加泛光和接光线 —— 贴屏幕边缘的面没有"上方
光源",加亮线会把它从页面上切下来,恰好破坏融为一体的感觉。
- 悬浮物(弹层/对话框)= pg-float,画面中央的药丸 HUD = pg-pill,材质发光:
四周有留白,光学上浮在页面上方,泛光层 + 双内高光 + 亮边框成立。
暗底上"更透"读不出来,能读出来的是这些材质要素;底色反而要实,
内容才好读。 */
.pg-surface {
/* 常驻贴边大面:播放器底部控制条(0.6)。站点 header/筛选栏压在
高亮海报上,文字对比要求更高,用 [--pg-surface-alpha:0.7] 收紧 */
background: rgba(var(--mat-surface-rgb), var(--pg-surface-alpha, 0.6));
backdrop-filter: var(--mat-surface-blur);
-webkit-backdrop-filter: var(--mat-surface-blur);
border-color: var(--mat-surface-hairline);
box-shadow: inset 0 1px 0 var(--mat-surface-highlight);
}
.pg-pill {
/* 画面中央短暂浮层:seek 进度环、播放/暂停 flash、toast、手势 HUD */
background:
var(--mat-pill-sheen),
var(--mat-pill-bg);
backdrop-filter: var(--mat-pill-blur);
-webkit-backdrop-filter: var(--mat-pill-blur);
border: 1px solid var(--mat-pill-border);
/* 液态玻璃语言:左上亮、右下暗的边光 + 外侧 1px 暗线 */
box-shadow:
inset 1px 1px 0 -0.25px var(--mat-pill-highlight),
inset -1px -1px 0 -0.25px var(--mat-pill-shade),
0 0 0 1px var(--mat-pill-edge),
var(--mat-pill-shadow);
}
/* 第四档:内容卡片,双主题(门户与 /speed 共用)。薄白/薄亮底 + 亮棱边 +
顶部内高光 + 斜反光,背景模糊由 --mat-slab-blur 给;/speed 的卡片贴着
高频重绘的实时区,在 .spd-bg 里把它关掉,零合成开销优先。 */
.pg-slab {
position: relative;
/* 建立层叠上下文,把 ::before 的 z-index:-1 关在自己内部 */
isolation: isolate;
/* 磨砂面,不追求透明:内容卡以好读为先,背景模糊只让漏光与明暗柔和地渗进来。
不做折射——背后没有细节可弯折,Chromium 专属的 SVG 折射也不值得 */
background: var(--mat-slab-bg);
backdrop-filter: var(--mat-slab-blur);
-webkit-backdrop-filter: var(--mat-slab-blur);
/* 立体感靠亮棱边与顶部内高光,不靠投影:投影只有贴边一层 + 很淡的环境一层,
越透的东西影子越淡,重投影会让玻璃读成实心板 */
border: 1px solid var(--mat-slab-border);
box-shadow: var(--mat-slab-shadow);
}
/* 实底 slab:同一套玻璃面,下面垫一层底色,只让光斑淡淡渗进来(满高工作面板用,几块并排时明暗一致) */
.pg-slab-solid {
background: var(--mat-slab-bg), var(--mat-slab-base);
}
/* slab 里的粘性表头:与卡片同色系的实底,不是一条纯黑 / 纯白的条 */
.pg-slab-head {
background: var(--mat-slab-head);
}
.pg-slab::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
border-radius: inherit;
pointer-events: none;
/* 斜掠反光,收窄且不对称 —— 对称高光读成"渐变背景"而不是"反射"。
浅色下卡片本身大面积偏白,反光峰值可以略高;作用仍是"察觉有一层
膜",能被明确看成光带就过了 */
background: var(--mat-slab-reflection);
}
/* 贴边 chrome 的双主题版(/speed 页头)。浅色:白磨砂 + 蓝调底缘投影;
深色:等同 pg-surface [--pg-surface-alpha:0.7] 的配方。只设边框颜色,
宽度由 border-b utility 给。 */
/* 2026-08-02 统一校准:① 暗色底从硬编码墨黑(rgba 12,13,17,流媒体
继承)改为 token 混色 —— 门户暗色是 271° 蓝紫调,chrome 必须同色相
否则读成另一种材质;② 边框掺 primary,与卡片"蓝棱线"同语言;
③ 竖直侧栏用 .pg-chrome-side:内侧细亮边 + 外侧细暗线 + 投影转向右侧,不画硬分隔线。 */
.pg-chrome {
background: var(--mat-chrome-bg);
backdrop-filter: var(--mat-chrome-blur);
-webkit-backdrop-filter: var(--mat-chrome-blur);
border-color: var(--mat-chrome-border);
box-shadow: var(--mat-chrome-shadow);
}
.pg-chrome-side {
box-shadow: var(--mat-chrome-side-shadow);
}
/* 全站唯一的悬浮层材质(2026-09-26 起):下拉菜单、弹出框、下拉选择、对话框、抽屉,
门户与流媒体、播放器共用;日夜跟随,播放页恒为夜间。圆角分两档:菜单类 rounded-2xl,
对话框 rounded-3xl。2026-09-30(SEARCH-4)起底色是不透明的 popover 实底、不做背景模糊,
立体感只靠边框与投影;组件侧不要再给弹层加半透明底或 backdrop-blur。 */
.pg-float {
background: var(--mat-float-bg);
backdrop-filter: var(--mat-float-blur);
-webkit-backdrop-filter: var(--mat-float-blur);
border: 1px solid var(--mat-float-border);
box-shadow: var(--mat-float-shadow);
}
/* 对话框、确认框、抽屉:要专心阅读和填写,底比菜单实。压在半透明遮罩上时,通透的白底会变成脏灰 */
.pg-float-modal {
--mat-float-bg: var(--mat-float-modal-bg);
}
/* 嵌在另一层磨砂里的菜单(页头、筛选栏、卡片内的下拉):外层磨砂是 backdrop 根,
里面的菜单糊不到页面,半透明底会透出没糊过的内容 —— 这类一律用近实底(动漫站同一做法)。
挂在 body 上的对话框、shadcn 弹出框不需要 */
.pg-float-solid {
--mat-float-bg: var(--mat-float-solid);
}
/* /speed 页面背景:玻璃要"有东西可透"才成立,这几团光斑就是卡片背后的内容。
纯静态渐变、零重绘成本。2026-09-26 主色改为无彩后光斑也去掉色相,只留明暗:
日间是几团极淡的墨,夜间是几团微光。强度照原来校准过的档位,玻璃仍读得出来。 */
.spd-bg {
/* 测速页的卡片贴着高频重绘的实时区,不开背景模糊 */
--mat-slab-blur: none;
background-color: var(--background);
background-image:
radial-gradient(
120% 80% at 12% -8%,
rgba(20, 22, 28, 0.08) 0%,
transparent 55%
),
radial-gradient(
90% 65% at 96% -6%,
rgba(20, 22, 28, 0.06) 0%,
transparent 52%
),
radial-gradient(
56% 44% at 38% 52%,
rgba(20, 22, 28, 0.04) 0%,
transparent 62%
),
radial-gradient(
80% 60% at 50% 112%,
rgba(20, 22, 28, 0.05) 0%,
transparent 60%
);
}
.dark .spd-bg,
[data-force-dark] .spd-bg {
background-image:
radial-gradient(
120% 80% at 15% -10%,
rgba(255, 255, 255, 0.06) 0%,
transparent 55%
),
radial-gradient(
100% 70% at 95% 0%,
rgba(255, 255, 255, 0.04) 0%,
transparent 50%
);
}
/* blur 不可用(老内核/省电模式)时透明底会让文字压在画面上没法读,
退回近实心 */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.pg-surface {
background: var(--mat-surface-solid);
}
.pg-pill {
background: var(--mat-pill-solid);
}
.pg-chrome {
background: var(--mat-chrome-solid);
}
.pg-float {
background: var(--mat-float-solid);
}
.dark .pg-float,
[data-force-dark] .pg-float {
background: rgba(20, 21, 25, 0.96);
}
}
/* Stream library layout */
/* 手机三列:两列时单张海报 190px,信息密度只有主流客户端的一半;三列
约 120px,一屏能看 9 张,标题字号在 MovieCard 里随之收到 15px */
.lib-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
column-gap: 0.5rem;
row-gap: 1.25rem;
}
@media (min-width: 480px) {
.lib-grid {
column-gap: 0.75rem;
row-gap: 2rem;
}
}
@media (min-width: 768px) {
.lib-grid {
grid-template-columns: repeat(4, minmax(0, 1fr));
column-gap: 1.25rem;
row-gap: 2.5rem;
}
}
@media (min-width: 1024px) {
.lib-grid {
/* 定宽 220 + 左对齐会在平板/宽屏右侧留大片空白(横屏 iPad 只排 4 列、
右边空 ~200px)。改成弹性列:每列 200px 起、用 1fr 拉伸铺满整行,
列数随宽度自适应,不再有右侧留白。 */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
}
/* 玻璃族的动效成员:沿元素边框匀速流动的一段高亮弧。用法:宿主已有
圆角与边框,挂 .pg-beam 即可;弧色取 var(--primary) 自动双主题。
克制档:1.5px 细、弧长约 15% 周长、5.5s 一圈;动画的是注册过的
自定义属性(角度),仅小面积重绘。reduced-motion 时静止为常亮弧。 */
.pg-beam {
position: relative;
}
.pg-beam::after {
content: "";
position: absolute;
inset: -2px;
padding: 1.5px;
border-radius: inherit;
pointer-events: none;
/* 弧的亮度与巡边周期可在使用处经 CSS 变量收弱(常驻元素建议弱档,
一次性 CTA 用默认档) */
background: conic-gradient(
from var(--pg-beam-angle),
transparent 0%,
transparent 74%,
color-mix(in oklch, var(--primary) var(--pg-beam-strength, 88%), transparent)
87%,
transparent 100%
);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask-composite: exclude;
animation: pg-beam-spin var(--pg-beam-duration, 5.5s) linear infinite;
}
@media (prefers-reduced-motion: reduce) {
.pg-beam::after {
animation: none;
}
}
/* Segmented tabs */
.tab-slider {
transition:
transform 380ms var(--ease-spring-soft),
width 380ms var(--ease-spring-soft),
top 380ms var(--ease-spring-soft),
height 380ms var(--ease-spring-soft);
will-change: transform, width, top, height;
}
/* 分段控件滑块的材质,位置与尺寸由组件量测后写进 style */
.seg-thumb {
background: var(--mat-seg-thumb-bg);
border: 1px solid var(--mat-seg-thumb-border);
box-shadow: var(--mat-seg-thumb-shadow);
backdrop-filter: blur(12px);
}
.tab-color {
transition: color 320ms var(--ease-standard);
}
/* Glass buttons */
/* 门户胶囊按钮(2026-09-26):主操作 pill-primary 是带棱镜环的半透明胶囊,次操作 pill-secondary 是描边胶囊。
只管底、边、字色与投影,形状尺寸(rounded-full、内边距、字号)由调用处给。
日夜差别全在 --mat-pill-* 参数里;以后要换回实底或调透明度只改参数。 */
.pill-secondary {
/* 液态玻璃 lens:几乎透明的填充 + 内阴影画的方向性边光 + 外侧暗线 */
background: var(--mat-lens-fill);
border: 1px solid transparent;
box-shadow: var(--mat-lens-rim), var(--mat-lens-edge), var(--mat-lens-shadow);
color: var(--content);
-webkit-backdrop-filter: var(--mat-lens-blur);
backdrop-filter: var(--mat-lens-blur);
transition:
background-color var(--duration-base) var(--ease-standard),
transform 220ms var(--ease-spring);
}
.pill-secondary:hover {
background: var(--mat-lens-fill-hover);
}
/* 开关型的次按钮(批量、按作品分组、显示隐藏文件)按下后与 pill-selected 同一外观:多一层填充、描边稍深 */
.pill-secondary[aria-pressed="true"],
.pill-secondary[aria-current="page"] {
background: var(--mat-pill-selected-bg);
box-shadow: var(--mat-lens-rim), 0 0 0 1px var(--mat-pill-selected-border);
color: var(--content-strong);
}
/* 主操作(方案 A,2026-09-26):和其他按钮一样是半透明胶囊,不做实心;靠沿边框缓慢流转的
一整圈棱镜光谱突出,内侧再透一层很淡的同色光。门户 .pill-primary 与流媒体
.btn-glass-primary 共用;减少动态效果时停转,只留彩色边框 */
.pill-primary,
.btn-glass.btn-glass-primary {
position: relative;
isolation: isolate;
overflow: visible;
background: var(--mat-lens-fill);
border: 1px solid transparent;
color: var(--mat-pill-primary-fg);
/* 液态玻璃:彩虹环就是它的边光,这里只补左上内高光和外侧暗线 */
box-shadow: var(--mat-lens-sheen), var(--mat-lens-edge), var(--mat-lens-shadow);
-webkit-backdrop-filter: var(--mat-lens-blur);
backdrop-filter: var(--mat-lens-blur);
transition:
background-color var(--duration-base) var(--ease-standard),
transform 220ms var(--ease-spring);
}
.pill-primary:hover,
.btn-glass.btn-glass-primary:hover {
background: var(--mat-lens-fill-hover);
}
/* 棱镜高光(2026-10-07 液态玻璃方案 2,替代整圈转动的光谱环):光从左上照来,在玻璃棱边上
分出一段光谱,右下是一段更淡的回光。静止不转,悬停时高光沿边扫过一小段。
::before = 棱边上的光谱弧;::after = 同一段光谱的柔光,透进玻璃本体、略洒出边外。
渐变直接写在伪元素上:--prism-angle 不继承,写进 :root 的变量会在根上就被算死 */
.pill-primary::before,
.btn-glass.btn-glass-primary::before,
.prism-ring::before {
content: "";
position: absolute;
inset: -1px;
border-radius: inherit;
padding: 1.75px;
pointer-events: none;
background: conic-gradient(
from calc(var(--prism-angle) + 225deg),
transparent 0deg,
oklch(var(--prism-l) var(--prism-c) 25) 22deg,
oklch(var(--prism-l) var(--prism-c) 70) 40deg,
oklch(calc(var(--prism-l) + 0.06) var(--prism-c) 105) 58deg,
oklch(var(--prism-l) var(--prism-c) 155) 76deg,
oklch(var(--prism-l) var(--prism-c) 205) 94deg,
oklch(calc(var(--prism-l) - 0.04) var(--prism-c) 265) 112deg,
oklch(calc(var(--prism-l) - 0.04) var(--prism-c) 305) 128deg,
transparent 152deg,
transparent 196deg,
oklch(var(--prism-l) var(--prism-c) 205 / 0.4) 226deg,
oklch(calc(var(--prism-l) - 0.04) var(--prism-c) 305 / 0.4) 254deg,
transparent 290deg
);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask-composite: exclude;
opacity: var(--prism-ring);
transition:
--prism-angle 700ms var(--ease-pop),
opacity var(--duration-base) var(--ease-standard);
}
.pill-primary::after,
.btn-glass.btn-glass-primary::after,
.prism-ring::after {
content: "";
position: absolute;
inset: 0;
z-index: -1;
border-radius: inherit;
pointer-events: none;
background: conic-gradient(
from calc(var(--prism-angle) + 225deg),
transparent 0deg,
oklch(var(--prism-l) var(--prism-c) 25) 22deg,
oklch(var(--prism-l) var(--prism-c) 70) 40deg,
oklch(calc(var(--prism-l) + 0.06) var(--prism-c) 105) 58deg,
oklch(var(--prism-l) var(--prism-c) 155) 76deg,
oklch(var(--prism-l) var(--prism-c) 205) 94deg,
oklch(calc(var(--prism-l) - 0.04) var(--prism-c) 265) 112deg,
oklch(calc(var(--prism-l) - 0.04) var(--prism-c) 305) 128deg,
transparent 152deg,
transparent 196deg,
oklch(var(--prism-l) var(--prism-c) 205 / 0.4) 226deg,
oklch(calc(var(--prism-l) - 0.04) var(--prism-c) 305 / 0.4) 254deg,
transparent 290deg
);
filter: blur(5px);
opacity: var(--prism-glow);
transition:
--prism-angle 700ms var(--ease-pop),
opacity var(--duration-base) var(--ease-standard);
}
.pill-primary:hover::before,
.btn-glass.btn-glass-primary:hover::before,
.group:hover .prism-ring::before,
.prism-ring:hover::before {
--prism-angle: 32deg;
opacity: 1;
}
.pill-primary:hover::after,
.btn-glass.btn-glass-primary:hover::after,
.group:hover .prism-ring::after,
.prism-ring:hover::after {
--prism-angle: 32deg;
opacity: calc(var(--prism-glow) * 1.8);
}
.pill-primary:disabled::before,
.pill-primary:disabled::after,
.btn-glass.btn-glass-primary:disabled::before,
.btn-glass.btn-glass-primary:disabled::after {
--prism-angle: 0deg;
filter: saturate(0.4);
}
@media (prefers-reduced-motion: reduce) {
.pill-primary::before,
.pill-primary::after,
.btn-glass.btn-glass-primary::before,
.btn-glass.btn-glass-primary::after,
.prism-ring::before,
.prism-ring::after {
transition: opacity var(--duration-base) var(--ease-standard);
}
}
/* 只要棱镜彩环与内侧淡光、不要胶囊底的宿主(如侧栏"前往流媒体"的播放键):彩环画在
宿主外沿,宿主本身不能 overflow:hidden;放在 .group 里时悬停整组也会点亮 */
.prism-ring {
position: relative;
isolation: isolate;
}
/* 侧栏"前往流媒体":点下去从播放键往外扩一圈七彩光再跳转(动漫站同一做法,光换成棱镜色) */
.stream-entry__burst {
opacity: 0;
transform: scale(1);
background: conic-gradient(
oklch(0.8 0.14 25),
oklch(0.85 0.13 105),
oklch(0.8 0.13 205),
oklch(0.72 0.15 305),
oklch(0.8 0.14 25)
);
}
.stream-entry--leaving .stream-entry__play {
transform: scale(0.92);
}
.stream-entry--leaving .stream-entry__burst {
animation: stream-entry-burst 360ms var(--ease-standard) both;
}
/* 流光图标:图标形状做遮罩,里面填和主按钮同一套的旋转光谱(如账户菜单里"流媒体"的三角)。
形状由 --prism-icon 给(SVG data URL),尺寸由调用处给 */
.prism-icon {
display: block;
flex-shrink: 0;
background: conic-gradient(
from var(--prism-angle),
oklch(var(--prism-l) var(--prism-c) 25),
oklch(var(--prism-l) var(--prism-c) 70),
oklch(calc(var(--prism-l) + 0.06) var(--prism-c) 105),
oklch(var(--prism-l) var(--prism-c) 155),
oklch(var(--prism-l) var(--prism-c) 205),
oklch(calc(var(--prism-l) - 0.04) var(--prism-c) 265),
oklch(calc(var(--prism-l) - 0.04) var(--prism-c) 305),
oklch(var(--prism-l) var(--prism-c) 25)
);
-webkit-mask: var(--prism-icon) center / contain no-repeat;
mask: var(--prism-icon) center / contain no-repeat;
animation: prism-spin 6s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
.prism-icon {
animation: none;
}
}
/* 选中态:分页当前页、角标、选中的选项等"不是按钮但要标出来"的地方。静态、不实心 */
/* 选中态 = 有填充的 lens 玻璃:比次按钮多一层填充,边由方向性边光 + 加深的外侧暗线给 */
.pill-selected {
background: var(--mat-pill-selected-bg);
border: 1px solid transparent;
box-shadow: var(--mat-lens-rim), 0 0 0 1px var(--mat-pill-selected-border);
color: var(--content-strong);
}
/* 详情页头图(MediaHero):剧照层上下、右缘渐隐成透明,露出页面底色与光斑,不留硬边;
::after 是压在剧照上的底色渐变(左侧文字区近乎不透明),参数见 --mat-hero-* */
.media-hero-backdrop {
-webkit-mask-image:
linear-gradient(to bottom, transparent 0%, #000 14%, #000 55%, transparent 100%),
linear-gradient(to right, #000 0%, #000 90%, transparent 100%);
-webkit-mask-composite: source-in;
mask-image:
linear-gradient(to bottom, transparent 0%, #000 14%, #000 55%, transparent 100%),
linear-gradient(to right, #000 0%, #000 90%, transparent 100%);
mask-composite: intersect;
}
.media-hero-backdrop > img {
opacity: var(--mat-hero-image-opacity);
}
.media-hero-backdrop::after {
content: "";
position: absolute;
inset: 0;
background: var(--mat-hero-scrim-stack);
}
@media (min-width: 640px) {
.media-hero-backdrop::after {
background: var(--mat-hero-scrim-side);
}
}
/* 折叠的长文本(ClampText):最后一行行尾渐隐,「展开」压在渐隐处;行数由 --clamp-lines 给 */
.clamp-fade {
max-height: calc(var(--clamp-lines, 3) * 1lh);
overflow: hidden;
-webkit-mask-image: linear-gradient(#000, #000), linear-gradient(to right, #000 62%, transparent 88%);
-webkit-mask-size: 100% calc(100% - 1lh), 100% 1lh;
-webkit-mask-position: top, bottom;
-webkit-mask-repeat: no-repeat;
mask-image: linear-gradient(#000, #000), linear-gradient(to right, #000 62%, transparent 88%);
mask-size: 100% calc(100% - 1lh), 100% 1lh;
mask-position: top, bottom;
mask-repeat: no-repeat;
}
/* 按下回弹,与 .btn-glass 同一手感 */
.pill-primary:active,
.pill-secondary:active {
transform: scale(0.97);
}
/* 卡片聚光:鼠标所在处的卡面微微提亮(借鉴 Aceternity Card Spotlight)。
宿主挂 .pg-spotlight 并用 rippleMove 写入 --mx/--my;只在能悬停的设备上出现。
宿主的 ::after 归它用,亮度见 --mat-spotlight */
.pg-spotlight {
isolation: isolate;
}
/* z-index:-1 + isolate:光铺在卡面底色之上、文字之下,不洗淡内容 */
.pg-spotlight::after {
content: "";
position: absolute;
inset: 0;
z-index: -1;
border-radius: inherit;
pointer-events: none;
background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 50%), var(--mat-spotlight), transparent 70%);
opacity: 0;
transition: opacity var(--duration-layout) var(--ease-standard);
}
@media (hover: hover) {
.pg-spotlight:hover::after {
opacity: 1;
}
}
/* 流媒体按钮(2026-09-26 起与门户胶囊同一外观):.btn-glass = 次操作(描边胶囊),
.btn-glass-primary = 主操作(棱镜胶囊),.btn-glass-icon = 圆形图标钮。只保留各自的
尺寸与排版,底、边、字色、投影全部引用 --mat-pill-*,改外观只改那组参数 */
.btn-glass {
@apply relative isolate inline-flex items-center gap-2 rounded-full px-6 py-2.5 text-[15px] font-medium tracking-tight cursor-pointer select-none overflow-hidden focus:outline-none focus-visible:ring-2 focus-visible:ring-content-strong/40;
}
.btn-glass,
.btn-glass-icon {
background: var(--mat-lens-fill);
border: 1px solid transparent;
box-shadow: var(--mat-lens-rim), var(--mat-lens-edge), var(--mat-lens-shadow);
color: var(--content-strong);
-webkit-backdrop-filter: var(--mat-lens-blur);
backdrop-filter: var(--mat-lens-blur);
transition:
background-color var(--duration-base) var(--ease-standard),
transform 220ms var(--ease-spring);
}
.btn-glass:hover,
.btn-glass-icon:hover {
background: var(--mat-lens-fill-hover);
}
/* LiquidSurface 只模糊不折射时(触屏、测速页、frost 面板):包在玻璃层顶部画的 50% 白光泽太亮,
夜间会压住第一行字。普通档收到很淡,frost(字多的面板)去掉 */
.liquid-surface-blur > :first-child {
background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0) 35%) !important;
}
.liquid-surface-blur.liquid-surface-frost > :first-child {
background-image: none !important;
}
/* 输入框 / 下拉选择触发器:淡底 + 1px 实边框,聚焦时边框加深并带一圈淡光晕;
调用处只给尺寸与内边距,不再各写底色、边框、阴影(由 Input / SelectTrigger 挂上) */
.field-glass {
background: var(--mat-field-bg);
/* 实打实的 1px 边框(不用阴影画线):阴影线太细,部分屏幕和浏览器上看不清输入框在哪 */
border: 1px solid var(--mat-field-edge);
box-shadow: inset 0 1px 0 var(--mat-field-highlight);
transition:
box-shadow var(--duration-base) var(--ease-standard),
border-color var(--duration-base) var(--ease-standard),
background-color var(--duration-base) var(--ease-standard);
}
.field-glass:hover:not(:focus-within, [data-state="open"], [aria-invalid="true"], :disabled) {
border-color: var(--mat-field-edge-hover);
}
.field-glass:focus-visible,
.field-glass:focus-within,
.field-glass[data-state="open"] {
outline: none;
border-color: var(--mat-field-edge-focus);
box-shadow: 0 0 0 3px var(--mat-field-ring);
}
.field-glass[aria-invalid="true"] {
border-color: color-mix(in oklch, var(--destructive) 70%, transparent);
box-shadow: 0 0 0 3px color-mix(in oklch, var(--destructive) 12%, transparent);
}
/* 登录类页面的表单卡片:内容卡的配方,但底换成实在的磨砂(夜间内容卡几乎透明,卡片、输入框、页面三层挤在一起分不开) */
.auth-card {
--mat-slab-bg: var(--mat-auth-card-bg);
--mat-slab-blur: blur(24px) saturate(160%);
}
/* 同 btn-glass 的 lens 玻璃外观,不带布局:尺寸会动画变化、不适合套 LiquidLens 折射的自定义控件 */
.lens-glass {
background: var(--mat-lens-fill);
box-shadow: var(--mat-lens-rim), var(--mat-lens-edge), var(--mat-lens-shadow);
-webkit-backdrop-filter: var(--mat-lens-blur);
backdrop-filter: var(--mat-lens-blur);
}
/* 小玻璃圆片 + 白色图标:glass-chip 跟随日夜(页面底上);glass-chip-media 恒为深烟色,
用于一切压在图片上的小控件(海报 / 缩略图的角标、状态圆片、悬停出现的操作键) */
.glass-chip,
.glass-chip-media {
display: grid;
place-items: center;
border-radius: 9999px;
color: #ffffff;
background: var(--mat-chip-glass);
-webkit-backdrop-filter: blur(6px) saturate(160%);
backdrop-filter: blur(6px) saturate(160%);
box-shadow:
inset 1px 1px 0 -0.25px rgba(255, 255, 255, 0.42),
inset -1px -1px 0 -0.25px rgba(255, 255, 255, 0.12),
0 0 0 1px rgba(0, 0, 0, 0.22);
}
.glass-chip-media {
background: rgba(0, 0, 0, 0.32);
}
/* 套在 LiquidLens 里的按钮:玻璃由外层画(真折射),按钮自己不再铺底、不再模糊、不画边光 */
.btn-glass.btn-liquid,
.btn-glass-icon.btn-liquid,
.pill-primary.btn-liquid,
.pill-secondary.btn-liquid {
background: transparent;
border-color: transparent;
box-shadow: none;
-webkit-backdrop-filter: none;
backdrop-filter: none;
}
.btn-glass.btn-liquid:hover,
.btn-glass-icon.btn-liquid:hover,
.btn-glass.btn-glass-primary.btn-liquid,
.btn-glass.btn-glass-primary.btn-liquid:hover,
.pill-primary.btn-liquid,
.pill-primary.btn-liquid:hover,
.pill-secondary.btn-liquid:hover {
background: transparent;
box-shadow: none;
-webkit-backdrop-filter: none;
backdrop-filter: none;
}
.btn-glass.btn-liquid:hover,
.btn-glass-icon.btn-liquid:hover,
.btn-glass.btn-glass-primary.btn-liquid:hover,
.pill-primary.btn-liquid:hover,
.pill-secondary.btn-liquid:hover {
background: rgba(255, 255, 255, 0.06);
}
.btn-glass:active,
.btn-glass-icon:active {
transform: scale(0.97);
}
.btn-glass-icon {
@apply relative isolate grid place-items-center rounded-full w-11 h-11 cursor-pointer overflow-hidden focus:outline-none focus-visible:ring-2 focus-visible:ring-content-strong/40;
}
/* Stream image overlays */
/* 大图压暗层,取页面底色:夜间压暗、日间提亮(文字随主题深 / 浅) */
.hero-vignette {
background:
radial-gradient(
circle at 70% 42%,
transparent 0%,
color-mix(in oklch, var(--canvas) 8%, transparent) 36%,
color-mix(in oklch, var(--canvas) 92%, transparent) 100%
),
linear-gradient(
90deg,
color-mix(in oklch, var(--canvas) 92%, transparent) 0%,
color-mix(in oklch, var(--canvas) 56%, transparent) 32%,
color-mix(in oklch, var(--canvas) 10%, transparent) 66%,
color-mix(in oklch, var(--canvas) 46%, transparent) 100%
),
linear-gradient(
180deg,
color-mix(in oklch, var(--canvas) 18%, transparent) 0%,
transparent 36%,
color-mix(in oklch, var(--canvas) 96%, transparent) 100%
);
}
/* 横向滚动行两侧的渐隐,取页面底色(日间原来是一道黑条) */
.row-fade-left {
background: linear-gradient(90deg, var(--canvas) 0%, transparent 100%);
}
.row-fade-right {
background: linear-gradient(270deg, var(--canvas) 0%, transparent 100%);
}
}
/* ───────────────────────────── Animations ────────────────────────────── */
/* .pg-beam 的旋转角:注册为 <angle> 才能被动画插值(普通自定义属性
只能离散跳变);@property 不允许出现在 @layer 内,故放此处 */
@property --pg-beam-angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
/* 主按钮棱镜环的旋转角,同理需注册 */
@property --prism-angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
@keyframes prism-spin {
to {
--prism-angle: 360deg;
}
}
@keyframes stream-entry-burst {
from {
opacity: 0.6;
transform: scale(1);
}
to {
opacity: 0;
transform: scale(2.6);
}
}
@keyframes pg-beam-spin {
to {
--pg-beam-angle: 360deg;
}
}
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 播放器弹出层:比 fade-in 快得多(200ms)并带轻微 scale,从触发按钮方向
"弹"出来(配 origin-bottom-right)。菜单是高频操作,520ms 的入场太拖 */
@keyframes ticker-in {
from {
opacity: 0;
transform: translateY(100%);
}
to {
opacity: 1;
transform: none;
}
}
@keyframes ticker-out {
from {
opacity: 1;
transform: none;
}
to {
opacity: 0;
transform: translateY(-100%);
}
}
@keyframes pg-pop {
from {
opacity: 0;
transform: translateY(6px) scale(0.97);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
/* 页面入场:从轻微失焦到清晰,只播一次(借鉴 Arc 的 blur-in;调用处用
motion-safe: 前缀,减少动态效果时直接显示)。填充模式用 backwards 而不是 both:
播完不能留下 filter/transform,否则页面里 position:fixed 的元素会改以这层为参照 */
@keyframes blur-in {
from {
opacity: 0;
filter: blur(6px);
transform: translateY(8px);
}
to {
opacity: 1;
filter: blur(0);
transform: translateY(0);
}
}
@keyframes hero-fade {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes ken-burns {
from {
transform: translateY(var(--parallax, 0)) scale(1.02);
}
to {
transform: translateY(var(--parallax, 0)) scale(1.08);
}
}
@keyframes shiny-text {
0%,
90%,
100% {
background-position: calc(-100% - var(--shiny-width)) 0;
}
30%,
60% {
background-position: calc(100% + var(--shiny-width)) 0;
}
}
@keyframes fadeUp {
from {
opacity: 0;
transform: translateY(24px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes player-flash {
0% {
opacity: 0;
transform: scale(0.55);
}
12% {
opacity: 1;
transform: scale(1.06);
}
18%,
75% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0;
transform: scale(1.15);
}
}
.animate-shiny-text {
animation: shiny-text 8s infinite;
}
.animate-player-flash {
animation: player-flash var(--player-flash-dur, 1500ms)
var(--ease-standard) forwards;
}
::view-transition-old(play-card),
::view-transition-new(play-card) {
animation-duration: 360ms;
animation-timing-function: var(--ease-sheet);
}
/* 主题切换的渐进过渡(theme-toggle.tsx):走 View Transitions 默认的
交叉淡化(plus-lighter 混合),这里只把 UA 默认的 250ms 放缓到 420ms
并换成标准减速曲线,让明暗互换从容一些。scoped 在 .theme-vt 下,
不影响其它 view transition(play-card 的导航过渡仍走默认时长)。 */
:root.theme-vt::view-transition-old(root),
:root.theme-vt::view-transition-new(root) {
animation-duration: 420ms;
animation-timing-function: var(--ease-standard);
}