/* ============================================================
   潜龙八字 · 运岁「三行下钻」（xy3.css）  UIUX-v3 · 260921
   ------------------------------------------------------------
   owner 定稿口径（v3 推翻 v2 的三列并列）：
     「分成三行 —— 第一行起小运+大运，第二行点进去大运的流年，
       第三行流年点进去的流月。」
   ⇒ 三行**横向时间轴**，逐级下钻；每行可横滑；三行**在所有骨架下同一套版式**。

        ┌──────────────────────────────────────────────┐
   ①    │ 小运（1 格）    │  大运（10 段）              │
        └──────────────────────────────────────────────┘
        ┌──────────────────────────────────────────────┐
   ②    │ 流年 —— 由上方选中的大运决定（10 年）          │
        └──────────────────────────────────────────────┘
        ┌──────────────────────────────────────────────┐
   ②③  │ 流月 —— 由上方选中的流年决定（12 节气月）      │
        └──────────────────────────────────────────────┘

   ★ 实现方式 ＝ **纯 CSS 重排既有 DOM，零 JS 改动**：
     `js/app.js` 本来就把四个 `.xy-pane` 全部渲染进 DOM（只靠 `hidden` 切换），
     而**下钻交互也早就实现了**：
       · 点 `[data-dayun]`   → `state.detailFocus.dayunStep` → `renderDetailPage()` 重建流年列
       · 点 `[data-liunian]` → `state.detailFocus.liunianIdx` → `updateDetail()` 重建流月列
     所以本文件只是把「同一份 DOM 的页签排法」改成「三行排法」，并隐藏页签切换器。

   ⛔ 不新增断点真源：骨架差异只用 #viewportStage[data-shell=...]（不用 @media 断点）。
   ⛔ 注释内禁写「星号紧跟斜杠」的片段（硬教训 10）。
   ============================================================ */

/* ============================================================
   0 · 可调参数
   ============================================================ */
#viewportStage{
  --xy-row-gap: 6px;            /* 三框之间的间距 */
  --xy-pad: 8px;                /* 框内边距（★ 皮肤层 skins/epic.patch.css 引用 ⇒ 改名/删除须同批） */
  /* ★★ 260923 三框制：第一框 **11 格等宽**（小运 1 格 ＋ 大运 10 格）★★
     owner 口径：「第一框 11 个可点击框格**平均分布**，分别为小运和十个大运」。
     ⛔ 旧值 `0.34 : 1`（小运独占逾三成行宽）正是 owner「小运框太大了」的量化根因。
     ⚠ 大运格数 = 引擎 `dayun.pillars.length`（260923 起恒 10，见 core.js::calcDayun 注释）。

     ⛔ 只写 `1fr : 10fr` 是**不够**的：两个 pane 各自有 border + padding，右侧 pane 还有
        9 个内部 gap，纯 fr 比会把它们算在外面 ⇒ 实测 wide 档「小运格 72px vs 大运格 85px」，
        差约 15%，与 owner「平均分布」不符。
     ✅ 反解补偿（设 p = 2·border + 2·pad，g = 单元间距，G = 两 pane 间距）：
          令  cA − p = (cB − p − 9g) / 10   且   cA + cB + G = 100%
          ⇒  cA = (100% + 9(p − g) − G) / 11
        ⇒ 骨架只改 `--xy-pad` / `--xy-gap` / `--xy-row-gap`，补偿量**自动跟随**，
          **不需要任何固定像素格宽**。 */
  --xy-c1-k: calc(9 * (2px + 2 * var(--xy-pad) - var(--xy-gap)) - var(--xy-row-gap));
  --xy-c1-a: minmax(0, calc((100% + var(--xy-c1-k)) / 11));
  --xy-c1-b: minmax(0, calc(100% - var(--xy-row-gap) - (100% + var(--xy-c1-k)) / 11));
  --xy-strip-h: 96px;           /* 行内条最小高度（统一视觉节奏） */
  /* ★★ 260923：单元宽**改由 grid 等分决定**，固定宽族整体退场 ★★
     ⛔ 旧制 = 固定 `--xy-item-w*` + 横滑，正是「46px 格内塞 90px 内容」的成因
        （实测：流年格 clientW=44 而 scrollW=90；流月格 42/96）⇒ owner「吞了那么多字」。
     ✅ 新制：`.tl-scroll` 用 `grid-auto-flow:column` + `grid-auto-columns:minmax(var(--xy-item-min),1fr)`
        ⇒ 格数由 DOM 子元素数决定、宽度自动等分，**不再需要任何固定宽变量**。
     ⇒ 旧变量 `--xy-item-w / -dy / -ly / -lm` **已删除**（全仓仅本文件声明、皮肤层零引用，已核）。
     仅保留 `--xy-item-min`：手机端等分后单格过窄会压坏文字 ⇒ 该档给下限并允许横滑兜底。 */
  --xy-item-min: 0px;
  --xy-gap: 4px;                /* 单元间距 */
}

