
/* ★ Text-long family 顶部对齐 (override 全局 ds-body justify-content: center)
   全局 ds-body center 让短内容在中间, 但 text-long 论述需要从顶部开始
   → 4-1 ~ 4-6 一致从 ds-body 顶部起 · !important 确保不被 specificity 戳穿 */
.ds-slide.tpl-prose .ds-body,
.ds-slide.tpl-prose-side .ds-body,
.ds-slide.tpl-tufte-margin .ds-body,
.ds-slide.tpl-pinned-text .ds-body,
.ds-slide.tpl-numbered-essay .ds-body,
.ds-slide.tpl-def-list .ds-body {
  justify-content: flex-start !important;
}

/* demo-code · standalone 模式右上角显示模板编号 (e.g. "2-1 · pair") */
.demo-code {
  position: fixed; top: var(--s-3); right: var(--s-3); z-index: 100;
  font-family: var(--f-mono); font-size: var(--t-label); font-weight: 700;
  color: var(--c-brand); background: var(--c-bg);
  padding: var(--s-2) var(--s-3); border: 1px solid var(--c-line);
  letter-spacing: var(--ls-label);
  pointer-events: none;
}

/* ════════════════════════════════════════════════════════════════════════
   v2 demo-shell.css · 三层 token 架构 (Brad Frost / Penpot / Contentful 标准)
   ────────────────────────────────────────────────────────────────────────
   Tier 1 · Primitives  · 原始值阶 (颜色 / 字号 / 间距 stops) — 永不动
   Tier 2 · Semantic    · 语义映射 (canvas / line / text role) — THEME 换这一层
   Tier 3 · Component   · 组件级 token (card / chip 等) — 用 Tier 2

   切 kraft / dark / thesis = 替换 Tier 2 一个 CSS 文件
   整库 0 改动, 所有 .ds-slide 自动按新 theme 渲染

   ════════════════════════════════════════════════════════════════════════
   ★ DESIGN SYSTEM INDEX (开发新 template 必读, 不准重复造轮子)
   ────────────────────────────────────────────────────────────────────────
   Tier 3 通用 components · 全部从这里引用, 不在 template 内 inline 重定义:

   [BUILDING BLOCKS]
   .prim-num-title          · 数字 + 标题 baseline 对齐 (agenda/pentad/...)
                              · variants: .sm / .lg
   .prim-pill               · 统一药丸标签
                              · variants: default / .brand / .brand-tint
                              · / .muted-fill / .warn / .on-brand (在 brand 面板上)
                              · sizes:    default / .lg / .sm
   .prim-eyebrow            · mono uppercase 标签文字 (col-tag/qa-eyebrow/...)
                              · variants: default / .brand / .on-brand / .strong
                              · sizes:    default / .lg / .sm
   .prim-bullet-list        · ✓ ✕ · 列表 (versus/scqa/...)
                              · variants: .check / .cross / .dot (.dot.brand)
                              · modifiers: .compact / .borderless
   .prim-side-card          · 双面对比 wrapper (versus/before-after/phase-compare)
                              · variants: default / .brand / .muted
   .prim-stat-cell          · 单 stat (大数字 + label + sub) (trio/before-after)
   .prim-cards-numbered     · 编号卡 (pair/triad/quartet) · data-count
   .prim-takeaway           · 高亮结论框 (consulting takeaway)
   .prim-action-title       · McKinsey 标题=结论句 (consulting)
   .prim-source             · slide 底部 absolute 数据来源 · 全库唯一位置
   .prim-caption            · body 内 insight 注释 (可选)
   .prim-qr                 · QR 槽 (per-tenant 可选) · .lg variant for close

   [RULES]
   1. 改 demo-shell.css 一处 = 改全库. 不要在 template 内 inline 重定义这些类
   2. template 内 inline <style> 只允许 layout-specific (grid columns / 特定 spacing)
   3. 所有颜色用 var(--c-*) token, 不准 hardcode hex (logo SVG defs 例外)
   4. 副标题不用圆点 ●, 只在 bullet point 用
   5. 写死 `.ds-slide.dark` / `.kraft` class banned · 用 [data-theme] / [data-pack] 走 Tier 2 token (dark mode 2026-05-11 已删 · 等 Theme_Onyx reinstate)
   ════════════════════════════════════════════════════════════════════════ */

/* ════════════════════════════════════════════════════════════════════════
   TIER 1 · PRIMITIVES (raw scales, immutable)
   refs:
   - Color: monochromatic + 60-30-10 rule (sixtythirtyten.co)
   - Type:  Modern B2B presentation scale (Stripe / Linear / Apple Keynote)
   - Spacing: 8px base scale (industry standard)
   - Radius: 6-24px range matches modern (Linear / Stripe / Apple HIG)
   ════════════════════════════════════════════════════════════════════════ */
:root {
  /* === BRAND HUE · 单一蓝色 5 阶 (Kalungi: B2B 卡死蓝 = trust) === */

  /* === NEUTRAL SCALE === */

  /* === SEMANTIC HUE (3% 用量, 仅状态指示, 禁装饰) === */

  /* === TYPE SCALE · v1 ALIAS only (v2 SOT 在 tokens.css) ===
     ★ 砸 --t-mega/-hero 重定义 (跟 tokens.css 200/110 冲突 · close Thanks 等大字号 fix) */

  /* === SPACING (8px base · industry standard) === */

  /* === RADIUS (modern 6-24px · ref: Linear 6-8 / Stripe 4-8 / Apple HIG 12-16) === */
}

/* ════════════════════════════════════════════════════════════════════════
   TIER 2 · SEMANTIC (theme = swap this layer)
   下方是默认 theme = "business" · 未来可换 theme-kraft / theme-kraft 等
   ════════════════════════════════════════════════════════════════════════ */
