/* ============================================================
   神马资源聚合站 — 豆瓣风格主题
   ============================================================ */
:root {
  --bg: #f6f7f9;
  --card: #ffffff;
  --text: #1f2329;
  --text-2: #6b7280;
  --text-3: #9ca3af;
  --line: #e8eaed;
  --brand: #2a9d8f;
  --brand-dark: #21867a;
  --rate: #00b51d;
  --radius: 10px;
  --shadow: 0 1px 3px rgba(0, 0, 0, .06);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, .12);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei",
               "Helvetica Neue", Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
.wrap { max-width: 1340px; margin: 0 auto; padding: 0 20px; }
.hidden { display: none !important; }
.dim { color: var(--text-3); font-size: 13px; }

/* ---------- 顶栏 ---------- */
.site-header {
  background: #fff;
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: var(--shadow);
}
.header-inner {
  display: flex;
  align-items: center;
  gap: 24px;
  height: 62px;
}
.logo {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -.3px;
  white-space: nowrap;
  color: var(--text);
}
.logo span { color: var(--brand); }

/* 顶栏搜索：整体做成一个胶囊，内部是「范围切换 + 输入框 + 搜索」三段。
   原先边框在输入框自己身上（左圆角）、右圆角在按钮上；现在边框统一提到外框，
   中间插进切换控件后左右仍是同一个圆角，不会出现「方一块、圆一块」。 */