/* ============================================================
   1 · 三行骨架（手机 / 平板 / 桌面共用同一套；只有比例微调）
   ============================================================ */
.tl-card[data-stack="xingyun"]{
  display: grid;
  grid-template-columns: var(--xy-c1-a) var(--xy-c1-b);
  grid-template-areas:
    "xy dy"
    "ln ln"
    "ly ly";
  row-gap: var(--xy-row-gap);
  column-gap: var(--xy-row-gap);
  padding: var(--xy-pad);
  align-items: stretch;
}

/* 页签退场：三行并列之后不再需要切换器（下钻即为交互） */
.tl-card[data-stack="xingyun"] > .xy-tabs{ display: none; }

/* 解禁 hidden：四页签本来就都在 DOM 里 */
.tl-card[data-stack="xingyun"] > .xy-pane[hidden]{ display: grid; }

/* 每个 pane ＝ 一行：行头（① ② ③ 标签）+ 横向条 + 可选行脚 */
.tl-card[data-stack="xingyun"] > .xy-pane{
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
}
.tl-card[data-stack="xingyun"] > [data-pane="xiaoyun"]{ grid-area: xy; }
.tl-card[data-stack="xingyun"] > [data-pane="dayun"]{   grid-area: dy; }
.tl-card[data-stack="xingyun"] > [data-pane="liunian"]{ grid-area: ln; }
.tl-card[data-stack="xingyun"] > [data-pane="liuyue"]{  grid-area: ly; }

/* ---------- 行头：把原来"页签下面的说明行"提成**行标题** ---------- */
.tl-card[data-stack="xingyun"] > .xy-pane > .tl-head{
  background: var(--surface-3);
  border-bottom: 1px solid var(--line-strong);
  padding: 7px 10px;
  display: flex; align-items: center; gap: 8px;
}
.tl-card[data-stack="xingyun"] > .xy-pane > .tl-head::before{
  font-size: var(--fs-min, 12px);
  font-weight: 800;
  color: var(--brand);
  letter-spacing: 1px;
  flex: none;
}
.tl-card[data-stack="xingyun"] > [data-pane="xiaoyun"] > .tl-head::before{ content: "① 小运"; }
.tl-card[data-stack="xingyun"] > [data-pane="dayun"] > .tl-head::before{ content: "① 大运"; }
.tl-card[data-stack="xingyun"] > [data-pane="liunian"] > .tl-head::before{ content: "② 流年"; }
.tl-card[data-stack="xingyun"] > [data-pane="liuyue"] > .tl-head::before{ content: "③ 流月"; }
/* 行头内的旧 `.lt` 退场（避免与上方标签重复）；右侧说明保留并统一字号 */
.tl-card[data-stack="xingyun"] > .xy-pane > .tl-head .lt{ display: none; }
.tl-card[data-stack="xingyun"] > .xy-pane > .tl-head .r-info{ font-size: var(--fs-min, 12px); }
/* 下钻提示：第二行/第三行给出「上一级选了什么」的可读指向 */
.tl-card[data-stack="xingyun"] > [data-pane="liunian"] > .tl-head::after,
.tl-card[data-stack="xingyun"] > [data-pane="liuyue"] > .tl-head::after{
  content: "← 点上方切换";
  margin-left: auto;
  font-size: var(--fs-min, 12px);
  color: var(--ink-3);
  font-weight: 600;
}