:root {
  /* === Brand role (单 hue 5 阶 60-30-10 应用) === */

  /* === Surface role === */

  /* === Text role === */

  /* === Line / divider role === */

  /* === Semantic (status only, NEVER decoration) === */

  /* === Shadow (modern flat / Linear 0 / Stripe subtle) === */

  /* ════════════════════════════════════════════════════════════════════
     v1 TOKEN ALIAS · 把 catlaxy-ds.css 的 v1 名字重定向到 v2 值
     原则: 库内绝不直接用 v1 名 (--c-blue / --c-white / --c-title 等),
     但短期内, 既有 template 仍引用. alias 让 brand picker / pack 切换
     一次性影响全部 — 不用一行行改 template
     ════════════════════════════════════════════════════════════════════ */
  /* ★ 2026-05-10 修正: --c-rose 取消 brand alias · 恢复真正 rose 色 (semantic negative)
     用于 caution / DON'T / 划掉 / 警示. 跟 --c-danger (#EF4444 量化负向) 语义错开:
     · --c-rose:    设计性 negative (DON'T, 撤销, 警告 → 立场陈述)
     · --c-danger:  量化 negative (loss, error, ↓ 跌)
     · --c-success: 量化 positive (gain, ↑ 涨)
     · --c-amber 保持 alias 到 brand (amber 在 v2 不用) */
  /* card / icon legacy (--card-radius removed 2026-05-11 · tokens.css :root SOT · 不再 override) */
}

/* ════════════════════════════════════════════════════════════════════════
   DEMO WRAPPER + AUTO-SCALE (1920×1080 fit-to-viewport)
   ════════════════════════════════════════════════════════════════════════ */
html, body { margin: 0; padding: 0; height: 100%; background: var(--c-card-strong); overflow: hidden; }
/* ★ FIX (round 5) 居中稳定: absolute 50%/50% + translate(-50%,-50%) scale
   不依赖 grid place-items (某些 viewport 高度下不对称) · scale 从 center 缩 */
.demo-wrap { position: fixed; inset: 0; overflow: hidden; }
.demo-wrap .ds-slide {
  position: absolute;
  top: 50%; left: 50%;
  transform-origin: center center;
  transform: translate(-50%, -50%) scale(1);
  /* JS sets transform: translate(-50%, -50%) scale(s) */
  box-shadow: var(--shadow-elevated);
  border-radius: var(--r-lg);
}

/* ════════════════════════════════════════════════════════════════════════
   ★ TOKEN-DRIVEN .ds-slide · 自动用 --c-canvas 不需 modifier class
   覆盖 v1 catlaxy-ds.css 的 background: var(--c-white) · v2 默认走暖白
   ════════════════════════════════════════════════════════════════════════ */
/* ★ Phase 5 Dim 1 · BG PATTERN · current themes + planned admin-managed theme variants
   :root default = none (Catlaxy 商务 flat) · 各 theme 在 tokens.css 委托 --bg-pattern */
.ds-slide {
  background-color: var(--c-canvas);
  background-image: var(--bg-pattern);
  overflow: hidden; position: relative;
}

/* ★ prim-header-stack 全库 swap · 主标题在上 副标题在下 (per user 2026-05-09)
   v1 默认 hs-sub eyebrow 在上 / hs-title 在下 · v2 反过来 (Editorial / 报纸 deck 风) */
.prim-header-stack.has-sub {
  display: flex;
  flex-direction: column-reverse;
}

/* ★ 标题/副标题/章节标题 全库强制单行 (字超限 ellipsis · spec 字数: hs-title 18 中字 / hs-sub 24 字 / ch-title 12 中字) */
.prim-header-stack .hs-title,
.prim-header-stack .hs-sub,
.prim-chapter .ch-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
/* ★ FIX (round 4) 真正修 layer-stack 底部空: ds-body 必须 flex:1 才能填 ds-safe 剩余空间
   不然 prim-layer-stack 的 height:100% 只是 0% (ds-body 自身没有高度)
   ds-safe 已是 flex column (catlaxy-ds.css), 给 ds-body 加 flex:1 就能撑满
   ★ ROUND 2 ds-body 留 source 空间 (80px), 避免 prim-source absolute 重叠内容 */
.ds-safe { padding-bottom: var(--s-8); }    /* 80→40 · ds-body 多 40px · 修底部 cut · prim-source absolute 不受影响 */
.ds-body {
  /* overflow: clip + clip-margin · 允许 shadow/hover lift 扩 12px 不裁
     vs 旧 overflow:hidden (硬裁 0px) · 跟 hover/shadow 系统配套 */
  overflow: clip;
  overflow-clip-margin: var(--clip-safe-margin);
  min-height: 0; flex: 1;
  display: flex; flex-direction: column; justify-content: center;   /* 让 children vertical center */
}

/* ════════════════════════════════════════════════════════════════════════
   P12 · BACKGROUND VARIANTS (6 商务级 · 砍掉 engineering grid)
   refs: Stripe gradient mesh · McKinsey band · Mercury asymmetric block
   ────────────────────────────────────────────────────────────────────────
   用法: <section class="ds-slide bg-mesh"> 或 <body class="bg-mesh">
   ════════════════════════════════════════════════════════════════════════ */

/* ① bg-soft · 默认 · 暖白底 (Anthropic 工艺感) */
.ds-slide.bg-soft { background: var(--warm-50); }

