/* ============================================================
   银序 SILVERA · 设计语言 v2（ui-v2.css）
   ============================================================
   老板的要求：「按照你的建议修改。**并且保留原版前后台界面，可以切换**」。

   所以这个文件**不是**「把老样式改掉」，而是**加上去的一层**：
     · 每一条规则都写在 `html[data-ui="v2"]` 下面 ⇒ 切回原版时**它们一条都不生效**，
       原版（tokens.css + admin-shell.css + admin-ui.css + shop-ui.css）**一个字都没被改**。
     · 这就是「保留原版」的技术前提：新版是叠加，不是替换。
       ⇒ **千万别把 v2 的规则提到 `html[data-ui="v2"]` 外面**（哪怕「就这一条」）——
         那一瞬间「切回原版」就变成了假的，而界面上看不出来。

   开关与值域在 `src/shared/ui-version.js`（唯一出处）。这一层只认那个属性。

   ============================================================
   这一层做了什么（按「改了什么、为什么」排）
   ============================================================
    ① **共用令牌**：把 v2 的颜色 / 圆角 / 阴影 / 密度收在一条 `:root` 里，
       前后台共用（前台舒展、后台紧凑，差的是字号与行高，不是色板）。
    ② **基础硬线**（前后台都补）：
       · **焦点必须看得见**（键盘 Tab 时 2px 描边）—— 原版把 outline 去掉了，键盘用户看不见自己在哪；
       · **点击目标 ≥ 32px**（移动端 ≥ 44px）—— 小按钮在触屏上点不准；
       · **状态不许只用颜色**（徽标必须带文字）。
    ③ **后台外壳换成左导航**（15 项菜单从前是顶栏一行、窄窗口要折行）：
       body 变成「左栏 + 右栏」，菜单按**已有的四类分组**（卖品 / 履约 / 客户 / 底层）竖排。
       ⚠️ 菜单表**一份都没新增**：分组与项都来自 permissions.js（`navGroups()`）。
    ④ **前台只做样式层**：排版节奏、金额等宽、卡片与按钮规范、可点区域。
       前台**结构**上的改动（分类进一级、加购吸底、结算独立页）是下一批的事 ——
       它们要动 DOM 与路由，属于「一次只能改一件」的那一类。
   ============================================================ */

/* ================================================================
   ① 令牌（两版并存的写法：只在 v2 下覆盖）
   ================================================================ */
html[data-ui="v2"]{
  /* 圆角：v2 统一 2px（原版后台是 3px、前台 2px —— 合成一个值） */
  --r:2px;
  --ui2-r:2px;

  /* 状态四色：成功 / 待处理 / 进行中 / 危险（前后台共用的那一份） */
  --ok:#3A6B4D;
  --warn:#8A6A1F;
  --info:#3D5A80;
  --sale:#B4413A;
  /* 色带上的**次要**文字（第 43 章：分组标题右边那个项数）。
     ⚠️ 这里不能用 `--faint`（#6E6E68）：它压在色带底色 #EDEBE4 上只有 **4.30:1**，
        压在「含当前页」那档的 #E8E5DC 上更差（**4.07:1**）—— 都低于 4.5。
        这个是量出来的（v2 那一趟可读性体检在 17 个页面上把它报了出来），
        不是估的：色带底色本来就比白卡深，同一个灰字搬过来就不够了。 */
  --ui2-band-2:#4A4A45;

  /* 密度：后台紧凑、前台舒展（差在这里，别在页面里再定义一次） */
  --ui2-row-h:36px;          /* 表格行高下界（触摸时按 --ui2-tap 抬到 44） */
  --ui2-gap:12px;
  --ui2-pad:16px;
  --ui2-tap:32px;            /* 点击目标的下界（硬线） */
  /* ---- 左导航的宽度两档（第 43 章）------------------------------------
     这三个数是**同一件事的三面**，别再往页面里写第三个数：
       `--ui2-nav-w`     展开宽（= admin-nav.js 的 SIDENAV_W，自检会比对两者）
       `--ui2-nav-w-min` 窄条宽（= SIDENAV_W_MIN：4 个 12px 字 + 留白 + 余量）
       `--ui2-nav-w-now` **当前占位宽**（派生的：窄条时取 min，其余取 w）
     ⚠️ 当初写成「窄条时把 `--ui2-nav-w` 自己改成 68px」是错的：
        hover 展开要 `width:var(--ui2-nav-w)`，一改就把展开宽也改小了 ——
        所以「展开宽」必须是个**不受状态影响**的数。 */
  --ui2-nav-w:224px;
  --ui2-nav-w-min:68px;
  --ui2-nav-w-now:var(--ui2-nav-w);
  --ui2-shadow-1:0 4px 16px rgba(0,0,0,.10);
  --ui2-shadow-2:0 8px 30px rgba(0,0,0,.14);
}
@media (pointer:coarse){
  /* 触屏：点击目标抬到 44（硬线在手指上才是真的） */
  html[data-ui="v2"]{ --ui2-tap:44px; --ui2-row-h:44px; }
}

