/* ===== 令牌 —— 默认「极夜蓝」主题 ===== */
:root {
  --gut: 16px;
  --card-gut: 8px;
  --panel-rgb: 22, 32, 66;
  --panel: rgba(var(--panel-rgb), .62);
  --panel-soft: rgba(var(--panel-rgb), .46);
  --panel-strong: rgba(18, 26, 54, .90);
  --line: rgba(120, 160, 255, .22);
  --line-strong: rgba(160, 190, 255, .5);
  --ink: #eaf0ff;
  --ink-dim: rgba(234, 240, 255, .66);
  --ink-faint: rgba(234, 240, 255, .42);
  --accent: #2ea6ff;
  --accent-2: #2f7bff;
  --accent-ink: #04121f;
  --grad: linear-gradient(120deg, #2fd0e8 0%, #39c0ff 28%, #2f7bff 52%, #5468ff 76%, #2fd0e8 100%);
  --accent-soft: rgba(46, 166, 255, .18);
  --accent-line: rgba(46, 166, 255, .5);
  --sheet-bg: #000000;
  --dyn-bg: var(--sheet-bg); --dyn-bg-rgb: 0, 0, 0;
  --bg1: #0c1533; --bg2: #0a1024; --bg3: #070b1a;
  --badge-bg: rgba(46, 166, 255, .92);
  --badge-border: rgba(160, 210, 255, .5);
  --badge-shadow: rgba(46, 166, 255, .35);
  --btn-shadow: rgba(46, 166, 255, .34);
  --ok: #4bd08a; --bad: #ff5c66; --lock: #ffc24d; --gray: #8b96b5;
  --radius: 12px;
  --safe-top: 12px; --safe-bottom: 12px; --safe-left: 0px; --safe-right: 0px;
}
/* ===== 内置主题：日落珊瑚（长按 Logo 切换）===== */
:root[data-theme="ember"] {
  --panel-rgb: 80, 42, 32;
  --panel-strong: rgba(46, 22, 16, .92);
  --line: rgba(255, 175, 130, .24);
  --line-strong: rgba(255, 190, 150, .5);
  --ink: #fff4ec;
  --ink-dim: rgba(255, 244, 236, .68);
  --ink-faint: rgba(255, 244, 236, .42);
  --accent: #ff7a45;
  --accent-2: #ffb23e;
  --accent-ink: #2a0e02;
  --grad: linear-gradient(135deg, #ff9a56 0%, #ff5f6d 100%);
  --accent-soft: rgba(255, 122, 69, .18);
  --accent-line: rgba(255, 122, 69, .5);
  --sheet-bg: #0f0605;
  --dyn-bg: var(--sheet-bg); --dyn-bg-rgb: 15, 6, 5;
  --bg1: #241210; --bg2: #180b09; --bg3: #0f0605;
  --badge-bg: rgba(255, 122, 69, .92);
  --badge-border: rgba(255, 190, 150, .5);
  --badge-shadow: rgba(255, 122, 69, .35);
  --btn-shadow: rgba(255, 122, 69, .34);
}
/* ===== 内置主题：极光靛蓝（长按 Logo 切换）===== */
:root[data-theme="aurora"] {
  --panel-rgb: 60, 45, 120;
  --panel-strong: rgba(28, 18, 58, .92);
  --line: rgba(155, 135, 255, .26);
  --line-strong: rgba(180, 160, 255, .55);
  --ink: #f0eeff;
  --ink-dim: rgba(240, 238, 255, .66);
  --ink-faint: rgba(240, 238, 255, .4);
  --accent: #8b5cf6;
  --accent-2: #22d3ee;
  --accent-ink: #0a0620;
  --grad: linear-gradient(135deg, #8b5cf6 0%, #22d3ee 100%);
  --accent-soft: rgba(139, 92, 246, .18);
  --accent-line: rgba(139, 92, 246, .5);
  --sheet-bg: #05030f;
  --dyn-bg: var(--sheet-bg); --dyn-bg-rgb: 5, 3, 15;
  --bg1: #140a33; --bg2: #0d0724; --bg3: #05030f;
  --badge-bg: rgba(139, 92, 246, .92);
  --badge-border: rgba(190, 175, 255, .5);
  --badge-shadow: rgba(139, 92, 246, .35);
  --btn-shadow: rgba(139, 92, 246, .34);
}
/* ===== 内置主题：苹果白（Apple TV+ 风格，白按钮黑字，长按 Logo 切换）=====
   页面背景保持黑色：大部分文字（标题/简介/卡片名等）直接铺在黑背景或图片上，用浅色；
   只有自身就是白色磨砂面板的小组件（搜索框、图标按钮、通知条、按钮、网盘资源行、
   设置面板、搜索联想、底部导航栏、toast）单独把文字/边框改回深色，跟它们自己的白底匹配。 */
:root[data-theme="appletv"] {
  --panel-rgb: 120, 120, 128;
  --panel: rgba(255, 255, 255, .74);
  --panel-soft: rgba(255, 255, 255, .55);
  --panel-strong: rgba(255, 255, 255, .96);
  --line: rgba(255, 255, 255, .16);
  --line-strong: rgba(255, 255, 255, .30);
  --ink: #f5f5f7;
  --ink-dim: rgba(245, 245, 247, .68);
  --ink-faint: rgba(245, 245, 247, .42);
  --accent: #0071e3;
  --accent-2: #0058b0;
  --accent-ink: #111114;
  --grad: linear-gradient(135deg, #ffffff 0%, #f0f0f2 100%);
  --accent-soft: rgba(0, 113, 227, .14);
  --accent-line: rgba(0, 113, 227, .4);
  --sheet-bg: #000000;
  --dyn-bg: var(--sheet-bg); --dyn-bg-rgb: 0, 0, 0;
  --bg1: #0c1533; --bg2: #0a1024; --bg3: #070b1a;
  --badge-bg: rgba(255, 255, 255, .92);
  --badge-border: rgba(0, 0, 0, .12);
  --badge-shadow: rgba(0, 0, 0, .22);
  --btn-shadow: rgba(0, 0, 0, .16);
}
:root[data-theme="appletv"] .search-box,
:root[data-theme="appletv"] .cat-searchbar,
:root[data-theme="appletv"] .hdr-ico,
:root[data-theme="appletv"] .clear-search,
:root[data-theme="appletv"] .notice,
:root[data-theme="appletv"] .search-suggest,
:root[data-theme="appletv"] .btn,
:root[data-theme="appletv"] .panel-sheet,
:root[data-theme="appletv"] .toast,
:root[data-theme="appletv"] .chips {
  --ink: #1d1d1f;
  --ink-dim: rgba(29, 29, 31, .65);
  --ink-faint: rgba(29, 29, 31, .38);
  --line: rgba(0, 0, 0, .12);
  --line-strong: rgba(0, 0, 0, .22);
}
:root[data-theme="appletv"] .cat-back { color: #ffffff; }
:root[data-theme="appletv"] .chips {
  background: rgba(255, 255, 255, .88); border-color: rgba(0, 0, 0, .08);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  box-shadow: none;
}
:root[data-theme="appletv"] .chip.active { background: rgba(0, 113, 227, .12); color: var(--accent); box-shadow: none; }
/* 类型筛选标签（分类页顶部的"全部/剧情/喜剧..."那一排）选中态：苹果白主题整体走"白底黑字"的
   按钮质感（跟 .btn / .chips 一样），这里单独覆盖成纯白底 + 深色字，不再沿用蓝色半透明底，
   跟主题基调统一，也比蓝底在黑色页面背景上更醒目。 */
:root[data-theme="appletv"] .genre-chip.active { background: #ffffff; border-color: #ffffff; color: #1d1d1f; font-weight: 700; }
:root[data-theme="appletv"] .panel-close { background: rgba(0, 0, 0, .05); }
:root[data-theme="appletv"] .set-group { background: rgba(0, 0, 0, .03); }
:root[data-theme="appletv"] .field input { background: rgba(0, 0, 0, .045); }
:root[data-theme="appletv"] .switch { background: rgba(0, 0, 0, .14); }
/* 开启态：苹果蓝（原先只有关的底色，且选择器压过了通用 .switch.on 的渐变，看起来开/关一样灰） */
:root[data-theme="appletv"] .switch.on { background: #0071e3; }
:root[data-theme="appletv"] #settingsOverlay .switch { background: rgba(0, 0, 0, .14); }
:root[data-theme="appletv"] #settingsOverlay .switch.on { background: #0071e3; }
/* 设置页 / 确认弹窗：白底上必须用深色字。全局 --ink 是给黑底首页用的浅色，
   虽已在 .panel-sheet 上覆写变量，但 #settingsOverlay 整页场景 + 部分子元素（status / label / close）
   仍可能落到浅色字，这里用更高优先级写死可读色。 */
:root[data-theme="appletv"] #settingsOverlay {
  background: #f5f5f7;
}
:root[data-theme="appletv"] #settingsOverlay .panel-sheet,
:root[data-theme="appletv"] #confirmOverlay .panel-sheet {
  background: #ffffff;
  color: #1d1d1f;
  --ink: #1d1d1f;
  --ink-dim: rgba(29, 29, 31, .68);
  --ink-faint: rgba(29, 29, 31, .42);
  --line: rgba(0, 0, 0, .12);
  --line-strong: rgba(0, 0, 0, .22);
  --panel-soft: rgba(0, 0, 0, .04);
  --panel-strong: #ffffff;
}
:root[data-theme="appletv"] #settingsOverlay .set-hd h3,
:root[data-theme="appletv"] #settingsOverlay .toggle-row .lbl,
:root[data-theme="appletv"] #settingsOverlay .field label,
:root[data-theme="appletv"] #settingsOverlay .panel-close,
:root[data-theme="appletv"] #confirmOverlay .confirm-title,
:root[data-theme="appletv"] #confirmOverlay .panel-close {
  color: #1d1d1f;
}
:root[data-theme="appletv"] #settingsOverlay .field label .hint,
:root[data-theme="appletv"] #settingsOverlay .toggle-row .lbl small,
:root[data-theme="appletv"] #settingsOverlay .login-state,
:root[data-theme="appletv"] #settingsOverlay .status-line,
:root[data-theme="appletv"] #confirmOverlay .confirm-text {
  color: rgba(29, 29, 31, .55);
}
:root[data-theme="appletv"] #settingsOverlay .status-line b {
  color: rgba(29, 29, 31, .78);
}
:root[data-theme="appletv"] #settingsOverlay .field input {
  color: #1d1d1f;
  background: rgba(0, 0, 0, .06);
  border-color: rgba(0, 0, 0, .14);
}
:root[data-theme="appletv"] #settingsOverlay .field input::placeholder {
  color: rgba(29, 29, 31, .38);
}
:root[data-theme="appletv"] #settingsOverlay .set-group {
  background: rgba(0, 0, 0, .04);
  border-color: rgba(0, 0, 0, .1);
}
:root[data-theme="appletv"] #settingsOverlay .set-group-title {
  color: #0071e3;
}
:root[data-theme="appletv"] #settingsOverlay .pan-type-chip {
  color: rgba(29, 29, 31, .55);
  border-color: rgba(0, 0, 0, .12);
  background: rgba(0, 0, 0, .03);
}
:root[data-theme="appletv"] #settingsOverlay .pan-type-chip.on {
  color: #1d1d1f;
  background: rgba(0, 113, 227, .12);
  border-color: rgba(0, 113, 227, .35);
}
:root[data-theme="appletv"] #settingsOverlay .btn:not(.primary):not(.danger) {
  color: #1d1d1f;
  background: rgba(0, 0, 0, .05);
  border-color: rgba(0, 0, 0, .12);
}
:root[data-theme="appletv"] #settingsOverlay .btn.primary,
:root[data-theme="appletv"] #confirmOverlay .btn.primary {
  color: #111114;
}
:root[data-theme="appletv"] #settingsOverlay .divider {
  background: rgba(0, 0, 0, .1);
}
:root[data-theme="appletv"] .pan-sub .q { color: #ffffff; font-weight: 700; }
:root[data-theme="appletv"] .cast-cell.sel { border-color: rgba(255, 255, 255, .7); animation: castSelBreatheWhite 2.2s ease-in-out infinite; }
@keyframes castSelBreatheWhite {
  0%, 100% { box-shadow: 0 0 0 1px rgba(255,255,255,.22), inset 0 0 10px 0 rgba(255,255,255,.16); }
  50% { box-shadow: 0 0 0 1px rgba(255,255,255,.4), inset 0 0 16px 2px rgba(255,255,255,.26); }
}
:root[data-theme="appletv"] .pan-item { background: transparent; border-color: rgba(255, 255, 255, .22); }
:root[data-theme="appletv"] .pan-play { color: #ffffff; }
:root[data-theme="appletv"] .pan-name { color: #ffffff; }
:root[data-theme="appletv"] .pan-sub { color: rgba(255, 255, 255, .68); }
:root[data-theme="appletv"] .ed-works-head { color: #f5f5f7; }
:root[data-theme="appletv"] .mh-more { color: var(--ink-dim); }

/* ===== 苹果白主题专属：底部导航栏 + 播放按钮，内置七彩流光呼吸 =====
   只加效果，不改原有形状：.chips 还是胶囊长条，.ed-play 还是圆角长条。
   做法：用 ::before 放一层模糊的七彩渐变（在元素内部、被圆角裁掉多余部分），
   ::after 盖一层半透明白让效果显得含蓄，真正的图标/文字再用 z-index 提到最上层。 */
@keyframes appletvRainbowFlowX { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }
@keyframes appletvRainbowBreatheBar { 0%, 100% { opacity: .4; transform: scale(1); } 50% { opacity: .78; transform: scale(1.03); } }
@keyframes appletvRainbowSpin { from { filter: blur(20px) hue-rotate(0deg); } to { filter: blur(20px) hue-rotate(360deg); } }
@keyframes appletvRainbowBreatheSoft { 0%, 100% { opacity: .26; transform: scale(.9); } 50% { opacity: .52; transform: scale(1.04); } }

/* 导航栏：七彩左右均匀分布 + 缓慢流动 + 呼吸（对应预览里的 B-2 方案） */
:root[data-theme="appletv"] .chips {
  position: fixed; overflow: hidden;
  background: rgba(255, 255, 255, .55);
}
:root[data-theme="appletv"] .chips::before {
  content: ""; position: absolute; inset: -60% 0; z-index: 0; pointer-events: none;
  background: linear-gradient(90deg, #ff3b3b, #ff9d3b, #ffe23b, #3bff6a, #3bd4ff, #7a3bff, #ff3bbf, #ff3b3b);
  background-size: 200% 100%; filter: blur(18px);
  animation: appletvRainbowFlowX 6s ease-in-out infinite, appletvRainbowBreatheBar 3s ease-in-out infinite;
}
:root[data-theme="appletv"] .chips::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: rgba(255, 255, 255, .7);
}
:root[data-theme="appletv"] .chip { position: relative; z-index: 1; }

/* 播放按钮：保持长条形状与原有布局，仅把内部换成七彩微呼吸（关掉原本的蓝色流光，避免叠加） */
:root[data-theme="appletv"] .ed-play {
  position: relative; overflow: hidden; animation: none;
  background: rgba(255, 255, 255, .92);
}
:root[data-theme="appletv"] .ed-play::before {
  content: ""; position: absolute; inset: -40%; z-index: 0; pointer-events: none;
  background: conic-gradient(from 0deg, #ff3b3b, #ff9d3b, #ffe23b, #3bff6a, #3bd4ff, #7a3bff, #ff3bbf, #ff3b3b);
  animation: appletvRainbowSpin 6s linear infinite, appletvRainbowBreatheSoft 4s ease-in-out infinite;
}
:root[data-theme="appletv"] .ed-play::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: rgba(255, 255, 255, .8);
}
:root[data-theme="appletv"] .ed-play .tri,
:root[data-theme="appletv"] .ed-play #edPlayLabel {
  position: relative; z-index: 1;
}
@media (prefers-reduced-motion: reduce) {
  :root[data-theme="appletv"] .chips::before,
  :root[data-theme="appletv"] .ed-play::before { animation: none; }
}
.no-css-functions:root { --safe-top: 0px; --safe-bottom: 0px; }
:root {
  --safe-top: min(max(var(--fm-safe-top, 0px), env(safe-area-inset-top, 0px)), 64px);
  --safe-bottom: min(max(var(--fm-safe-bottom, 0px), env(safe-area-inset-bottom, 0px)), 40px);
  --safe-left: max(var(--fm-safe-left, 0px), env(safe-area-inset-left, 0px));
  --safe-right: max(var(--fm-safe-right, 0px), env(safe-area-inset-right, 0px));
}
/* 非全屏（normal）：原生顶部/底部 UI 已避让系统栏，WebHome 不再叠加安全区，避免顶部大空白 */
html.chrome-normal { --safe-top: 0px; --safe-bottom: 0px; }
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body {
  margin: 0; min-height: 100%; color: var(--ink);
  background: var(--dyn-bg, #000000);
  /* 故意不加 transition：hero-shade / hero-blend 两层融合渐变本身就是瞬时跟着 --dyn-bg-rgb 变的
     （见下面 .hero-blend 的注释），如果这里的页面背景还带着延迟过渡，融合层已经瞬间到位、
     页面背景却还在慢慢追，两者交界处（融合层贴着页面背景那条边）就会露出一条"追赶中"的接缝——
     不管是自动轮播还是手动拖拽，只要颜色一变就会看见。两边都改成瞬时，才能真正无缝衔接。 */
  font-family: "PingFang SC", "HarmonyOS Sans SC", "Microsoft YaHei", "Noto Sans CJK SC", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 15px; line-height: 1.5; -webkit-font-smoothing: antialiased;
}
html:not(.fm-native), html:not(.fm-native) body {
  background: var(--dyn-bg, #000000);
}
.mono { font-family: ui-monospace, "SF Mono", "Roboto Mono", "DejaVu Sans Mono", Consolas, monospace; letter-spacing: .04em; }
/* 首页 / 分类页 这种"整页切换"原来是纯粹的 style.display 硬切，一帧内直接消失/出现，
   没有任何过渡。这里给刚显示出来的那个视图补一个轻微的"弹入"动画（略微放大回弹 + 上浮淡入），
   由 JS 在切换时手动重新触发（先移除类名强制重排，再加回去），不影响原有 display 切换逻辑，
   也不需要两个视图同时占位，所以不会有布局跳动的风险。 */
@keyframes viewPopIn { from { opacity: 0; transform: translateY(14px) scale(.965); } to { opacity: 1; transform: translateY(0) scale(1); } }
.view-pop { animation: viewPopIn .46s cubic-bezier(.34, 1.56, .64, 1); }
@media (prefers-reduced-motion: reduce) { .view-pop { animation: none; } }
/* TV 端：遥控操作追求最简单直接的响应，所有装饰性 keyframe 动画（呼吸光、流光、shimmer 加载条、
   弹入弹出）统一关掉，跟 prefers-reduced-motion 用同一套思路，只是不看系统设置、只认 tv-mode。
   注意这里只关 animation，不动 transition——面板/详情页开合那种短过渡还留着，纯瞬切会显得很生硬。 */
.tv-mode * { animation: none !important; }
.app { position: relative; z-index: 1; min-height: 100vh; min-height: var(--fm-web-height, 100vh); background: transparent; padding-left: var(--safe-left); padding-right: var(--safe-right); }
/* 苹果橡皮筋回弹：越界拉伸时 JS 给容器加 translateY，松手用这条弹性过渡弹回。
   .rubber-snap 只在"松手弹回"那一刻加上（回弹用带过冲的缓动），跟手拖拽时不加过渡（实时跟手）。 */
.rubber-snap { transition: transform .42s cubic-bezier(.22, 1, .36, 1); }
#detailSheet.rubber-snap { transition: transform .42s cubic-bezier(.22, 1, .36, 1); }
button { font: inherit; color: inherit; cursor: pointer; border: 0; background: none; padding: 0; margin: 0; appearance: none; -webkit-appearance: none; text-align: inherit; }
input { font: inherit; color: inherit; }
img { display: block; border: 0; }

.focusable:focus, .focusable.focus { outline: none; }
.tv-mode .focusable:focus, .tv-mode .focusable.focus { transform: scale(1.06); }

/* 头部 */
.header { position: sticky; top: 0; z-index: 30; padding-top: calc(var(--safe-top) + 8px); padding-bottom: 8px; background: transparent; }
.fm-native .header { background: transparent; }
.header-row { display: flex; align-items: center; padding: 0 16px; }
.brand { flex: 0 0 auto; display: flex; align-items: center; background: none; border: 0; padding: 4px 2px; cursor: pointer; }
.brand:active { transform: scale(.94); }
.tv-mode .brand.focus, .tv-mode .brand:focus { transform: scale(1.08); }
.brand-mark { flex: 0 0 auto; display: block; }
.brand .name { font-size: 18px; font-weight: 800; margin-left: 9px; letter-spacing: 1px; }
.hdr-spacer { flex: 1 1 auto; }
/* 搜索面板（顶部固定浮层，搜索时出现） */
.search-panel { position: fixed; top: 0; left: 0; right: 0; z-index: 60; visibility: hidden; padding: calc(var(--safe-top) + 10px) 16px 12px;
  background: transparent;
  opacity: 0; -webkit-transform: translateY(-14px); transform: translateY(-14px); pointer-events: none;
  transition: opacity .22s ease, -webkit-transform .3s cubic-bezier(.34,1.56,.64,1), transform .3s cubic-bezier(.34,1.56,.64,1), visibility 0s linear .26s; }
.search-panel.open { visibility: visible; opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); pointer-events: auto;
  transition: opacity .2s ease, -webkit-transform .32s cubic-bezier(.34,1.56,.64,1), transform .32s cubic-bezier(.34,1.56,.64,1); }
/* 搜索面板打开时的背景遮罩：模糊 + 半透明，禁止背景滑动，点击空白处回弹关闭 */
.search-mask { position: fixed; top: 0; right: 0; bottom: 0; left: 0; inset: 0; z-index: 55; visibility: hidden; opacity: 0;
  background: rgba(6,10,22,.46); -webkit-backdrop-filter: blur(0px); backdrop-filter: blur(0px);
  -ms-touch-action: none; touch-action: none;
  transition: opacity .24s ease, visibility 0s linear .24s; }
.search-mask.open { visibility: visible; opacity: 1; -webkit-backdrop-filter: blur(16px) saturate(1.3); backdrop-filter: blur(16px) saturate(1.3);
  transition: opacity .2s ease, -webkit-backdrop-filter .3s ease, backdrop-filter .3s ease; }
body.search-lock { position: fixed; left: 0; right: 0; width: 100%; }
.search-box { display: flex; align-items: center; background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 0 6px 0 12px; min-width: 0; position: relative; }
.search-ico { flex: 0 0 auto; display: flex; color: var(--ink-faint); margin-right: 8px; }
.search-input { flex: 1 1 auto; min-width: 0; background: transparent; border: 0; outline: none; padding: 10px 0; color: var(--ink); font-size: 15px; }
.search-input::placeholder { color: var(--ink-faint); }
.search-go { flex: 0 0 auto; padding: 7px 15px; border-radius: 9px; background: var(--grad); color: var(--accent-ink); font-weight: 800; font-size: 13px; background-size: 220% 220%; animation: gradFlow 8s ease-in-out infinite; }
/* 统一的圆角图标按钮底座：背景/描边/按下反馈只在这里定义一次，
   hdr-ico / cat-back / recent-clear-btn 都基于它，只覆盖各自的尺寸和默认字色。 */
.icon-btn { flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  background: var(--panel); border: 1px solid var(--line); color: var(--ink-dim);
  outline: none; -webkit-tap-highlight-color: transparent; }
.icon-btn::-moz-focus-inner { border: 0; }
.icon-btn:active { transform: scale(.92); background: var(--accent-soft); border-color: var(--accent-line); }
.icon-btn.active { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
.tv-mode .icon-btn.focus, .tv-mode .icon-btn:focus { transform: scale(1.12); }
.hdr-ico { width: 40px; height: 40px; border-radius: 11px; }
.search-go svg { display: block; }
.tv-mode .search-go.focus, .tv-mode .search-go:focus { transform: scale(1.08); }
/* emby 式首页多行 */
#homeRows { padding-top: 6px; }
.mh-section { margin-bottom: 22px; }
.mh-section-head { display: flex; align-items: baseline; justify-content: space-between; padding: 0 16px; margin-bottom: 10px; }
.mh-section-title { font-size: 17px; font-weight: 800; letter-spacing: -.02em; }
.mh-more { font-size: 13px; font-weight: 700; color: var(--accent); background: none; border: 0; display: inline-flex; align-items: center; gap: 2px; padding: 2px 0; }
.mh-more:active { opacity: .6; }
.mh-row { display: flex; gap: var(--card-gut); overflow-x: auto; padding: 0 var(--card-gut) 4px; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.mh-row::-webkit-scrollbar { display: none; }
.mh-row .card { width: 128px; flex: 0 0 auto; margin: 0; }
/* 继续观看：横版剧照比例（16:9），而不是竖版海报比例 */
.mh-row-recent .card { width: 208px; }
.mh-row-recent .poster { padding-top: 56.25%; }
.mh-row-recent .poster img { object-position: center 25%; }
/* JAVDB / JavRanking：横版封面行（与继续观看同比例，宽卡片） */
.mh-row-land .card { width: 208px; }
.mh-row-land .poster { padding-top: 56.25%; }
.mh-row-land .poster img { object-position: center center; object-fit: cover; }
.grid.grid-recent { grid-template-columns: repeat(2, 1fr); }
.grid-recent .poster { padding-top: 56.25%; }
.grid-recent .poster img { object-position: center center; }
@media (min-width: 600px) { .grid.grid-recent { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 900px) { .grid.grid-recent { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1200px) { .grid.grid-recent { grid-template-columns: repeat(5, 1fr); } }
.mh-row-empty { padding: 4px var(--gut); color: var(--ink-faint); font-size: 12.5px; }

/* 分类页头 */
/* 分类页头：原来写死纯黑（#000000），跟首页/详情页现在都跟着海报自动变色的暖色调背景放一起，
   顶上突兀地卡一条黑条，很显眼很尴尬。改成跟 --dyn-bg-rgb 同色系的半透明磨砂条——颜色跟着
   当前页面的主题色走，同时留一点模糊（backdrop-filter）方便下面滚动的内容衬着文字看得清，
   观感上就是"同一块背景延伸上去"，而不是另外扣一块黑色盖子上去。 */
.cat-head { display: flex; align-items: center; gap: 8px; padding: calc(var(--safe-top) + 8px) var(--gut) 8px;
  position: sticky; top: 0; z-index: 20;
  background: rgba(var(--dyn-bg-rgb, 0,0,0), .82);
  -webkit-backdrop-filter: blur(20px) saturate(1.15);
  backdrop-filter: blur(20px) saturate(1.15); }
/* 返回按钮：原来直接吃 .icon-btn 的通用方形底座（10px 圆角、纯色板 + 细描边），
   跟其它功能性图标按钮长一个样，放在页头左上角显得很"工具栏"，不够精致。
   改成苹果系统里常见的圆形毛玻璃返回键：正圆形、更强的模糊透光、外投影给一点浮起的
   厚度感，再叠一条极淡的内上高光模拟玻璃球面反光。按压时用回弹曲线代替瞬间跳变的
   scale，松手时的手感更软。箭头本身在 24 视口里其实比几何中心略靠右一点点，
   这里用 svg 自身的 translateX 往左挪 1px，视觉上更居中。 */
.cat-back {
  width: 36px; height: 36px; border-radius: 50%; color: var(--ink);
  background: var(--panel-soft);
  border: 1px solid var(--line);
  box-shadow: 0 3px 12px rgba(0, 0, 0, .22), 0 1px 2px rgba(0, 0, 0, .16), inset 0 1px 0 rgba(255, 255, 255, .1);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  backdrop-filter: blur(16px) saturate(1.4);
  transition: transform .38s cubic-bezier(.34, 1.56, .64, 1), background .2s ease, box-shadow .2s ease, border-color .2s ease;
}
.cat-back svg { transform: translateX(-1px); }
.cat-back:active {
  transform: scale(.86);
  background: var(--accent-soft);
  border-color: var(--accent-line);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .18), inset 0 1px 0 rgba(255, 255, 255, .06);
}
.tv-mode .cat-back.focus, .tv-mode .cat-back:focus {
  transform: scale(1.14);
  box-shadow: 0 0 0 3px var(--accent-line), 0 3px 12px rgba(0, 0, 0, .22);
}
.cat-title { font-size: 18px; font-weight: 800; flex: 0 0 auto; max-width: 40%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 搜索结果页头：把"搜索：关键词"这行纯文字标题换成一个"搜索框"样式的按钮——
   里面放一个放大镜图标 + 当前关键词，点它重新打开搜索面板改词（参考设计图，搜完仍看得到搜索框本身，
   而不是只剩一行标题文字）。同时把站源筛选胶囊单独挪到下一行。默认不显示，只有 #catView.searching 时出现。 */
.cat-searchbar { display: none; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; cursor: pointer;
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 9px 10px 9px 14px; color: var(--ink);
  -webkit-backdrop-filter: blur(16px) saturate(1.3); backdrop-filter: blur(16px) saturate(1.3);
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none; user-select: none; transition: background .18s ease, border-color .18s ease; }
.cat-searchbar .csb-ico { flex: 0 0 auto; display: flex; color: var(--ink-faint); }
.cat-searchbar .csb-kw { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; text-align: left; }
.cat-searchbar:active { background: var(--accent-soft); border-color: var(--accent-line); }
#catView.searching .cat-title { display: none; }
#catView.searching .cat-searchbar { display: flex; }
#catView.searching .cat-head { flex-wrap: wrap; row-gap: 10px; }
/* 胶囊掉到第二行、整行左对齐；order 拉大保证它排在这一行所有元素最后（即换行到下一行） */
#catView.searching #genreChips { order: 99; flex: 0 0 100%; max-width: 100%; width: 100%; margin: 0; justify-content: flex-start; flex-wrap: wrap; align-items: center; }
.hero-wrap { position: relative; }
.hero-wrap[hidden] { display: none; }
.hero { position: relative; width: 100%; height: 58vh; min-height: 340px; max-height: 560px; overflow: hidden; margin: 0 0 6px; background: transparent; }
.hero:empty { display: none; }
@media (orientation: landscape) { .hero { height: 85vh; min-height: 280px; } }
/* 平板竖屏（宽度够大且竖屏）：轮播海报加高 8vh，画面更饱满。max-height 也放宽以免被 560px 卡住 */
@media (min-width: 600px) and (orientation: portrait) { .hero { height: 66vh; max-height: 720px; } }
/* 图片层：不参与左右翻页位移，只在当前帧/目标帧之间做透明度交叉渐隐渐显，
   叠色（hero-shade/hero-blend）跟着 --dyn-bg-rgb 同步瞬时变化，观感上颜色融合和图片过渡完全同步。 */
.hero-imgs { position: absolute; inset: 0; width: 100%; height: 100%; overflow: hidden; z-index: 0; }
.hero-track { position: relative; z-index: 1; display: flex; height: 100%; transition: transform .5s cubic-bezier(.4, 0, .2, 1); will-change: transform; }
.hero-slide { position: relative; flex: 0 0 100%; height: 100%; overflow: hidden; display: flex; flex-direction: column; justify-content: flex-end; }
.hero-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center 22%; opacity: 0; transition: opacity .7s linear; transform: none; }
.hero-bg.active { opacity: 1; }
/* ============================================================
   首页轮播与页面背景融合（对齐 Solene 方案）：
   清晰海报用 mask 从中下部渐隐到透明，露出背后整页同源模糊壁纸 .page-bg-blur；
   上下是同一张图的清晰/模糊两态，构造上不再靠「取色纯色收尾」硬接，避免横缝。
   .hero-blend 只保留极轻的中性压暗方便底部标题可读，末端归零透明，不再铺实色 --dyn-bg。
   ============================================================ */
.hero-bgwrap {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
  /* mask 挂在不动的外层：视差只作用在内部 .hero-bg，渐隐位置永远钉在海报底边 */
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 40%, rgba(0,0,0,.75) 62%, rgba(0,0,0,.32) 82%, rgba(0,0,0,0) 97%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 40%, rgba(0,0,0,.75) 62%, rgba(0,0,0,.32) 82%, rgba(0,0,0,0) 97%);
}
.hero-shade { position: absolute; inset: 0; z-index: 1; pointer-events: none; background:
  linear-gradient(to bottom, rgba(0,0,0,.28) 0%, transparent 22%); }
/* 底部只做文字可读性压暗，末端透明，把融合交给背后的 page-bg-blur */
.hero-blend {
  position: absolute; left: 0; right: 0; bottom: 0; height: 55%; pointer-events: none; z-index: 1;
  background: linear-gradient(to bottom,
    rgba(0,0,0,0) 0%,
    rgba(0,0,0,.22) 40%,
    rgba(0,0,0,.18) 72%,
    rgba(0,0,0,0) 100%);
}
@media (orientation: landscape) { .hero-blend { height: 44%; } }
.hero-info { position: relative; z-index: 1; padding: 0 20px 36px; text-align: center; }

/* ============================================================
   整页「毛玻璃壁纸」背景：position:fixed 常驻整个视口，不随内容滚动，
   用当前 hero 海报本身的模糊放大图铺满——往下滚到「继续观看」「推荐」再远也不会露出一块
   跟海报毫无关系的生硬纯色，感觉像是同一张图一直延伸到底。
   多张图层按 hero 逻辑序号一一对应、opacity 交叉淡入淡出，跟 .hero-bg 的切换完全同步
   （见 renderHeroSlides / setHeroImageActive 里对 _blurImgMap 的同步处理）。
   inset:-10%/120% 是让图片比视口本身大一圈再模糊——模糊半径会啃掉图片自身边缘，
   不放大会在四周露出一圈"没被模糊糊到"的生硬直边。
   叠一层 --dyn-bg-rgb 半透明色，把偏色/发灰的截图往当前主色上收一收，暗部也压深些方便叠文字。
   只在首页显示（进分类/搜索/详情等其它视图时 setPageBgBlurVisible(false) 淡出），
   避免"浏览蜗牛动漫分类，背景却还是别的电影海报"这种不搭边的观感。 */
.page-bg-blur { position: fixed; inset: 0; z-index: 0; overflow: hidden; background: var(--dyn-bg, #050507);
  pointer-events: none; opacity: 1; transition: opacity .45s ease; }
.page-bg-blur.hidden { opacity: 0; }
/* 与清晰海报同一锚点 center 22%；半径/饱和度对齐 Solene 的 app-wall，保证 mask 渐隐区露出的是同一构图的模糊延续 */
.page-bg-blur-img { position: absolute; inset: -14%; width: 128%; height: 128%; object-fit: cover; object-position: center 22%;
  opacity: 0; filter: blur(36px) saturate(1.35) brightness(0.58); transition: opacity .7s linear; transform: translateZ(0); will-change: opacity; }
.page-bg-blur-img.active { opacity: 1; }
.page-bg-blur::after { content: ""; position: absolute; inset: 0; z-index: 5; background: rgba(0,0,0,.34); pointer-events: none; }
/* TV 模式一贯把大尺寸滤镜/合成砍到最低（遥控器场景，性能优先），这层常驻的高斯模糊直接关掉退回纯色 */
.tv-mode .page-bg-blur-img { display: none; }
@media (prefers-reduced-motion: reduce) { .page-bg-blur-img, .page-bg-blur { transition: none; } }

/* ============================================================
   首页轮播「异步滑动」视差（自 emby 首页移植）
   目标：下滑时只有海报图(.hero-bg)慢半拍上移，.hero-shade / .hero-blend / .hero-info
   全部保持页面常速、和下面的内容行一起走 —— 融合渐变便会自下而上把慢下来的海报逐渐"淹没"，
   出现景深分层感；而信息文字始终贴着内容，不会脱节割裂。

   为什么用滚动驱动动画(animation-timeline)而不是 JS 监听 scroll 写 transform：
   滚动本身跑在合成器线程，JS 改 transform 跑在主线程，海报位置永远比内容慢一帧 → 肉眼可见抖动，
   这是原理性的，调参数消不掉。绑到滚动时间轴上则整条动画由浏览器在合成器线程驱动，与滚动同帧。

   ⚠ 两个坑（都已避开）：
   1) 时间轴用 scroll(root block) —— 本页是「整个窗口」在滚（window.scrollTo/pageYOffset），
      根滚动器就是文档。这里绝不能用 scroll(nearest)：.hero 和 .hero-slide 都带 overflow:hidden，
      它们本身就算"滚动容器"，nearest 会命中它们，而它们根本不滚 → 进度恒为 0 → 完全没效果。
   2) 位移只加在 .hero-bg 上，绝不碰 .hero-track —— 那一层的 transform 是轮播左右翻页在用的，
      动它会把轮播搞坏。
   ============================================================ */
@supports (animation-timeline: scroll()) {
  /* 动画区间要知道 hero 实际高度：用与 .hero 完全相同的算式复刻（含 min/max-height → clamp） */
  .hero { --hero-h: clamp(340px, 58vh, 560px); }
  @media (orientation: landscape) { .hero { --hero-h: clamp(280px, 85vh, 560px); } }
  @media (min-width: 600px) and (orientation: portrait) { .hero { --hero-h: clamp(340px, 66vh, 720px); } }

  /* 海报：慢速下压(视差) + 极轻微推近(景深)。整条动画在合成器上跑，带 scale 也依然丝滑 */
  @keyframes heroParallax {
    /* scale 始终 ≥1.12，保证下移时上下不露空；位移收小，减轻回顶卡半截 */
    from { transform: translate3d(0, 0, 0) scale(1.12); }
    to   { transform: translate3d(0, calc(var(--hero-h, 58vh) * .22), 0) scale(1.18); }
  }
  /* 信息层：前 30% 完全不动、保持清晰，之后随滚动优雅淡出（只改透明度、不改位移，
     所以依旧与内容同速，不会重现"脱节"的割裂感） */
  @keyframes heroInfoFade {
    0%, 30% { opacity: 1; }
    100%    { opacity: 0; }
  }
  /* 注意声明顺序：animation 简写会把 animation-timeline 重置为 auto，
     所以 animation-timeline / animation-range 必须写在简写「之后」，否则又变成不动。 */
  /* 海报不再做位移视差：安卓 WebView 回顶时 scroll-driven transform 易卡在中间态，
     表现为「半截海报」，再滑一下又恢复。信息层淡出仍保留。 */
  .hero-bg {
    animation: none !important;
    transform: none !important;
    will-change: auto;
    backface-visibility: hidden;
  }
  .hero-info {
    animation: heroInfoFade linear both;
    animation-timeline: scroll(root block);
    animation-range: 0px calc(var(--hero-h, 58vh) * .78);
  }
  @media (prefers-reduced-motion: reduce) {
    .hero-bg { animation: none; }
    .hero-info { animation: none; opacity: 1; }
  }
}
.hero-title-wrap {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  position: relative; width: 100%; min-height: 1.08em;
}
.hero-title { font-size: 30px; font-weight: 900; letter-spacing: -.02em; line-height: 1.08; text-shadow: 0 2px 18px rgba(0,0,0,.55); max-width: 90%; margin: 0 auto 10px; text-align: center; }
@keyframes logoRiseIn {
  from { opacity: 0; transform: translateY(22px) scale(.96); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
/* 与详情页 .ed-logo img 同一套自下而上弹出；居中不参与横向排版，避免和标题并排导致左移 */
.hero-logo {
  display: block; max-width: min(750px, 74%); max-height: 84px; width: auto; height: auto;
  margin: 0 auto 12px; object-fit: contain; filter: drop-shadow(0 4px 16px rgba(0,0,0,.6));
  animation: logoRiseIn .58s cubic-bezier(.22, 1.15, .36, 1) both;
}
@media (prefers-reduced-motion: reduce) { .hero-logo { animation: none; } }
.hero-meta { display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; font-size: 13px; color: var(--ink-dim); text-shadow: 0 1px 6px rgba(0,0,0,.6); }
.hero-meta { color: #d8def0; }
.hero-ov { margin: 9px auto 0; font-size: 13px; color: #c7cddf; line-height: 1.55; max-width: 94%; text-shadow: 0 1px 6px rgba(0,0,0,.6); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; }
/* 横版（手机横屏）时轮播信息改左对齐：标题、徽标、元信息、简介都靠左，不再居中，
   跟竖版是两套独立的对齐方式，互不影响。 */
@media (orientation: landscape) {
  .hero-info { text-align: left; }
  .hero-title-wrap { align-items: flex-start; }
  .hero-title { margin: 0 0 10px; max-width: 60%; text-align: left; }
  .hero-logo { margin: 0 0 12px; }
  .hero-meta { justify-content: flex-start; }
  .hero-ov { margin: 9px 0 0; max-width: 60%; }
}
/* 轮播指示器（圆点） */
.hero-dots { position: absolute; left: 0; right: 0; bottom: 13px; z-index: 4; display: flex; align-items: center; justify-content: center; gap: 6px; pointer-events: none; }
.hero-dots:empty { display: none; }
.hero-dot { width: 6px; height: 6px; border-radius: 50%; background: rgba(255,255,255,.4); box-shadow: 0 1px 4px rgba(0,0,0,.4); transition: width .25s ease, background-color .25s ease, opacity .25s ease; }
.hero-dot.on { width: 16px; background: #fff; }
.chips { position: fixed; left: 50%; bottom: calc(10px + var(--safe-bottom)); transform: translateX(-50%);
  width: auto; max-width: 94%; display: inline-flex; align-items: center; gap: 2px; justify-content: center; z-index: 45;
  background: rgba(18, 26, 54, 0.62); -webkit-backdrop-filter: blur(24px) saturate(1.7); backdrop-filter: blur(24px) saturate(1.7);
  border: 1px solid rgba(160, 190, 255, 0.16); border-radius: 999px; padding: 5px 7px; overflow: visible;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.42), inset 0 1px 0 rgba(255, 255, 255, 0.10);
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.chip { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  padding: 7px 22px; border-radius: 999px; background: none; border: 0; color: var(--ink-dim); font-size: 10px; font-weight: 700; white-space: nowrap; transition: color .16s, background .16s;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
.chip .chip-ico { width: 23px; height: 23px; display: block; }
.chip[data-nav="settings"] .chip-ico { width: 22px; height: 22px; }
.chip.active { background: var(--accent-soft); color: var(--accent); }
.chip:active { transform: scale(.94); }
.tv-mode .chip.focus, .tv-mode .chip:focus { transform: scale(1.08); }
/* 给内容留出底栏空间；详情/设置打开时隐藏底栏 */
main { padding-bottom: calc(78px + var(--safe-bottom)); }
body.detail-active .chips { display: none; }
/* 「查看全部」/最近观看：二级页不需要底栏导航，腾出空间 */
body.browse-active .chips { display: none; }
body.browse-active main { padding-bottom: calc(16px + var(--safe-bottom)); }
.chips::-webkit-scrollbar { display: none; }
/* 二级类型筛选 chips：横向滑动这里不再自己用 JS 接管 touchmove 手搓惯性/橡皮筋——
   之前 touch-action: none 会把这块区域的滚动完全交给 JS 主线程处理，每一帧 touchmove
   都要走一遍 JS（还强制 preventDefault），走不了浏览器/系统那条硬件加速的合成线程滚动
   通道，参数调得再准也比不过原生滚动的跟手度，低端设备上还会明显掉帧、延迟，这才是
   "不灵敏"的根子，不是触摸区域大小的问题。
   改成 touch-action: pan-x：告诉浏览器"这个元素只接管横向平移手势"，横向滑动直接走原生
   滚动（自带真实的惯性衰减和越界橡皮筋回弹，观感就是 iOS 原生的样子），竖直方向的手势
   不被这里拦截，会正常冒泡去滚整个页面，不会出现"划到这排标签就滑不动整页"的问题。 */
/* 查看全部页 tab 栏：必须能手指横滑浏览标签。
   注意：justify-content:flex-end 在不少 Android WebView 里会让 overflow-x 滚动"假死"
   （内容贴右、scrollWidth 算得出但拖不动），所以改 flex-start；标签多时从左往右排，
   需要看后面的标签就横滑。sticky 顶栏 + backdrop-filter 偶发合成层 bug，给滚动容器
   单独建层（translateZ）提高可滚概率。 */
.cat-head { overflow: hidden; }
.genre-chips {
  display: flex; flex: 1 1 auto; min-width: 0; max-width: 100%;
  justify-content: flex-start;
  overflow-x: auto; overflow-y: hidden;
  white-space: nowrap; margin-left: 8px; padding: 2px 0;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
  touch-action: pan-x; overscroll-behavior-x: contain;
  position: relative; z-index: 1;
  -webkit-transform: translate3d(0,0,0); transform: translate3d(0,0,0);
  will-change: transform;
}
.genre-chips.rubber-snap {
  transition: transform .45s cubic-bezier(.22, 1.15, .36, 1);
}
.genre-chips::-webkit-scrollbar { display: none; }
.genre-chips:empty { display: none; margin: 0; }
.genre-chip { -webkit-user-select: none; user-select: none; }
.genre-chip { flex: 0 0 auto; margin-right: 6px; padding: 4px 11px; border-radius: 8px; font-size: 12px; background: rgba(255,255,255,.05); border: 1px solid var(--line); color: var(--ink-dim); }
.genre-chip.active { background: var(--accent-soft); border-color: var(--accent-line); color: var(--ink); font-weight: 600; }
/* 搜索结果站源筛选栏复用 .genre-chip，额外挂一个计数徽标（如截图里"全部 75"那种圆角数字）。
   分组标题 .search-group-title 直接放进 #grid 里，用 grid-column:1/-1 撑满整行，
   不需要另起一个网格容器——分组之间共用同一个网格的列宽/间距，视觉上更连贯。 */
.genre-chip .chip-count { margin-left: 5px; font-size: 10.5px; font-weight: 700; line-height: 15px; min-width: 15px;
  display: inline-block; text-align: center; padding: 0 5px; border-radius: 999px; background: rgba(255,255,255,.12); color: inherit; }
.genre-chip.active .chip-count { background: rgba(0,0,0,.18); }
.search-group-title { grid-column: 1 / -1; display: flex; align-items: baseline; gap: 8px;
  font-size: 15px; font-weight: 700; color: var(--ink); margin: 18px 0 6px; padding: 8px 2px 6px;
  border-bottom: 1px solid var(--line); }
.search-group-title:first-child { margin-top: 2px; }
.search-group-title .cnt { font-size: 12px; font-weight: 500; color: var(--ink-dim); }
.card .card-src { font-size: 11px; font-weight: 600; color: var(--accent); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 区块 */
.section { padding: 12px 0 0; }
.section-head { display: flex; align-items: center; margin-bottom: 10px; padding: 0 var(--gut); }
.section-title { display: none; }
.section-sub { display: none; }
.clear-search { flex: 0 0 auto; width: 26px; height: 26px; margin-left: 2px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel); border: 1px solid var(--line); color: var(--ink-faint);
  -webkit-tap-highlight-color: transparent; transition: background .15s ease, border-color .15s ease, color .15s ease; }
.clear-search:active { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
.clear-search svg { display: block; }

.rail { display: flex; gap: 6px; overflow-x: auto; white-space: nowrap; padding-bottom: 4px; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.rail::-webkit-scrollbar { display: none; }
.rail .card { flex: 0 0 auto; width: 132px; margin-right: 0; white-space: normal; }

.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--card-gut); margin: 0; padding: 0 var(--card-gut); align-items: start; width: 100%; min-width: 0; overflow: hidden; }
/* 左右滑动切换分类/筛选标签时，新内容的方向性动画（见 gridSwipeAnim）。
   之前用多阶段关键帧模拟"弹簧回弹"，位移会先冲过头再往回缩一点，视觉上是内容在原地
   小幅度弹跳/抖动，不是真的"流动过来"的感觉，观感反而更别扭。
   现在改回最直接的思路：内容整体从滑动方向的那一侧，用单段纯位移 + 减速缓动
   （不过冲、不回弹）滑到位——手指往左划，新内容就从右边平滑流进来；往右划，
   就从左边流进来。没有缩放、没有透明度变化，只有一次干净利落的横向位移，
   最贴近"内容左右流动过来"这种直观的滑动手感。 */
@keyframes gridSwipeInL { from { transform: translateX(64px); } to { transform: translateX(0); } }
@keyframes gridSwipeInR { from { transform: translateX(-64px); } to { transform: translateX(0); } }
.grid.grid-swipe-l { animation: gridSwipeInL .36s cubic-bezier(.22, 1, .36, 1); will-change: transform; }
.grid.grid-swipe-r { animation: gridSwipeInR .36s cubic-bezier(.22, 1, .36, 1); will-change: transform; }
@media (prefers-reduced-motion: reduce) { .grid.grid-swipe-l, .grid.grid-swipe-r { animation: none; } }
.grid .card { width: auto; max-width: none; min-width: 0; margin: 0; box-sizing: border-box; }

.poster { position: relative; width: 100%; padding-top: 150%; border-radius: 12px; overflow: hidden; background: linear-gradient(135deg, rgba(255,255,255,.06), rgba(255,255,255,.02)); border: 1px solid var(--line); box-shadow: 0 4px 12px rgba(8,24,64,.38); }
/* 未加载完 / 加载失败时不露出浏览器裂图：失败图用 display:none，成功前半透明 */
.poster img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .18s ease; }
.poster img.is-ready { opacity: 1; }
.poster img.is-fail { display: none !important; opacity: 0; }
.poster .ph { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; color: var(--ink-faint); font-size: 13px; font-weight: 600; text-align: center; padding: 8px; letter-spacing: .04em; z-index: 0; }
.poster .ph.ph-title { font-size: 15px; font-weight: 700; line-height: 1.35; padding: 10px 12px; white-space: normal; word-break: break-word; text-align: center; }
.poster .ph.ph-title.ph-bundle { font-size: 14px; font-weight: 700; }
.card-del { position: absolute; top: 5px; right: 5px; width: 19px; height: 19px; border-radius: 50%; border: none; background: rgba(0,0,0,.55); color: #fff; font-size: 10px; line-height: 1; display: flex; align-items: center; justify-content: center; z-index: 3; -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
.card-del:active { background: var(--bad, #ff5c66); }
.recent-clear-btn { margin-left: auto; width: 34px; height: 34px; border-radius: 10px; }
.recent-clear-btn:active { background: rgba(255,92,102,.14); border-color: rgba(255,92,102,.5); color: var(--bad, #ff5c66); }
.badge { position: absolute; top: 7px; left: 7px; padding: 2px 7px; border-radius: 6px; background: var(--badge-bg); border: 1px solid var(--badge-border); color: var(--accent-ink); font-size: 9.5px; font-weight: 800; letter-spacing: .02em; box-shadow: 0 2px 8px var(--badge-shadow); }
.card-title { margin-top: 8px; font-size: 14px; font-weight: 700; letter-spacing: -.2px; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card-meta { display: none; }
.card { transition: transform .12s ease; }
.tv-mode .card.focus { transform: scale(1.06); }

.notice { margin: 12px 16px; padding: 16px; background: var(--panel-soft); border: 1px solid var(--line); border-radius: var(--radius); }
.notice h4 { margin: 0 0 6px; font-size: 14px; }
.notice p { margin: 0 0 10px; font-size: 13px; color: var(--ink-dim); }
.notice .link { color: var(--accent); font-weight: 700; }
.loading-row { padding: 26px 16px; text-align: center; color: var(--ink-faint); font-size: 13px; }

/* 详情 / 资源浮层 —— 满幅海报英雄区（参考 HBO/Emby）
   打开/关闭走苹果风格的弹性过渡：sheet 本身只负责整体淡入淡出 + 可见性开关
  （不能给 .sheet 自己加 transform，它内部 .ed-hero 是 position:fixed 贴合视口的背景层，
   一旦祖先元素有了 transform 就会变成新的包含块，.ed-hero 会跟着祖先一起动而不是贴着视口，
   动画过程中背景会明显错位跳动）；.ed-hero 自己也只淡入淡出（opacity），不能再给它加
   transform —— 它的子层 .ed-hero-blend 用了 backdrop-filter 模糊，只要“背景模糊层的祖先”
   在做 transform 动画，模糊层的合成边界每帧都要重新采样，很容易撑不住，表现为开合时闪几下
   白块、甚至整个过渡看着像被跳过、瞬间完成。真正需要放大回弹手感的，放到 .ed-hero-imgs
  （纯图片层，没有 backdrop-filter 后代）上就安全了；.ed-body 同理没有 fixed/模糊后代，
   可以放心加 transform。 */
.sheet { position: fixed; top: 0; right: 0; bottom: 0; left: 0; inset: 0; z-index: 60; background: transparent; overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior-y: contain;
  visibility: hidden; opacity: 0; pointer-events: none;
  transition: opacity .22s ease, visibility 0s linear .3s; }
.sheet.active { visibility: visible; opacity: 1; pointer-events: auto; transition: opacity .26s ease; }
.sheet .ed-hero { opacity: 0; transition: opacity .3s ease; }
.sheet.active .ed-hero { opacity: 1; transition: opacity .34s ease; }
.sheet .ed-hero-imgs { transform: scale(1.05); transition: transform .3s ease; }
.sheet.active .ed-hero-imgs { transform: scale(1); transition: transform .5s cubic-bezier(.22, 1, .36, 1); }
.sheet .ed-body { transform: translateY(26px); transition: transform .26s ease; }
.sheet.active .ed-body { transform: translateY(0); transition: transform .48s cubic-bezier(.34, 1.56, .64, 1); }
body.detail-active .app { visibility: hidden; pointer-events: none; }
body.detail-active { background: var(--ed-bg, var(--sheet-bg)); transition: background-color 1.1s ease; }

.ed-hero { position: fixed; inset: 0; z-index: -2; overflow: hidden; background: var(--ed-bg, #070b1a); transform: translateZ(0); backface-visibility: hidden; }
.ed-hero-imgs { position: absolute; inset: 0; }
.ed-hero-imgs img { position: absolute; inset: -1px; width: calc(100% + 2px); height: calc(100% + 2px); object-fit: cover; object-position: center 18%;
  transform: translateZ(0); backface-visibility: hidden; opacity: 0; transition: opacity 1.1s ease, filter .2s linear; }
.ed-hero-imgs img.active { opacity: 1; }
/* 去掉默认呼吸放大；仅入场淡入。纵深感改由滚动驱动 #edHeroImgs 的 scale/translate */
.ed-hero-imgs img.active.first-in { animation: heroIn 0.9s cubic-bezier(.2,.7,.2,1) forwards; }
@keyframes heroIn { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .ed-hero-imgs img.active, .ed-hero-imgs img.active.first-in { animation: none; } }
#edHeroImgs { will-change: transform, filter; transform-origin: center 30%; }
.ed-hero.contain .ed-hero-imgs img { object-fit: contain; object-position: center top; }
/* 贴底那截跟首页轮播同一套思路：颜色不再写死 rgba(6,5,10,.85)，改用当前海报自动取色算出来的
   --ed-bg-rgb / --ed-bg，让详情页背景也跟着每张海报的主色走，不再是固定藏青色兜底。
   没算出颜色前用 6,5,10 / var(--sheet-bg) 兜底，跟改之前效果一致，不会有空档。
   之前这里用 radial-gradient（椭圆，中心在顶部）来同时兼顾顶部轻微压暗和底部融合，
   代价是椭圆形状离中心越远（也就是画面两侧靠下的角落）衰减越快，中间又相对"漏"得更久，
   肉眼看上去底部是一个"U 型"的糊/暗区，跟首页轮播那种不分左右、只看高度的"平行"糊
   完全是两套观感，而且这一层本身根本没用 backdrop-filter，只是纯色渐变压暗，压根没有模糊。
   这里拆成两层，跟首页 .hero-shade / .hero-blend 的结构一一对应：
   ed-hero-shade 只负责顶部一丝丝压暗（不模糊，纯黑到透明，跟首页 hero-shade 的顶部渐变同理），
   ed-hero-blend 负责底部——真正用 backdrop-filter 把背后的海报本身模糊掉，再叠一层从透明到
   实色的动态色渐变，且渐变方向是 to bottom（水平等高线，不分左右），这样详情页底部就和
   首页轮播的底部融合是同一种"平行模糊"，不再是圆形衰减出来的 U 型效果。 */
.ed-hero-shade { position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to bottom, rgba(0,0,0,.32) 0%, rgba(0,0,0,.08) 18%, transparent 30%); }
/* 底部融合改成"渐变模糊"：单层 backdrop-filter 的模糊强度是均匀的，看着就是一整块糊。
   这里叠 3 层，每层模糊强度不同、且用 mask 限制在不同高度带——顶部只有最轻的一层生效，
   越往下越重的层依次叠加，于是模糊从上到下由轻到重平滑过渡（顶部几乎不糊、贴底最糊）。
   色彩渐变（把底部染成背景色、和下方页面连成一片）单独放在 .ed-hero-blend 自己身上。 */
.ed-hero-blend {
  /* 雾化高度略收：从 72% 收到约一半，多露一点海报主体 */
  position: absolute; left: -1px; right: -1px; bottom: -1px; height: 48%; z-index: 1; pointer-events: none;
  transform: translateZ(0); backface-visibility: hidden;
  background: linear-gradient(to bottom,
    rgba(var(--ed-bg-rgb, 6,5,10), 0) 0%,
    rgba(var(--ed-bg-rgb, 6,5,10), .14) 18%,
    rgba(var(--ed-bg-rgb, 6,5,10), .42) 38%,
    rgba(var(--ed-bg-rgb, 6,5,10), .78) 58%,
    rgba(var(--ed-bg-rgb, 6,5,10), 1) 78%,
    rgba(var(--ed-bg-rgb, 6,5,10), 1) 100%);
}
/* 三层模糊：轻(顶)、中、重(底)，各自 mask 到不同区间（随高度缩短同比收紧） */
.ed-hero-blend::before, .ed-hero-blend::after, .ed-blur-mid {
  content: ""; position: absolute; inset: 0; pointer-events: none; transform: translateZ(0); backface-visibility: hidden;
}
.ed-hero-blend::before {   /* 轻模糊，从顶部淡入 */
  -webkit-backdrop-filter: blur(8px) saturate(1.08); backdrop-filter: blur(8px) saturate(1.08);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,.45) 16%, #000 42%, #000 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,.45) 16%, #000 42%, #000 100%);
}
.ed-blur-mid {             /* 中模糊，中下段 */
  -webkit-backdrop-filter: blur(20px) saturate(1.1); backdrop-filter: blur(20px) saturate(1.1);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, transparent 28%, rgba(0,0,0,.55) 48%, #000 68%, #000 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, transparent 28%, rgba(0,0,0,.55) 48%, #000 68%, #000 100%);
}
.ed-hero-blend::after {    /* 重模糊，贴底 */
  -webkit-backdrop-filter: blur(40px) saturate(1.14); backdrop-filter: blur(40px) saturate(1.14);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, transparent 50%, rgba(0,0,0,.55) 70%, #000 88%);
  mask-image: linear-gradient(to bottom, transparent 0%, transparent 50%, rgba(0,0,0,.55) 70%, #000 88%);
}
.ed-hero-spacer { width: 100%; height: 68vh; min-height: 380px; }
@media (orientation: landscape) { .ed-hero-spacer { height: 81vh; min-height: 320px; } }
/* 横屏时屏幕更矮更宽，原来 72% 高度的模糊区域相对占比更大，容易糊到人脸。
   这里单独把横屏下的模糊层调矮一些、往下移，渐变/遮罩的比例是跟着这个高度百分比自动收缩的，
   所以只是模糊起始的位置下移了，不影响下面页面信息（spacer 高度没变，内容位置不动）。 */
@media (orientation: landscape) { .ed-hero-blend { height: 55%; } }

.ed-back { position: fixed; top: calc(var(--safe-top) + 8px); left: 14px; z-index: 3;
  width: 40px; height: 40px; border-radius: 50%; font-size: 24px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  background: rgba(7,11,26,.5); color: #fff; border: 1px solid rgba(160,190,255,.22);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
.ed-logo { width: 100%; text-align: center; margin: -104px 0 14px; position: relative; z-index: 3; }
.ed-logo:empty { display: none; }
.ed-logo img { display: inline-block; max-width: 72%; max-height: 78px; width: auto; height: auto; filter: drop-shadow(0 3px 14px rgba(0,0,0,.7));
  animation: logoRiseIn .58s cubic-bezier(.22, 1.15, .36, 1) both; }
@media (prefers-reduced-motion: reduce) { .ed-logo img { animation: none; } }

.ed-body { position: relative; z-index: 2; margin-top: -60px; padding: 0 18px calc(var(--safe-bottom) + 26px);
  display: flex; flex-direction: column; align-items: center; text-align: center; }
.ed-title { font-size: 30px; font-weight: 900; line-height: 1.14; letter-spacing: -.02em; margin-bottom: 13px; text-shadow: 0 2px 20px rgba(0,0,0,.75); }
.ed-title.hidden { display: none; }

.ed-chips { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; margin-bottom: 2px; }
.ed-chips .t { display: inline-flex; align-items: center; margin: 0 0 6px; padding: 0; border: 0; background: none;
  font-size: 12.5px; font-weight: 600; letter-spacing: .03em; color: var(--ink-dim); }
.ed-chips .t:not(:last-child)::after { content: "\2022"; margin: 0 6px; color: var(--ink-faint); font-size: 10px; }
.ed-chips .t.cert { color: var(--ink); font-weight: 700; padding: 2px 7px; border: 1px solid rgba(255,255,255,.32); border-radius: 3px; letter-spacing: .04em; }

.ed-play { width: 100%; max-width: 320px; margin: 2px 0 0; padding: 11px; border-radius: 14px;
  background: var(--grad); color: var(--accent-ink); font-weight: 800; font-size: 16px;
  display: flex; align-items: center; justify-content: center;
  -webkit-mask-image: -webkit-radial-gradient(white, black);
  transform: translateZ(0); -webkit-transform: translateZ(0);
  backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.ed-play .tri { font-size: 13px; margin-right: 10px; color: inherit; transition: color .25s ease; }
/* 至少一条有效可播资源就绪：播放三角变绿 */
.ed-play.has-valid .tri { color: var(--ok); text-shadow: 0 0 8px rgba(75, 208, 138, .45); }
.ed-play:active { transform: scale(.99) translateZ(0); }
/* 预告片：主播放按钮的次要形态，描边 + 透明底，不与主按钮抢视觉 */
.ed-play-ghost { margin-top: 8px; background: transparent; color: var(--ink); border: 1px solid var(--accent); font-weight: 700; font-size: 15px; }
.ed-play-ghost .tri { color: var(--accent); }
.ed-play-ghost:active { opacity: .8; }
.ed-play[disabled] { opacity: .55; }
.ed-play[disabled] .tri { color: inherit; text-shadow: none; }
.tv-mode .ed-play.focus, .tv-mode .ed-play:focus { transform: scale(1.05); }

.ed-actions { display: flex; justify-content: center; align-items: center; margin: 8px 0 2px; }
.ed-ico { display: flex; align-items: center; justify-content: center; width: 44px; height: 40px; margin: 0 18px; font-size: 20px; color: var(--ink-dim);
  transition: transform .12s ease, color .15s ease; }
.ed-ico svg { width: 20px; height: 20px; display: block; }
.ed-ico.on { color: #ff5d8f; }
.ed-ico:active { transform: scale(.88); }
.tv-mode .ed-ico.focus, .tv-mode .ed-ico:focus { transform: scale(1.2); }

.overview { margin: 8px 2px 2px; font-size: 14px; color: var(--ink-dim); line-height: 1.7; text-align: left; align-self: stretch; position: relative; }
/* 有内容/骨架时固定约 4 行高度，避免加载时整页上下跳；空则彻底收起（AV 站不展示简介） */
.overview:not(:empty) { min-height: calc(1.7em * 4); }
.overview:empty { display: none; margin: 0; min-height: 0; padding: 0; }
.overview.clamp { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.overview.clamp:empty { display: none; }
.ed-title { min-height: 1.14em; }
.ed-chips { min-height: 28px; }
.ed-play { min-height: 44px; }
.ed-actions { min-height: 40px; }
.pan-head { min-height: 36px; }
.pan-list { min-height: 168px; } /* 约 3~4 条资源位，加载时不把底栏顶来顶去 */
.ed-cast { min-height: 0; }
.ed-cast:not(:empty) { min-height: 72px; }
.ed-episodes:not(:empty) { min-height: 120px; }
/* 详情打开瞬间的整页骨架：占住版面，减少异步块陆续插入时的跳动 */
.ed-body.ed-loading .overview,
.ed-body.ed-loading .pan-list { opacity: .95; }

/* 横版详情页简介也改居中，跟标题/元信息等其它横版居中的区块保持一致 */
@media (orientation: landscape) { .overview { text-align: center; } }

/* 演职员（TMDB） */
.ed-cast { align-self: stretch; margin: 10px 0 0; }
.ed-cast:empty { display: none; margin: 0; min-height: 0; padding: 0; }
/* AV（JAVDB / JavRanking）详情：不展示简介/演员，去掉可能残留的占位间距 */
.ed-body.ed-av .overview,
.ed-body.ed-av .ed-cast,
.ed-body.ed-av .ed-works,
.ed-body.ed-av .ed-episodes { display: none !important; margin: 0 !important; min-height: 0 !important; padding: 0 !important; }
/* 黄果/黄豆短剧：藏简介与演员，但保留选集列表 */
.ed-body.ed-short .overview,
.ed-body.ed-short .ed-cast,
.ed-body.ed-short .ed-works { display: none !important; margin: 0 !important; min-height: 0 !important; padding: 0 !important; }
.ed-cast-head { font-size: 15px; font-weight: 700; margin: 0 0 9px; }
.ed-cast-row { display: flex; align-items: stretch; overflow-x: auto; white-space: nowrap; -webkit-overflow-scrolling: touch; scrollbar-width: none; padding: 4px 18px; margin: 0 -18px; }
.ed-cast-row::-webkit-scrollbar { display: none; }
.cast-cell { flex: 0 0 auto; max-width: 240px; margin-right: 12px; display: flex; align-items: center; gap: 11px; text-align: left; background: transparent; border: 1px solid var(--line); border-radius: 999px; padding: 2px 18px 2px 6px; }
.cast-av { flex: 0 0 auto; width: 48px; height: 48px; border-radius: 50%; overflow: hidden; background: var(--panel-soft); border: none; position: relative; }
.cast-cell.tappable { cursor: pointer; }
.cast-cell.sel { border-color: var(--accent); animation: castSelBreathe 2.2s ease-in-out infinite; }
@keyframes castSelBreathe {
  0%, 100% { box-shadow: 0 0 0 1px var(--accent-soft), inset 0 0 10px 0 var(--accent-soft); }
  50% { box-shadow: 0 0 0 1px var(--accent-line), inset 0 0 16px 2px var(--accent-soft); }
}
.cast-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cast-av.ph { display: flex; align-items: center; justify-content: center; color: var(--ink-faint); font-size: 20px; font-weight: 800; }
.cast-info { min-width: 0; flex: 1 1 auto; }
.cast-name { font-size: 13.5px; font-weight: 700; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cast-orig { margin-top: 2px; font-size: 11px; color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cast-role { margin-top: 2px; font-size: 11px; color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 演员相关作品（展开横排） */
.ed-works { align-self: stretch; }
.ed-works:empty { display: none; }
.ed-works-head { font-size: 13px; font-weight: 700; color: var(--accent); margin: 14px 0 9px; }
.ed-works-row { display: flex; align-items: flex-start; overflow-x: auto; white-space: nowrap; -webkit-overflow-scrolling: touch; scrollbar-width: none; padding: 0 18px; margin: 0 -18px; }
.ed-works-row::-webkit-scrollbar { display: none; }
.work-cell { flex: 0 0 auto; width: 104px; margin-right: 11px; text-align: left; }
.work-poster { position: relative; width: 104px; height: 156px; border-radius: 10px; overflow: hidden; background: var(--panel-soft); border: 1px solid var(--line); box-shadow: 0 6px 18px rgba(8,24,64,.45); }
.work-poster img { width: 100%; height: 100%; object-fit: cover; display: block; }
.work-title { margin-top: 7px; font-size: 12px; line-height: 1.3; color: var(--ink-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tv-mode .work-cell.focus .work-poster { transform: scale(1.06); }

/* 搜索联想下拉 */
.search-box { position: relative; }
.search-suggest { position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 40; max-height: 60vh; overflow-y: auto;
  background: var(--panel-strong); border: 1px solid var(--line); border-radius: 12px; padding: 6px; box-shadow: 0 18px 44px rgba(0,0,0,.5);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
.search-suggest:empty { display: none; }
.sug-item { display: flex; align-items: center; padding: 6px; border-radius: 9px; }
.sug-item:active { background: var(--accent-soft); }
.sug-pos { flex: 0 0 auto; width: 34px; height: 50px; border-radius: 6px; overflow: hidden; background: var(--panel-soft); margin-right: 10px; }
.sug-pos img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sug-body { min-width: 0; flex: 1 1 auto; }
.sug-title { font-size: 13.5px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sug-meta { font-size: 11px; color: var(--ink-faint); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sug-empty { padding: 10px 8px; font-size: 12px; color: var(--ink-faint); }
.ed-qtabs { display: flex; flex: 1 1 auto; min-width: 0; flex-wrap: nowrap; margin: 0 0 0 10px; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.ed-qtabs::-webkit-scrollbar { display: none; }
.ed-qtab { flex: 0 0 auto; white-space: nowrap; margin: 0 6px 0 0; padding: 4px 11px; border-radius: 8px; font-size: 12px; font-weight: 600;
  background: rgba(255,255,255,.06); border: 1px solid var(--line); color: var(--ink-dim); }
.ed-qtab.active { background: var(--grad); color: var(--accent-ink); border-color: transparent; }
/* 该 tab 下有「当前点进站源」的有效资源：用站源色描边提示，不改变默认选中逻辑 */
.ed-qtab.has-origin { border-color: var(--origin-c, var(--accent)); color: var(--origin-c, var(--accent)); background: color-mix(in srgb, var(--origin-c, var(--accent)) 14%, transparent); }
.ed-qtab.has-origin.active { background: var(--grad); color: var(--accent-ink); border-color: transparent; }
.tv-mode .ed-qtab.focus, .tv-mode .ed-qtab:focus { transform: scale(1.08); }

.pan-head { display: flex; align-items: center; align-self: stretch; margin: 14px 0 8px; }
.pan-head .title { font-size: 15px; font-weight: 700; flex: 0 0 auto; }
.pan-head .sub { margin-left: 8px; font-size: 11px; color: var(--ink-faint); }
.pan-list { align-self: stretch; min-height: 40px; }
.btn { padding: 11px 24px; border-radius: 11px; font-size: 14px; font-weight: 700; background: var(--panel-soft); border: 1px solid var(--line); color: var(--ink); text-align: center; }
.btn.primary { background: var(--grad); border-color: transparent; color: var(--accent-ink); box-shadow: 0 4px 16px var(--btn-shadow); }
.btn.danger { background: var(--bad, #ff5c66); border-color: transparent; color: #fff; }
.confirm-sheet { max-width: 320px; text-align: center; }
.confirm-title { margin: 0; font-size: 17px; color: var(--ink); }
.confirm-text { color: var(--ink-dim); font-size: 14px; line-height: 1.6; margin: 8px 0 0; }
.btn:active { transform: scale(.985); }
.tv-mode .btn.focus, .tv-mode .btn:focus { transform: scale(1.05); }

.pan-head { display: flex; align-items: center; margin: 14px 0 8px; }
.pan-head .title { font-size: 15px; font-weight: 700; flex: 0 0 auto; }
.pan-head .sub { margin-left: 8px; font-size: 11px; color: var(--ink-faint); }
.pan-list { min-height: 60px; max-height: 480px; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--line); border-radius: 12px; padding: 8px 6px 8px 8px; background: rgba(255,255,255,.02); }
.pan-list::-webkit-scrollbar { width: 4px; }
.pan-list::-webkit-scrollbar-track { background: transparent; }
.pan-list::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 4px; }
.pan-item { display: flex; align-items: center; padding: 11px 12px; margin-bottom: 8px; background: rgba(var(--panel-rgb), .13); border: 1px solid var(--line); border-radius: 10px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pan-item:last-child { margin-bottom: 0; }
.pan-item:active { background: rgba(var(--panel-rgb), .26); }
.tv-mode .pan-item.focus, .tv-mode .pan-item:focus { transform: scale(1.03); }
.pan-dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; margin-right: 10px; background: var(--gray); }
.pan-dot.ok { background: var(--ok); } .pan-dot.bad { background: var(--bad); }
.pan-dot.locked { background: var(--lock); } .pan-dot.uncertain, .pan-dot.unsupported { background: var(--gray); }
.pan-dot.checking { background: var(--accent); animation: pulse 1s infinite; }
@keyframes pulse { 0%,100%{opacity:.45} 50%{opacity:.9} }
.pan-body { flex: 1 1 auto; min-width: 0; }
.pan-name { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pan-sub { font-size: 11px; color: var(--ink-faint); margin-top: 2px; }
.pan-sub .q { color: #9cc7ff; margin-right: 6px; }
.pan-sub .site-tag { display: inline-block; padding: 0 6px; margin-right: 6px; border-radius: 5px; border: 1px solid; font-size: 10px; font-weight: 800; line-height: 16px; vertical-align: 1px; }
.pan-sub .q-tag { display: inline-block; padding: 0 5px; margin-right: 4px; border-radius: 5px; border: 1px solid; font-size: 10px; line-height: 15px; vertical-align: 1px; font-weight: 700; }
.pan-sub .pwd { margin-right: 6px; }
.pan-sub .st { color: var(--ink-faint); }
.pan-play { flex: 0 0 auto; margin-left: 10px; width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; color: var(--accent); }
.pan-empty, .pan-loading { padding: 22px 14px; text-align: center; color: var(--ink-faint); font-size: 13px; }
/* 详情页骨架屏：概览 / 演员 / 网盘资源在数据到手前先铺占位条 + 流光动效，避免长时间空白或干等文案。
   三处都直接把骨架节点塞进真实容器里（#detailOverview / #edCast / #panList），容器本身没有独立文本节点，
   等真实内容用 textContent= 或 replaceChildren(...) 覆盖时，骨架节点自然被替换掉，不用额外维护显隐状态。 */
.detail-skel-bar { border-radius: 5px; background: rgba(255,255,255,.07);
  background-image: linear-gradient(100deg, rgba(255,255,255,.05) 30%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.05) 70%);
  background-size: 420px 100%; animation: skelShimmer 1.3s linear infinite; }
.ov-skel { display: flex; flex-direction: column; gap: 8px; padding: 2px 0 4px; }
.ov-skel .detail-skel-bar { height: 13px; }
.ov-skel .detail-skel-bar:nth-child(1) { width: 97%; }
.ov-skel .detail-skel-bar:nth-child(2) { width: 89%; }
.ov-skel .detail-skel-bar:nth-child(3) { width: 58%; }
.cast-skel { display: flex; gap: 14px; overflow: hidden; padding: 4px 18px; margin: 0 -18px; }
.cast-skel-item { flex: 0 0 auto; width: 54px; display: flex; flex-direction: column; align-items: center; gap: 7px; }
.cast-skel-item .detail-skel-bar.av { width: 52px; height: 52px; border-radius: 50%; }
.cast-skel-item .detail-skel-bar.nm { width: 40px; height: 9px; }
.pan-skel { display: flex; flex-direction: column; gap: 12px; padding: 14px 2px; }
.pan-skel-item { display: flex; align-items: center; gap: 11px; }
.pan-skel-item .detail-skel-bar.ic { width: 34px; height: 34px; border-radius: 9px; flex: 0 0 auto; }
.pan-skel-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.pan-skel-body .detail-skel-bar.t1 { width: 76%; height: 12px; }
.pan-skel-body .detail-skel-bar.t2 { width: 42%; height: 10px; }
/* 详情页大海报：图还没到手时（站内无海报 / TMDB 图集没回来）铺一块流光占位，不留纯黑/纯色空屏 */
.ed-hero-imgs .ed-hero-img.is-fail,
.ed-hero-imgs .ed-hero-img[src=""],
.ed-hero-imgs img:not([src]) { display: none !important; visibility: hidden !important; }
.ed-hero-imgs .ph { display: none !important; } /* 详情大图区禁止「无封面」文字占位 */
.ed-hero-skel { position: absolute; inset: 0;
  background-image: linear-gradient(100deg, rgba(255,255,255,.03) 30%, rgba(255,255,255,.09) 50%, rgba(255,255,255,.03) 70%);
  background-size: 420px 100%; animation: skelShimmer 1.3s linear infinite; }
/* 「剧集」单集卡骨架：跟 .ep-tcard 同款尺寸（148px 宽 + 16:9 缩略图 + 两行标题），分季/翻季时先垫上 */
.ep-skel-rail { display: flex; gap: 12px; overflow: hidden; padding: 4px 18px 6px; margin: 0 -18px; }
.ep-skel-card { flex: 0 0 auto; width: 176px; }
.ep-skel-card .detail-skel-bar.thumb { width: 176px; aspect-ratio: 16/9; border-radius: 10px; }
.ep-skel-card .detail-skel-bar.line1 { width: 92%; height: 11px; margin-top: 8px; }
.ep-skel-card .detail-skel-bar.line2 { width: 58%; height: 11px; margin-top: 6px; }
.pan-item.pan-hit { animation: panHitFlash 1.6s ease; }
@keyframes panHitFlash {
  0% { background: var(--accent-soft); box-shadow: 0 0 0 2px var(--accent) inset; }
  70% { background: var(--accent-soft); box-shadow: 0 0 0 2px var(--accent) inset; }
  100% { background: rgba(var(--panel-rgb), .13); box-shadow: none; }
}

.ep-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: 8px;
  padding: 2px 0;
  width: 100%;
  max-width: 560px;
  margin-left: auto;
  margin-right: auto;
  box-sizing: border-box;
  justify-items: stretch;
}
.ed-episodes {
  width: 100%;
  max-width: 100%;
  padding-left: max(12px, env(safe-area-inset-left, 0px));
  padding-right: max(12px, env(safe-area-inset-right, 0px));
  box-sizing: border-box;
}
.ed-episodes-head {
  width: 100%;
  max-width: 560px;
  margin-left: auto;
  margin-right: auto;
}
.ep-cell { position: relative; display: flex; align-items: center; justify-content: center; min-height: 46px; padding: 8px 6px; border-radius: 10px; background: rgba(var(--panel-rgb), .16); border: 1px solid var(--line); color: var(--ink); font-size: 14px; font-weight: 600; text-align: center; line-height: 1.15; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: transform .06s ease; }
.ep-cell:active { transform: scale(.94); }
.ep-cell.playing { background: var(--grad); color: var(--accent-ink); border-color: transparent; }
.ep-cell.resolving { color: var(--accent); border-color: var(--accent); }
.ep-cell.bad { opacity: .45; }
.ep-cell .ep-dot { position: absolute; top: 5px; right: 6px; width: 6px; height: 6px; border-radius: 50%; background: transparent; }
.ep-cell .ep-dot.ok { background: var(--ok); } .ep-cell .ep-dot.bad { background: var(--bad); } .ep-cell .ep-dot.checking { background: var(--accent); animation: pulse 1s infinite; }
.tv-mode .ep-cell.focus, .tv-mode .ep-cell:focus { transform: scale(1.08); }

/* 详情页「剧集」区：TMDB 分季 + 单集卡（类似 Emby），放在简介和演职人员之间 */
.ed-episodes { align-self: stretch; margin-top: 4px; width: 100%; box-sizing: border-box;
  padding-left: max(12px, 3.2vw); padding-right: max(12px, 3.2vw); }
.ed-episodes:empty { display: none; }
.ed-episodes-head { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin: 14px auto 9px; width: 100%; max-width: 560px; box-sizing: border-box; }
.ed-episodes-head .ed-works-head { margin: 0; flex: 0 0 auto; font-size: 15px; color: var(--ink); }
.ep-season-tabs { display: flex; flex: 1 1 auto; min-width: 0; gap: 6px; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; justify-content: flex-start; }
.ep-season-tabs::-webkit-scrollbar { display: none; }
.ep-season-chip { flex: 0 0 auto; white-space: nowrap; padding: 5px 13px; border-radius: 999px; font-size: 12px; font-weight: 700;
  background: rgba(255,255,255,.06); border: 1px solid var(--line); color: var(--ink-dim); }
.ep-season-chip.active { background: var(--grad); color: var(--accent-ink); border-color: transparent; }
.tv-mode .ep-season-chip.focus, .tv-mode .ep-season-chip:focus { transform: scale(1.08); }
.ep-rail { display: flex; align-items: flex-start; gap: 12px; overflow-x: auto; white-space: nowrap; -webkit-overflow-scrolling: touch; scrollbar-width: none; padding: 4px 18px 6px; margin: 0 -18px; }
.ep-rail::-webkit-scrollbar { display: none; }
.ep-tcard { flex: 0 0 auto; width: 176px; white-space: normal; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.ep-tcard:active { transform: scale(.98); }
.ep-tcard-img { position: relative; width: 176px; aspect-ratio: 16/9; border-radius: 10px; overflow: hidden; background: var(--panel-soft); border: 1px solid var(--line); }
.no-aspect-ratio .ep-tcard-img { height: 83px; }
.ep-tcard-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ep-tcard-num { position: absolute; left: 6px; bottom: 6px; padding: 1px 7px; border-radius: 6px; background: rgba(0,0,0,.6); color: #fff; font-size: 10.5px; font-weight: 700; }
.ep-tcard-title { margin-top: 6px; font-size: 12px; line-height: 1.35; color: var(--ink-dim); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.tv-mode .ep-tcard.focus .ep-tcard-img, .tv-mode .ep-tcard:focus .ep-tcard-img { transform: scale(1.06); }
.ep-loading { padding: 14px 4px; color: var(--ink-faint); font-size: 13px; white-space: normal; }

/* 设置 —— 居中独立弹出卡片 */
/* 弹窗打开/关闭改成苹果风格的弹性缩放：遮罩只做淡入淡出，.panel-sheet 本身带一点
   过冲的回弹（cubic-bezier 峰值超过 1 再回落），比原来的 display none/flex 硬切换更跟手。 */
.panel-overlay { position: fixed; top: 0; right: 0; bottom: 0; left: 0; inset: 0; z-index: 80; display: flex; align-items: center; justify-content: center; padding: 24px calc(16px + var(--safe-right)) calc(16px + var(--safe-bottom)) calc(16px + var(--safe-left)); background: rgba(8,11,15,.6);
  visibility: hidden; opacity: 0; pointer-events: none;
  transition: opacity .2s ease, visibility 0s linear .26s; }
.panel-overlay.active { visibility: visible; opacity: 1; pointer-events: auto; transition: opacity .22s ease; }
.panel-sheet { position: relative; width: 100%; max-width: 460px; max-height: 100%; background: var(--panel-strong); border: 1px solid var(--line); border-radius: 18px; overflow-y: auto; padding: 18px 16px calc(var(--safe-bottom) + 14px); box-shadow: 0 24px 64px rgba(0,0,0,.5);
  transform: translateY(18px) scale(.94); transition: transform .24s ease; }
.panel-overlay.active .panel-sheet { transform: translateY(0) scale(1); transition: transform .46s cubic-bezier(.34, 1.56, .64, 1); }
.panel-close { position: absolute; top: 14px; right: 14px; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 999px; color: var(--ink-dim); font-size: 16px; line-height: 1; background: rgba(255,255,255,.06); }
.panel-close:active { transform: scale(.88); }
.tv-mode .panel-close.focus, .tv-mode .panel-close:focus { transform: scale(1.15); }
.set-hd { display: flex; align-items: center; margin-bottom: 12px; padding-right: 30px; }
.set-hd h3 { margin: 0; font-size: 17px; color: var(--ink); }
.set-group { background: rgba(255,255,255,.03); border: 1px solid var(--line); border-radius: 13px; padding: 12px 12px 4px; margin-bottom: 10px; }
.set-group-title { font-size: 11px; font-weight: 800; letter-spacing: .1em; color: var(--accent); margin-bottom: 10px; text-transform: uppercase; }
.set-2col { display: flex; margin: 0 -5px; }
.set-2col .field { flex: 1 1 0; min-width: 0; margin: 0 5px 10px; }
.field { margin-bottom: 10px; }
.field label { display: block; font-size: 12px; color: var(--ink-dim); margin-bottom: 5px; }
.field label .hint { color: var(--ink-faint); font-size: 10.5px; font-weight: 400; }
.field input { width: 100%; box-sizing: border-box; padding: 10px 12px; border-radius: 9px; background: rgba(0,0,0,.28); border: 1px solid var(--line); outline: none; color: var(--ink); font-size: 13px; }
.field input:focus, .field input.focus { border-color: var(--accent); }
.pan-type-wrap { display: flex; flex-wrap: wrap; gap: 8px; }
.pan-type-chip { flex: 0 0 auto; padding: 6px 13px; border-radius: 999px; font-size: 12.5px; font-weight: 600; border: 1px solid var(--line); background: rgba(255,255,255,.04); color: var(--ink-faint); }
.pan-type-chip.on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--ink); }
.tv-mode .pan-type-chip.focus, .tv-mode .pan-type-chip:focus { transform: scale(1.08); }
.toggle-row { display: flex; align-items: center; justify-content: space-between; padding: 4px 2px 8px; }
.toggle-row .lbl { font-size: 13.5px; }
.toggle-row .lbl small { display: block; font-size: 11px; color: var(--ink-faint); margin-top: 2px; }
.login-row { display: flex; align-items: center; gap: 10px; margin: 2px 0 10px; }
/* 站源紧凑行：名称 | 域名 | 眼睛（主页显隐） */
.src-list { display: flex; flex-direction: column; gap: 6px; margin: 0 0 8px; }
.src-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.src-row .src-name { flex: 0 0 72px; width: 72px; min-width: 56px; max-width: 88px; padding: 8px 8px; border-radius: 9px; border: 1px solid var(--line); background: var(--panel-soft); color: var(--ink); font-size: 12.5px; font-weight: 700; text-align: center; }
.src-row .src-url { flex: 1 1 auto; min-width: 0; padding: 8px 10px; border-radius: 9px; border: 1px solid var(--line); background: var(--panel-soft); color: var(--ink); font-size: 12.5px; }
.src-row .src-eye { flex: 0 0 34px; width: 34px; height: 34px; border-radius: 9px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--line); background: var(--panel-soft); color: var(--ink-dim); padding: 0; }
.src-row .src-eye svg { width: 16px; height: 16px; display: block; }
.src-row .src-eye.on { color: var(--accent); border-color: var(--accent-line); background: var(--accent-soft); }
.src-row .src-eye:active { transform: scale(.92); }
.src-row .src-eye[aria-pressed="false"] { opacity: .45; }
.src-hint { font-size: 11px; color: var(--ink-faint); margin: 0 0 8px; line-height: 1.45; }
.set-group-title { font-size: 13px; font-weight: 800; color: var(--accent); margin: 0 0 10px; letter-spacing: .02em; }
:root[data-theme="appletv"] .src-row .src-name,
:root[data-theme="appletv"] .src-row .src-url,
:root[data-theme="appletv"] .src-row .src-eye {
  background: rgba(0,0,0,.045); border-color: rgba(0,0,0,.12); color: #1d1d1f;
}
:root[data-theme="appletv"] .src-row .src-eye.on { color: #0071e3; background: rgba(0,113,227,.12); border-color: rgba(0,113,227,.35); }

/* 账号登录：盘链 / 蜗牛 / 聚影 分段 Tab */
.login-tabs {
  display: flex; gap: 4px; margin: 0 0 12px; padding: 3px;
  background: rgba(0,0,0,.22); border: 1px solid var(--line); border-radius: 11px;
}
.login-tab {
  flex: 1 1 0; min-width: 0; padding: 8px 6px; border-radius: 9px; border: 0;
  background: transparent; color: var(--ink-dim); font-size: 13px; font-weight: 700;
  text-align: center; -webkit-tap-highlight-color: transparent;
  transition: background .15s ease, color .15s ease;
}
.login-tab.active {
  background: var(--accent-soft); color: var(--accent);
  box-shadow: 0 1px 0 rgba(255,255,255,.06);
}
.login-tab:active { transform: scale(.97); }
.tv-mode .login-tab.focus, .tv-mode .login-tab:focus { transform: scale(1.04); }
.login-pane { display: none; }
.login-pane.active { display: block; }
:root[data-theme="appletv"] .login-tabs {
  background: rgba(0,0,0,.06); border-color: rgba(0,0,0,.1);
}
:root[data-theme="appletv"] .login-tab { color: rgba(29,29,31,.55); }
:root[data-theme="appletv"] .login-tab.active {
  background: rgba(0,113,227,.12); color: #0071e3;
  box-shadow: none;
}
:root[data-theme="appletv"] #settingsOverlay .login-tab.active { color: #0071e3; }

.btn.small { flex: 0 0 auto; padding: 8px 16px; font-size: 13px; border-radius: 9px; }
.login-state { font-size: 11.5px; color: var(--ink-faint); min-width: 0; }
.login-state.ok { color: var(--ok); }
.login-state.bad { color: var(--bad); }
.login-state.busy { color: var(--accent); }
.wn-captcha-row { display: flex; align-items: center; gap: 8px; margin: 8px 0; }
/* 验证码盒：失败/加载时只显示占位文字，绝不露出浏览器裂图。
   原因：固定 96×38 + object-fit:cover 会在服务端图宽高比与盒子不一致时裁掉上下/左右，
   表现为「验证码掉下去半截」（与屏幕大小无关，纯比例裁切）。改为 contain 完整显示。 */
.wn-captcha-box {
  position: relative; flex: 0 0 auto; width: 100px; height: 40px; padding: 0; margin: 0;
  border-radius: 6px; border: 1px solid var(--line); overflow: hidden; cursor: pointer;
  background: rgba(255,255,255,.08); color: var(--ink-faint);
  -webkit-tap-highlight-color: transparent;
}
.wn-captcha-box:active { opacity: .85; transform: scale(.97); }
.wn-captcha-box .wn-captcha-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; object-position: center;
  display: none; border: 0; border-radius: 0; background: #fff;
}
.wn-captcha-box.has-img .wn-captcha-img { display: block; }
.wn-captcha-box.has-img { background: #fff; }
.wn-captcha-hint {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 600; letter-spacing: .02em; color: var(--ink-faint);
  pointer-events: none; user-select: none; -webkit-user-select: none;
}
.wn-captcha-box.has-img .wn-captcha-hint { display: none; }
.wn-captcha-box.is-loading .wn-captcha-hint { color: var(--accent); }
.wn-captcha-box.is-fail .wn-captcha-hint { color: var(--bad); }
/* 蜗牛等裸 img 验证码同样用 contain，避免 cover 裁字 */
.wn-captcha-img { height: 40px; width: 100px; object-fit: contain; object-position: center; border-radius: 6px; background: #fff; flex: 0 0 auto; }
.wn-captcha-input { width: 84px; flex: 0 0 auto; color: #000; min-width: 0; }
.login-row .wn-captcha-input { flex: 0 0 84px; }
.login-row .login-state { flex: 0 0 auto; white-space: nowrap; }
.pl-remember-row {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 2px 0 8px; padding: 2px 0; cursor: pointer;
  font-size: 12.5px; color: var(--ink-dim); user-select: none; -webkit-user-select: none;
}
.pl-remember-row .pl-remember-cb {
  width: 16px; height: 16px; margin: 0; accent-color: var(--accent);
  flex: 0 0 auto; cursor: pointer;
}
.pl-remember-row:active { opacity: .85; }
:root[data-theme="appletv"] .pl-remember-row { color: rgba(29,29,31,.65); }
.switch { width: 46px; height: 26px; border-radius: 999px; background: rgba(255,255,255,.16); position: relative; flex: 0 0 auto; }
.switch.on { background: var(--grad); }
/* 动态流光：主色渐变缓慢流动（约 8s 一轮，蓝调） */
@keyframes gradFlow { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } }
.ed-play, .ed-qtab.active, .btn.primary, .switch.on {
  background-size: 220% 220%;
  animation: gradFlow 8s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .ed-play, .ed-qtab.active, .btn.primary, .switch.on { animation: none; }
}
.switch .knob { position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; transition: left .15s; }
.switch.on .knob { left: 23px; }
.panel-actions { display: flex; justify-content: center; margin-top: 16px; }
.panel-actions .btn { min-width: 116px; }
.panel-actions .btn + .btn { margin-left: 12px; }
/* ===== 设置页改为「正常页面」而非弹窗：铺满整个视口、顶部对齐、不带半透明遮罩，
   跟 .sheet（详情页）观感一致，而不是浮在中间的对话框卡片。confirmOverlay 仍保留
   原来居中弹窗的样式，这里只单独覆盖 #settingsOverlay。 ===== */
#settingsOverlay { padding: 0; align-items: stretch; justify-content: stretch; background: var(--sheet-bg); }
/* 设置页是"整页"而不是居中卡片，弹入方式跟 .panel-sheet 默认的缩放不一样：
   改成从底部带过冲地滑上来，跟详情页 sheet 的滑入手感统一。 */
#settingsOverlay .panel-sheet { width: 100%; max-width: none; height: 100%; max-height: none; border-radius: 0; border: none; box-shadow: none; background: var(--panel-strong); padding: calc(var(--safe-top) + 18px) calc(16px + var(--safe-right)) calc(var(--safe-bottom) + 18px) calc(16px + var(--safe-left));
  transform: translateY(5%); }
#settingsOverlay.active .panel-sheet { transform: translateY(0); transition: transform .48s cubic-bezier(.34, 1.56, .64, 1); }
#settingsOverlay .panel-close { top: calc(var(--safe-top) + 14px); right: calc(var(--safe-right) + 14px); }
.set-status { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 10px; padding: 10px 0; }
.status-line { font-size: 11.5px; color: var(--ink-faint); margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.status-line b { color: var(--ink-dim); font-weight: 600; }
.status-line .on { color: var(--ok); } .status-line .off { color: var(--bad); }
.divider { height: 1px; background: var(--line); margin: 16px 0; }

.toast { position: fixed; left: 50%; bottom: calc(var(--safe-bottom) + 22px); transform: translateX(-50%); z-index: 90; max-width: 84%; padding: 10px 16px; border-radius: 999px; background: var(--panel-strong); border: 1px solid var(--line-strong); color: var(--ink); font-size: 13px; opacity: 0; pointer-events: none; transition: opacity .2s; }
.toast.top { top: calc(var(--safe-top) + 12px); bottom: auto; }
.toast.show { opacity: 1; }

/* centered notice */
.unlock-egg {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(0,0,0,.55) 0%, rgba(0,0,0,.25) 55%, transparent 75%);
  opacity: 0;
  transition: opacity .35s ease;
}
.unlock-egg.show { opacity: 1; pointer-events: auto; }
.unlock-egg-core {
  position: relative;
  padding: 22px 36px;
  border-radius: 20px;
  background: linear-gradient(145deg, rgba(255,255,255,.16), rgba(255,255,255,.06));
  border: 1px solid rgba(255,255,255,.28);
  box-shadow: 0 0 0 1px rgba(255,107,203,.25), 0 12px 40px rgba(0,0,0,.45), 0 0 60px rgba(255,107,203,.35);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  backdrop-filter: blur(18px) saturate(1.3);
  transform: scale(.72);
  opacity: 0;
  transition: transform .55s cubic-bezier(.2,1.2,.3,1), opacity .35s ease;
}
.unlock-egg.show .unlock-egg-core {
  transform: scale(1);
  opacity: 1;
}
.unlock-egg-title {
  font-size: 22px; font-weight: 800; letter-spacing: .12em;
  text-align: center; color: #fff;
  text-shadow: 0 0 18px rgba(255,107,203,.85), 0 2px 8px rgba(0,0,0,.5);
}
.unlock-egg-sub {
  margin-top: 8px; font-size: 13px; text-align: center;
  color: rgba(255,255,255,.72); letter-spacing: .06em;
}
.unlock-egg-ring {
  position: absolute; left: 50%; top: 50%; width: 120%; height: 120%;
  transform: translate(-50%,-50%) scale(.6);
  border-radius: 50%;
  border: 2px solid rgba(255,107,203,.55);
  opacity: 0;
  pointer-events: none;
}
.unlock-egg.show .unlock-egg-ring {
  animation: unlockRing 1.1s ease-out forwards;
}
@keyframes unlockRing {
  0% { opacity: .9; transform: translate(-50%,-50%) scale(.55); }
  100% { opacity: 0; transform: translate(-50%,-50%) scale(1.35); }
}

/* 下拉刷新 */
.ptr { position: fixed; left: 0; right: 0; top: 0; z-index: 25; height: 54px; display: flex; align-items: center; justify-content: center;
  margin-top: var(--safe-top); color: var(--ink-dim); font-size: 13px; opacity: 0; pointer-events: none;
  transform: translateY(-10px); transition: opacity .15s; }
.ptr .ptr-ico { display: inline-block; margin-right: 8px; transition: transform .2s; }
.ptr.ready .ptr-ico { transform: rotate(180deg); }
.ptr.spin .ptr-ico { animation: ptrspin .8s linear infinite; }
@keyframes ptrspin { from { transform: rotate(0); } to { transform: rotate(360deg); } }

/* 自适应：竖屏仍按宽度自适应；横屏固定最多 8 列，避免宽屏卡片过密 */
@media (min-width: 600px) and (orientation: portrait) { .grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); } }
@media (min-width: 1180px) and (orientation: portrait) { .grid { grid-template-columns: repeat(auto-fill, minmax(156px, 1fr)); } }
@media (orientation: landscape) {
  .grid { grid-template-columns: repeat(8, minmax(0, 1fr)); }
}
/* 横屏窄机（手机横持）8 列太挤，略减列数 */
@media (orientation: landscape) and (max-width: 699px) {
  .grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
@media (orientation: landscape) and (min-width: 700px) and (max-width: 899px) {
  .grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
.tv-mode .grid .card { width: calc(12.5% - var(--card-gut)); max-width: calc(12.5% - var(--card-gut)); }
@media (min-width: 1600px) { .tv-mode .grid .card { width: calc(12.5% - var(--card-gut)); max-width: calc(12.5% - var(--card-gut)); } }
.tv-mode .rail .card { width: 150px; }
.tv-mode body, .tv-mode .app { font-size: 17px; }
.tv-mode .card-title { font-size: 15px; }
.tv-mode .section { padding: 20px 40px 0; }
.tv-mode .header-row, .tv-mode .chips { padding-left: 40px; padding-right: 40px; }
@supports (height: 100dvh) { .app { min-height: 100dvh; min-height: var(--fm-web-height, 100dvh); } }

/* ===== 主页整页骨架屏（首次加载遮罩，中央显示"宝宝巴士"）===== */
@keyframes skelShimmer { 0% { background-position: -420px 0; } 100% { background-position: 420px 0; } }
@keyframes skelFade { to { opacity: 0; visibility: hidden; } }
.home-skeleton { position: absolute; inset: 0; z-index: 30; background: var(--dyn-bg, #0c0b12); padding: 0 var(--gut); overflow: hidden; }
.home-skeleton.hiding { animation: skelFade .45s ease forwards; pointer-events: none; }
.home-skeleton .sk-hero { width: 100%; height: 46vh; min-height: 260px; max-height: 460px; border-radius: 16px; margin: 8px 0 22px; }
.home-skeleton .sk-rowtitle { width: 120px; height: 18px; border-radius: 6px; margin: 18px 0 12px; }
.home-skeleton .sk-cards { display: flex; gap: var(--card-gut, 10px); }
.home-skeleton .sk-card { flex: 0 0 auto; width: 30vw; max-width: 128px; }
.home-skeleton .sk-poster { width: 100%; aspect-ratio: 2/3; border-radius: 12px; }
.home-skeleton .sk-line { height: 12px; border-radius: 5px; margin-top: 8px; }
.home-skeleton .sk-line.w70 { width: 70%; } .home-skeleton .sk-line.w45 { width: 45%; }
.home-skeleton .sk-shimmer { background: linear-gradient(100deg, rgba(255,255,255,.05) 30%, rgba(255,255,255,.12) 50%, rgba(255,255,255,.05) 70%); background-size: 840px 100%; animation: skelShimmer 1.3s linear infinite; }
.home-skeleton .sk-brand { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; pointer-events: none; }
.home-skeleton .sk-brand-text { font-size: 30px; font-weight: 900; letter-spacing: 4px; background: var(--grad); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent; background-size: 220% 220%; animation: gradFlow 5s ease-in-out infinite; text-shadow: 0 2px 20px rgba(0,0,0,.3); }
.home-skeleton .sk-brand-sub { margin-top: 10px; font-size: 12px; color: var(--ink-faint); letter-spacing: 2px; }
.home-skeleton .sk-brand-dots { margin-top: 14px; display: flex; gap: 6px; }
.home-skeleton .sk-brand-dots span { width: 7px; height: 7px; border-radius: 50%; background: var(--accent, #6ea8fe); opacity: .35; animation: skelDotPulse 1.1s ease-in-out infinite; }
.home-skeleton .sk-brand-dots span:nth-child(2) { animation-delay: .18s; } .home-skeleton .sk-brand-dots span:nth-child(3) { animation-delay: .36s; }
@keyframes skelDotPulse { 0%,100% { opacity: .25; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-4px); } }
/* ===== 轮播图骨架屏 ===== */
.hero-skeleton { position: relative; width: 100%; height: 58vh; min-height: 340px; max-height: 560px;
  background: linear-gradient(135deg, rgba(46,166,255,.04) 0%, rgba(22,32,66,.55) 60%, rgba(7,11,26,.7) 100%);
  overflow: hidden; margin: 0 0 6px; }
@media (orientation: landscape) { .hero-skeleton { height: 85vh; min-height: 280px; } }
.hero-skeleton::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,.07) 50%, transparent 100%);
  -webkit-animation: heroSkelShimmer 1.8s ease-in-out infinite;
  animation: heroSkelShimmer 1.8s ease-in-out infinite; }
@-webkit-keyframes heroSkelShimmer { 0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)} 100%{-webkit-transform:translateX(100%);transform:translateX(100%)} }
@keyframes heroSkelShimmer { 0%{transform:translateX(-100%)} 100%{transform:translateX(100%)} }
.hero-skel-body { position: absolute; bottom: 40px; left: 0; right: 0;
  display: -webkit-flex; display: flex; -webkit-flex-direction: column; flex-direction: column;
  -webkit-align-items: center; align-items: center; gap: 10px; padding: 0 20px; z-index: 1; }
.hero-skel-title { width: 52%; height: 26px; border-radius: 7px; background: rgba(255,255,255,.09); }
.hero-skel-meta { width: 36%; height: 12px; border-radius: 5px; background: rgba(255,255,255,.06); }
.hero-skel-dots { position: absolute; bottom: 13px; left: 0; right: 0; z-index: 1;
  display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center;
  -webkit-justify-content: center; justify-content: center; gap: 6px; }
.hero-skel-d { width: 6px; height: 6px; border-radius: 50%; background: rgba(255,255,255,.18); }
.hero-skel-d.a { width: 16px; background: rgba(255,255,255,.35); border-radius: 3px; }

/* 追剧星标：与盘搜/刷新同款描边 SVG */
.ed-follow { color: var(--ink-dim); }
.ed-follow .star-svg { width: 22px; height: 22px; display: block; }
.ed-follow.on { color: #ffc24d; }
.ed-follow.on .star-svg {
  fill: #ffc24d;
  stroke: #ffc24d;
}
.card.zj-today .badge { background: rgba(255, 90, 70, .92); }
/* 在追：统一白底深色字；仅「有更新」用橙色高亮 */
.card.zj-followed .badge {
  background: rgba(255, 255, 255, .92);
  border-color: rgba(0, 0, 0, .12);
  color: #1d1d1f;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .18);
}
.card.zj-update .badge {
  background: linear-gradient(135deg, #ff5a46, #ff8a3d);
  border-color: rgba(255, 190, 150, .5);
  color: #fff;
  animation: zjBadgePulse 1.6s ease-in-out infinite;
}
@keyframes zjBadgePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,90,70,.45); }
  50% { box-shadow: 0 0 0 6px rgba(255,90,70,0); }
}
.card.zj-ready .badge::after { content: " · 可播"; font-size: 9px; opacity: .9; }
.search-group-title.zj-group { margin-top: 12px; }