/* ② bg-paper · 暖白 + SVG noise 纸纹 (data URI 用 ;charset=utf-8 标准) */
.ds-slide.bg-paper {
  background-color: var(--warm-50);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' seed='3'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.06 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ③ bg-dots · ★ 加大对比 (10%→16%) + 加大 dot (1.5px→2px) Linear/engineering 风 */
.ds-slide.bg-dots {
  background-color: var(--pure-white);
  background-image: radial-gradient(circle, rgba(17,24,39,0.16) 2px, transparent 2.5px); /* anchor: dot grain needs sub-3px optical edge */
  background-size: var(--s-7) var(--s-7);
}

/* ④ bg-topo · ★ 改用纯 CSS repeating-radial-gradient 等高线 (避免 SVG data URI 兼容问题) */
.ds-slide.bg-topo {
  background-color: var(--pure-white);
  background-image:
    repeating-radial-gradient(circle at 92% 12%, transparent 0 70px, color-mix(in srgb, var(--c-brand) 10%, transparent) 70px 72px), /* anchor: topo ring spacing */
    repeating-radial-gradient(circle at 8% 88%, transparent 0 80px, color-mix(in srgb, var(--c-brand) 6%, transparent) 80px 82px); /* anchor: topo ring spacing */
}

/* ⑤ bg-splash · 动态 organic blobs · 复用 v1 catlaxy-ds.css 的 .splash/.pa/.b1-.b11/@keyframes d1/d2/d3
   demo-shell.js 检测 .bg-splash 时 inject SVG filter#sf + 11 blobs · pack=dark 自动加 .splash-dk
   v1 splash 系统: catlaxy-ds.css line 2222-2253 (光暗双版自动适配) */
.ds-slide.bg-splash { background: var(--c-canvas); }
.ds-slide.bg-splash .splash { z-index: 0; }
/* z-index 不动 absolute · .ds-logo/.ds-safe/.ds-bbar 在 catlaxy-ds.css 已是 absolute,
   absolute 定位元素 z-index 直接生效, 不需要改 position. splash z-index:0 在底, 其他 z-index:1 覆盖 */
.ds-slide.bg-splash > .ds-logo,
.ds-slide.bg-splash > .ds-safe,
.ds-slide.bg-splash > .ds-bbar { z-index: 1; }

/* future · bg-custom (per-tenant 上传图) */

/* ════════════════════════════════════════════════════════
   ★ TEMPLATE PACK ★ (= 整套客户样版 · Tier 2 token swap)
   data-pack on .ds-slide 控制整套视觉规范
   refs: 像 web 的 light/dark mode, 不只 bg, 是全套 token
   ──────────────────────────────────────────────────────── */

/* pack=catlaxy · 默认 (品牌蓝 + logo) — 不需 data-pack 属性 */

/* Current Standard family themes · 无 logo (kraft / onyx)
   ★ visibility: hidden (不是 display: none) · open/close logo 进 normal flow 后, display:none 让标题上移
   visibility:hidden 保留 layout space, 视觉空白 · absolute logo (chain/timeline 等) 也 OK (不占 layout)
   只 catlaxy theme (Vendor family) 保留 logo · planned themes wait for v2 admin theme-management */
.ds-slide[data-pack="kraft"]      .ds-logo,
.ds-slide[data-pack="onyx"]       .ds-logo { visibility: hidden; }

/* ════════════════════════════════════════════════════════
   ★ SPLASH PALETTE · brand-derived override (v2 only)
   ────────────────────────────────────────────────────────
   v1 catlaxy-ds.css .pa palette 是 hardcoded catlaxy 蓝 hex
   v2 改 brand-derived · 客户改 brand picker / pack swap · 11 blob 颜色自动跟
   每 blob 用 linear-gradient(var(--c-brand-*)) · color-mix runtime 重算
   2026-05-11 v2 architecture refactor · 跟 Theme system 同步
   specificity 0,0,2,0 = v1 same · demo-shell.css 加载在 catlaxy-ds.css 后 · wins
   ──────────────────────────────────────────────────────── */
.ds-slide .splash.pa .b1  { background: linear-gradient(135deg, var(--c-brand-40), var(--c-brand)); }
.ds-slide .splash.pa .b2  { background: linear-gradient(180deg, var(--c-brand-40), var(--c-brand-60)); }
.ds-slide .splash.pa .b3  { background: linear-gradient(220deg, var(--c-brand-40), var(--c-brand)); }
.ds-slide .splash.pa .b4  { background: linear-gradient(160deg, var(--c-brand-40), var(--c-brand-60)); }
.ds-slide .splash.pa .b5  { background: linear-gradient(280deg, var(--c-brand-40), var(--c-brand-60)); }
.ds-slide .splash.pa .b6  { background: linear-gradient(200deg, var(--c-brand-40), var(--c-brand-60)); }
.ds-slide .splash.pa .b7  { background: linear-gradient(315deg, var(--c-brand), var(--c-brand-40)); }
.ds-slide .splash.pa .b8  { background: linear-gradient(250deg, var(--c-brand-60), var(--c-brand-40)); }
.ds-slide .splash.pa .b9  { background: linear-gradient(200deg, var(--c-brand-60), var(--c-brand-40)); }
.ds-slide .splash.pa .b10 { background: linear-gradient(170deg, var(--c-brand-40), var(--c-brand)); }
.ds-slide .splash.pa .b11 { background: linear-gradient(140deg, var(--c-brand-40), var(--c-brand-60)); }

/* MOTION 已 redesign 2026-05-11 · 不再用 CSS pause class
   Motion=off · demo-shell.js applyMotion('off') 移除整 .splash DOM
   Motion=splash · demo-shell.js applyMotion('splash') 注入 .splash
   无需 CSS rule (splash 不存在则无动 · 真静态) */


/* ★ demo-spec chip · 在 ds-bbar 左侧 (跟 pg-num right:60 对称) · demo identification 用
   显示 "9-3 · LINE" 这种 spec 编号, 让 demo 跟 spec md 对得上
   page-num (右) 是 deck 占位 · demo-spec (左) 是 demo 身份 · 双轨编号 */
.ds-bbar .demo-spec {
  position: absolute;
  left: 60px; /* anchor: mirrors page number inset from slide edge */
  bottom: var(--s-6-5);
  font-family: var(--f-mono);
  font-size: var(--t-label);
  font-weight: 900;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-text-muted);
  white-space: nowrap;
}

.ds-bbar .pg-num {
  display: none !important;
}


/* ════════════════════════════════════════════════════════
   ★ pack-immune class · rare whole-slide opt-out
   不参与 pack/bg 切换 · 仅给明确品牌锁定场景使用
   ──────────────────────────────────────────────────────── */
.ds-slide.pack-immune,
.ds-slide.pack-immune[data-pack],
.ds-slide.pack-immune.kraft {
  --c-canvas:    #FAFAF8 !important;
  --c-canvas-pure: #FFFFFF !important;
  --c-surface:   #FFFFFF !important;
  --c-text:      #111827 !important;
  --c-text-strong: #111827 !important;
  --c-text-muted: #6B7280 !important;
  --c-line:      #EAEAEA !important;
  --c-brand:     #0078FC !important;
  --c-brand-60:  #0060D0 !important;
  --c-brand-40:  #4DA6FF !important;
  --c-brand-10:  #EFF6FF !important;
  --c-blue:      #0078FC !important;
  --c-white:     #FFFFFF !important;
  --c-title:     #111827 !important;
  --c-divider:   #E5E7EB !important;
  background: #FAFAF8 !important;
  background-image: none !important;
  color: #111827 !important;
}

/* ════════════════════════════════════════════════════════
   ★ pack=kraft · 暖纸笔触风 (前曾错误命名为 kraft)
   ref: Anthropic Claude design system · Tufte kraft
   ──────────────────────────────────────────────────────── */
/* ★ tokens 已上移到 tokens.css [data-pack="kraft"] · 这里只留 PPT element 视觉
   ★ Phase 5 · paper texture 已迁入 tokens.css 的 --bg-pattern · 这里只保留 color 设置 */
