/* /liby/demo —— 演示中心的共享外壳（配色 + 水印 + 声明条 + 顶栏栈 + 基础组件）。
 *
 * 为什么是一个文件而不是每页各抄一份：这套演示由多个页面拼成（成品原型 / 知识库工场 /
 * AI 评估台 / 巡检回放 / UI 原型走廊），它们由不同的人先后写。**水印与「演示原型 · 数据为
 * 合成样例」的声明条是硬约束**（合成数据被读成客户真实数据是这次最贵的失败），
 * 各抄一份就会漏；放这里，新页面 link 一行就自带。
 *
 * 三条纪律，加页面前先读：
 * ① 每张页面都要 `<link rel="stylesheet" href="/liby/demo/tokens.css">`（**绝对路径**——
 *    入口 URL 是无尾斜杠的 /liby/demo，相对路径会按 /liby/ 解析然后 404）；
 * ② 每张页面 <body> 开头照抄 `.wm` 平铺水印 + `.topstack > .ribbon`（模板见本文件末尾注释）；
 * ③ 零外部请求：不引 webfont、不引 CDN、不发接口调用。讲标现场的网络不由我方控制。
 */

:root{
  /* 存量系统 chrome：冷色，示意「贵方现有的合同管理系统」 */
  --sys:#2B3A4A; --sys-2:#3A4C60; --sys-line:#DDE3EA; --sys-ink:#EAF0F6;
  /* 我方建设的部分：品牌青，与存量系统在视觉上分得开 */
  --teal:#20B898; --teal-dark:#158A72; --teal-soft:#E9F8F5; --teal-line:#A6E4D5;
  --ink:#232629; --body:#5A6068; --muted:#8B9198;
  --line:#E7EAEE; --sunken:#F4F6F9; --card:#FFFFFF;
  --hi:#C0392B; --hi-soft:#FDECEA; --hi-line:#F3B5AC;
  --md:#B7791F; --md-soft:#FDF5E6; --md-line:#EDD9A8;
  --lo:#5B6B7C; --lo-soft:#EEF2F6; --lo-line:#CBD6E0;
  --ok:#1E8E5A; --ok-soft:#E8F6EE; --ok-line:#A9DCC1;
  --font:'Helvetica Neue',Helvetica,'PingFang SC','Hiragino Sans GB','Microsoft YaHei',Arial,sans-serif;
  --mono:ui-monospace,Menlo,Consolas,monospace;
}
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
/* ★ 别给 `html` 与 `body` **同时**设非 visible 的 overflow / overflow-x —— 那个组合会让
   body 真的成为滚动容器，页内所有 position:sticky（声明条、系统导航、侧边栏）**当场全部
   失效且不报错**。也别给包住整页内容的**高祖先元素**设 overflow-x:hidden（要裁就用 `clip`）。
   横向溢出靠量（document.documentElement.scrollWidth === clientWidth），不靠这一行盖住。
   ⚠️ `:root` **就是** `html` —— 而本文件上面正好有一个 `:root{...}` 块，是最顺手会被
   续写的地方：往它加一句 overflow，就与某张页内联的 `body{...}` 跨文件凑齐了危险组合。
   守卫认得这一格（它把 `:root` 归到 html），但读这段警告的人未必，所以在这里点名。
     实测对照（同一页同一元素，滚动约一屏后量 `.topstack` 的 `top`，issue #2694/#2693）：

       注入的 CSS                                  top     sticky
       `body{overflow-x:hidden}` 单写                0      ✅ 活
       `html{overflow-x:hidden}` 单写                0      ✅ 活
       `body{overflow:hidden}` 双轴单写              0      ✅ 活
       `html,body{overflow-x:hidden}`             −900     ❌ 死
       高祖先 div `{overflow-x:hidden}`            −900     ❌ 死
       高祖先 div `{overflow-x:clip}`                0      ✅ 活

     机制：`html` 的 overflow 为 `visible` 时，`body` 的 overflow **传播到视口**，body 自己
     不成为滚动容器，其内的 sticky 照常对视口生效；只有 `html` 也被设成非 visible，传播链
     才断掉。另一条真凶与 body 无关：任何**高祖先元素**的 overflow 非 visible（`clip` 除外）
     都会把 sticky 的粘附范围钳在那个盒子里。
     ⚠ 复现时别只把 `.topstack` 包进一个 div —— 那个 div 的高度就等于 topstack 高度，sticky
     本就无处可粘，`top` 直接 −900 看着像 overflow 干的。必须把 body 的**全部子元素**包进去。
     守卫：`ai-site/app/lib/liby-demo.test.ts` 的「演示页 sticky 承重 · html/body overflow」
     —— 按页合并「`<link>` 的每个 css + 页内**全部** `<style>`」后判（危险组合跨文件才凑齐，
     逐文件独立判是看不见的），另断言顶栏仍是 `<body>` 直接子元素：那是把上面第二条真凶
     （高祖先 overflow）归约成第一条的**前提**，顶栏一旦被包进 wrapper 就得去补「任意祖先」
     那条检查。别在别处再写第二份 —— 这条判据只有一个实现，就在那里。
   ⚠ 危险组合可以**跨文件**凑齐（本文件设 html + 某张页的内联 <style> 设 body），
   两个文件各自看都无辜 —— 所以守卫按「一张页最终加载到的所有 CSS」合并后判。 */