/* ================================================================
   ② 基础硬线（前后台共用）
   ================================================================ */
html[data-ui="v2"] :focus-visible{
  outline:2px solid var(--ink);
  outline-offset:2px;
  border-radius:1px;
}
/* 键盘焦点要看得见，鼠标点击不要留一圈出来 —— 上面用 :focus-visible 就是为了这个 */
html[data-ui="v2"] a:focus:not(:focus-visible),
html[data-ui="v2"] button:focus:not(:focus-visible){outline:0}

html[data-ui="v2"] .btn,
html[data-ui="v2"] .tab,
html[data-ui="v2"] .row-btn{
  min-height:var(--ui2-tap);
  display:inline-flex;align-items:center;justify-content:center;
}
html[data-ui="v2"] .btn--sm{min-height:calc(var(--ui2-tap) * .75)}

/* 状态徽标：颜色只讲状态，而且**必须带文字**（不许只有红点绿点） */
html[data-ui="v2"] .badge{
  border-radius:99px;font-size:12px;padding:3px 9px;
}
html[data-ui="v2"] .badge--ok{background:#F2F7F3;border-color:#CFE1D5;color:var(--ok)}
html[data-ui="v2"] .badge--warn{background:#FDF6E3;border-color:#EFD9A0;color:var(--warn)}
html[data-ui="v2"] .badge--err{background:#FBF1F0;border-color:#E4C3C0;color:var(--sale)}
html[data-ui="v2"] .badge--info{background:#F2F6FA;border-color:#CFDBE8;color:var(--info)}

/* ================================================================
   ③ 后台外壳：左导航（v2）
   ----------------------------------------------------------------
   body 从「纵向弹性列」变成「两列网格」：
     第 1 列 = 左导航（占两行）· 第 2 列 = 顶栏 + 主区
   ⚠️ 顶栏那份菜单（#topnav）在 v2 里**仍然渲染**（`renderTopNav` 一直跑，原版靠它），
      只是被藏起来 —— 藏的是「显示」，不是「事实」：菜单唯一的出处仍是 permissions.js，
      两版读的是同一份（`navGroups()`）。**别在这里删掉它**：原版切回来还要用。
   ================================================================ */
/* ⚠️⚠️ 这一段**必须**带 `:has(> #sidenav)` 这个限定（实测踩出来的）：
   ① 前台页面也在 `html[data-ui="v2"]` 里，它们**没有左导航** ——
      不加限定的结果是「前台左侧凭空多出 224px 的空栏 + 整页高度被锁成 100vh」；
   ② 工作台（index.html）**故意不调 mountAdminPage**（它是交付状态页），
      早先它连左导航都没有 —— 后来补上了，但这条限定仍然要留着：
      判断「我是不是后台壳」的依据应该是**有没有那一栏**，而不是「页面是不是后台页」。
   ⇒ 一句话：**有左导航才按后台壳排版**。 */
html[data-ui="v2"] body:has(> #sidenav){
  display:grid;
  /* ⚠️ 第二列必须写 `minmax(0,1fr)` 而不是 `1fr`：`1fr` 的默认最小尺寸是
     `auto`（= 内容的 min-content），表格里一列长文本就能把整页撑出横向滚动条。
     实测：写成 `1fr` 时，订单页在 1440 宽的窗口下量到 1520px（★ 横向溢出）。 */
  grid-template-columns:var(--ui2-nav-w-now) minmax(0,1fr);
  grid-template-rows:auto 1fr;
  height:100vh;
}
html[data-ui="v2"] body:has(> #sidenav) > #sidenav{grid-column:1;grid-row:1 / -1;min-height:0}
html[data-ui="v2"] body:has(> #sidenav) > .top{grid-column:2;grid-row:1}
html[data-ui="v2"] body:has(> #sidenav) > .main{
  grid-column:2;grid-row:2;
  height:auto;min-height:0;display:flex;
}
/* v2 的顶栏不再放「品牌 + 一整排菜单」：品牌在左导航里，菜单在左导航里，
   顶栏只剩「我在哪 / 我是谁 / 我能做什么」——这也是它不会再被挤满的原因。 */
html[data-ui="v2"] .topnav{display:none}
html[data-ui="v2"] .top__logo,
html[data-ui="v2"] .top__sep{display:none}
html[data-ui="v2"] body:has(> #sidenav) > .top{min-height:48px;padding:0 16px}

/* 左栏收成窄条时的**占位宽**（派生值；唯一来源是 `<html data-nav>`，由 admin-nav.js 一处算） */
html[data-ui="v2"][data-nav="collapsed"]{--ui2-nav-w-now:var(--ui2-nav-w-min)}

/* 左导航本体
   ⚠️ 这些规则也要带 `html[data-ui="v2"]` 前缀（自检有一条「每条规则都必须挂在 v2 下」）：
      虽然这个容器只在 v2 里被建出来、原版下根本不存在，但「**加法不是替换**」这条规矩
      必须是**结构上成立**的，而不是「恰好不会有影响」。少写一个前缀，
      那条断言就帮你把它抓出来（第 42 章就是它抓到的）。

   ★ 第 43 章这一块做了两件事（老板报的）：
     ① **分组名和菜单项要明显区分** ⇒ 分组标题变成**色带**
        （有浅底 + 深色字 + 字母间距 + 上方留白 + 组间一条分隔线 + 一个开合三角），
        而菜单项是**没有底**的浅灰字。两者不再只是「差 1px」。
     ② **三级折叠** ⇒ 见下面三段：组级（aria-expanded）/ 整栏（data-nav）/
        窄窗口自动收（由 JS 写 data-nav，**这里没有媒体查询** —— 那会是第二处判据）。
   ============================================================ */
html[data-ui="v2"] .sidenav{
  background:#FAFAF8;border-right:1px solid var(--line);
  display:flex;flex-direction:column;min-height:0;overflow-y:auto;padding:14px 10px 12px;
}

/* ---- 品牌行 + 折叠按钮（折叠按钮是「整栏收成窄条」的手动入口）---------- */
html[data-ui="v2"] .sidenav__brand{
  display:flex;align-items:center;gap:6px;
  font-family:'Sora',sans-serif;font-weight:600;letter-spacing:.22em;font-size:13px;
  color:var(--ink);padding:2px 0 14px 10px;
}
html[data-ui="v2"] .sidenav__brand-t{
  flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
html[data-ui="v2"] .sidenav__fold{
  flex:0 0 auto;display:inline-flex;align-items:center;gap:4px;
  min-height:var(--ui2-tap);padding:3px 8px;
  border:1px solid var(--line);border-radius:var(--ui2-r);
  background:var(--panel);color:var(--muted);font-size:12px;
}
html[data-ui="v2"] .sidenav__fold:hover{color:var(--ink);border-color:var(--accent)}
html[data-ui="v2"] .sidenav__fold svg{transition:transform .18s}
html[data-ui="v2"][data-nav="collapsed"] .sidenav__fold svg{transform:rotate(180deg)}

/* ---- ① 分组标题：**色带**（这是「要和菜单项明显区分」的答案）---------- */
html[data-ui="v2"] .sidenav__grp{border-top:1px solid var(--line);padding-top:10px}
/* 第一个分组紧跟在「工作台」后面，不需要再来一条分隔线 */
html[data-ui="v2"] .sidenav__a--home + .sidenav__grp{border-top:0;padding-top:4px}
html[data-ui="v2"] .sidenav__g{
  display:flex;align-items:center;gap:6px;width:100%;
  min-height:var(--ui2-tap);padding:6px 10px;
  border:0;border-radius:var(--ui2-r);
  background:#EDEBE4;color:var(--ink);
  /* ⚠️ 12px 是**下限**（后台可读性体检守着）：分组名是「扫一眼找模块」的路标，
     第 42 章第一版写了 11px，v2 那一趟体检在 16 个页面上把它报了出来。 */
  font-size:12px;font-weight:500;letter-spacing:.12em;
  text-align:left;
}
html[data-ui="v2"] .sidenav__g:hover{background:#E5E2D9}
html[data-ui="v2"] .sidenav__g-t{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
html[data-ui="v2"] .sidenav__g-n{
  font-style:normal;font-weight:400;color:var(--ui2-band-2);font-variant-numeric:tabular-nums;
}
/* 收起来的那一组里**有当前页** ⇒ 色带加深 + 一条深色竖条。
   少了它，人把自己所在的组收起来之后就「看不见自己在哪」了。 */
html[data-ui="v2"] .sidenav__grp[data-has-cur="1"] .sidenav__g{
  background:#E8E5DC;box-shadow:inset 2px 0 0 var(--ink);
}
/* 开合三角：色带是**按钮**这件事要看得出来（只有底色的话，人未必知道它能点）。
   朝右 = 已收起 · 朝下 = 已展开。 */
html[data-ui="v2"] .sidenav__g-c{
  flex:0 0 auto;width:0;height:0;margin-left:2px;
  border-left:6px solid currentColor;
  border-top:4px solid transparent;border-bottom:4px solid transparent;
  opacity:.7;transition:transform .16s;
}
html[data-ui="v2"] .sidenav__g[aria-expanded="true"] .sidenav__g-c{transform:rotate(90deg)}

/* ---- ② 组级折叠：开合状态挂在标题按钮的 `aria-expanded` 上（**一处**）----
   CSS 与读屏软件读的是同一份，不存在「看着收了、读屏还念有」。 */
html[data-ui="v2"] .sidenav__items{display:flex;flex-direction:column;padding:4px 0 0}
html[data-ui="v2"] .sidenav__g[aria-expanded="false"] + .sidenav__items{display:none}

/* ---- 菜单项 ---------------------------------------------------------- */
html[data-ui="v2"] .sidenav__a{
  display:flex;align-items:center;gap:8px;
  padding:8px 10px;border-radius:var(--ui2-r);
  border:1px solid transparent;
  font-size:13px;color:var(--muted);text-decoration:none;
  min-height:var(--ui2-tap);white-space:nowrap;
}
html[data-ui="v2"] .sidenav__a:hover{background:var(--wash);color:var(--ink)}
html[data-ui="v2"] .sidenav__a.on{background:#fff;border-color:var(--line);color:var(--ink);font-weight:500}
html[data-ui="v2"] .sidenav__a em{margin-left:auto;font-style:normal;font-size:12px;color:var(--faint)}
html[data-ui="v2"] .sidenav__a--home{font-family:'Sora',sans-serif;letter-spacing:.12em;font-size:12px}
/* 每一项都渲染了名字（见 admin-nav.js 的 `link`）：窄条里显示**短名**、藏起全名；
   展开时反过来。
   ⚠️ 为什么不是「用 JS 换文字」：窄条 → 展开是**鼠标挪上去**触发的，
      那一刻没有 JS 介入的余地（纯 CSS），所以两份都在 DOM 里。 */
html[data-ui="v2"] .sidenav__l{display:none}
/* ⚠️⚠️ 这一条不能少：**短名与全名相同的项**（两端那两个固定项：工作台 / 店铺前台）
   只渲染**一个** span，而它同时带着这两个类。
   少了这一条：基础规则 `.sidenav__l{display:none}` 会把它藏掉 ⇒ 窄条里那两项**变成两条空行**
   （还能点，但一个字都没有）。
   实测——第 43 章第一次跑全量回归时，够得着体检在 1280 档的每一页上报到：
   「左导航里有一项没有可见的名字（index.html）—— 它就是一条空行」。
   具体度：`.sidenav__s.sidenav__l`（3 个类）压过 `.sidenav__l`（1 个类）✓ */
html[data-ui="v2"] .sidenav__s.sidenav__l{display:inline}
html[data-ui="v2"][data-nav="expanded"] .sidenav__s{display:none}
/* ⚠️ 这一条必须写在**上一条之后**：两者具体度相同（都是 4 个类/属性 + 1 个元素），
   同分时后写的胜。调换顺序 ⇒ 带两个类的固定项在展开态下被上一条藏掉（同样变成空行）。 */
html[data-ui="v2"][data-nav="expanded"] .sidenav__l{display:inline}

html[data-ui="v2"] .sidenav__foot{
  margin-top:auto;padding:12px 10px 2px;border-top:1px solid var(--line);
  font-size:12px;color:var(--faint);line-height:1.7;
}
html[data-ui="v2"] .sidenav__foot b{color:var(--muted);font-weight:400}
html[data-ui="v2"] .sidenav__foot-note{margin-left:10px}

/* ================================================================
   ③-2 整栏收成窄条（`data-nav="collapsed"`）
   ----------------------------------------------------------------
   ★ 窄条是 **fixed 浮在上面**的，不是把网格第一列压窄：
     如果它还在文档流里，鼠标一挪上去展开就会**把整张表推窄** ——
     于是「鼠标一动，表格宽度就跳」，那是没法用的。
     脱离文档流之后：占位宽永远是 `--ui2-nav-w-now`（窄条那档），
     展开只是**盖**在内容上（带阴影），底下的表格一个像素都不动。
   ================================================================ */
html[data-ui="v2"][data-nav="collapsed"] .sidenav{
  position:fixed;left:0;top:0;bottom:0;
  width:var(--ui2-nav-w-min);
  /* ⚠️ 纵向要能滚：窄条里 15 个短名 + 4 条分隔 + 两端 ⇒ 约 674px，
     在 800/900 高的窗口里放得下，但**窗口再矮就该能滚**（裁掉 = 静默丢内容）。 */
  z-index:70;padding:14px 6px 12px;overflow-y:auto;overflow-x:hidden;
  transition:width .16s ease,box-shadow .16s ease;
}
/* 鼠标挪上来（或键盘 Tab 进来）临时展开 —— 两种都要有：
   只用 `:hover` 的话，用键盘的人永远打不开它。 */
html[data-ui="v2"][data-nav="collapsed"] .sidenav:hover,
html[data-ui="v2"][data-nav="collapsed"] .sidenav:focus-within{
  width:var(--ui2-nav-w);overflow-y:auto;box-shadow:var(--ui2-shadow-2);
}

/* ---- 窄条里长什么样（且鼠标没挪上来、键盘没聚焦时）----------------------
   ★ 一句话：**色带换成一条分隔线，其余全是一列短名。**
     为什么不是「把组体也收起来」：窄条的意义是**省宽度但仍然点得到** ——
     组体一收，15 个菜单项在窄条里就全都点不到了，只剩 4 条光杆标题，
     而老板要的是「收成窄条还能用」（他的原话是「只留首字」）。
   ★ 为什么要让色带 `display:none` 而不是把它做矮：这样**读屏软件看到的和眼睛看到的一致**
     （窄条里没有「折叠按钮」，只有分隔线）—— 否则读屏会念一个视觉上不存在的折叠按钮，
     而窄条里那几项其实全是显示的（`aria-expanded` 说「已收起」，对不上）。
     ⚠️ 顺带也就没有「点了没反应」的风险：`display:none` 的东西点不到，不需要去禁用它的点击。 */
html[data-ui="v2"][data-nav="collapsed"] .sidenav:not(:hover):not(:focus-within) .sidenav__g,
html[data-ui="v2"][data-nav="collapsed"] .sidenav:not(:hover):not(:focus-within) .sidenav__brand-t,
html[data-ui="v2"][data-nav="collapsed"] .sidenav:not(:hover):not(:focus-within) .sidenav__foot-note,
html[data-ui="v2"][data-nav="collapsed"] .sidenav:not(:hover):not(:focus-within) .sidenav__fold-t{
  display:none;
}
/* 组与组之间用一条分隔线代替色带（线的位置就是色带原来的位置） */
html[data-ui="v2"][data-nav="collapsed"] .sidenav:not(:hover):not(:focus-within) .sidenav__grp{
  border-top:1px solid var(--line);padding-top:8px;margin-top:2px;
}
/* 窄条里所有组体**一律显示**（一列短名本来就短，这是窄条的意义）。
   ⚠️ 这一条会盖过 `[aria-expanded="false"] + .sidenav__items{display:none}`，是**有意的**：
      窄条里不按组收纳。而组开合的状态**没有被动过** ⇒ 鼠标挪上去展开时照旧生效。 */
html[data-ui="v2"][data-nav="collapsed"] .sidenav:not(:hover):not(:focus-within) .sidenav__items{
  display:flex;
}
/* 品牌行与底部都收到零内边距：
   ⚠️ 底部那一块（`.sidenav__foot`）自带左右 10px，不收掉的话
      「店铺前台」这一项只剩 36px 宽，4 个字（12px = 48px）**当场挤出 13px**（实测）。
      菜单项本身也收到 2px，`justify-content:center` 让短名居中 —— 两侧各留 4px 余量。 */
html[data-ui="v2"][data-nav="collapsed"] .sidenav:not(:hover):not(:focus-within) .sidenav__brand,
html[data-ui="v2"][data-nav="collapsed"] .sidenav:not(:hover):not(:focus-within) .sidenav__foot{
  padding-left:0;padding-right:0;
}
html[data-ui="v2"][data-nav="collapsed"] .sidenav:not(:hover):not(:focus-within) .sidenav__brand{
  justify-content:center;
}
html[data-ui="v2"][data-nav="collapsed"] .sidenav:not(:hover):not(:focus-within) .sidenav__a{
  justify-content:center;padding-left:2px;padding-right:2px;font-size:12px;
}

/* 页面里那几块（工具条 / 页签 / 列表）在 v2 下换一套密度与圆角 */
/* ⚠️ 工具条**不许改成一换行**：v1 的 `.bar` 就是「一行固定高」（46px），
   而 v2 第一版给它加了 `flex-wrap:wrap` —— 实测在 1280 宽下，私域「客户与好友」
   那一栏的按钮排到 4 行、**从 46px 变成 177px**，直接把列表挤到只看得见 2 行。
   ⇒ v2 只把**可点高度**抬到 44（手指够得着），不碰它「一行」这件事。 */
html[data-ui="v2"] .bar{min-height:44px;padding:0 14px;gap:10px}
html[data-ui="v2"] .tabbar{padding:0 14px}
html[data-ui="v2"] .tab{padding:6px 10px}
html[data-ui="v2"] .aside{background:#FCFBF9}
html[data-ui="v2"] .sec__t{letter-spacing:.08em;color:var(--muted)}

/* 表格：行高、悬停、选中、数字列等宽（这些是「一屏看几十行」的界面真正吃力的地方） */
html[data-ui="v2"] table.tbl tbody tr{min-height:var(--ui2-row-h)}
html[data-ui="v2"] table.tbl tbody tr.on{background:#F5F5F2}
html[data-ui="v2"] table.tbl td{font-variant-numeric:tabular-nums}

/* 空态与加载：原版只有 `.empty` 一句话，v2 给它版式（标题 + 一句怎么做 + 出口） */
html[data-ui="v2"] .empty{padding:44px 22px;line-height:1.95}

/* 浮层：两级阴影 + 统一圆角（原版逐页各写一遍 padding/max-width 的地方不动，只统一观感） */
html[data-ui="v2"] .modal__box,
html[data-ui="v2"] .drawer{box-shadow:var(--ui2-shadow-2)}
html[data-ui="v2"] .toast{box-shadow:var(--ui2-shadow-1)}

/* ================================================================
   ④ 前台皮肤（样式层）
   ----------------------------------------------------------------
   ⚠️ 只做「不动 DOM」的那些事：排版节奏、金额口径、按钮与可点区域、焦点。
      前台要**改结构**的三件（分类进一级 · 加购吸底 · 结算独立页）在下一批，
      因为那三件要改 DOM 与路由，混在一起做就没法单独回退了。
   ================================================================ */
/* ⚠️ 这里**不要**写 `html[data-ui="v2"] body{font-size:…}`（第一版写了，被体检抓出来）：
   前后台的字号是两个口径（前台 15/1.7、后台 13/1.6），统一设 body 等于把后台整体放大 ——
   实测后果：私域那两屏的说明条从 79px 涨到 120px、表格行也变高，
   于是「一块表看得见几行」在 1280×800 下**掉到 1 行**（新版体检当场报红）。
   ⇒ 前台的排版只写在前台自己的组件上（下面那些），不许碰 body。 */
html[data-ui="v2"] .sec-head h2{font-size:28px;letter-spacing:.015em}
html[data-ui="v2"] .sec-head .kicker{letter-spacing:.24em}
html[data-ui="v2"] .sec-head p{max-width:62ch}

/* 金额：等宽数字 + 两位小数（金额列不对齐，眼睛就要一个个读） */
html[data-ui="v2"] .price,
html[data-ui="v2"] .subtotal-row b,
html[data-ui="v2"] .ci-info .p{font-variant-numeric:tabular-nums;letter-spacing:.01em}

/* 按钮：抬高到 44（触屏够得着）+ 只有一种主按钮色 */
html[data-ui="v2"] .btn-solid,
html[data-ui="v2"] .btn-outline{min-height:44px}
html[data-ui="v2"] .btn-checkout{min-height:48px;font-size:15px}
html[data-ui="v2"] .qty button{width:32px;height:32px}
html[data-ui="v2"] .ci-remove{min-height:32px;display:inline-flex;align-items:center}

/* ★ 第 45 章：详情页的「决策四件事」（内容由 product.js 在 v2 下渲染）
   ----------------------------------------------------------------
   把顾客真正要回答的四个问题（材质 / 净重 / 可选规格 / 保养）摆在价格旁边，
   而不是让他从下面的长文案里一行行找。
   四项**全部来自已有的结构化字段**，缺哪一项就不显示哪一项（见 fact4Block 抬头）。 */
html[data-ui="v2"] .fact4{
  margin:14px 0 2px;padding:12px 14px;
  background:var(--wash);border-radius:var(--ui2-r);
  display:grid;grid-template-columns:1fr;gap:6px;
}
/* ⚠️ 一行一件事（标签 64px + 值自适应），**不是两列**：
   两列时「可选规格：40cm / 45cm / 50cm」会在窄格里断成「40cm / 45cm /」+「50cm」，
   看着像排版坏了（实测截图里就是这样）。一行一件事多占两行，但每一行都读得完。 */
html[data-ui="v2"] .fact4 > div{
  display:grid;grid-template-columns:64px 1fr;gap:10px;align-items:baseline;min-width:0;
}
html[data-ui="v2"] .fact4 dt{
  font-size:12px;letter-spacing:.08em;color:var(--muted);white-space:nowrap;
}
html[data-ui="v2"] .fact4 dd{
  margin:0;min-width:0;font-size:13px;color:var(--ink);overflow-wrap:anywhere;
}

/* ★ 加购键吸底（第 45 章）：详情页往下翻很长，滚到哪儿都该点得到「加入购物车」。
   ⚠️ `position:sticky` 而不是 `fixed`：它在正常流里**仍然占位** ——
      用 fixed 的话，页面最底下会一直压着一条，把心愿单那行盖住。 */
html[data-ui="v2"] .buy__acts{
  position:sticky;bottom:0;z-index:20;
  background:linear-gradient(to top,var(--bg) 72%,rgba(250,250,248,0));
  padding:12px 0 10px;
}

/* 商品网格：v2 的间距更松一点（轻奢靠留白，不靠装饰） */
html[data-ui="v2"] .products{gap:32px 22px}
html[data-ui="v2"] .card-name{line-height:1.6}
html[data-ui="v2"] .quick-add{min-height:44px;display:flex;align-items:center;justify-content:center}
html[data-ui="v2"] .card-tag{border-radius:1px;letter-spacing:.08em}

/* 导航：滚动后不再跳高度（原版 68→54 会让内容整体上跳一下） */
html[data-ui="v2"] .nav-inner{height:64px}
html[data-ui="v2"] .nav.scrolled .nav-inner{height:60px}
html[data-ui="v2"] .nav-links a{min-height:32px;display:inline-flex;align-items:center}

/* 购物袋抽屉：v2 下给一个明确的主按钮区（去结算换页那一版在下一批） */
html[data-ui="v2"] .drawer-head h3{font-size:16px}
html[data-ui="v2"] .ship-bar{border-radius:var(--ui2-r)}