.ds-slide[data-pack="kraft"],
.ds-slide.kraft {
  color: var(--c-text);
}
/* kraft splash hide rule 已删 2026-05-11 redesign
   Motion 独立控制 splash visibility · kraft + Motion=splash 允许 (paper texture + 蓝 blob 共存)
   kraft 想纯 paper feel · 切 Motion=Off 即可 */

/* kraft 标题用 serif (Playfair) — 编辑感 */
.ds-slide[data-pack="kraft"] .hs-title,
.ds-slide.kraft .hs-title,
.ds-slide[data-pack="kraft"] .ncard-title,
.ds-slide.kraft .ncard-title,
.ds-slide[data-pack="kraft"] .oc-title,
.ds-slide.kraft .oc-title,
.ds-slide[data-pack="kraft"] .ch-title,
.ds-slide.kraft .ch-title,
.ds-slide[data-pack="kraft"] .cl-thanks,
.ds-slide.kraft .cl-thanks {
  font-family: var(--f-serif);
}

/* kraft .ncard override 砸 · default .prim-cards-numbered .ncard 已用 var(--c-surface/-line),
   kraft scope 自动 swap, 不需要再写一遍 */

/* kraft logo / em-blue / hs-sub-bar · v1 catlaxy-ds.css 写死 brand-blue, 这里用 token 覆 */
.ds-slide[data-pack="kraft"] .ds-logo,
.ds-slide.kraft .ds-logo { color: var(--c-brand); }
.ds-slide[data-pack="kraft"] .em-blue,
.ds-slide.kraft .em-blue { color: var(--c-brand); }
.ds-slide[data-pack="kraft"] .hs-sub.with-bar::before,
.ds-slide.kraft .hs-sub.with-bar::before { background: var(--c-brand); }

/* kraft bg-band/bg-* 协调 */
.ds-slide[data-pack="kraft"].bg-soft,
.ds-slide.kraft.bg-soft { background-color: var(--c-canvas); }

/* P5 · TAKEAWAY BOX · 已删除 2026-05-11 (banned Claude callout · border-left: 6px solid + 0 HTML 使用)
   未来要 takeaway box 用 brand-fill icon + brand-tint BG pattern (e.g. case-study cs-result · pillar-stack vault) */

/* ════════════════════════════════════════════════════════
   ACTION TITLE · McKinsey 风格 (标题=结论句, 不是话题)
   ──────────────────────────────────────────────────────── */
.prim-action-title {
  font-size: var(--t-h3); font-weight: var(--type-display-weight); color: var(--c-text);
  line-height: var(--lh-snug); letter-spacing: var(--type-display-tracking);
  max-width: 90%; margin: 0;
}

/* ★ Phase 5 Dim 4 · DISPLAY TRACKING · token-driven per-theme display spacing
   覆盖 v1 catlaxy-ds.css 的 letter-spacing: 0.02em · 单点 token 切 theme 整套 display 字距跟切
   覆盖范围: hs-title (主标题) / ch-title (章节大字) / cl-thanks (close) / oc-title (open) · 关键 display 字号
   specificity: .ds-slide 祖先 (0,1,1) win v1 .prim-header-stack .hs-title (0,2,0) — 平 specificity 但 demo-shell.css 加载后, source order wins */
.ds-slide .prim-header-stack .hs-title,
.ds-slide .prim-chapter .ch-title,
.ds-slide .cl-thanks,
.ds-slide .oc-title {
  letter-spacing: var(--type-display-tracking);
  font-weight: var(--type-display-weight);
  color: var(--c-title, var(--c-text-strong));
}
/* ★ Phase 5 Dim 3 · EM ACCENT · current themes + planned admin-managed theme variants
   全局 em rule (跨 template inline em) · 单点 token 切 theme 整套 em 视觉跟切
   覆盖 template HTML 内部 em (.bf-hero-body em / .cs-desc em / .qa-text em / .callout-block em 等)
   specificity 0,1,1 cover most cases · .prim-card-brand em 已有 color:inherit override (line ~880) wins on brand cards
   2026-05-11 Phase 5: 从单点 token 驱动 theme em emphasis 差异化 */
.ds-slide em {
  font-style: var(--em-style);
  color: var(--em-color);
  font-weight: var(--em-weight);
  text-decoration: var(--em-decoration);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px; /* anchor: em underline optical offset tighter than --s-1 */
  background: var(--em-background);
  padding: var(--em-padding);
  text-shadow: var(--em-text-shadow);
  border-radius: var(--r-xs);  /* em-bg pill round · transparent 时 invisible */
}
/* action-title em 已 inherit 全局 .ds-slide em · 不再单独重复声明 */
.prim-action-title em {
  font-style: var(--em-style);
  color: var(--em-color);
}

.prim-action-eyebrow {
  font-family: var(--f-mono); font-size: var(--t-label); font-weight: 700;
  color: var(--c-brand); letter-spacing: var(--ls-label); text-transform: uppercase;
  margin-bottom: var(--s-3);
}

/* ════════════════════════════════════════════════════════
   ★ UNIVERSAL SOURCE · 全库统一: 跟 ds-bbar 同高度 · 靠左跟 logo 对齐
   砍 eyebrow (用户: 不需要 SOURCE 字), 简单 mono 一行
   ──────────────────────────────────────────────────────── */