/* ---------- 行内条：三框制 = **grid 等分**（不再横滑、不再固定单元宽） ----------
   ★★ 260923 改造 ★★
   · `grid-auto-flow: column` + `grid-auto-columns: minmax(var(--xy-item-min), 1fr)`
     ⇒ 格数由子元素数决定（小运段 1 / 大运 10 / 流年 10 或小运段 N / 流月 12），**每格等宽平摊整行**；
   · 等分后必然「一屏放下」⇒ **不再需要横滑**（`overflow: hidden`）。旧制的
     `scroll-snap-type` / 滚动条染色 / `:hover` 显形等一整套横滑配套样式随之全部退场。
   · 手机档另在 §2 给 `--xy-item-min` 下限 + `overflow-x:auto` 兜底（等分过窄时唯一可滑的场景）。 */
.tl-card[data-stack="xingyun"] > .xy-pane > .tl-scroll{
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(var(--xy-item-min, 0px), 1fr);
  gap: var(--xy-gap, 4px);
  padding: var(--xy-pad);
  overflow: hidden;
  /* ★ 260923 补：`app.css` 的 `.tl-scroll` 带 `scroll-snap-type:x mandatory`（横滑时代遗留），
     等分制下不再横滑 ⇒ 必须**显式清零**。实测未清时 dayun 条计算值仍为 `x mandatory`
     （xiaoyun 条因另有规则得 `none` ⇒ 三条不一致），属「同一制式两种状态」的隐性矛盾。 */
  scroll-snap-type: none;
  min-height: var(--xy-strip-h);
  min-width: 0;
}

/* 行内单元：小卡（竖排信息：岁/年 · 干支 · 十神）
   ★ 260923：宽度**交给 grid 等分** ⇒ 本节不再声明 width / max-width / flex
     （原 `flex:0 0 auto` + `--xy-item-w` 固定宽正是「46px 格内塞 90px 内容」的成因，已废）。 */
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item{
  min-width: 0;
  display: grid;
  /* ★★ 260923 复位：**必须显式写单列**（本行是整个三框制的关键补丁）★★
     ⛔ 根因：`app.css` 三处**按页签**的老模板至今仍在生效 ——
          `[data-pane="xiaoyun"] .tl-item{grid-template-columns:78px minmax(0,1fr) minmax(0,1fr)}`
          `[data-pane="liunian"] .tl-item{grid-template-columns:54px minmax(0,1fr) minmax(0,1fr) auto}`
          `[data-pane="liuyue"]  .tl-item{grid-template-columns:60px minmax(0,1fr) minmax(0,1fr)}`
        那是**横排卡**时代的版式（每格宽 100–140px，年份｜干支｜十神 三列并排）。
        三框制只声明了 `grid-template-rows`（4 行竖排），**从未复位 columns**
        ⇒ 每格变成「4 行 × 3~4 列」的杂交网格，子元素按 row-major 落到 (r1,c1)(r1,c2)(r1,c3)…
        ⇒ 实测（390px）小运格计算值 `grid-template-columns: 78px 0px 0px`：
          首列 78px 塞进 38px 内容框 ⇒ `.gz`/`.ss` 盒宽被压成 **0px**（内容外溢 34px），
          整格 `scrollWidth 116 vs clientWidth 42` ⇒ owner「吞了那么多字」的直接成因。
     ✅ 复位为单列 ⇒ 子元素回归**竖直堆叠**（岁/年 · 干支 · 十神 · 信号 · 引动 · 关系），
        与 xy3 的 `grid-template-rows` 配套，格子多窄都不会把兄弟行挤成 0 宽。
     ⚠ 老模板**不在本批删除**（`app.css` 非本线真源、且删它会牵动 `readability.css` 的同族覆盖），
        由本行「后加载 + 同特异度」压制即可；如需清退须另开一批并同步 `audit_shell.py`。 */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto auto auto;
  gap: 1px;
  align-content: start;
  justify-items: center;
  text-align: center;
  padding: 5px 3px;
  margin: 0;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--surface-2);
  cursor: pointer;
  box-sizing: border-box;
  /* ★★ 260923：裁剪方式从 `hidden` 改 `clip` ＋ `overflow-clip-margin` ★★
     ⛔ 起因（实测坐实）：本档给单元格加 `overflow:hidden` 后，「今年所在格」的
        `.now-badge`（`app.css` 定死 `top:-5px; right:-4px`，21.5×18px）被裁掉
        **右 3px ＋ 上 4px**（390/1760 两档同值，逐壳一致）—— 角标是
        「今年 vs 焦点」的唯一显式标记（本轮刚拆开的语义），被削掉顶部三成笔画即失效。
        设计原意是让角标**挂在格角外侧**、正好落在 `--xy-gap` 的缝里（4px）。
     ✅ `overflow:clip` ＋ `overflow-clip-margin:6px` ＝ 只在**超出 6px** 处才裁：
        角标外挂 4px ⇒ 完整可见；而任何真正的文字外溢（>6px）仍被拦下，
        不会糊到邻格上。且 `clip` **不产生滚动容器**，语义比 `hidden` 更干净。
     ⚠ 保留一行 `overflow:hidden` 作**老引擎兜底**（不认识 `clip` 时退回旧行为＝角标被削，
        属可接受的降级，不是错值）。 */
  overflow: hidden;
  overflow: clip;
  overflow-clip-margin: 6px;
}
/* 关系芯片 / 引动说明：整宽另起一行 */
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item .age,
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item .dayun-act,
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item .dayun-align{
  justify-self: stretch;
  text-align: center;
}
/* ★ 260923：原「大运/小运略宽 · 流年次之 · 流月最窄」三段**差异化格宽整体删除** ——
   三框制下「每格等宽」是 owner 明确口径（「11 个可点击框格**平均分布**」），
   信息量差异改由「格内换行 + 逐层字号」消化（见下方 §单元内字号与换行），不再靠格宽区分。 */