.search-box {
  flex: 1;
  display: flex;
  align-items: center;
  max-width: 520px;
  height: 38px;
  padding-left: 5px;
  border: 1px solid var(--line);
  border-radius: 19px;
  background: #fafbfc;
  overflow: hidden;
  transition: border-color .2s, background .2s;
}
.search-box:focus-within { border-color: var(--brand); background: #fff; }

/* 搜索范围切换（网盘 / 资源站）—— 元素由 common.js 注入，见该文件说明 */
.search-scope { display: flex; flex: 0 0 auto; align-items: center; gap: 2px; }
.scope-btn {
  height: 26px;
  padding: 0 10px;
  border: none;
  border-radius: 13px;
  background: transparent;
  color: var(--text-3);
  font-size: 12.5px;
  line-height: 1;
  font-family: inherit;
  white-space: nowrap;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.scope-btn:hover { color: var(--brand); }
.scope-btn.active { background: var(--brand); color: #fff; font-weight: 500; }
.scope-btn.active:hover { color: #fff; }

.search-box input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0 8px 0 9px;
  border: none;
  outline: none;
  background: transparent;
  font-size: 14px;
  font-family: inherit;
}
/* 只作用于搜索按钮 —— 范围切换也是 button，但它们不是 .search-box 的直接子元素 */
.search-box > button {
  flex: 0 0 auto;
  height: 100%;
  padding: 0 20px;
  border: none;
  border-radius: 0;
  background: var(--brand);
  color: #fff;
  font-size: 14px;
  font-family: inherit;
  cursor: pointer;
  transition: background .2s;
}
.search-box > button:hover { background: var(--brand-dark); }

/* 顶栏在窄窗口本来就紧张（logo + 搜索框 + 5 个导航项都得排一行）。
   多出来的切换控件不能把输入框挤没，所以窄屏时把三处的内边距一起收紧，
   让给输入框 —— 正常宽度（≥1000px）下完全不生效。 */
@media (max-width: 900px) {
  .search-box { padding-left: 3px; }
  .scope-btn { padding: 0 7px; font-size: 12px; }
  .search-box input { padding: 0 4px 0 6px; }
  .search-box > button { padding: 0 14px; }
}

/* ---------- 资源站搜索结果（顶栏切到「资源站」时用，见 app.js 的 renderCmsSearch）
   与 .pan-item 的区别：这块要多一个海报位、并且每条要能展开线路胶囊。
   线路直接复用 .wl-chips / .wl-chip（自动采集卡片那套），样式天然一致。 */
.cms-item {
  display: flex;
  gap: 14px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 13px 15px;
  transition: border-color .2s, box-shadow .2s;
}
.cms-item:hover { border-color: #d5d9de; box-shadow: var(--shadow); }
.cms-poster {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 76px;
  height: 106px;
  border-radius: 6px;
  overflow: hidden;
  background: #f0f2f5;
  color: var(--text-3);
  font-size: 12px;
}
.cms-poster img { display: block; width: 100%; height: 100%; object-fit: cover; }
.cms-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.cms-name { font-size: 16px; font-weight: 600; color: var(--text); line-height: 1.3; }
.cms-meta { font-size: 12.5px; color: var(--text-3); }
.cms-sum { font-size: 12.5px; color: var(--text-2); }

.nav { display: flex; gap: 20px; margin-left: auto; }
.nav a {
  font-size: 14px;
  color: var(--text-2);
  padding: 4px 0;
  border-bottom: 2px solid transparent;
  transition: color .2s, border-color .2s;
  white-space: nowrap;
}
.nav a:hover, .nav a.active { color: var(--brand); border-bottom-color: var(--brand); }
.nav .nav-btn {
  font-size: 14px;
  color: var(--text-2);
  padding: 4px 0;
  border: none;
  border-bottom: 2px solid transparent;
  background: transparent;
  font-family: inherit;
  cursor: pointer;
  transition: color .2s, border-color .2s;
}
.nav .nav-btn:hover { color: var(--brand); border-bottom-color: var(--brand); }

/* ---------- 筛选 ---------- */
.tabs {
  display: flex;
  gap: 8px;
  margin: 22px 0 14px;
  flex-wrap: wrap;
}
.tab {
  padding: 7px 20px;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: #fff;
  font-size: 15px;
  cursor: pointer;
  color: var(--text-2);
  font-family: inherit;
  transition: all .18s;
}
.tab:hover { border-color: var(--brand); color: var(--brand); }
.tab.active {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
  font-weight: 500;
}

.tagbar {
  display: flex;
  gap: 14px;
  margin-bottom: 18px;
  font-size: 13px;
  flex-wrap: wrap;
  align-items: center;
}
.tag {
  border: none;
  background: none;
  color: var(--text-2);
  cursor: pointer;
  padding: 3px 0;
  font-size: 13px;
  font-family: inherit;
  border-bottom: 1px solid transparent;
  transition: color .18s;
}
.tag:hover { color: var(--brand); }
.tag.active { color: var(--brand); border-bottom-color: var(--brand); font-weight: 500; }

/* ---------- 区块标题 ---------- */
.section-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 4px 0 16px;
}
.section-head h2 { font-size: 17px; font-weight: 600; }
.status { font-size: 12px; color: var(--text-3); margin-left: auto; }
.btn-text {
  margin-left: auto;
  background: none;
  border: none;
  color: var(--brand);
  font-size: 13px;
  cursor: pointer;
  font-family: inherit;
}
.btn-text:hover { text-decoration: underline; }

/* 首页热播区：标题「今日热播」已按用户要求去掉，整行就不要再占高度了
   （只隐藏 h2 的话，右边的统计还会把那一行撑起来，左边留一块空白）。
   ★ 用 #hotArea 限定作用域 —— .section-head 年份视图和自动采集也在用，不能全局隐藏。
   副作用：右侧「N 个分类 · 共 M 条」的统计也跟着隐藏了（它需要时可以再放回别处）。 */
#hotArea .section-head { display: none; }

/* 数据新鲜度条：抓取于 hh:mm:ss · 下次拉取还有 m分ss秒 · 立即刷新
   放在热播区最上面 —— 那一行标题被隐藏了，这里补上更有用的信息。 */
.refresh-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin: 2px 0 14px;
  font-size: 12px;
  color: #9aa1a9;
  line-height: 1.5;
}
.refresh-bar .refresh-sep { color: #d7dbe0; }
.refresh-bar #countdownText { color: var(--text-2); }
.refresh-bar #refreshNow { font-size: 12px; margin-left: 2px; }
.refresh-bar #refreshNow:disabled { color: #b6bcc2; cursor: default; text-decoration: none; }
.refresh-bar.busy #freshText { color: var(--brand); }

/* 自动采集卡片：状态行（「已同步：BBA、qsvip」）
   —— 只在这一类卡片里生效，不动首页卡片的 .card-sub。
   字号压到 12px 并强制一行：超长时末尾省略，完整内容仍在 title 里悬停可见。 */
.watch-card .wc-status {
  font-size: 12px;
  line-height: 1.5;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- 自动采集标题行：「自动采集」开关 + 一键采集 ---------- */
/* 有了底色块就得改成 center 对齐，baseline 会让按钮和旁边的文字错开；
   再允许换行 —— 开关带底色后比原来的纯文字宽，窄窗口下让状态栏整段掉到第二行，别把标题行挤爆 */
.watch-head { align-items: center; flex-wrap: wrap; row-gap: 6px; }

/* 「自动采集」四个字本身就是开关。
   ★ 颜色语义（2026-09-23 用户拍板**对调**）：
     **红底 = 开着**（后台正在按间隔自动跑，会持续打采集源，要让人一眼看见）
     **绿底 = 关着**（安全、正常状态，不做事）
   ⚠️ 改前是相反的（绿=开、红=关），用户反馈「关着的功能显示红色，看着像警告」。
   红用站点已有的 #ef4444（与 .card-sub.bad 同一只红），绿用 var(--brand)，不另起配色。
   状态仍由 aria-checked 承载（role=switch），读屏能念对。
   ★ 只影响 aria-checked 真会变的按钮 —— 「线路开关」那颗恒为 true（它是展开/收起，不是开关），
     所以它永远绿底，不会跟着变红。 */
.auto-switch {
  padding: 5px 14px;
  background: #ef4444;          /* 默认（= 开启态）= 红 */
  color: #fff;
  border: none;
  border-radius: 999px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.5;
  cursor: pointer;
  transition: background .2s;
}
.auto-switch:hover { background: #dc2626; }
.auto-switch[aria-checked="false"] { background: var(--brand); }
.auto-switch[aria-checked="false"]:hover { background: var(--brand-dark); }
.auto-switch:disabled { opacity: .6; cursor: default; }

/* 「线路同步」开关：与「自动采集」同一套红/绿语义（**红=定时同步开着**，绿=关着），只是小一号。
   它管的是「刷新显示」，比「自动采集」次要，不该抢同一个视线权重。 */
.sync-switch { padding: 4px 11px; font-size: 13px; }

/* 「每 N 分钟」的同步间隔：跟着开关一起走，用灰字避免和开关本身平权 */
.sync-cfg {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  color: var(--text-3);
}
.sync-num {
  width: 52px;
  padding: 3px 6px;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-family: inherit;
  font-size: 13px;
  color: var(--text);
  background: #fff;
}
.sync-num:focus { outline: none; border-color: var(--brand); }

/* ---------- 自动采集：线路总开关（标题栏按钮 + 展开面板） ----------
   点标题栏的「线路开关」展开一个面板，列出所有出现过的线路，每条一个开关。
   关掉 = **所有剧**都不再采这条线路（含以后新加入的剧）—— 免得同一条线路要在每张卡片上各点一次。
   ★ 关掉的线路在卡片上是**直接不显示**的（不再留一堆灰胶囊占位置）；想知道隐藏了哪几条，
     剧名行右侧有一枚「已隐藏 N 条」小签，悬停能看全名单。
     ★ 那枚小签只能挂在剧名行 —— 放进 CMS/源 那两行会抢走胶囊宽度、把线路名挤成省略号。
   ★ 它跟 .auto-switch 共用 class，但**尺寸、颜色全部自己覆盖**：
     它是「展开/收起」不是开/关，`aria-checked` 恒为 true —— 颜色语义对调后
     （true = 红），不覆盖的话它会被染成红色，看着像"刚打开了什么危险开关"。 */
.line-switch { padding: 4px 11px; font-size: 13px; background: var(--brand); }
/* hover 也要自己写：否则命中 .auto-switch:hover（#dc2626 红） */
.line-switch:hover { background: var(--brand-dark); }
/* 展开时压深一点，跟「收起」有个可辨的差别（它没有开/关语义，所以不用红/绿去表达） */
.line-switch[aria-expanded="true"] { background: var(--brand-dark); }

/* 「已隐藏 N 条」小签：线路被总开关关掉后卡片上不显示，用它告诉用户「这儿本来还有几条」。
   ★ 位置必须跟着 .wl-merge / .wl-sync 待在**剧名行**，外观也做成一家人（同尺寸小药丸）。
     千万别挪进 CMS / 源 那两行 —— 那两行是 flex 横排，多一个元素就抢 .wl-chips 的宽度，
     胶囊里的线路名会被省略号吃掉（实测：容器 234px → 162px，名字框只剩 7px）。 */
.wl-hide {
  flex: 0 0 auto;
  padding: 1px 7px;
  border-radius: 9px;
  font-size: 11px;
  line-height: 1.6;
  color: var(--text-2);
  background: #eef1f4;
}
.line-panel {
  margin: 10px 0 2px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
}
.line-panel-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.line-panel-head b { font-size: 14px; font-weight: 500; }
.line-count { font-size: 12px; color: var(--text-3); }
.line-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
  gap: 6px;
}
.line-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fbfcfd;
}
.line-row .ln {
  flex: 1;
  min-width: 0;
  font-family: inherit;
  font-size: 13.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.line-row .lc { flex: 0 0 auto; font-size: 11.5px; color: var(--text-3); }
.line-row.off { background: #f6f7f9; }
.line-row.off .ln { color: var(--text-3); text-decoration: line-through; }
.line-row.cms-only .ln { color: var(--text-3); }
.line-btn {
  flex: 0 0 auto;
  padding: 3px 12px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-family: inherit;
  font-size: 12.5px;
  cursor: pointer;
  transition: background .15s;
}
.line-btn.on { background: #e7f4ef; color: var(--brand-dark); border-color: #bde3d9; }
.line-btn.on:hover { background: #d7ece5; }
.line-btn.off { background: #f3f4f6; color: var(--text-3); border-color: var(--line); }
.line-btn.off:hover { background: #eaecf0; }
.line-btn:disabled { opacity: .55; cursor: default; }
.line-panel-foot { margin-top: 10px; font-size: 12px; color: var(--text-3); }

/* ---------- 自动采集：标题行里的「搜片名加入」 ----------
   就地搜索，省得回首页翻卡片找「采集」按钮。
   输入框用 .sync-num 同一套描边/圆角，跟旁边的「每 N 分钟」视觉上是一家人。 */
.wa-add {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.wa-input {
  width: 190px;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-family: inherit;
  font-size: 13px;
  color: var(--text);
  background: #fff;
}
.wa-input:focus { outline: none; border-color: var(--brand); }

/* 搜索结果面板：贴在标题行下面，不参与左右分栏 */
.wa-result {
  margin: 10px 0 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.wa-result-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  color: var(--text-2);
}
.wa-result-head .dim { color: var(--text-3); font-size: 12px; }
.wa-list { max-height: 320px; overflow-y: auto; }
.wa-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}
.wa-item:last-child { border-bottom: none; }
.wa-item:hover { background: #fafbfc; }
.wa-name { font-weight: 600; color: var(--text); flex-shrink: 0; }
.wa-meta { color: var(--text-3); font-size: 12px; flex: 1; min-width: 0;
           overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wa-add-btn {
  flex-shrink: 0;
  padding: 4px 14px;
  border: 1px solid var(--brand);
  border-radius: 999px;
  background: #fff;
  color: var(--brand);
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
  transition: all .18s;
}
.wa-add-btn:hover { background: var(--brand); color: #fff; }
.wa-add-btn.done { border-color: var(--line); color: var(--text-3); cursor: default; }
.wa-add-btn.done:hover { background: #fff; color: var(--text-3); }
.wa-add-btn:disabled { opacity: .6; cursor: default; }

/* 小号实心按钮：标题行里用，比 .btn-primary 小一圈（不抢标题行的高度） */
.btn-mini {
  padding: 5px 13px;
  background: var(--brand);
  color: #fff;
  border: none;
  border-radius: 999px;
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
  transition: background .2s;
}
.btn-mini:hover { background: var(--brand-dark); }
.btn-mini:disabled { opacity: .6; cursor: default; }

/* ---------- 影片网格 ---------- */
.grid {
  display: grid;
  /* 固定一行六个，海报按 2:3 比例等比放大（不再按容器宽度自动增减列数） */
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 26px 18px;
  padding-bottom: 8px;
}

.card { cursor: pointer; }

.poster {
  position: relative;
  width: 100%;
  aspect-ratio: 2 / 3;
  border-radius: var(--radius);
  overflow: hidden;
  background: #eceef1;
  box-shadow: var(--shadow);
  transition: transform .25s cubic-bezier(.2,.8,.2,1), box-shadow .25s;
}
.card:hover .poster {
  transform: translateY(-5px);
  box-shadow: var(--shadow-lg);
}
.poster img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .4s;
}
.card:hover .poster img { transform: scale(1.05); }

/* 评分角标 */
.rate {
  position: absolute;
  right: 6px;
  bottom: 6px;
  background: var(--rate);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: 4px;
  line-height: 1.5;
  letter-spacing: -.2px;
}
.badge-new {
  position: absolute;
  left: 6px;
  top: 6px;
  background: rgba(255, 84, 84, .94);
  color: #fff;
  font-size: 11px;
  padding: 1px 6px;
  border-radius: 4px;
  line-height: 1.5;
}
.badge-ep {
  position: absolute;
  left: 6px;
  bottom: 6px;
  background: rgba(0, 0, 0, .66);
  color: #fff;
  font-size: 11px;
  padding: 1px 6px;
  border-radius: 4px;
  max-width: 72%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 剧名 + 网盘按钮 同一排（网盘在右侧，视觉上位于海报右下角） */
.card-title-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 9px;
}
.card-title {
  flex: 1;
  min-width: 0;               /* 让下面的省略号在 flex 子项里生效 */
  font-size: 14px;
  font-weight: 500;
  line-height: 1.4;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.btn-pan {
  flex: none;
  padding: 3px 9px;
  border: 1px solid var(--brand);
  background: #fff;
  border-radius: 12px;
  font-size: 12px;
  color: var(--brand);
  cursor: pointer;
  font-family: inherit;
  transition: background .15s, color .15s;
}
.btn-pan:hover { background: var(--brand); color: #fff; }
.card-sub {
  font-size: 12px;
  color: var(--text-3);
  margin-top: 2px;
  height: 18px;
  overflow: hidden;
}

.play-cta { text-align: center; margin-top: 16px; }

/* ---------- 播放页 ---------- */
#player {
  display: block;
  width: 100%;
  max-height: 72vh;
  background: #000;
  border-radius: var(--radius);
}

/* ★ 三栏：左=海报与信息 ｜ 中=播放器 ｜ 右=线路与集数
   ★ 宽度是「三栏互相挤」的：总宽固定（.wrap 内容区 1300px），中栏独占剩余，
     所以中栏要变窄只能把宽度让给左右两栏，否则右边会留白、不占满屏。
     中栏高度由 aspect-ratio 撑出，左右两栏 stretch 跟它等高。
   ★ 右栏宽度**按内容自适应**（原先是写死的 190px）：
       线路列 = --src-btn-w(最长线路名按钮) + 17（滚动条 15 + 余量 2）
       集数列 = --eps-text-w(最长集数名)     + 27（内边距 10 + 边框 2 + 滚动条 15）
       右栏   = 两列 + gap 10 + #playArea 内边距 16 + 边框 2 = 两列 + 28
     两列都带下限（100 / 62，正是原来写死的值），所以：
       集数名短（「01」）→ 右栏仍 190px，跟以前一模一样；
       集数名长（「第86集」48px）→ 才多让出几 px 给集数列。
     两个变量都由 play.js 用 canvas 量出、写在 :root 上。 */
#stage {
  display: grid;
  grid-template-columns:
    230px
    minmax(0, 1fr)
    calc(max(100px, calc(var(--src-btn-w, 83px) + 17px))
       + max(62px, calc(var(--eps-text-w, 35px) + 27px))
       + 28px);
  gap: 14px;
  align-items: stretch;
  margin-top: 24px;
}

/* 左栏：海报 + 片名 + 元信息。
   ★ 内层 #topArea 用绝对定位填满 —— 这样左栏内容多高都不参与 #stage 的
     行高计算，行高完全由中栏（16:9）决定；内容超出就在左栏里滚动。
     不这么做：左栏内容会把行高撑到 700+，中栏只有 457，播放器下方空一大块。 */
.play-left {
  position: relative;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.play-left > #topArea {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  padding: 12px;
}

/* 右栏：线路一列 + 集数一列，各自滚动（同理用绝对定位，不参与行高计算） */
.play-right {
  position: relative;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.play-right > #playArea {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: 8px;
}
#localPanel,
#cmsPanel {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* 线路 ｜ 集数 两列并排；两列各自滚动（线路可能 11 条、集数可能 80+ 集）。
   ★ 两列宽度都**按内容自适应**（变量由 play.js 量出，见 #stage 上方说明），
     各自保底 100 / 62px —— 保底值就是原来写死的宽度，所以内容不长时观感不变。
   ★ scrollbar-gutter: stable —— 让两列一直预留滚动条的位置。
     不预留的话：线路少时没滚动条（列宽 100），线路一多冒出滚动条（列宽掉到 85），
     按钮会跟着突然变窄。 */
.cms-cols {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns:
    max(100px, calc(var(--src-btn-w, 83px) + 17px))
    max(62px, calc(var(--eps-text-w, 35px) + 27px));
  gap: 10px;
}
#cmsSources,
#cmsEps {
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-gutter: stable;
}
/* 详情区：flex-basis:100% 让它跳到海报+标题的下一行 */
.detail-detail {
  flex: 0 0 100%;
  margin-top: 12px;
  padding-top: 16px;
  border-top: 1px dashed var(--line);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* 紧贴剧名下面：年份/地区/类型/导演/演员 */
.detail-info-rows {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-2);
}
.detail-info-rows .detail-row-label { flex: 0 0 36px; color: var(--text-3); font-size: 12.5px; }
.detail-info-rows .detail-row-value { color: var(--text); }
.detail-row {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text-2);
}
.detail-row-label {
  flex: 0 0 36px;
  color: var(--text-3);
  font-size: 12.5px;
  padding-top: 1px;
  text-align: justify;
}
.detail-row-value {
  flex: 1;
  min-width: 0;
  color: var(--text);
  word-break: break-word;
}
.detail-row-plot .detail-row-value { display: block; flex-basis: 100%; }
.detail-plot {
  white-space: pre-wrap;
  word-break: break-word;
  display: block;
}
.plot-toggle {
  border: none;
  background: transparent;
  color: var(--brand);
  cursor: pointer;
  padding: 4px 0 0 0;
  font-size: 12.5px;
  font-family: inherit;
  display: inline-block;
}
.plot-toggle:hover { text-decoration: underline; }
.player-box {
  /* ★ 三件套缺一不可（实测踩过）：
     aspect-ratio 定高、width/max-width 100% 锁宽、align-self:start 拒绝被拉伸。
     少了 width/max-width：行高被拉高后 aspect-ratio 会**反过来用高度算宽度**
       （711 × 16/9 = 1264px），把列宽撑破、整个盖住右栏 ——
       表现就是「右边栏的线路不见了」。 */
  aspect-ratio: 16 / 9;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  min-height: 0;
  align-self: start;
  position: relative;
  margin: 0;
  background: #000;
  border-radius: var(--radius);
  overflow: hidden;
  /* 跟顶栏/卡片同一套阴影，中间这块黑才不像「贴上去的」 */
  box-shadow: var(--shadow);
}
.player-box #player,
.player-box #playerFrame {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 0;
  background: #000;
  border: none;
  object-fit: contain;
}
/* 未播放时的占位画面（美化后）= 海报虚化铺底 + 深色遮罩 + 中央播放按钮 + 剧名 + 说明。
   ★ z-index 1 要低于 .fs-btn(5)，否则盖住全屏按钮。
   ★ pointer-events: none —— 占位只是一层「皮」，不该拦住点击；
     底下的 video 控件仍然能收到事件。
   拿不到海报时（本地库场景等）只剩径向渐变底，文字照样清楚。 */
.play-hint {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: radial-gradient(125% 125% at 50% 0%, #1d2229 0%, #0a0c0f 72%);
  pointer-events: none;
}
/* 海报铺底：往四周各溢 6% 再虚化 —— 模糊会把边缘「吃」进去，不溢出来会露出一圈底色。
   透明度/模糊度是调的：太清会抢文字，太糊就变成一片死灰（实测 blur 26 + opacity .5
   几乎看不出是海报），所以 blur 收到 24、透明度提到 .58，让海报的颜色透出来。 */
.ph-bg {
  position: absolute;
  inset: -6%;
  background-size: cover;
  background-position: center;
  filter: blur(24px) saturate(125%);
  opacity: .58;
}
/* 深色遮罩：中间最透（让海报色透出来）、上下压暗（文字区都在中线附近） */
.ph-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(6, 8, 11, .66) 0%,
    rgba(6, 8, 11, .36) 42%,
    rgba(6, 8, 11, .82) 100%);
}
/* 内容层：按钮 / 剧名 / 说明 竖排居中 */
.ph-body {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  max-width: 88%;
  text-align: center;
}
.ph-play {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  margin-bottom: 17px;
  border-radius: 50%;
  color: #fff;
  background: var(--brand);
  /* 细细一圈高光 + 品牌色投影：白底海报上也有轮廓，不会跟背景糊在一起 */
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .18), 0 6px 22px rgba(42, 157, 143, .42);
  /* ★ 整个 .play-hint 是 pointer-events:none（免得挡住 video 自己的控件），
     只有这个按钮单独放行 —— 点它 = 播右栏里的第一集（见 play.js showPlayHint）。 */
  pointer-events: auto;
  cursor: pointer;
  transition: transform .16s ease, box-shadow .16s ease;
}
.ph-play:hover {
  transform: scale(1.06);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .3), 0 8px 26px rgba(42, 157, 143, .5);
}
.ph-play:active { transform: scale(.96); }
.ph-play:focus-visible { outline: 2px solid rgba(255, 255, 255, .85); outline-offset: 3px; }
/* 播放三角：50px —— 用 Bootstrap Icons 的 play-fill，路径见 play.js 的 ICON_PLAY。
   ★ transform: translateX(2px) 是**光学居中补偿**，不是几何误差：
     这个图标在 viewBox 里本身是几何居中的（实测 offsetX = 0），
     但三角形右边是尖的、旁边留白看着更大，人眼会判定它偏左 —— 经典的光学错觉。
     做过 -2 / 0 / +2 / +4 四档真实渲染对比，+2px 那档视觉上最正，故取 2px。 */
.ph-play svg { width: 50px; height: 50px; transform: translateX(2px); }
.ph-title {
  max-width: 100%;
  margin-bottom: 4px;
  font-size: 19px;
  font-weight: 500;
  line-height: 1.35;
  color: #fff;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .5);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ph-sub {
  max-width: 100%;
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .66);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 全屏按钮：平时淡一点不抢戏，鼠标进播放器就完全显出来 */
.fs-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 6px 11px;
  font-size: 12.5px;
  color: #fff;
  background: rgba(0, 0, 0, .45);
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: 8px;
  cursor: pointer;
  font-family: inherit;
  opacity: .58;
  backdrop-filter: blur(6px);
  transition: opacity .18s, background .18s, border-color .18s;
}
.player-box:hover .fs-btn { opacity: 1; }
.fs-btn:hover { background: rgba(0, 0, 0, .78); border-color: rgba(255, 255, 255, .45); }
.fs-btn svg { display: block; }

/* 加载态：盖在播放器上的一层暗幕（z 3，低于全屏按钮 5），中间转圈 + 文案。
   只在「点完集数、画面还没出来」这一段显示，出第一帧就收（见 play.js）。
   ★ 自己写一套浅色 spinner：全局 .spinner 是给白底用的深色描边，
     放到黑播放器上几乎看不见。 */
.play-load {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  /* 压到 .95：下面是原生 controls 和时间轴，透出来会显乱 */
  background: rgba(6, 8, 11, .95);
  pointer-events: none;
}
.pl-spin {
  width: 34px;
  height: 34px;
  border: 2.5px solid rgba(255, 255, 255, .16);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: spin .8s linear infinite;
}
.pl-text { font-size: 13px; color: rgba(255, 255, 255, .62); }
.player-box:fullscreen {
  width: 100vw;
  height: 100vh;
  max-width: none;
  border-radius: 0;
}
.player-box:fullscreen #player,
.player-box:fullscreen #playerFrame { height: 100%; }
/* 窄屏：三栏挤不下 → 降级成上下堆叠（左栏横排、中栏 16:9、右栏在下） */
@media (max-width: 1080px) {
  #stage { grid-template-columns: minmax(0, 1fr); }
  /* 堆叠后不再需要「绝对定位填满」那套，恢复成普通文档流 */
  .play-left, .play-right { position: static; overflow: visible; padding: 12px; }
  .play-left > #topArea, .play-right > #playArea { position: static; inset: auto; overflow: visible; padding: 0; }
  .play-left .detail-top { flex-direction: row; flex-wrap: wrap; gap: 14px 18px; }
  .play-left .detail-poster { width: 140px; flex: 0 0 140px; }
  .play-left .detail-info { flex: 1; min-width: 0; }
  .play-left .detail-detail { flex: 0 0 100%; }
  .play-right { min-height: 320px; }
  /* 窄屏右栏变全宽，两列撑开一些更舒展 */
  .cms-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
}
.play-tip { margin: 10px 0 0; font-size: 12px; }
.ep-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}
.ep-btn {
  max-width: 100%;
  padding: 7px 14px;
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 8px;
  font-size: 13px;
  color: var(--text-2);
  cursor: pointer;
  font-family: inherit;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: border-color .15s, color .15s, background .15s;
}
.ep-btn:hover { border-color: var(--brand); color: var(--brand); }
.ep-btn.active { background: var(--brand); border-color: var(--brand); color: #fff; }

/* ---------- 数据源切换（本地库 / 我的CMS）---------- */
.source-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
}
.source-tabs button {
  padding: 8px 18px;
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 999px;
  font-size: 13.5px;
  color: var(--text-2);
  cursor: pointer;
  font-family: inherit;
  transition: all .15s;
}
.source-tabs button:hover { border-color: var(--brand); color: var(--brand); }
.source-tabs button.active { background: var(--brand); border-color: var(--brand); color: #fff; }

/* 线路按来源站分组：容器必须块级 ——
   ★ 之前用的是 .src-tabs（display:flex），结果「白菜/蓝光/西瓜」三个组被当成
     flex 项横向并排，站名全挤在一排；分组要的是纵向堆叠。 */
.src-groups { margin: 12px 0 4px; }

/* 一组 = 一个资源站：站名独占一行，下面紧跟它的线路按钮 */
.src-group { width: 100%; margin: 12px 0 0; }
.src-group:first-child { margin-top: 0; }

.src-group-name {
  display: block;
  width: 100%;
  box-sizing: border-box;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: 6px;
  padding: 1px 0 1px 8px;
  border-left: 3px solid var(--brand);
  line-height: 1.35;
}
.src-group-btns { display: flex; flex-wrap: wrap; gap: 8px; }
.src-btn {
  padding: 6px 14px;
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 8px;
  font-size: 13px;
  color: var(--text-2);
  cursor: pointer;
  font-family: inherit;
  transition: all .15s;
}
.src-btn:hover { border-color: var(--brand); color: var(--brand); }
.src-btn.active { background: var(--brand-soft, #e7f4f1); border-color: var(--brand); color: var(--brand); font-weight: 600; }

/* ============================================================
   播放页左右两栏的版式（覆盖上面的通用样式）
   左栏 230px（海报 206x309 + 片名/元信息）、右栏 230px（线路 ｜ 集数 两列）。
   两栏都比正文窄，所以：字号收到 12~12.5px、按钮改纵向排列、
   线路名超过 5 字符用省略号（完整名字在按钮 title 里，悬停可见）。
   ============================================================ */

/* ---------- 左栏：海报 + 片名 + 元信息（纵向紧凑） ---------- */
.play-left .detail-top {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 0;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 0;
}
.play-left .detail-poster { width: 100%; box-shadow: none; border-radius: 6px; }
.play-left .detail-info h1 { font-size: 16px; font-weight: 500; margin-bottom: 6px; line-height: 1.35; }
.play-left .detail-meta { font-size: 12px; gap: 10px; margin-bottom: 6px; }
.play-left .detail-rate { font-size: 16px; font-weight: 500; }
.play-left .detail-info-rows { font-size: 12.5px; gap: 4px; margin-top: 5px; line-height: 1.5; }
.play-left .detail-info-rows .detail-row { display: block; }
.play-left .detail-info-rows .detail-row-label { display: inline; flex: none; font-size: 11px; margin-right: 4px; }
.play-left .detail-info-rows .detail-row-value { display: inline; }
.play-left .detail-detail { margin-top: 10px; padding-top: 8px; }
.play-left .detail-row { font-size: 12.5px; gap: 6px; line-height: 1.55; }
.play-left .detail-row-label { flex: 0 0 30px; font-size: 12px; }
.play-left .detail-plot { font-size: 12.5px; }
.play-left .plot-toggle { font-size: 12.5px; }

/* ---------- 右栏：标题 + 两列（线路 ｜ 集数） ---------- */
.play-right .sec-title {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 500;
  margin: 0 0 6px;
  gap: 4px;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
}
.play-right .sec-title .count { font-size: 11px; overflow: hidden; text-overflow: ellipsis; }
.play-right .play-tip { flex: 0 0 auto; font-size: 11px; margin: 0 0 6px; }
.play-right #cmsMsg { flex: 0 0 auto; font-size: 11px; margin-top: 6px; }

/* 线路列：分组标题 + 纵向按钮（按钮宽按内容自适应，长的靠省略号） */
.play-right .src-groups { margin: 0; display: flex; flex-direction: column; gap: 8px; }
.play-right .src-group { margin: 0; }
.play-right .src-group-name {
  font-size: 11px;
  font-weight: 500;
  margin-bottom: 4px;
  padding: 0 0 0 5px;
  border-left: 2px solid var(--brand);
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 线路按钮：**全部统一成同一个固定宽度**，宽度按「最长的那个线路名」定。
   ★ 宽度由 JS 量出来写进 --src-btn-w（见 play.js renderCmsSources）——
     只用 CSS 做不到「跨分组统一」：每个分组是独立的容器，
     grid/flex 只能让**组内**等宽，实测会出现 46 / 70 / 78 三种宽度。
     拿不到变量时退回贴合内容（auto），至少不会错。 */
.play-right .src-group-btns {
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: 2px;
}
.play-right .src-btn {
  width: var(--src-btn-w, auto);
  max-width: 100%;
  padding: 3px 6px;
  font-size: 12px;
  line-height: 1.35;
  border-radius: 5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 集数列：纵向铺满列宽（本地库的文件名列表也走这里，同一个规则） */
.play-right .ep-list { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 2px; margin-top: 0; }
/* ★★ flex: 0 0 auto 是必需品，不是保险丝：
   这个列表是 column flex。集数一多（实测 86 集 = 内容 2234px 挤进 438px 容器），
   item 默认 flex-shrink:1 会被**均匀压扁** —— 86 个按钮全压到 8px 高，
   而文字行高是 16px，被 overflow:hidden 从底部裁掉，
   整个列表于是变成一排「空白细条」（用户报的「第 10 集往后显示不出来」就是它）。
   ★ 不要指望 min-height:auto 兜底：item 带 overflow:hidden 时，
     按规范 auto 的最小尺寸会解析为 0，一点保护都没有。
   0 0 auto = 不放大 / 不收缩 / 按内容高度，纵向列表就该这样。 */
.play-right .ep-btn {
  flex: 0 0 auto;
  width: 100%;
  padding: 3px 5px;
  font-size: 12px;
  line-height: 1.35;
  border-radius: 5px;
  /* ★ 居中显示（用户最终选定，别再动）：
     0738f9a 曾改成靠左对齐（理由是集数名长短不一、居中时左边缘参差），
     用户看过实际效果后明确要求改回居中 —— 以实际观感为准，不要再改。 */
  text-align: center;
}

/* 窄栏里的提示块要收干净：.empty 原是 padding:60px（宽栏用），
   .spinner 是 margin:40px auto —— 放到 143px 的右栏里会撑出一大片空白 */
.play-right .empty { padding: 12px 4px; font-size: 12px; }
.play-right .empty.small { padding: 12px 4px; font-size: 11px; }
.play-right .spinner { width: 20px; height: 20px; margin: 16px auto; }
.play-right #cmsMsg:empty { display: none; }

/* 本地库面板在窄栏里的收尾 */
.play-right #noLocal .empty { font-size: 12px; }
.play-right .play-cta { margin-top: 10px; }
.play-right .play-cta .btn-primary { padding: 6px 12px; font-size: 12px; border-radius: 14px; }


/* ---------- 骨架屏 ---------- */
.skeleton .poster { background: linear-gradient(90deg,#eceef1 25%,#f5f6f8 37%,#eceef1 63%); background-size: 400% 100%; animation: sk 1.3s ease-in-out infinite; }
.skeleton .card-title { background: #eceef1; color: transparent; border-radius: 4px; width: 70%; }
.skeleton .card-sub { background: #f2f3f5; border-radius: 4px; width: 45%; }
@keyframes sk { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ---------- 加载更多 ---------- */
.more { text-align: center; margin: 30px 0 10px; }
.btn-more {
  padding: 10px 40px;
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 22px;
  font-size: 14px;
  color: var(--text-2);
  cursor: pointer;
  font-family: inherit;
  transition: all .2s;
}
.btn-more:hover:not(:disabled) { border-color: var(--brand); color: var(--brand); }
.btn-more:disabled { opacity: .5; cursor: default; }

/* ---------- 年份热播（首页「年份热播」分类：按年份自上而下分段） ---------- */
.year-block { margin-bottom: 36px; }
.year-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0 0 14px;
  padding-bottom: 9px;
  border-bottom: 1px solid var(--line);
}
.year-title { font-size: 16px; font-weight: 600; }
/* 年份前的小色条，让分段边界一眼可辨 */
.year-title::before {
  content: '';
  display: inline-block;
  width: 3px;
  height: 14px;
  margin-right: 8px;
  vertical-align: -1px;
  border-radius: 2px;
  background: var(--brand);
}
.year-meta { font-size: 12px; color: var(--text-3); margin-left: auto; }
/* 分段内的「加载更多」比整页的收敛一些，避免抢视觉 */
.year-block .more { margin: 18px 0 4px; }
.year-block .btn-more { padding: 8px 30px; font-size: 13px; }
.empty.small { padding: 26px 20px; font-size: 13px; }

/* ---------- 首页四段总览（电视剧 / 电影 / 综艺 / 动漫） ---------- */
.home-block { margin-bottom: 44px; }
.home-block .year-head { margin-bottom: 12px; }
/* btn-text 默认 margin-left:auto，这里和 .year-meta 抢空间，改成紧跟其后 */
.home-block .btn-text { margin-left: 12px; white-space: nowrap; font-size: 13px; }

/* 段内的国区切换 */
.region-bar { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 16px; }
.region-tag {
  padding: 5px 14px;
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 15px;
  font-size: 13px;
  color: var(--text-2);
  cursor: pointer;
  font-family: inherit;
  transition: border-color .15s, color .15s, background .15s;
}
.region-tag:hover { border-color: var(--brand); color: var(--brand); }
.region-tag.active {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}

@media (max-width: 640px) {
  .home-block { margin-bottom: 32px; }
  .region-tag { padding: 4px 11px; font-size: 12px; }
}

@media (max-width: 640px) {
  .year-block { margin-bottom: 28px; }
  .year-title { font-size: 15px; }
  .year-meta { font-size: 11px; }
}

/* ---------- 网盘结果列表 ---------- */
.pan-list { display: flex; flex-direction: column; gap: 12px; }

.pan-item {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  transition: border-color .2s, box-shadow .2s;
}
.pan-item:hover { border-color: #d5d9de; box-shadow: var(--shadow); }

.pan-head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 8px;
}
.pan-name {
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.5;
  flex: 1;
  word-break: break-all;
}
.pan-time { font-size: 12px; color: var(--text-3); white-space: nowrap; }

.pan-types { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.type-badge {
  font-size: 11.5px;
  color: #fff;
  padding: 1.5px 8px;
  border-radius: 10px;
  line-height: 1.6;
}

.pan-links { display: flex; flex-direction: column; gap: 7px; }

.link-row {
  display: flex;
  align-items: center;
  gap: 9px;
  background: #fafbfc;
  border: 1px solid #f0f1f3;
  border-radius: 7px;
  padding: 8px 11px;
  font-size: 13px;
  transition: background .18s, border-color .18s;
  cursor: pointer;             /* 整行可点 */
  position: relative;
}
.link-row:hover { background: #f4f8f7; border-color: #b9dcd7; }
.link-row:hover .lgo { opacity: 1; transform: translateX(0); }

/* 磁力/电驴：点击=复制，用不同色调区分 */
.link-row.no-jump { cursor: copy; }
.link-row.no-jump:hover { background: #fffaf3; border-color: #f0d9b5; }
.link-row.no-jump .lgo { color: #d97706; }

/* 本地直链：点击=播放 */
.link-row.playable { cursor: pointer; }
.link-row.playable .lgo { color: var(--brand); }

/* 右侧动作提示，hover 才完全显现 */
.lgo {
  font-size: 11.5px;
  color: var(--brand);
  white-space: nowrap;
  opacity: .55;
  transform: translateX(-3px);
  transition: opacity .18s, transform .18s;
}
.link-row .lname { font-weight: 500; white-space: nowrap; min-width: 62px; }
.link-row .lurl {
  flex: 1;
  color: var(--text-2);
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: ui-monospace, Menlo, Consolas, monospace;
}
.link-row .lpwd {
  font-size: 12px;
  color: #d97706;
  background: #fef3c7;
  padding: 1px 7px;
  border-radius: 4px;
  white-space: nowrap;
}
.btn-copy {
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 6px;
  padding: 3px 12px;
  font-size: 12.5px;
  cursor: pointer;
  color: var(--text-2);
  font-family: inherit;
  white-space: nowrap;
  transition: all .18s;
}
.btn-copy:hover { border-color: var(--brand); color: var(--brand); }
.btn-copy.done { border-color: var(--brand); color: #fff; background: var(--brand); }

.pan-content {
  font-size: 12.5px;
  color: var(--text-3);
  margin-bottom: 9px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-all;
}

.source-report {
  margin-top: 14px;
  font-size: 12px;
  color: var(--text-3);
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}
.source-report .ok { color: var(--brand); }
.source-report .fail { color: #ef4444; }

/* ---------- 空状态 / 加载 ---------- */
.empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-3);
  font-size: 14px;
}
.spinner {
  width: 26px;
  height: 26px;
  border: 2.5px solid var(--line);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: spin .8s linear infinite;
  margin: 40px auto;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- 提示 toast ---------- */
#toast {
  position: fixed;
  left: 50%;
  bottom: 42px;
  transform: translate(-50%, 20px);
  background: rgba(31, 35, 41, .93);
  color: #fff;
  font-size: 13.5px;
  padding: 9px 20px;
  border-radius: 20px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s, transform .25s;
  z-index: 999;
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- 确认弹窗（替代原生 confirm，见 common.js 的 uiConfirm） ----------
   配色全部取自 :root，跟页面同源：白卡片、灰字、品牌绿确定按钮。
   z-index 低于 #toast（999），保证弹窗开着时 toast 仍显示在最上层。 */
.ui-modal-mask {
  position: fixed;
  inset: 0;
  z-index: 998;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(31, 35, 41, .38);
  opacity: 0;
  transition: opacity .16s ease;
}
.ui-modal-mask.show { opacity: 1; }
.ui-modal {
  width: min(420px, 100%);
  max-height: calc(100vh - 40px);
  overflow: auto;
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 22px 24px 18px;
  transform: translateY(-8px) scale(.98);
  transition: transform .18s ease;
}
.ui-modal-mask.show .ui-modal { transform: none; }
.ui-modal-title { font-size: 16px; font-weight: 500; color: var(--text); }
.ui-modal-body {
  margin-top: 10px;
  font-size: 14.5px;
  line-height: 1.75;
  color: var(--text-2);
  white-space: pre-wrap;   /* 保留调用处文本里的换行与缩进（如详情页的多行确认文案） */
  word-break: break-word;
}
.ui-modal-foot { margin-top: 20px; display: flex; justify-content: flex-end; gap: 10px; }
.ui-btn {
  font: inherit;
  font-size: 14px;
  line-height: 1;
  padding: 9px 20px;
  border: 1px solid transparent;
  border-radius: 8px;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}
.ui-btn-ghost { background: var(--card); border-color: #dce0e5; color: var(--text-2); }
.ui-btn-ghost:hover { border-color: #c4cad2; color: var(--text); }
.ui-btn-primary { background: var(--brand); color: #fff; }
.ui-btn-primary:hover { background: var(--brand-dark); }

/* ---------- 详情页 ---------- */
.detail-top {
  display: flex;
  gap: 26px;
  background: #fff;
  border-radius: var(--radius);
  padding: 22px;
  margin: 22px 0;
  border: 1px solid var(--line);
}
.detail-poster {
  width: 230px;
  flex-shrink: 0;
  aspect-ratio: 2 / 3;
  border-radius: var(--radius);
  overflow: hidden;
  background: #eceef1;
  box-shadow: var(--shadow);
}
.detail-poster img { width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }
.detail-info { flex: 1; min-width: 0; }
.detail-info h1 { font-size: 24px; font-weight: 600; margin-bottom: 8px; line-height: 1.3; }
.detail-meta { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; margin-bottom: 14px; font-size: 13px; color: var(--text-2); }
.detail-rate { font-size: 20px; font-weight: 700; color: var(--rate); }
.detail-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }
.btn-primary {
  padding: 9px 22px;
  background: var(--brand);
  color: #fff;
  border: none;
  border-radius: 20px;
  font-size: 14px;
  cursor: pointer;
  font-family: inherit;
  transition: background .2s;
}
.btn-primary:hover { background: var(--brand-dark); }
.btn-ghost {
  padding: 9px 22px;
  background: #fff;
  color: var(--text-2);
  border: 1px solid var(--line);
  border-radius: 20px;
  font-size: 14px;
  cursor: pointer;
  font-family: inherit;
  transition: all .2s;
}
.btn-ghost:hover { border-color: var(--brand); color: var(--brand); }

.sec-title {
  font-size: 16px;
  font-weight: 600;
  margin: 26px 0 14px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.sec-title .count {
  font-size: 12.5px;
  font-weight: 400;
  color: var(--text-3);
}

/* 网盘类型筛选 */
.type-filter { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.tf {
  padding: 4px 14px;
  border: 1px solid var(--line);
  border-radius: 15px;
  background: #fff;
  font-size: 12.5px;
  cursor: pointer;
  color: var(--text-2);
  font-family: inherit;
  transition: all .18s;
}
.tf:hover { border-color: var(--brand); color: var(--brand); }
.tf.active { background: var(--brand); border-color: var(--brand); color: #fff; }

/* ---------- 本地库页 ---------- */
.local-bar {
  display: flex;
  gap: 12px;
  align-items: center;
  margin: 20px 0;
  flex-wrap: wrap;
}
.local-bar input {
  flex: 1;
  min-width: 200px;
  height: 38px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 19px;
  font-size: 14px;
  outline: none;
  background: #fff;
  font-family: inherit;
}
.local-bar input:focus { border-color: var(--brand); }
.local-stat { font-size: 13px; color: var(--text-3); }

.file-list { display: flex; flex-direction: column; gap: 9px; }
.file-row {
  display: flex;
  align-items: center;
  gap: 12px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px 16px;
  transition: border-color .18s, box-shadow .18s;
}
.file-row:hover { border-color: #d5d9de; box-shadow: var(--shadow); }
.file-icon {
  width: 34px;
  height: 34px;
  border-radius: 8px;
  background: #eef7f6;
  color: var(--brand);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  flex-shrink: 0;
  text-transform: uppercase;
}
.file-main { flex: 1; min-width: 0; }
.file-name { font-size: 14px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-path { font-size: 12px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-size { font-size: 12.5px; color: var(--text-2); white-space: nowrap; }

/* ---------- 页脚 ---------- */
.site-footer {
  border-top: 1px solid var(--line);
  background: #fff;
  margin-top: 50px;
  padding: 24px 0;
  text-align: center;
  font-size: 13px;
  color: var(--text-2);
}
.site-footer p { margin: 3px 0; }

/* ---------- 响应式 ---------- */
/* 桌面基准一行六个，窗口变窄时按档递减，不再自动增减列数 */
@media (max-width: 1180px) { .grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (max-width: 980px)  { .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

@media (max-width: 820px) {
  .header-inner { flex-wrap: wrap; height: auto; padding: 12px 0; gap: 12px; }
  .search-box { max-width: none; order: 3; flex-basis: 100%; }
  .nav { margin-left: 0; }
  .detail-top { flex-direction: column; }
  .detail-poster { width: 140px; margin: 0 auto; }
  .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px 12px; }
  .link-row { flex-wrap: wrap; }
  .link-row .lurl { flex-basis: 100%; order: 3; }
}

/* ============================================================
   卡片行内「采集」按钮（片名右边、网盘前面；颜色即状态）
   ============================================================ */
.btn-collect {
  flex: none;
  padding: 3px 9px;
  border: 1px solid #d5d9df;
  background: #fff;
  color: var(--text-2);
  border-radius: 12px;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
}
.btn-collect:hover:not(:disabled) {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}
/* 已在自动采集里：绿色实底 = 添加成功，不可再点 */
.btn-collect.added,
.btn-collect.added:disabled,
.btn-collect.added:hover {
  border-color: #1aa34a;
  background: #1aa34a;
  color: #fff;
  cursor: default;
}

/* ============================================================
   自动采集视图（卡片带海报 + 状态，可就地暂停 / 移出）
   ============================================================ */
.watch-card { cursor: default; }
.watch-card.off { opacity: .62; }

/* 自动采集列表的网格：卡片要放得下右侧的信息列，所以比首页的六列宽得多 */
.watch-grid { grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); gap: 18px; }

/* 卡片改横向：左边「海报 + 三个按钮」（同一列，宽度天然一致）；
   右边信息纵列（片名 / 状态 / 线路） */
.wc-main { display: flex; align-items: flex-start; gap: 12px; }
.wc-left { flex: 0 0 150px; width: 150px; }
.watch-card:hover .poster { transform: none; box-shadow: var(--shadow); }
/* 按钮只占海报那点宽度，所以做得更紧凑一点 */
.watch-card .wc-actions { margin-top: 7px; gap: 4px; }
.watch-card .wc-btn { padding: 2px 0; font-size: 11px; border-radius: 9px; }
.wc-info { flex: 1; min-width: 0; }
.watch-card .card-title-row { margin-top: 0; }
.watch-card .wc-lines { margin-top: 8px; }

/* 信息列里的文字适当放大（只作用于自动采集卡片，首页那套六列不受影响） */
.watch-card .card-title { font-size: 20px; }
.watch-card .card-sub { font-size: 15px; }
/* 剧名行右侧的两枚小药丸（同名合并 / 同步时间）：卡片里字号抬到 12px 才跟得上 20px 的剧名；
   剧名是 flex:1，把药丸顶到最右，标题过长时由剧名自己省略号（药丸 flex:0 0 auto 不被压扁） */
.watch-card .card-title-row .wl-merge,
.watch-card .card-title-row .wl-sync,
.watch-card .card-title-row .wl-hide { font-size: 12px; }
.watch-card .wl-row { font-size: 15px; gap: 6px; }
.watch-card .wl-tag { font-size: 15px; line-height: 22px; padding: 0 7px; }

/* 信息列里不截断：状态允许换行，别再出现「显示不全」 */
.watch-card .card-sub { height: auto; white-space: normal; overflow: visible; line-height: 1.45; }
.watch-card .card-sub.ok  { color: var(--brand); }
.watch-card .card-sub.bad { color: #ef4444; }

/* 没海报时显示首字占位（有图时 .poster 不带 noimg，占位自动隐藏） */
.wc-ph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 34px;
  font-weight: 700;
  color: #c3c8cf;
  user-select: none;
}
.poster:not(.noimg) .wc-ph { display: none; }

.wc-del {
  position: absolute;
  right: 6px;
  top: 6px;
  width: 22px;
  height: 22px;
  padding: 0;
  line-height: 1;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  font-size: 12px;
  cursor: pointer;
  opacity: 0;
  transition: opacity .15s, background .15s;
}
.watch-card:hover .wc-del { opacity: 1; }
.wc-del:hover { background: #ef4444; }
@media (hover: none) { .wc-del { opacity: 1; } }

.wc-paused {
  position: absolute;
  left: 6px;
  top: 6px;
  background: rgba(0, 0, 0, .6);
  color: #fff;
  font-size: 11px;
  padding: 1px 6px;
  border-radius: 4px;
}

.wc-actions { display: flex; gap: 6px; margin-top: 7px; }
.wc-btn {
  flex: 1;
  padding: 4px 8px;
  border: 1px solid var(--brand);
  background: #fff;
  color: var(--brand);
  border-radius: 12px;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
}
.wc-btn:hover { background: var(--brand); color: #fff; }
.wc-btn:disabled { opacity: .5; cursor: default; }
.wc-btn.ghost { border-color: var(--line); color: var(--text-2); }
.wc-btn.ghost:hover { background: #fdecec; border-color: #f5b5b5; color: #d64545; }
/* 「采集」：实心主色，与「暂停 / 移出」拉开主次 */
.wc-btn.run { background: var(--brand); border-color: var(--brand); color: #fff; }
.wc-btn.run:hover { background: var(--brand); color: #fff; filter: brightness(1.08); }
.wc-btn.run:disabled { background: var(--brand); color: #fff; opacity: .6; }

/* ------------------------------------------------------------
   图片下面的两行线路信息：上行 = 你CMS里实际存的（反查）
                           下行 = 采集源侧（= 推给CMS的内容）
   gap 特意调到 14px：两行内容都是「一堆线路胶囊」，形状几乎一样、只靠 CMS/源 标签区分，
   6px 时两行会糊成一片；拉开后视线能明确落在「哪一行在读」上。
   这个 gap 只作用两行之间，不动上方的状态文字到本块的距离（那条由
   .watch-card .wc-lines 的 margin-top: 8px 管，两者互不影响）。
   ------------------------------------------------------------ */
.wc-lines { margin-top: 6px; display: flex; flex-direction: column; gap: 14px; }
.wl-row {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-size: 10.5px;
  line-height: 1.45;
  color: var(--text-2);
  word-break: break-word;
}
.wl-row.dim { color: var(--text-3); }
.wl-row span { min-width: 0; }
.wl-tag {
  flex: 0 0 50px;          /* CMS / 源 强制等宽：两行的线路胶囊从同一条竖线开始 */
  text-align: center;
  font-weight: 400;
  font-size: 9.5px;
  line-height: 14px;
  padding: 0 4px;
  border-radius: 999px;
  white-space: nowrap;
}
.wl-tag.cms { background: #ecf3ff; color: #3f6fd0; }
.wl-tag.src { background: #eaf6f1; color: #3f8a63; }

/* 线路胶囊：一条线路一个（加深浅底圆角），里面是「线路名 - 集数圆」。
   长度不按内容走 —— **所有胶囊统一固定 90px**（grid 每格定宽，不随内容伸缩），
   线路名左对齐、集数圆靠右：这样一列排下来左右两条边都是齐的，数字也落在同一条竖线上。
   宽度只有 90px，很紧，所以右半边全部压到最小：「-」和集数圆紧贴胶囊右缘，
   把省下的横向空间都留给线路名（右 padding 5px、圆自身 padding 3px），免得名字掉字母。
   线路名过长时仍用省略号兜底（完整名在 title 提示里）。
   grid 的 auto-fill 需要容器有确定宽度，所以 .wl-chips 必须 flex:1 占满标签右侧的剩余空间。 */
.wl-chips {
  flex: 1;
  display: grid;
  /* ★ 改成固定 3 列（原先是 auto-fill + 定宽 90px，容器宽度只排得下 2 个）。
     用 minmax(0,1fr) 等分：容器约 280px 时每列 ≈ (280-2×6)/3 ≈ 89px，
     和原来的 90px 几乎一样，所以胶囊内部排版（线路名 41px + 集数圆）不受影响；
     同时窄屏也能自适应收缩，不会溢出。
     gap 由 8px 收到 6px，把省下的横向空间还回给胶囊宽度。 */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  min-width: 0;
}
.wl-chip {
  /* ★ 要给「源比 CMS 多 N 集」的 +N 角标当定位父级（角标挂在胶囊外，见 .wl-plus） */
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 100%;
  /* 内边距由 0 5px 0 9px 收到 0 3px 0 6px：省下 5px 全给线路名。
     和下面 em / i 的两处收窄是一组（三处一共腾出 8px），缺一个就不够。 */
  padding: 0 3px 0 6px;
  border: 1px solid #2a9d8f;
  border-radius: 999px;
  background: #dce4ec;
  line-height: 22px;
  font-size: 15px;
  white-space: nowrap;
  /* ★ 不能再用 hidden：+N 角标要「长出」胶囊边界。
     线路名的省略号是 .wl-chip b 自己的 overflow:hidden 负责的，不受影响
     （实测：改 visible 后名字 0/62 被挤，与改前完全一致）。 */
  overflow: visible;
}
.wl-chip b { font-weight: 500; color: var(--text); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* 简写名后面的超小角标：xiguam3u8 在界面上显示成 xigua，缀一个角标用来跟
   「本来就叫 xigua」的另一条线路区分开。宽度刻意只占**一个字母**（实测 8.8px）。
   ★ 必须是独立元素、不能串进 <b> —— 串进去会被省略号连角标一起吃掉。
   ★ 它占的宽度是从分隔号「-」那儿让出来的（简写过的线路不画横杠，见 app.js#lineChips）：
     实测即便角标只有 5.9px，保留横杠也会把名字挤出一个省略号（盒子只剩 0.6px 余量）。
   ★ align-self:flex-start + 小 margin-top = 贴在名字右上角（不是垂直居中）。
   ★ 想换角标文字改 app.js#lineChips 里那一个字符即可（现在用 M）。 */
.ln-sfx {
  flex: 0 0 auto;
  align-self: flex-start;
  margin: 2px 0 0 1px;
  padding: 0 1px;
  border-radius: 2px;
  font-size: 7px;
  line-height: 8px;
  letter-spacing: 0;
  color: #fff;
  background: #9aa4b2;
}
/* ★★ 「源比 CMS 多 N 集」的角标（如 +5）：挂在**集数圆正上方、溢出到胶囊外**。
   为什么必须挂在外面：胶囊内部一点余量都没有 —— qsvip 这种名字需求 38px、容器正好
   38px（余量 0），而角标要占 23px。实测硬塞进胶囊里会把名字挤成省略号（3 列网格下
   62 个胶囊里挤坏 22 个）。挂到外面后：名字 0/62 被挤、与相邻胶囊重叠 0 次。
   ★ 只向上溢出、**绝不向右溢出** —— 右边紧接着就是下一个胶囊的名字。
   ★ 位置由 .wl-chip 的 position:relative + overflow:visible 支撑（两者缺一不可）。
   语义：源站比 CMS 多几集（= 下次采集会补上的量）。CMS 里完全没有这条线路时不显示。 */
.wl-plus {
  position: absolute;
  right: 0;
  top: -7px;
  z-index: 3;
  padding: 0 3px;
  border-radius: 7px;
  font-size: 9px;
  line-height: 12px;
  font-weight: 600;
  letter-spacing: -.2px;
  color: #854F0B;
  background: #FAEEDA;
  box-shadow: 0 0 0 1px #fff;
  white-space: nowrap;
  cursor: inherit;
}

/* 分隔号：左边 margin:auto 把「- 集数」整体推到胶囊右端（贴到最小间距），各胶囊的数字因此对齐。
   ★ margin-left:auto 千万别去掉 —— 去掉以后集数圆会紧贴线路名（tv189 15 读起来像 tv18915）。
   font-size 由继承的 15px 收到 11px：横杠细一点，省下约 4px 给线路名。 */
.wl-chip em { font-style: normal; font-size: 11px; margin: 0 0 0 auto; color: var(--text-3); flex: 0 0 auto; }
/* 集数圆标：白字数字 + 主色圆底，跟在分隔号后面（不参与收缩，永远是个圆）。
   padding 4px→3px→1px、min-width 16px→14px，同样是为了把宽度让给线路名。
   ★ 实测（真实浏览器 / 1080 视口 / 真实数据 53 个胶囊，判定用 scrollWidth > clientWidth，
     即 >0 就算被省略号切 —— 零点几像素的溢出浏览器照样画省略号，别用 ≤1px 当"完好"）：
       · 3 列网格容器 234px → 每列 74px；固定开销（内边距 + 横杠 + 集数圆）收窄前吃掉 42px
       · 收窄前：留给线路名 32px，53 个里 41 个有省略号（tv189 差 8px）
       · 收窄后：留给线路名 38~40px，53 个里 0 个有省略号
       · 库内最长名实测需求：tv189 40px / YDZX 39px / xigua 39px / qsvip 38px
   ⇒ 这已经是"不动网格列数、不改字号"的前提下能腾出来的极限。若要再加宽，先按上面的方法量一遍。 */
.wl-chip i {
  box-sizing: border-box;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 14px;
  height: 16px;
  padding: 0 1px;
  font-style: normal;
  font-size: 10px;
  line-height: 1;
  font-weight: 600;
  letter-spacing: -.2px;
  color: #fff;
  background: var(--brand);
  border-radius: 999px;
}

/* 可点的胶囊（源侧那行）渲染成 <button>，样式与只读的 <span> 共用 .wl-chip，
   这里补按钮特有的：继承字体（button 默认不继承）、手型、悬停反馈，
   以及 **整套蓝色（边框 + 底色）** —— 两行线路的形状完全一样，只靠 CMS/源 两个标签区分，
   一绿一蓝之后扫一眼就知道哪行是哪行（绿=你CMS里实际存的，蓝=采集源）。
   边框蓝取 #3b82f6：站点报错红用的是 #ef4444（Tailwind red-500），
   蓝同取 Tailwind blue-500，色系一致；又比 CMS 标签的 #3f6fd0 更亮，不会跟标签混成一片。
   底色由共用 .wl-chip 的冷灰 #dce4ec 换成**同色相的淡蓝 #e8f0fe** ——
   只给整行"染个调"、不抢内容（大色块才醒目，单靠 1px 边框还是弱）；
   CMS 行的冷灰底保持不变，两行因此连底色都不同。
   全局 reset 已有 box-sizing:border-box + margin/padding:0，不必再重置一遍，
   所以尺寸与只读胶囊完全一致，不会因为变成按钮就变宽变高。
   ★ 特异性：(0,1,1) 低于 .wl-chip.off 的 (0,2,0) —— 「已关闭」的线路仍是灰底灰框 +
   名字划线，不会被这套蓝覆盖（这正是想要的：蓝=在采，灰=已关闭）。 */
button.wl-chip {
  font-family: inherit;
  cursor: pointer;
  transition: background .15s, border-color .15s;
  border-color: #3b82f6;
  background: #e8f0fe;
}
/* hover 必须跟着换蓝：底色已经变蓝，再沿用原来那档灰 #cfd9e3 会很突兀 */
button.wl-chip:hover { background: #d4e4fc; }
button.wl-chip:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }

/* 已关闭的线路：灰底 + 名字划掉 + 集数圆变灰 —— 扫一眼就知道「这条不采」 */
.wl-chip.off { background: #eef1f4; border-color: #dae1e8; }
.wl-chip.off b { color: var(--text-3); text-decoration: line-through; }
.wl-chip.off i { background: #b7c0ca; }
button.wl-chip.off:hover { background: #e6ebf0; }

/* 同名条目合并提示 / 同步时间：两枚小药丸，都挂在**剧名行右侧**。
   （原先挂在源侧那行的末尾 —— 那行是 flex 横排，药丸会和 90px 固定列的
     .wl-chips 抢宽度，线路一多就被挤成一列，所以整体挪到剧名行。）
   剧名行 .card-title-row 是 align-items:center，这里不再需要 align-self/margin-top。 */
.wl-merge {
  flex: 0 0 auto;
  padding: 1px 7px;
  border-radius: 9px;
  font-size: 11px;
  line-height: 1.6;
  color: var(--brand-dark);
  background: rgba(42, 157, 143, .1);
  white-space: nowrap;
}

/* ★ 「同名 N 条已合并 · M 个源」这枚药丸放在**海报的左下角、盖在图上**（不再放剧名行）。
   位置是 left:6px + bottom:6px —— 海报左上角已经被「已暂停」（.wc-paused）占了、
   右上角是 ✕（.wc-del），只有左下角是空的，摆这儿谁都不撞。
   为什么从剧名行挪走：它一个就占 145px，而剧名行总共才 290px；跟「同步」+「已隐藏」叠一起是
   301px > 290px —— 剧名被 flex 压成 **0px**，7 部剧一个字都看不见（实测 7/7 都这样）。
   挪到图上以后剧名行只剩两枚小药丸（73 + 83），名字就有位置了。
   配色必须换一套：海报是照片，原来那浅绿底 + 深绿字糊在图上根本看不清 ⇒ 深色半透明 + 白字。
   海报比药丸窄，所以字号收到 10px 并允许折行（完整说明在 title 悬停里）。 */
.poster > .wl-merge {
  position: absolute;
  left: 6px;
  bottom: 6px;
  z-index: 2;
  max-width: calc(100% - 12px);
  padding: 1px 6px;
  font-size: 10px;
  line-height: 1.5;
  color: #fff;
  background: rgba(0, 0, 0, .55);
  white-space: normal;
  overflow: hidden;
}

/* 同步时间：这行线路是「几时从采集站读回来的」。
   用中性灰，别跟「同名已合并」的绿药丸抢注意力：那说的是内容，这只说新鲜度。 */
.wl-sync {
  flex: 0 0 auto;
  padding: 1px 7px;
  border-radius: 9px;
  font-size: 11px;
  line-height: 1.6;
  color: var(--text-2);
  background: #eef1f4;
  white-space: nowrap;
}

/* ★ 「同步 16:26」也挪到**海报上**，摆在「同名合并」那枚的正上方（都在左下角）。
   为什么必须叠起来：两枚一起宽 121 + 55 = 176px，而海报内宽只有 138px ——
   一左一右放会直接重叠，所以只能上下叠。
   为什么挪：剧名行总宽只有 290px，原来「同名合并(145) + 同步(73) + 已隐藏(83) = 301px」
   把剧名压成 0px。两枚都挪到图上以后，剧名行只剩「已隐藏」一枚 ⇒
   剧名可用宽度 ≈ 200px，连 9 个字的「法医秦明之龙番往事」（180px）都放得下。
   配色跟海报上另一枚统一：深色半透明 + 白字（浅灰底贴在照片上看不清）。 */
.poster > .wl-sync {
  position: absolute;
  left: 6px;
  bottom: 28px;
  z-index: 2;
  padding: 1px 6px;
  font-size: 10px;
  line-height: 1.5;
  color: #fff;
  background: rgba(0, 0, 0, .55);
}

.wl-none { font-size: 15px; color: var(--text-3); }

/* ------------------------------------------------------------
   运行日志列（自动采集页右侧：实时显示后台在干什么）
   ------------------------------------------------------------ */
.watch-layout {
  display: flex;
  align-items: flex-start;
  gap: 20px;
}
.watch-layout > .grid { flex: 1; min-width: 0; }

.log-panel {
  flex: 0 0 280px;
  width: 280px;
  position: sticky;
  top: 78px;                       /* 贴着顶栏下方 */
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 120px);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}
/* 收起日志列：卡片区独占整行（海报恢复全宽尺寸） */
#watchArea.log-folded .log-panel { display: none; }

.log-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--line);
  background: #fbfbfc;
}
.log-title { flex: 1; font-size: 13px; font-weight: 600; }
.log-state { font-size: 11px; color: var(--text-3); white-space: nowrap; }
.log-state.busy { color: var(--brand); }
.log-state.busy::before {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 4px;
  vertical-align: 1px;
  border-radius: 50%;
  background: currentColor;
  animation: logpulse 1s ease-in-out infinite;
}
@keyframes logpulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

.log-list {
  flex: 1;
  min-height: 120px;
  overflow-y: auto;
  padding: 6px 10px 10px;
  font-size: 12px;
  line-height: 1.5;
}
.log-row {
  display: flex;
  gap: 6px;
  padding: 3px 0;
  border-bottom: 1px dashed #f2f3f5;
}
.log-time { flex: none; color: var(--text-3); font-variant-numeric: tabular-nums; }
.log-text { flex: 1; min-width: 0; color: var(--text-2); word-break: break-word; }
.log-row.lv-ok   .log-text { color: #1a8f42; }
.log-row.lv-warn .log-text { color: #b7791f; }
.log-row.lv-err  .log-text { color: #d64545; font-weight: 500; }
.log-empty { color: var(--text-3); text-align: center; padding: 20px 6px; }

@media (max-width: 980px) {
  .watch-layout { flex-direction: column; }
  .log-panel { position: static; width: 100%; flex: none; max-height: 240px; }
  /* 窄屏放不下「海报 + 信息列」，改成一行一张，信息列独占剩余宽度 */
  .watch-grid { grid-template-columns: 1fr; }
}