.prim-source {
  position: absolute;
  /* 注意: ds-safe 是 positioned ancestor (absolute), ds-safe.bottom 距 slide 底 = var(--slide-safe-bot) = 130px
     要让 .prim-source 视觉距 slide 底 28px (跟 .pg-num 对齐), 需要相对 ds-safe bottom = 28 - 130 = -102 */
  bottom: calc(var(--s-6-5) - var(--slide-safe-bot));
  left: 0;                                               /* ds-safe 内 left:0 = 跟 hs-title 左对齐 (ds-safe 自己 left:130) */
  max-width: calc(100% - 200px);                         /* anchor: leaves room for page number */
  font-family: var(--f-mono);
  font-size: var(--t-label);
  font-weight: 500;
  color: var(--c-text-muted);
  letter-spacing: var(--ls-label);
  line-height: var(--lh-cozy);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.prim-source strong { color: var(--c-text); font-weight: 700; }

/* ════════════════════════════════════════════════════════
   ★ UNIVERSAL PRIMITIVES (round 2 · 系统层统一)
   ──────────────────────────────────────────────────────── */

/* prim-num-title · 数字 + 标题 字底真对齐 (agenda / pentad / block-finding 通用)
   ★ FIX: Inter 字体 descender 占 ~16% line-box (line-box 底 ≠ 字底), 中文字底跟 line-box 底接近重合.
   解法: align-items:flex-end + nt-num margin-bottom:-0.16em 缩 layout-box 底贴近字底, 让 flex-end 真字底对齐 */
.prim-num-title {
  display: flex;
  align-items: flex-end;
  gap: var(--s-6);
  flex-wrap: wrap;
}
.prim-num-title .nt-num {
  font-family: var(--anchor-font-family); font-size: var(--t-h1); font-weight: var(--anchor-weight);
  color: var(--c-brand); line-height: var(--lh-display);
  letter-spacing: var(--ls-tighter); flex-shrink: 0;
  font-variant-numeric: tabular-nums;   /* Inter 等宽数字 · 多行 num 列宽一致 → title 左对齐 */
  margin-bottom: -0.16em;          /* Inter descender 补偿 · 让 layout-box 底贴字底 */
}
.prim-num-title .nt-title {
  font-size: var(--t-body-lg); font-weight: 900;
  color: var(--c-title, var(--c-text-strong)); line-height: var(--lh-display);
  letter-spacing: var(--ls-tight);
  margin-bottom: -0.04em;          /* 中文 descender 微补偿 · 字底贴 line-box 底 */
}
.prim-num-title.sm .nt-num   { font-size: var(--t-h3); }
.prim-num-title.sm .nt-title { font-size: var(--t-body); }
.prim-num-title.lg .nt-num   { font-size: var(--t-display); }
.prim-num-title.lg .nt-title { font-size: var(--t-h3); }

/* prim-eyebrow · 全库统一 mono uppercase 标签文字
   用法: 副标题 eyebrow / col-tag / qa-eyebrow / ag-sub / col-label / pent-sub etc */
.prim-eyebrow {
  font-family: var(--f-mono); font-size: var(--t-label); font-weight: 900;
  color: var(--c-text-muted);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  line-height: var(--lh-tight);
}
.prim-eyebrow.brand    { color: var(--c-brand); }
.prim-eyebrow.on-brand { color: var(--c-text-on-brand); opacity: 0.7; }
.prim-eyebrow.lg       { font-size: var(--t-label); }
.prim-eyebrow.sm       { font-size: var(--t-label); }
.prim-eyebrow.strong   { color: var(--c-text-strong); }
.prim-eyebrow.chapter  { font-size: var(--t-body-sm); letter-spacing: var(--ls-label); }    /* mark chapter 装饰用 */

/* prim-bullet-list · ✓ ✕ · list 通用 (versus / scqa / mq / etc) */
.prim-bullet-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column;
}
.prim-bullet-list li {
  font-size: var(--t-body-sm); color: var(--c-text);
  padding: var(--s-4) 0 var(--s-4) var(--s-7); position: relative; line-height: var(--lh-cozy);
  border-top: 1px solid var(--c-line);
}
.prim-bullet-list li:first-child { border-top: none; }
.prim-bullet-list li::before {
  position: absolute; left: 0; top: var(--s-4);
  font-weight: 900; font-size: var(--t-body-sm);
}
.prim-bullet-list.check li::before { content: '✓'; color: var(--c-brand); font-size: var(--t-body); }
.prim-bullet-list.cross li::before { content: '✕'; color: var(--c-text-muted); }
.prim-bullet-list.dot   li::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--c-text-muted); top: var(--s-6); }
.prim-bullet-list.dot.brand li::before { background: var(--c-brand); }
.prim-bullet-list.compact li { padding: var(--s-2) 0 var(--s-2) var(--s-6); font-size: var(--t-body-sm); }
.prim-bullet-list.compact li::before { top: var(--s-2); font-size: var(--t-body-sm); }
.prim-bullet-list.borderless li { border-top: none; padding-top: var(--s-2); padding-bottom: var(--s-2); }
/* ★ 在 brand panel 内 list 自动适配 border (避免 template 内 inline override) */
.prim-side-card.brand .prim-bullet-list li { border-top-color: var(--c-brand-40); }

/* prim-stat-cell · 单 stat (大数字 + label + sub) · duo / trio / metric 通用
   规则: 显式 align-items: center · label 1 行 / sub 2 行 + min-height (cell 等高对齐) */
.prim-stat-cell {
  text-align: center; padding: var(--s-7) var(--s-5);
  display: flex; flex-direction: column; gap: var(--s-5);
  justify-content: center; align-items: center;       /* 显式横向居中 · 不靠 stretch */
}
.prim-stat-cell .stat-num {
  font-family: var(--anchor-font-family); font-size: var(--t-mega); font-weight: var(--anchor-weight);
  line-height: var(--lh-display); letter-spacing: var(--ls-display-lg); color: var(--c-brand);
  font-variant-numeric: tabular-nums;
}
.prim-stat-cell .stat-num small {
  font-size: 0.35em; font-weight: 700; opacity: 0.85;
  vertical-align: 0;                                  /* 不上标 · 字底大致对齐 · 砍 margin-left 避免居中右偏 */
}
.prim-stat-cell .stat-label {
  font-size: var(--t-h3); font-weight: 900; color: var(--c-title, var(--c-text-strong));   /* 跟 cards .ncard-title 一致 (40) */
  letter-spacing: var(--ls-tight); line-height: var(--lh-snug);                          /* line-height 跟 cards 一致 */
  /* label 强制 1 行 · 超截断 */
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
  overflow: hidden; text-overflow: ellipsis;
  max-width: 100%;
}
.prim-stat-cell .stat-sub {
  font-size: var(--t-body); color: var(--c-text-muted); line-height: var(--lh-cozy);     /* 跟 cards .ncard-body 一致 (22) */
  max-width: 14em;                                                   /* trio: 14 中字 / line (font 22 → 跟 22 字号匹配) · duo override 20em */
  /* sub 强制 ≤ 2 行 + min-height 等高 (单行/双行 cell 对齐) */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; text-overflow: ellipsis;
  min-height: calc(2 * 1.5em);
}

/* duo cell 比 trio 宽 · sub 可以放更长一行 (18 中字) */
.prim-stats-grid[data-count="2"] .prim-stat-cell .stat-sub { max-width: 18em; }