/* ---------- 260922-r2 · 单元内字号与换行（owner「强化弱化字体根本渲染错误」）----------
   ⛔ 旧版无字号约束 ⇒ `.ss`（十神/信号）继承默认字号，在 46px 宽单元内
      ① 溢出被 `overflow:hidden` 裁掉；② 「强化/弱化」与十神挤在同一基线、互相压字
      ⇒ 表现为「字体渲染错误」。正解＝**逐层定字 + 各占一行 + 允许必要换行**。 */
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item .y{
  font-size: var(--fs-min-2, 10.5px);
  line-height: 1.25;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item .gz{
  font-size: var(--fs);
  line-height: 1.2;
  font-weight: 700;
  white-space: nowrap;
  max-width: 100%;
}
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item .ss{
  font-size: var(--fs-min-2, 10.5px);
  line-height: 1.25;
  color: var(--ink-3);
  white-space: normal;          /* 十神名可折行（2 字一格内放得下） */
  word-break: break-all;
  max-width: 100%;
  text-align: center;
}
/* 「强化 / 弱化」信号：独立一格、独立字号（不再与十神挤压） */
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item [class*="sig"],
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item .dayun-align,
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item .dayun-act{
  font-size: var(--fs-min-2, 10.5px);
  line-height: 1.3;
  white-space: normal;
  word-break: break-all;
  max-width: 100%;
}

/* 「今年所在格」= `.thisyear`（中性加重；另带「今」角标），与下方**.now（焦点）**刻意区分开。
   ★ 260923 拆分理由：旧版两者都挂 `.now` ⇒ 在「含今年」的运里会**同时亮两格且外观完全相同**，
     用户点了别的运/年无法分辨哪格是选中项；且 `updateDetail()` 的 toggle 只设 `now`
     ⇒ 同一状态经 renderDetailPage / updateDetail 两条路径呈现不一致（实测 nowIdx 得 2 vs 5）。
   ⛔ 顺序要紧：本规则须在 `.now` **之前**，否则会盖掉选中态的底色。 */
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item.thisyear{
  background: var(--surface-3);
  border-color: var(--brand);
}

/* 选中 / 焦点：底色 + 左侧色条（文字标签仍在，不用颜色单独表意） */
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item.now{
  background: var(--brand-soft);
  border-color: var(--brand);
  box-shadow: inset 3px 0 0 var(--brand);
}
.tl-card[data-stack="xingyun"] > .xy-pane .tl-scroll .tl-item:hover{
  background: var(--surface-3);
  border-color: var(--line-strong);
}

/* ---------- 卡级行脚（口径）：整宽一行，落在三行之下 ----------
   ★★ 260923 改位置 ★★ 原「小运 pane 内的行脚」在三框制下被压进 1/11 行宽 ⇒
   百余字成**竖排条**、把第一行顶高近三倍（实拍 Y1 已证）。
   铁律 5：流派差异必须面向用户透出 ⇒ **只改位置，不删文本**。
   ⛔ 该元素是 `.tl-card` 的**直接子项**（不是 `.xy-pane` 之子）⇒
      原 `> .xy-pane > .tl-foot` 与「流年/流月 pane 内脚注 display:none」两段
      对**任何现存元素都不再命中**（`js/app.js` 现仅此一处产出 `.tl-foot`，已核）
      ⇒ 属结构性死码，同批清退（铁律⑩）；本段即其**替代者**。
   ⚠ `grid-column:1/-1` ⇒ 自动落 row 4（前三行已被 grid-template-areas 占满），
      故**不必**也**不应**新增 grid-template-rows 声明（那会动版式层骨架）。 */
.tl-card[data-stack="xingyun"] > .tl-foot.xy-foot-global{
  grid-column: 1 / -1;
  padding: 6px 10px;
  font-size: var(--fs-min, 12px);
  line-height: 1.6;
  color: var(--ink-3);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  max-height: 7em;
  overflow-y: auto;
}
.tl-card[data-stack="xingyun"] > .tl-foot.xy-foot-global b{ color: var(--ink-2); font-weight: 800; }

/* ============================================================
   2 · 骨架微调（比例与密度；**不改三行结构**）
   ============================================================ */
/* ★★ 260923 三框制：**平板 / 宽屏**不再覆盖 `--xy-c1-a/-b`（手机档为例外，见下方）★★
   ⛔ 旧制此处按骨架给 `--xy-c1-a: 0.26~0.32fr`（配合固定格宽「一屏放下不横滑」）。
      三框制下这会**直接破坏等分**：`0.30fr : 10fr` ⇒ 小运 pane 只占行宽 1/34，
      与 owner「小运那一格应与大运格等宽」正相反。
   ✅ 平板 / 宽屏 = 第一框比例恒定（§0 的 calc 反解），骨架差异只调**密度类**参数。
   ⚠ **手机档是唯一例外**：该档下限（`--xy-item-min`）会生效 ⇒ 反解前提「无溢出」不成立，
      必须另给第一列宽度。三处口径就此收束，勿再各自为政。 */
/* ★★ 260923 手机档：**从「硬等分」改为「最小可读宽 + 横滑兜底」** ★★
   ⛔ 旧值 `--xy-item-min: 26px` 是错的：390px 宽实测「等分自然值 26.2px ≥ 下限 26px」
      ⇒ 兜底条件**永不触发**，11 格被硬塞进一行，逐格实测**全部横向裁切**
      （大运格 clientW 24 / scrollW 38 ⇒ 「8-18岁」被截成「8-1…」；流月格 24/96）；
      小运 pane 只剩 40px 宽 ⇒ 行头「① 小运」也被裁。
   ⛔ 第二版取 `--xy-item-min: 44px` **仍然不够**：那是按「最宽 nowrap 项 ≈30px」**估算**的，
      实测（390px · `.y` 逐格量 `scrollWidth`）「18-28岁」需 **41px**，而 44px 格的内容框
      ＝ 44 − 2×3(padding) − 2×1(border) ＝ 36px ⇒ 仍差 5px，`.y` 的 `text-overflow:ellipsis`
      把它显示成「18-2…」，**大运 10 格有 9 格中招**。
      ⚠ 该缺陷此前被「格级 `scrollWidth` 无溢出」的指标漏掉 —— `.y` 自带 `overflow:hidden`，
        自身溢出不外传父级，格级指标恒绿。**判据须下沉到 `.y` 自身**。
   ✅ 正解＝下限改为**实测最宽项**：`98-108岁`（第 10 步大运）需 **47px** 内容 ＋ 2×3 padding
      ＋ 2×1 border ＝ 55px，取 **56px**（余 1px）⇒ 溢出条件成立 ⇒ 走 §2 已声明的
      **唯一横滑兜底**，格宽 56px、**全部格零截断**。
      ⚠ 本档横滑**不可避免**：11 格 × 56px ＝ 616px ≫ 可用 289px。手机档的取舍是
        「宁可横滑，不可截字」——年龄区间是每格的首要标识，截成「98-1…」即失效。
   ⚠ 下限生效后**不能再靠 §0 的 fr 反解**保持「小运格＝大运格」——反解假设「无溢出」。
      故本档显式给出第一列宽度＝`--xy-item-min + 2·pad + 2·border`（即让 pane 内正好容下
      一格 44px），第二列取其剩余 ⇒ **两 pane 的格宽仍精确相等**，与 owner「平均分布」不悖。 */
#viewportStage[data-shell="phone"]{
  --xy-pad: 6px;
  --xy-row-gap: 5px;
  --xy-strip-h: 88px;
  --xy-item-min: 56px;
  --xy-gap: 3px;
  --xy-c1-a: calc(var(--xy-item-min) + 2 * var(--xy-pad) + 2px);
  --xy-c1-b: minmax(0, calc(100% - var(--xy-row-gap) - var(--xy-item-min) - 2 * var(--xy-pad) - 2px));
}
/* 手机档小运 pane（仅 70px 宽）：行头容不下「① 小运 ＋ 逆排 · 起运前 8 年」
   ⇒ 收成只留序号、撤右侧说明（段位摘要格内已有「1-8岁／小运／8 年」）。
   ⛔ 撤的是**行头重复项**，不是唯一信息源（铁律 5 不受影响：口径脚注仍在卡底整宽行列）。 */