body{margin:0; background:var(--sunken); color:var(--ink); font-family:var(--font);
  -webkit-font-smoothing:antialiased; line-height:1.66; font-size:14px}
b,strong{font-weight:600}
button{font:inherit; cursor:pointer}
a{color:var(--teal-dark)}
::-webkit-scrollbar{width:7px;height:7px}
::-webkit-scrollbar-thumb{background:#CFD6DE;border-radius:4px}

/* ── 常驻水印：平铺、不可关、盖在所有常规内容之上（弹层除外）────────────────
   ★ 必须是平铺在像素里的 <svg><pattern>，不是可关掉的角标。本仓踩过：和贵 demo 的
   合成数据靠页内 chip 兜底，**印进 PPT 就没有 chip 了**。 */
.wm{position:fixed; inset:0; width:100%; height:100%; z-index:900; pointer-events:none;
  color:#1B2733; opacity:.06}
.wm text{font-size:15px; letter-spacing:2px; font-weight:600; fill:currentColor;
  font-family:'PingFang SC','Microsoft YaHei',sans-serif}

/* ── 顶栏栈：声明条 +（可选）系统栏 + 导航，合成**一个** sticky ──────────────
   此前是三个各自 sticky + 手写偏移(top:0/29/75)，窄屏上声明条一换行就比 29px 高，
   当场把系统栏盖住一半 —— 而且完全静默。偏移只要是手写的就会在某个宽度上错位。 */
.topstack{position:sticky; top:0; z-index:60}
.ribbon{background:#1B2733; color:#E7EEF5; font-size:12px; letter-spacing:.4px;
  padding:6px 14px; display:flex; align-items:center; gap:10px}
.ribbon .dot{width:6px;height:6px;border-radius:50%;background:#F0B429;flex:none}
.ribbon .txt{flex:1; min-width:0}
.ribbon a,.ribbon button{background:transparent; border:1px solid rgba(231,238,245,.42);
  color:inherit; font-size:11.5px; border-radius:6px; padding:2px 9px; white-space:nowrap;
  text-decoration:none}
/* 窄屏单行截断：完整定位措辞在弹层／首页里，声明条只保留最要紧的半句，顺带让顶栏栈保持矮。
   合成样例的兜底不靠这行字——靠平铺水印。 */
@media (max-width:720px){ .ribbon .txt{white-space:nowrap; overflow:hidden; text-overflow:ellipsis} }

/* ── 存量系统外壳 ───────────────────────────────────────────────────────── */
.sysbar{background:var(--sys); color:var(--sys-ink); padding:0 14px; overflow:hidden;
  display:flex; align-items:center; gap:14px; height:46px}
.sysbar .logo{display:flex; align-items:center; gap:8px; font-weight:700; font-size:14px; white-space:nowrap}
.sysbar .logo i{width:20px;height:20px;border-radius:5px;background:var(--sys-2);
  display:grid;place-items:center;font-style:normal;font-size:11px;color:#9FB4C9}
.sysbar .who{margin-left:auto; font-size:12px; color:#9FB4C9; white-space:nowrap}
@media (max-width:720px){ .sysbar .who{display:none} .sysbar .logo span{display:none} }
.sysnav{background:#fff; border-bottom:1px solid var(--sys-line)}
.sysnav .in{display:flex; gap:2px; padding:0 10px; overflow-x:auto; scrollbar-width:none}
.sysnav .in::-webkit-scrollbar{display:none}
.sysnav button,.sysnav a{flex:none; background:none; border:0; border-bottom:2px solid transparent;
  padding:10px 12px; font-size:13px; font-weight:600; color:var(--body); text-decoration:none}
.sysnav .on{color:var(--teal-dark); border-bottom-color:var(--teal)}
.sysnav .inert{color:#AEB6BF; cursor:default}

/* ── 通用容器与卡片 ─────────────────────────────────────────────────────── */
.pane{background:var(--card); border:1px solid var(--line); border-radius:12px; min-width:0}
.pane > h2{margin:0; padding:12px 16px; border-bottom:1px solid var(--line);
  font-size:13.5px; font-weight:700; display:flex; align-items:center; gap:8px; flex-wrap:wrap}
.pane > h2 .sub{font-weight:500; color:var(--muted); font-size:11.5px}

.tag{font-size:11px; font-weight:600; border-radius:5px; padding:1px 7px; white-space:nowrap}
.tag.ty{background:var(--sunken); color:var(--lo); border:1px solid var(--line)}
.tag.lv-高{background:var(--hi); color:#fff}
.tag.lv-中{background:var(--md); color:#fff}
.tag.lv-提示{background:var(--lo); color:#fff}
.tag.ok{background:var(--ok); color:#fff}
.tag.wait{background:var(--md); color:#fff}
.tag.pass{background:var(--ok-soft); color:var(--ok); border:1px solid var(--ok-line)}

.chip{font-size:11px; border:1px solid var(--line); border-radius:999px; padding:2px 8px;
  color:var(--body); background:#fff; white-space:nowrap}
.chip.src{border-color:var(--teal-line); background:var(--teal-soft); color:var(--teal-dark)}
.chip.warn{border-color:var(--md-line); background:var(--md-soft); color:var(--md)}
.chips{display:flex; flex-wrap:wrap; gap:5px; margin:6px 0 0}

.act{display:block; width:100%; text-align:left; background:var(--teal); color:#fff; border:0;
  border-radius:9px; padding:10px 12px; font-size:13px; font-weight:600}
.act:disabled{background:#DCE3E9; color:#98A1AA; cursor:not-allowed}
.act.ghost{background:#fff; color:var(--teal-dark); border:1px solid var(--teal)}
.act.ghost:disabled{background:#fff; color:#B6BEC6; border-color:var(--line)}
.act .k{font-size:11px; opacity:.85; font-weight:500; display:block; margin-top:1px}

/* ── 提示条 ─────────────────────────────────────────────────────────────── */
.toast{position:fixed; left:50%; transform:translateX(-50%) translateY(14px); z-index:1100;
  bottom:calc(78px + env(safe-area-inset-bottom)); background:#1B2733; color:#fff; font-size:12.5px;
  padding:9px 15px; border-radius:10px; opacity:0; pointer-events:none;
  transition:opacity .25s, transform .25s; max-width:min(92vw,460px); text-align:center; line-height:1.6}
.toast.on{opacity:1; transform:translateX(-50%) translateY(0)}

/* ── 说明弹层 ───────────────────────────────────────────────────────────── */
.modal{position:fixed; inset:0; z-index:1000; display:none; align-items:center; justify-content:center; padding:16px}
.modal.on{display:flex}
.modal .bg{position:absolute; inset:0; background:rgba(20,28,36,.5)}
.modal .box{position:relative; background:#fff; border-radius:14px; max-width:560px; width:100%;
  max-height:82vh; overflow:auto; padding:18px 20px}
.modal h3{margin:0 0 10px; font-size:15px}
.modal p{margin:0 0 9px; font-size:13px; color:var(--body); line-height:1.8}
.modal .close{position:absolute; right:12px; top:10px; background:none; border:0; font-size:18px; color:var(--muted)}

/*
  ── 新页面照抄这段 <body> 开头 ────────────────────────────────────────────

  <link rel="stylesheet" href="/liby/demo/tokens.css">
  <script src="/track.js?v=1" defer></script>   ← 漏挂 = 这页在方案统计里整个不存在，且不报错

  <svg class="wm" aria-hidden="true">
    <defs><pattern id="wmp" width="300" height="150" patternUnits="userSpaceOnUse" patternTransform="rotate(-22)">
      <text x="0" y="34">演示原型 · 数据为合成样例</text>
      <text x="150" y="112">演示原型 · 数据为合成样例</text>
    </pattern></defs>
    <rect width="100%" height="100%" fill="url(#wmp)"></rect>
  </svg>

  <div class="topstack">
    <div class="ribbon">
      <span class="dot"></span>
      <span class="txt"><b>演示原型 · 数据为合成样例</b>——用于需求对齐，不代表本项目已完成的工作量</span>
      <a href="/liby/demo">← 演示中心</a>
    </div>
  </div>
*/