/* prim-stats-grid · stats 系列 layout · data-count="2|3" · duo / trio 共用 */
.prim-stats-grid {
  display: grid; gap: 0; align-items: stretch;
  flex: 1; min-height: 0;
}
.prim-stats-grid[data-count="2"] { grid-template-columns: 1fr 1fr; }
.prim-stats-grid[data-count="3"] { grid-template-columns: repeat(3, 1fr); }
.prim-stats-grid .prim-stat-cell { position: relative; }

/* 分隔线 · 2px 实心 brand 立柱 · 32% 高度 · 中心对齐 stat-num (cell 高度 34% 处) */
.prim-stats-grid .prim-stat-cell + .prim-stat-cell::before {
  content: ''; position: absolute;
  left: -1px; top: 18%; bottom: 50%;
  border-left: 2px solid var(--c-brand);
}

/* prim-metric · 单数字 hero (1 cell · 满版居中 · 字号比 stat-cell 再大一级)
   规则: 主张型 punchline · 占满 ds-body 居中 · 可选 insight 一行 takeaway */
.prim-metric {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: var(--s-8) 0;
}
.prim-metric .prim-stat-cell { padding: 0; }
.prim-metric .prim-stat-cell .stat-num {
  font-size: var(--t-mega); letter-spacing: var(--ls-mega); line-height: var(--lh-display);
}
.prim-metric .prim-stat-cell .stat-num small { font-size: 0.3em; }
.prim-metric .prim-stat-cell .stat-label {
  font-size: var(--t-h1); letter-spacing: var(--ls-tighter); margin-top: var(--s-3);
}
.prim-metric .prim-stat-cell .stat-sub {
  font-size: var(--t-body-lg); max-width: 38ch; line-height: var(--lh-cozy);
  -webkit-line-clamp: unset; display: block; min-height: 0;     /* metric 单 cell 不需等高对齐 */
}

/* prim-side-card · versus/before-after/phase-compare 双面对比通用 wrapper
   规则: hairline 边框 surface bg (default), brand 强化 (good/after/future) */
.prim-side-card {
  background: var(--c-surface);
  border: var(--card-border-width-default) solid var(--c-line);   /* ★ Tier 3 · per-theme commit (0/1/2) */
  border-radius: var(--card-radius);                              /* ★ Tier 3 · per-theme commit */
  box-shadow: var(--card-shadow);                                 /* ★ Tier 3 · per-theme commit */
  padding: var(--s-8) var(--s-7);
  display: flex; flex-direction: column; gap: var(--s-5);
}
.prim-side-card.brand {
  border: 2px solid var(--c-brand);
  background: var(--c-brand-10);
}
.prim-side-card.muted {
  background: var(--c-canvas);
}
.prim-side-card h3 {
  font-size: var(--t-body-lg); font-weight: 900; color: var(--c-title, var(--c-text-strong));
  line-height: var(--lh-tight); margin: 0; letter-spacing: var(--ls-tight);
}
.prim-side-card.brand h3 { color: var(--c-brand); }

/* prim-pill · 统一药丸 · 全库 (砍各 template 自己定义的 tag/pill/badge) */
.prim-pill {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-pill);
  font-family: var(--f-mono); font-size: var(--t-label); font-weight: 900;
  letter-spacing: var(--ls-label); text-transform: uppercase;
  border: 1px solid var(--c-line);
  background: var(--c-canvas);
  color: var(--c-text-muted);
  line-height: var(--lh-tight);
  white-space: nowrap;
}
.prim-pill.brand      { background: var(--c-brand);    color: var(--c-text-on-brand); border-color: var(--c-brand); }
.prim-pill.brand-tint { background: var(--c-brand-10); color: var(--c-brand);         border-color: var(--c-brand-40); }
.prim-pill.muted-fill { background: var(--c-text-muted); color: var(--c-text-on-brand); border-color: var(--c-text-muted); }
.prim-pill.warn       { background: var(--c-danger);   color: var(--c-text-on-brand); border-color: var(--c-danger); }
.prim-pill.on-brand   { background: var(--c-on-brand-tint-18); color: var(--c-text-on-brand); border-color: var(--c-on-brand-tint-30); }
.prim-pill.lg         { padding: var(--s-2) var(--s-4); font-size: var(--t-label); }
.prim-pill.sm         { padding: var(--s-1) var(--s-3); font-size: var(--t-label); }

/* QR slot · per-tenant 可选, 默认右下角 88px · close 用 .lg 200px */
.prim-qr {
  position: absolute; bottom: 60px; right: var(--slide-pad-x); /* anchor: QR default floats above slide footer */
  display: flex; align-items: center; gap: var(--s-4);
  font-family: var(--f-mono); font-size: var(--t-label);
  color: var(--c-text-muted); letter-spacing: var(--ls-label);
}
.prim-qr .qr-img {
  width: 88px; height: 88px; /* anchor: tenant QR fixed asset scan size */
  background: var(--c-surface);
  border: 2px solid var(--c-line);                 /* 1px → 2px solid · 跟 4-4 image slot 同视觉系 (实线) */
  border-radius: var(--r-md);
  flex-shrink: 0;
  display: grid; place-items: center;
  font-family: var(--f-mono); font-size: var(--t-label); color: var(--c-text-muted);
}
.prim-qr .qr-label strong { color: var(--c-text); display: block; font-weight: 900; font-size: var(--t-label); }
.prim-qr.lg .qr-img { width: 200px; height: 200px; }
.prim-qr.lg .qr-label { font-size: var(--t-body-sm); }
.prim-qr.lg .qr-label strong { font-size: var(--t-body); }

/* ════════════════════════════════════════════════════════════════════════
   P5 · UNIVERSAL CAPTION SLOT
   ════════════════════════════════════════════════════════════════════════ */
/* prim-caption · body 内说明文字 (insight / 注释) · 跟 prim-source (数据来源, slide 底) 区分
   ★ 字号 20px (用户反馈: 18 太小, 投影看不见)
   ★ 砸 border-top (2026-05-10 · 用户反馈: 上方那条线视觉断裂, 拿掉更优雅) */