#viewportStage[data-shell="phone"] .tl-card[data-stack="xingyun"] > [data-pane="xiaoyun"] > .tl-head{
  padding: 7px 4px;
  justify-content: center;
}
#viewportStage[data-shell="phone"] .tl-card[data-stack="xingyun"] > [data-pane="xiaoyun"] > .tl-head::before{
  content: "①";
  letter-spacing: 0;
}
#viewportStage[data-shell="phone"] .tl-card[data-stack="xingyun"] > [data-pane="xiaoyun"] > .tl-head .r-info{
  display: none;
}
/* 手机兜底：等分下限（56px）必然溢出 ⇒ 退化为**横向可滑**——
   这是三框制下**唯一**保留横滑的场景（其余档一律 `overflow:hidden` 等分到底）。
   ⚠ 260923 修正：本条**不是**「≤340px 超窄机才用」的罕见分支，而是**所有手机档的常态**
     （390px 实测：大运 10 格 × 56px ＋ 9 gap ＝ 587px > 可用 289px ⇒ 必滑）。
     旧注释把 26px 下限写成「够用」是**误判**，实测反而造成全格裁切，已改。 */
#viewportStage[data-shell="phone"] .tl-card[data-stack="xingyun"] > .xy-pane > .tl-scroll{
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}
#viewportStage[data-shell="phone"] .tl-card[data-stack="xingyun"] > .xy-pane > .tl-scroll::-webkit-scrollbar{ height: 6px; }
#viewportStage[data-shell="phone"] .tl-card[data-stack="xingyun"] > .xy-pane > .tl-scroll::-webkit-scrollbar-thumb{
  background: var(--line-strong);
  border-radius: 3px;
}
/* 平板（约 640–820px 内容宽）：等分后单格 ≥ 40px，无需下限 */
#viewportStage[data-shell="tab"]{
  --xy-pad: 7px;
  --xy-strip-h: 92px;
  --xy-item-min: 0px;
  --xy-gap: 4px;
}
/* 宽屏（≥ 1024px 内容宽）：单格 ≥ 70px，纯等分即可 */
#viewportStage[data-shell="wide"]{
  --xy-strip-h: 104px;
  --xy-item-min: 0px;
  --xy-gap: 4px;
}

/* ============================================================
   3 · 降级
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  .tl-card[data-stack="xingyun"] .tl-item{ transition: none !important; }
}