.prim-caption {
  margin-top: var(--s-6);
  font-family: var(--f-mono);
  font-size: var(--t-body-sm);
  font-weight: 500;
  color: var(--c-text-muted);
  letter-spacing: 0.02em;
  line-height: var(--lh-normal);
  display: flex; gap: var(--s-4); align-items: baseline;
}
.prim-caption::before {
  content: '—'; color: var(--c-brand);
  font-weight: 900; flex-shrink: 0;
}
.prim-caption strong { color: var(--c-text-strong); font-weight: 700; }

/* ════════════════════════════════════════════════════════════════════════
   P9 · NEW PRIMITIVE: prim-cards-numbered
   编号 anchor 替代 icon · pair / triad / quartet 共用
   ★ 字号统一 (用 pair 大号 base) · count=4 改 2x2 grid · solid-card 提升设计感
   ════════════════════════════════════════════════════════════════════════ */
.prim-cards-numbered {
  display: grid;
  gap: var(--s-6);                         /* 方块间距 (统一 2/3/4 cell · per user 50% 宽于之前) */
  align-items: stretch; width: 100%;
  /* cell 高度 = content (不撑满 ds-body) · ds-body justify-content:center 让 cards 居中 */
}
.prim-cards-numbered[data-count="2"] { grid-template-columns: 1fr 1fr; }
.prim-cards-numbered[data-count="3"] { grid-template-columns: 1fr 1fr 1fr; }
.prim-cards-numbered[data-count="4"] {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;       /* row 同高 · 撑 ds-body 让 row 同高生效 */
  flex: 1; min-height: 0;            /* 严格 fit ds-body · 不溢出 */
  gap: var(--s-4);                         /* 4 cell 专用: gap 缩 24→14 让 row 显著加高 (+5px each) */
  margin-top: 0;                     /* 砍 ds-head + * margin-top · ds-body 多 32px 给 cells (16/cell) */
}

/* 字号统一 · pair/triad/quartet 同字号 · catlaxy minimalist hairline 风 */
.prim-cards-numbered .ncard {
  padding: var(--card-padding);
  display: flex; flex-direction: column; gap: var(--card-gap);
  background: var(--c-surface);
  border: var(--card-border-width-default) solid var(--card-border-color-default);   /* Tier 3 · width 跟 theme commit (0/1/2) */
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);                                                    /* Tier 3 · shadow 跟 theme commit (none/subtle/brutalist) */
  transition:
    border-color var(--duration-hover) var(--easing-decisive),
    box-shadow var(--duration-hover) var(--easing-decisive),
    transform var(--duration-hover) var(--easing-decisive);
  min-height: 0; min-width: 0;
  overflow: hidden;
}
.prim-cards-numbered .ncard:hover {
  border-color: var(--card-border-color-hover);
  box-shadow: 0 0 0 1px var(--card-border-color-hover) inset, var(--card-shadow-hover);
  transform: var(--hover-transform);                                                 /* Tier 3 · per-theme commit (lift/static/brutalist-shift/bouncy) */
}
/* ★ Phase 5 Dim 2 · ANCHOR · token-driven per-theme headline anchor
   每 theme 在 tokens.css 委托 anchor 4 token · 切 theme 数字 anchor 视觉跟切 */
.prim-cards-numbered .ncard-num {
  font-family: var(--anchor-font-family);
  font-size: var(--t-display); font-weight: var(--anchor-weight);
  color: var(--anchor-color);
  letter-spacing: var(--anchor-letter-spacing); line-height: var(--lh-display);
  /* anchor-decoration: none / underline · per-theme · 用 text-decoration shorthand 让 underline color 跟随 currentColor */
  text-decoration: var(--anchor-decoration);
  text-decoration-thickness: 2px;
  text-underline-offset: var(--s-1);
}
.prim-cards-numbered .ncard-title {
  font-size: var(--t-h3); font-weight: 900;
  color: var(--c-title, var(--c-text-strong));
  margin: 0; line-height: var(--lh-snug); letter-spacing: var(--ls-tight);          /* 1.15 太紧, "body"/"y"/"g" descender 超 line-box 被 overflow 切 → 1.3 给 ~9px 缓冲 */
  /* 单行 · 超字数 ellipsis (LLM 必须自检字数) */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-bottom: var(--s-1);                                          /* 再加 4px 保险 · descender clipping 双保险 */
}
.prim-cards-numbered .ncard-body {
  font-size: var(--t-body); line-height: var(--lh-cozy);
  color: var(--c-text);
  margin: 0;
  /* 2/3 cell 默认 3 行 ellipsis · 不 flex:1 (cell 高 = content, 不撑满) */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* .ncard-body em 已 inherit 全局 .ds-slide em rule (Phase 5) · 删 redundant rule */

/* 4 cell · cell = flex column · top (grid: num+body 同行 底对齐) + title (flex 末位 · flex-shrink:0)
   ncard-top 用 grid (不用 flex) 因 body 是 -webkit-box · grid cell 兼容性更好 */
.prim-cards-numbered[data-count="2"] {
  align-items: start;
}
.prim-cards-numbered[data-count="2"] .ncard {
  height: auto;
  overflow: visible;
}
.prim-cards-numbered[data-count="2"] .ncard-body {
  display: block;
  -webkit-line-clamp: unset;
  -webkit-box-orient: unset;
  overflow: visible;
}

.prim-cards-numbered[data-count="4"] .ncard {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  padding: var(--s-7) var(--s-11) var(--s-7) var(--s-7);       /* right 100 让 body 宽缩 ~3 中字 (per user) */
}
.prim-cards-numbered[data-count="4"] .ncard-top {
  display: flex;                       /* 简洁 flex row · 不用 grid */
  align-items: flex-end;               /* num 跟 body 都贴 row 底 */
  gap: var(--s-6);
  flex: 1;                             /* top 占满 cell 剩余 · title 自动到底 */
  min-height: 0;
}
.prim-cards-numbered[data-count="4"] .ncard-num {
  flex: 0 0 auto;                      /* 不缩不长, 内容宽 */
  line-height: var(--lh-display);                    /* 紧 line-box · "01" 底 OK */
}
.prim-cards-numbered[data-count="4"] .ncard-body {
  flex: 1 1 0;                         /* 吃完 horizontal 剩余 */
  min-width: 0;
  margin: 0 0 var(--s-4) 0;                  /* bottom 14 让 body 比 num 底略高 (视觉对齐 num baseline 而非 line-box) */
  /* override base -webkit-box · grid/flex item 渲染不稳 → 改 display:block + max-height */
  display: block;
  -webkit-line-clamp: unset;
  -webkit-box-orient: unset;
  max-height: 3em;                     /* 2 × 1.5em · 4 cell body 强制 2 行 max (与 spec 一致) */
  overflow: hidden;
}
.prim-cards-numbered[data-count="4"] .ncard-title {
  flex-shrink: 0;                      /* title 不被挤压 · 永远贴 cell 底 (padding-bot 32 内) */
}

/* solid-card 是 legacy 别名 · 视觉已合并 default · class 留兼容 */
.prim-cards-numbered.solid-card .ncard {}

/* ════════════════════════════════════════════════════════════════════════
   ★ LAYER 2 · Composite Primitives · 通用 card 组合
   ────────────────────────────────────────────────────────────────────────
   规则: 写新模板时, 优先继承 .prim-card · 不再 inline `border + radius + bg`
   3 个 variant 覆盖 90% 用例:
     .prim-card        = 默认 surface card (canvas 上的白卡)
     .prim-card-strong = 强调 card (hard offset shadow + 2px title 边)
     .prim-card-brand  = brand 卡 (蓝底白字 / brand-tinted shadow)
   组合用 utility class (e.g. <div class="prim-card u-shadow-md">)
   ──────────────────────────────────────────────────────────────────────── */

/* ─── default · canvas surface card ─── */
.prim-card {
  background: var(--c-surface);
  border: var(--border-hairline);
  border-radius: var(--card-radius);
  padding: var(--s-6);
  color: var(--c-text);
  /* shadow 默认不开 · 走 utility class 加 */
}

/* ─── strong · 2px title 边 + 商务 SaaS layered shadow ─── */
.prim-card-strong {
  background: var(--c-surface);
  border: var(--border-strong);
  border-radius: var(--card-radius);
  padding: var(--s-7);
  box-shadow: var(--card-shadow);                         /* 商务 layered (跟 token swap · 不是硬黑 brutalist) */
  color: var(--c-text);
}

/* ─── brand · 蓝底白字 + brand-tinted soft glow ─── */
.prim-card-brand {
  background: var(--c-brand);
  color: var(--c-text-on-brand);
  border: 2px solid var(--c-title);
  border-radius: var(--card-radius);
  padding: var(--s-7);
  box-shadow: var(--card-shadow);                         /* 商务 layered + brand glow */
}
.prim-card-brand h1, .prim-card-brand h2, .prim-card-brand h3,
.prim-card-brand h4, .prim-card-brand h5, .prim-card-brand h6,
.prim-card-brand p, .prim-card-brand strong, .prim-card-brand em {
  color: inherit;
}

/* ─── rose · 警示 / DON'T card ─── */
.prim-card-rose {
  background: var(--c-rose-10);
  color: var(--c-text);
  border: 2px solid var(--c-rose);
  border-radius: var(--card-radius);
  padding: var(--s-6);
  box-shadow: var(--shadow-rose);
}

/* ─── tint · brand-10 软底 (low-attention card) ─── */
.prim-card-tint {
  background: var(--c-surface-tint);
  border: var(--border-brand);
  border-radius: var(--card-radius);
  padding: var(--s-6);
  color: var(--c-text);
}

/* ─── ghost · 透明底 + 仅 hairline (减视觉重量) ─── */
.prim-card-ghost {
  background: transparent;
  border: var(--border-hairline);
  border-radius: var(--card-radius);
  padding: var(--s-6);
  color: var(--c-text);
}

/* .prim-chrome-dark · 已删除 2026-05-11 (⑫ Code family 砸 · 0 HTML 用 · dead code)
   原: macOS-style code/terminal window chrome (dark BG + window dots)
   未来若需要重加: 用 /* immune · code chrome */ 注释 + Tier-1 直引用 (--gray-900 等) */

/* ════════════════════════════════════════════════════════════════════════
   ★ LAYER 2 · Card-like Hover · 全库通用 hover lift
   ────────────────────────────────────────────────────────────────────────
   规则: 所有「卡式容器」共享 hover behavior · 单点 token (--card-shadow-hover
   / --card-translate-hover / --card-border-color-hover) · 改一处全跟
   选择器加 .ds-slide 祖先 (specificity 0,3,0 胜 template inline 0,2,0)
   覆盖: ncard · tool-grid.tg-cell · side-card · matrix.cell · table row
   不覆盖: pillar.col (column-shape 非 card) · pmtx 用 brand-tint 不加 lift
   ──────────────────────────────────────────────────────────────────────── */

/* tool-grid · 工具盘点卡 · .ds-slide 祖先 win 模板 inline 同选择器 */
.ds-slide .prim-tool-grid .tg-cell {
  box-shadow: var(--card-shadow);
  transition:
    border-color var(--duration-hover) var(--easing-decisive),
    box-shadow var(--duration-hover) var(--easing-decisive),
    transform var(--duration-hover) var(--easing-decisive);
}
.ds-slide .prim-tool-grid .tg-cell:hover {
  border-color: var(--card-border-color-hover);
  box-shadow: 0 0 0 1px var(--card-border-color-hover) inset, var(--card-shadow-hover);
  transform: var(--hover-transform);
}

/* side-card · versus / before-after / phase-compare 共用 (defined in this file, no specificity 战) */
.prim-side-card {
  box-shadow: var(--card-shadow);
  transition:
    border-color var(--duration-hover) var(--easing-decisive),
    box-shadow var(--duration-hover) var(--easing-decisive),
    transform var(--duration-hover) var(--easing-decisive);
}
.prim-side-card:hover {
  border-color: var(--card-border-color-hover);
  box-shadow: 0 0 0 1px var(--card-border-color-hover) inset, var(--card-shadow-hover);
  transform: var(--hover-transform);
}

/* table row · 加 transition 让 :hover bg 平滑切换 */
.ds-slide .prim-table tbody tr td {
  transition: background var(--duration-hover) var(--easing-default);
}

/* matrix-quadrant / priority-matrix · v3 (2026-05-10)
   · 非 brand cell hover 走 brand-tint-08 软填底 · brand cell 不变 (避免覆盖单 emphasis) */
.ds-slide .prim-mq .mq-cell,
.ds-slide .prim-pmtx .pmtx-cell {
  transition: background var(--duration-hover) var(--easing-default);
}
.ds-slide .prim-mq .mq-cell:not(.brand):hover,
.ds-slide .prim-pmtx .pmtx-cell:not(.brand):hover {
  background: var(--c-brand-tint-08);
}
