/* ============================================================
   雷迪恩中台 · 设计系统（2026-09-24）

   **app（Jinja 页）与 console（Nuxt 看板）共用这一份。**
   原来两边各有一套色板、各自复刻顶栏 / 看板入口 / 日期面板，
   改一边忘一边，看板页和工具页长得像两个产品。现在：
     design.css  —— 令牌、字体、底座、以及两边都有的组件（顶栏 / 看板入口 / 日期面板 / 胶囊 / 主题开关）
     theme.css   —— 只放 app 自己的组件（上传框、步骤卡、日志面板…）
     console/assets/css/tokens.css —— 只放看板自己的版式
   两边任何一处想改颜色，改这里。

   ── 设计语言：石墨与纸 ──────────────────────────────────────
   参考：一组交通调度看板（夜）与一组健康数据看板（日）。共同点提炼成四条：
   1. **单色打底，颜色是信号不是装饰。** 界面本身只有黑白灰；唯一的签名色是品牌蓝
      （官网 tailwind 的 brand #2d9ed0），只出现在「这里有事 / 这是当前 / 这一步」的位置：
      步骤号、选中态、进度、焦点。2026-09-24 由青柠改回品牌蓝（用户要求）。
      底色不是死平的黑 / 白：一层极缓慢漂移的氛围光（左上品牌蓝、右上靛、右下青）
      加暗角，把卡片「托」出层次 —— 颜色压得很低，是空气不是装饰。
   2. **实体卡片装内容，玻璃只给浮层。** 卡片是有质感的纯色（夜：石墨；日：纸白），
      毛玻璃只用在浮在内容之上的东西：顶栏胶囊、看板面板、下拉、对话框。
      满屏玻璃是塑料，浮层是玻璃才像玻璃。
   3. **大数字用细字重。** 数字是看板的主角，细字重反而更显分量；小数与单位压暗一级。
   4. **动效克制到几乎察觉不到。** 翻页、切日期 / 周次、切日夜都是**整页叠化**，
      没有位移、没有逐个浮起（2026-09-24 用户反馈逐个浮起像闪烁，已删）。
      只有胶囊滑块与看板抽屉保留官网磐石页那条带过冲的弹性曲线。

   ── 对比度（WCAG，对卡片与页面底色分别算，取较差的那个）──
   夜  ink 16.3 · ink-2 7.7 · ink-3 4.7 · ok 9.3 · warn 10.0 · err 6.8 · accent-ink 8.3
   日  ink 11.4 · ink-2 6.8 · ink-3 5.0 · ok 5.5 · warn 5.8 · err 5.3 · accent-ink 4.7（最深的底色上，2026-11-06）
   蓝底白字：夜 3.0、日 4.1 —— 品牌蓝本身就亮，白字过不了 4.5。所以蓝底上**只放 600 字重
   的短标签**（选中的日期、选中的筛选项），正文从不放在蓝底上。
   **改这几个值之前先算对比度** —— 凭眼睛调必然越调越浅（2026-09-22 日间 faint 调到过 2.48）。
   ============================================================ */

/* 字体声明在 fonts.css（体积大、与样式无关，单独一个文件；页面里要先于本文件引入）*/

:root{
  /* 字体：正文 —— Inter 负责拉丁字母与数字，汉字落到普惠体。
     菜单与标题 —— --font-title：英文字母 Michroma（RayLatin，见 fonts.css），其余同正文。
     （2026-09-24 晚：先试过全站英文 Michroma，正文与说明里读起来太累，用户改为只用在菜单和标题） */
     普惠体只有 300/400/500 三个字重 —— 关掉合成加粗，600/700 落到 500 上，
     不会出现浏览器硬描出来的糊字。 */
  --font:"Inter","PuHuiTi",-apple-system,BlinkMacSystemFont,"PingFang SC",
         "Microsoft YaHei",system-ui,sans-serif;
  --font-title:"RayLatin","Inter","PuHuiTi",-apple-system,BlinkMacSystemFont,"PingFang SC",
         "Microsoft YaHei",system-ui,sans-serif;
  --font-brand:"Michroma","PuHuiTi",system-ui,sans-serif;
  --font-mono:"SF Mono","JetBrains Mono",ui-monospace,Consolas,monospace;

  --r-xl:28px; --r-lg:22px; --r-md:16px; --r-sm:12px; --r-xs:9px; --r-pill:999px;

  /* 三条曲线各管一类：浮起用 out（起步快收尾慢，有惯性），
     胶囊滑块用 spring（官网磐石页同款，末端过冲再回落），翻转类用 in-out */
  --ease-out:cubic-bezier(.16,1,.3,1);
  --ease-spring:cubic-bezier(.34,1.56,.64,1);
  --ease-io:cubic-bezier(.65,0,.35,1);

  --bar-h:76px;
  --blur:26px;
  --grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E");
}

/* ── 夜：石墨 ───────────────────────────────────────────────── */
:root,[data-theme="dark"]{
  color-scheme:dark;
  --bg:#0b0c0e;
  --surface:#16171a;
  --surface-2:#1d1e22;
  --surface-3:#26272c;
  --line:rgba(255,255,255,.065);
  --line-2:rgba(255,255,255,.12);
  --ink:#f4f4f2;
  --ink-2:#a8aab0;
  --ink-3:#80838a;
  --ink-4:#4f5258;                      /* 只给装饰与大号数字的小数部分，不承载小字 */

  --accent:#2d9ed0;                     /* 官网 brand，原值 */
  --on-accent:#fff;
  --accent-ink:#5cbbe6;                 /* 蓝当文字用要提亮一档，原值在卡片上只有 5.9 */
  --accent-soft:rgba(45,158,208,.16);
  --accent-line:rgba(45,158,208,.5);

  /* 氛围光：左上一束品牌蓝、右上一点靛、右下一点青、左下一点紫，外加暗角。
     第一版透明度 ≤.2 截图里和纯黑分不出；第二版 ≤.3 用户仍觉得弱、范围小，
     第三版（2026-09-24 晚）主光 .42、范围放大到视口的 80%，暗角减轻 */
  --atmo:
    radial-gradient(80% 70% at 2% -10%,rgba(45,158,208,.42),transparent 74%),
    radial-gradient(62% 58% at 102% -2%,rgba(96,104,216,.3),transparent 74%),
    radial-gradient(80% 72% at 86% 112%,rgba(30,140,190,.34),transparent 74%),
    radial-gradient(56% 56% at 8% 108%,rgba(88,76,190,.2),transparent 72%),
    radial-gradient(140% 100% at 50% 45%,transparent 66%,rgba(0,0,0,.22) 100%),
    linear-gradient(180deg,#0e1014 0%,#0b0c0e 46%,#08090b 100%);

  --ok:#4ad295;  --ok-bg:rgba(74,210,149,.12);
  --warn:#f2b84b;--warn-bg:rgba(242,184,75,.12);
  --err:#ff7466; --err-bg:rgba(255,116,102,.12);

  --glass:rgba(22,23,27,.56);
  --glass-2:rgba(26,27,31,.84);          /* 面板里要读字的浮层，透明度低一些 */
  --rim-hi:rgba(255,255,255,.18);
  --rim-lo:rgba(255,255,255,.02);
  --shadow-card:inset 0 1px 0 rgba(255,255,255,.035);
  --shadow-float:0 30px 70px -24px rgba(0,0,0,.75),0 2px 8px rgba(0,0,0,.35);
  --shadow-lift:0 22px 50px -26px rgba(0,0,0,.8);
  --scrim:rgba(5,6,8,.62);
  --grain-op:.07;

  /* 图表分类色：用 dataviz 校验脚本逐项过了明度带 / 彩度 / 色盲 ΔE≥8 / 正常视觉 ΔE≥15 / 对比≥3:1。
     **顺序就是色盲安全的一部分，不要调换**；第 8 类以后并入「其他」，不生成新颜色。 */
  --s1:#4a7de8; --s2:#d9622f; --s3:#17a576; --s4:#bb8508;
  --s5:#8e67e2; --s6:#cf4c80; --s7:#679717; --s-other:#6e7178;
  /* 图表主色（2026-11-06）：单系列 / 重点用 viz-1，弱化的（往期柱、低效询单）用同色相的 viz-2。
     原来这些用墨色，日间一片黑白灰。不用品牌蓝：蓝留给「当前 / 这里」。对比系列用 --s2 橙 */
  --viz-1:#1e9e90; --viz-2:#2f6660;
  --pill-hi:var(--surface-3);
  --grid-line:rgba(255,255,255,.055);
  --axis:rgba(255,255,255,.12);
  /* 热力图的单色阶：石墨 → 低饱和青绿。**不用饱和的强调色**：命中率高的表几乎整面都是高端色，
     用强调色就成了一面荧光墙（2026-09-24 用青柠实测过），颜色从信号变成了装饰 */
  --heat-0:#1d1e22; --heat-1:#8fc9c2;
  /* 占比热力格的顺序色阶（客服报告产品洞察，2026-10-30）：5 档蓝，越高越饱和。深色主题里**高端不能是最亮的白** ——
     那样「占比变大」看起来是「变浅」（用户指出）；改成近底色 → 饱和蓝 */
  --seq-0:#222a35; --seq-1:#1f3e63; --seq-2:#22609f; --seq-3:#2d7fd4; --seq-4:#4a9cf4;
}

/* ── 日：纸 ─────────────────────────────────────────────────── */
[data-theme="light"]{
  /* 2026-11-06 用户：太亮，看久眼累。分两次压暗：卡片（亮度）.96 → .85 → .74，页面底 .80 → .70 → .59。
     字从近黑放到 #1f2126，降低黑白反差。第二次同时压深 ink-2/3、accent-ink、状态色，各级字在最暗底色上都 ≥ 4.9；
     图表色对 --surface ≥ 3。再改底色要重算，见文件头
     2026-11-11 用户：压过头了，整体偏暗 → 退回约一档（底与卡片各提亮约 8%）。字色不动，对比度只升不降 */
  color-scheme:light;
  --bg:#dfdfd6;
  --surface:#efeee8;
  --surface-2:#e7e6df;
  --surface-3:#dddcd4;
  --line:rgba(17,18,20,.08);
  --line-2:rgba(17,18,20,.15);
  --ink:#1f2126;
  --ink-2:#3c3f45;
  --ink-3:#4b4e54;
  --ink-4:#86888b;

  --accent:#1a6f9c;                     /* 品牌蓝压深：纸色底比原来暗，白字要过 4.5 */
  --on-accent:#fff;
  --accent-ink:#115575;
  --accent-soft:rgba(26,111,156,.12);
  --accent-line:rgba(26,111,156,.45);

  /* 日光版：去掉原来右上角的纯白高光，整体压一档 */
  --atmo:
    radial-gradient(80% 70% at 2% -12%,rgba(45,158,208,.24),transparent 74%),
    radial-gradient(60% 56% at 102% -2%,rgba(240,239,232,.6),transparent 74%),
    radial-gradient(80% 72% at 86% 114%,rgba(110,145,220,.26),transparent 74%),
    radial-gradient(56% 56% at 6% 110%,rgba(120,200,210,.22),transparent 72%),
    linear-gradient(180deg,#e3e4db 0%,#dfdfd6 50%,#d9d9d0 100%);

  --ok:#0f5230;  --ok-bg:rgba(18,95,52,.1);
  --warn:#5f3d00;--warn-bg:rgba(180,115,0,.14);
  --err:#8c231d; --err-bg:rgba(158,42,35,.09);

  --glass:rgba(239,238,232,.66);
  --glass-2:rgba(239,238,232,.92);
  --rim-hi:rgba(255,255,255,.5);
  --rim-lo:rgba(255,255,255,.18);
  --shadow-card:0 1px 2px rgba(17,18,20,.04),0 14px 34px -22px rgba(17,18,20,.18);
  --shadow-float:0 30px 80px -28px rgba(17,18,20,.32),0 2px 10px rgba(17,18,20,.07);
  --shadow-lift:0 26px 60px -30px rgba(17,18,20,.3);
  --scrim:rgba(223,223,214,.62);
  --grain-op:.05;

  --s1:#3a6ee0; --s2:#d4552c; --s3:#0f9068; --s4:#a57300;
  --s5:#8f5bd6; --s6:#cc4580; --s7:#5b8a12; --s-other:#74777c;
  --viz-1:#008a7e; --viz-2:#9fcbc5;
  --pill-hi:#f6f5ef;
  --grid-line:rgba(17,18,20,.07);
  --axis:rgba(17,18,20,.16);
  --heat-0:#e7e6df; --heat-1:#2a6f6b;
  --seq-0:#d3dade; --seq-1:#bcd3e8; --seq-2:#83b0e0; --seq-3:#4583d0; --seq-4:#1d5cbd;
}

/* ── 旧令牌名的别名 ──────────────────────────────────────────
   app 的 14 个页面与 console 的组件里散落着旧名字（--cy、--ink2、--dim、--card…）。
   不逐个改名，在这里指过去 —— 改名是纯风险没有收益。新代码请用上面的新名字。 */
:root,[data-theme]{
  /* app 旧名 */
  --cy:var(--accent-ink); --cy-soft:var(--accent); --cy-deep:var(--accent);
  --cy-glow:var(--accent-soft); --cy-faint:var(--accent-soft);
  --ink2:var(--ink-2); --ink3:var(--ink-3);
  --glass-hi:var(--surface-3); --line-hi:var(--line-2);
  --r:var(--r-lg);
  --glass-dark:var(--glass); --glass-dark-hi:var(--glass-2); --glass-blur:var(--blur);
  --ease:var(--ease-out);
  /* console 旧名 */
  --card:var(--surface); --card-2:var(--surface-2);
  --line-strong:var(--line-2); --glass-line:var(--line);
  --dim:var(--ink-2); --faint:var(--ink-3);
  --accent-lit:var(--accent); --accent-soft-2:var(--accent-line);
  --good:var(--ok); --bad:var(--err);
  --good-bg:var(--ok-bg); --bad-bg:var(--err-bg);
  --pop:var(--glass-2); --track:var(--surface-3);
  --shadow:var(--shadow-card);
  --p1:var(--s1); --p2:var(--s2); --p3:var(--s3); --p4:var(--s4);
  --c1:var(--s1); --c2:var(--s2); --c3:var(--s3); --c4:var(--s4);
  --c5:var(--s5); --c6:var(--s6); --c7:var(--s-other);
  --font-body:var(--font); --font-hero:var(--font-brand);
  --scheme:inherit;
}

/* ============================================================
   底座
   ============================================================ */
*{box-sizing:border-box}
html{font-synthesis-weight:none;-webkit-text-size-adjust:100%}
body{
  margin:0;min-height:100vh;
  color:var(--ink);font-family:var(--font);
  font-size:14.5px;line-height:1.65;letter-spacing:.005em;
  font-feature-settings:"cv11","ss01";         /* Inter 的单层 a 与更圆的数字 */
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  background:none;                  /* 底色画在 html 与 html::before 上，见下 */
}
/* 氛围层：固定在视口，**静止**。
   2026-11-06 去掉了 60 秒漂移动画：它让浏览器每帧重画全屏（含颗粒混合层和所有毛玻璃），
   2560×1600 @165Hz 实测 GPU 23%、CPU 0.85 核，去掉后与空白页相同。**全站不要再加全屏的循环动画。**
   ⚠️ 画在 html::before 而不是 body 上：body 的背景会盖住负 z-index 的层。
   2026-09-24 用户反馈「纯黑、没有层次、空洞」—— 原来只有顶部一束很淡的白光 */
html{background:var(--bg)}
html::before{
  content:"";position:fixed;inset:-6%;z-index:-2;pointer-events:none;
  background:var(--atmo);
}
/* 颗粒：纯色平面一眼就是渲染图。极淡，看不出纹理但能感觉到「材质」 */
body::before{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background-image:var(--grain);opacity:var(--grain-op);mix-blend-mode:overlay;
}

::selection{background:var(--accent);color:var(--on-accent)}

/* 菜单与标题里的英文用 Michroma（--font-title）。正文、说明、表格、图表都留在 Inter */
h1,h2,h3,h4,.appbar nav a,.appbar .who a,.setnav a,.bd-txt b,.bd-head small{font-family:var(--font-title)}

*{scrollbar-width:thin;scrollbar-color:var(--line-2) transparent}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:99px;
  border:3px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover{background:var(--ink-3);background-clip:content-box}
::-webkit-scrollbar-corner{background:transparent}

/* 焦点环：只在键盘操作时出现。用品牌蓝 —— 它本来就是「这里」的意思 */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--accent);outline-offset:2px;
}

/* 旧的背景层：彩色光斑与粒子流场。氛围改由 html::before 统一画，各页不再各画一套 */
.bg,.orbs,.ambient,.vortex{display:none!important}

/* ============================================================
   卡片：有质感的纯色
   ============================================================ */
.card{
  position:relative;
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r-lg);
  box-shadow:var(--shadow-card);
  transition:border-color .5s var(--ease-out),box-shadow .5s var(--ease-out),
             transform .5s var(--ease-out),background-color .5s var(--ease-out);
}

/* ============================================================
   浮层玻璃：只给浮在内容之上的东西
   高光边取自官网 LiquidGlass 的降级分支：渐变描边 + mask 抠空中间，
   上缘最亮、下缘一道弱反光，模拟单一光源。
   ============================================================ */
.glass-layer{
  position:relative;
  background:var(--glass);
  backdrop-filter:blur(var(--blur)) saturate(1.7);
  -webkit-backdrop-filter:blur(var(--blur)) saturate(1.7);
  box-shadow:var(--shadow-float);
}
.glass-layer::before{
  content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;pointer-events:none;
  background:linear-gradient(160deg,var(--rim-hi) 0%,var(--rim-lo) 40%,var(--rim-lo) 62%,
                             color-mix(in srgb,var(--rim-hi) 45%,transparent) 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}

/* ============================================================
   胶囊（状态标签）
   ============================================================ */
.pill{
  display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  font-size:11.5px;font-weight:500;line-height:1;padding:5px 10px;border-radius:var(--r-pill);
  color:var(--ink-2);background:var(--surface-2);border:1px solid var(--line);
}
.pill.on,.pill.ok{color:var(--ok);background:var(--ok-bg);border-color:transparent}
.pill.warn{color:var(--warn);background:var(--warn-bg);border-color:transparent}
.pill.bad,.pill.no{color:var(--err);background:var(--err-bg);border-color:transparent}
.pill.hot{color:var(--on-accent);background:var(--accent);border-color:transparent;font-weight:600}
/* 状态点：参考图里的在线/离线就是一颗小点 + 文字，颜色从不单独承载含义 */
.dot{width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}

/* ============================================================
   顶栏（app 与 console 共用 —— console 的 AppBar.vue 输出同一套结构）

   不再是一整条横贯的深色条：左边 logo、中间一枚玻璃胶囊导航、右边一枚玻璃胶囊账号区，
   三者悬浮，内容从底下滑过去。导航的选中底块会跟着鼠标滑（弹性），离开时回到当前页。
   ============================================================ */
.appbar{
  position:fixed;top:0;left:0;right:0;z-index:60;height:var(--bar-h);
  display:flex;align-items:center;gap:14px;padding:0 20px;
  pointer-events:none;
}
/* 顶部渐隐：内容滚到胶囊底下时被**同一层氛围底**盖住，往下渐隐。
   不能用 --bg 实色 —— 换成氛围底之后左上那束蓝光会被切出一道色带；
   也不靠 backdrop-filter —— 实测在这里没生效（2026-09-24 晚截图里表格数字清清楚楚地透过顶栏）。
   background-attachment:fixed 让这块背景与 html::before 按同一个视口对齐，看不出接缝 */
.appbar::before{
  content:"";position:absolute;inset:0 0 -22px;z-index:-1;pointer-events:none;
  background:var(--atmo);background-attachment:fixed;
  -webkit-mask:linear-gradient(#000 58%,transparent);mask:linear-gradient(#000 58%,transparent);
}
.appbar>*{pointer-events:auto}
.appbar .logo{display:flex;align-items:center;height:44px;padding:0 6px;flex:none;border-radius:var(--r-pill)}
.appbar .logo img{height:36px;width:auto;display:block;transition:transform .5s var(--ease-out),filter .5s}
/* logo 是纯白 SVG，日间压成墨色 */
[data-theme="light"] .appbar .logo img{filter:brightness(0) opacity(.9)}
.appbar .logo:hover img{transform:translateY(-1px)}

.appbar nav{
  position:absolute;left:50%;transform:translateX(-50%);
  display:flex;align-items:center;gap:2px;padding:4px;border-radius:var(--r-pill);
}
.appbar nav a{
  position:relative;z-index:1;display:flex;align-items:center;height:36px;padding:0 18px;
  border-radius:var(--r-pill);font-size:13.5px;font-weight:500;letter-spacing:.02em;
  color:var(--ink-3);text-decoration:none;transition:color .35s var(--ease-out);
}
.appbar nav a:hover{color:var(--ink)}
.appbar nav a.on{color:var(--ink)}
/* 当前页左侧一颗品牌蓝点：颜色只用在「这里」 */
.appbar nav a.on::before{
  content:"";width:5px;height:5px;border-radius:50%;margin-right:8px;
  background:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);
}
.appbar .navpill{
  position:absolute;z-index:0;top:4px;bottom:4px;left:0;border-radius:var(--r-pill);
  background:var(--surface-3);box-shadow:0 1px 0 rgba(255,255,255,.05) inset;
  transition:transform .46s var(--ease-spring),width .46s var(--ease-spring),opacity .3s;
  pointer-events:none;
}
[data-theme="light"] .appbar .navpill{background:var(--pill-hi);box-shadow:0 2px 8px -2px rgba(17,18,20,.12)}
.appbar .spacer{flex:1}
.appbar .who{
  position:relative;display:flex;align-items:center;gap:2px;height:44px;padding:4px 4px 4px 16px;
  border-radius:var(--r-pill);font-size:13px;color:var(--ink-3);
}
.appbar .who:empty{display:none}
.appbar .who .uname{color:var(--ink);font-weight:500;margin-right:8px}
/* 右上角菜单与中间导航同一套动效：底块跟着鼠标滑（.navpill，ui.js / AppBar.vue 放进来） */
.appbar .who a{
  position:relative;z-index:1;display:flex;align-items:center;height:36px;padding:0 12px;
  font-size:13.5px;font-weight:500;letter-spacing:.02em;
  color:var(--ink-3);text-decoration:none;border-radius:var(--r-pill);
  transition:color .35s var(--ease-out);
}
.appbar .who a:hover,.appbar .who a.on{color:var(--ink)}
.appbar .who a.on::before{
  content:"";width:5px;height:5px;border-radius:50%;margin-right:8px;
  background:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);
}
/* 设置页左侧菜单（ui.js settingsNav） */
.setnav{position:fixed;left:84px;top:104px;z-index:5;width:148px;display:flex;flex-direction:column;gap:2px;padding:10px;border-radius:var(--r-md)}
.setnav b{font-size:12px;font-weight:500;letter-spacing:.08em;color:var(--ink-3);padding:4px 10px 8px}
/* 文字色、悬停底色与顶部导航一致（底色 = .navpill） */
.setnav a{display:block;padding:9px 12px;border-radius:10px;font-size:13.5px;font-weight:500;letter-spacing:.02em;color:var(--ink-3);text-decoration:none;
  transition:color .35s var(--ease-out),background-color .35s var(--ease-out),box-shadow .35s var(--ease-out)}
.setnav a:hover,.setnav a.on{color:var(--ink);background:var(--surface-3);box-shadow:0 1px 0 rgba(255,255,255,.05) inset}
[data-theme="light"] .setnav a:hover,[data-theme="light"] .setnav a.on{background:var(--pill-hi);box-shadow:0 2px 8px -2px rgba(17,18,20,.12)}
body.has-setnav{padding-left:240px}
body.has-setnav .pagehead .back{display:none}
@media(max-width:900px){
  .setnav{position:static;width:auto;flex-direction:row;flex-wrap:wrap;margin:84px 16px -60px}
  .setnav b{display:none}
  body.has-setnav{padding-left:0}
}
@media(max-width:900px){
  .appbar nav{position:static;transform:none}
  .appbar .who .uname{display:none}
}
.appbar nav a,.appbar .who a,.appbar .who .uname{white-space:nowrap}
@media(max-width:640px){
  /* 手机上预算很紧（390 宽里要放 logo + 三个导航 + 退出 + 主题开关）：
     收窄内边距、缩小 logo，当前页的蓝点也收小。实测不加 nowrap 时「首页」会被挤成竖排 */
  .appbar{padding:0 10px;gap:6px}
  .appbar .logo{padding:0 2px}
  .appbar .logo img{height:22px}
  .appbar nav{padding:3px}
  .appbar nav a{padding:0 10px;height:34px;font-size:13px}
  .appbar nav a.on::before{width:4px;height:4px;margin-right:5px;box-shadow:none}
  .appbar .who{height:40px;padding:3px 3px 3px 6px}
  .appbar .who a:not(.ulogout){display:none}
}

/* ── 主题开关：顶栏最右，每一页都在同一个位置 ──
   2026-11-11 用户：改成两档开关，日 / 夜分列左右，点哪边滑块就滑向哪边，要有吸附感和弹性（iOS 的质感）。
   - 滑块位置跟着开关自己的 data-pos 走（不是 html 的 data-theme）：滑块在视图过渡的新画面里接着弹。
   - 弹性 = 回弹曲线（--ease-spring 冲过头一点再落回）；按住时滑块往按的方向拉长一点，松手弹回。
   - 切主题时全站关过渡（见下面 html.theming），这里单独放行滑块和图标。 */
.theme-toggle{
  flex:none;position:relative;display:inline-grid;grid-template-columns:1fr 1fr;align-items:center;
  width:84px;height:42px;padding:4px;border-radius:var(--r-pill);
  --tx:0px;--sx:1;--to:left center;
}
.theme-toggle[data-pos="dark"]{--tx:38px;--to:right center}
.theme-toggle.press{--sx:1.16}
.theme-toggle .tt-thumb{
  position:absolute;left:4px;top:4px;width:38px;height:34px;border-radius:var(--r-pill);pointer-events:none;
  will-change:transform;
  background:linear-gradient(180deg,#fff,#f1f1ee);
  box-shadow:0 3px 8px rgba(0,0,0,.16),0 1px 1px rgba(0,0,0,.08),inset 0 -1px 0 rgba(0,0,0,.04);
  transform:translateX(var(--tx)) scaleX(var(--sx));transform-origin:var(--to);
  /* 0.2s 弹到位（2026-11-11 三改）：必须在扫屏开始前停稳 —— 扫屏一开始旧画面就被截成静态图，滑块还在半路的话，
     旧画面里它就偏在一边，扫过去时一下跳正（用户：切换只许变颜色，不许变形状和位置）。ui.js THUMB_MS = 230 比这长一点 */
  transition:transform .2s cubic-bezier(.3,1.35,.5,1),background .35s,box-shadow .35s;
}
[data-theme="dark"] .theme-toggle .tt-thumb{
  background:linear-gradient(180deg,#3a3c43,#2c2e34);
  box-shadow:0 3px 10px rgba(0,0,0,.5),inset 0 1px 0 rgba(255,255,255,.12);
}
.theme-toggle button{
  position:relative;z-index:1;height:34px;border:0;background:none;padding:0;cursor:pointer;border-radius:var(--r-pill);
  display:grid;place-items:center;color:var(--ink-3);transition:color .3s;
}
.theme-toggle button:hover{color:var(--ink-2)}
.theme-toggle button[aria-checked="true"]{color:#1f2126}
[data-theme="dark"] .theme-toggle button[aria-checked="true"]{color:#f4f4f2}
.theme-toggle button:focus-visible{outline:2px solid var(--accent-line);outline-offset:1px}
.theme-toggle svg{width:17px;height:17px;overflow:visible;transition:transform .2s cubic-bezier(.3,1.35,.5,1)}
.theme-toggle button[data-t="light"][aria-checked="true"] svg{transform:rotate(90deg)}
.theme-toggle button[data-t="dark"][aria-checked="true"] svg{transform:rotate(-18deg) scale(1.05)}
@media(max-width:640px){
  .theme-toggle{width:74px;height:38px}
  .theme-toggle .tt-thumb{width:33px;height:30px}
  .theme-toggle[data-pos="dark"]{--tx:33px}
  .theme-toggle button{height:30px}
}

/* 切主题：晨昏线扫过（2026-11-11 用户：借鉴「地球被太阳照亮的区域随自转线性推移」，不要泼墨 / 流水引导）。
   新主题整页一张图（顶栏、看板胶囊也在这张图里，不再单独成层 —— 以前它们各走各的时长，顶栏先变完），
   一条带晨昏过渡带的软边遮罩从右往左扫过：地球自西向东转，东边先天黑也先天亮，所以两个方向都从右往左。
   用遮罩平移而不是 clip-path：软边、只动合成层。切的那一刻关掉所有过渡（滑块例外，见上） */
html.theming,html.theming *,html.theming *::before,html.theming *::after{transition:none!important}
/* 扫屏期间不再放行滑块与图标的过渡：它们在扫屏开始前已经停稳，扫屏只换颜色 */
html.theming .appbar,html.theming .bdock-btn{view-transition-name:none}
html.theming::view-transition-group(root),html.theming::view-transition-old(root){animation:none}
html.theming::view-transition-new(root){
  /* 2026-11-11 二改：分界线由斜切光带换成 logo 里 N 的闪电（用户要求「用雷迪恩 logo 图形扫过去」）；三改：分界线 = 实心闪电左侧外轮廓（logo 六点多边形，与 theme_sweep.js 的 BOLT 同一组点，x 加 5）。
     遮罩图宽 10 个视口高、高 = 视口高，闪电在第 5 个视口高处，右边不透明（显示新主题）、左边透明（还是旧主题），边缘轻微羽化。
     平移由 /static/theme_sweep.js 用 Web Animations 按像素做（起止点和视口宽高比有关，CSS 关键帧写不死）；
     沿分界线的那道光是 theme_sweep.js 临时插入的 .ray-bolt */
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 1'%3E%3Cdefs%3E%3Cfilter id='s' x='-.1' y='-.5' width='1.2' height='2'%3E%3CfeGaussianBlur stdDeviation='.0015'/%3E%3C/filter%3E%3C/defs%3E%3Cpolygon filter='url(%23s)' points='5.8134,-.1 5.8134,0 5.4648,.4527 5.3174,.2901 5,1 5,1.1 10.5,1.1 10.5,-.1'/%3E%3C/svg%3E");
          mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 1'%3E%3Cdefs%3E%3Cfilter id='s' x='-.1' y='-.5' width='1.2' height='2'%3E%3CfeGaussianBlur stdDeviation='.0015'/%3E%3C/filter%3E%3C/defs%3E%3Cpolygon filter='url(%23s)' points='5.8134,-.1 5.8134,0 5.4648,.4527 5.3174,.2901 5,1 5,1.1 10.5,1.1 10.5,-.1'/%3E%3C/svg%3E");
  -webkit-mask-size:auto 100%;mask-size:auto 100%;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  animation:none;
}
/* 沿分界线的闪电光：只在切换的一秒里存在，自己成一层盖在两张画面上面 */
.ray-bolt{position:fixed;left:0;top:0;z-index:9999;height:100vh;width:calc(100vh * (0.8134 + 0.16));pointer-events:none;
  view-transition-name:ray-bolt}
.ray-bolt svg{width:100%;height:100%;display:block;overflow:visible}
html.theming::view-transition-group(ray-bolt),html.theming::view-transition-new(ray-bolt),html.theming::view-transition-old(ray-bolt){animation:none}
html:not(.theming) .ray-bolt{display:none}
/* 看板切日期 / 周次：取完数再整页叠化，0.42 秒（console 的 useSwap 负责加这个类）。
   不再先把内容压暗到 18% 再亮回来 —— 那一暗一亮就是用户说的「闪」 */
html.swap-vt::view-transition-old(root),html.swap-vt::view-transition-new(root){
  animation-duration:.42s;animation-timing-function:ease;
}

/* ============================================================
   看板入口（app 与 console 共用 —— 两边的标记结构一致，样式只此一份）

   2026-09-24 重做。用户提的方案是「半透明毛玻璃大面板从左侧整体抽出、占满左侧完整高度」，
   评估后采纳，但做了三处调整：
   1. **四边留 12px，不贴边。** 贴边的整高侧栏是后台系统的老样子；全站其他浮层
      （顶栏三枚胶囊、日期面板）都是悬浮的圆角玻璃，抽屉也悬浮，才是同一套语言。
   2. **整高的空间要装值得看的东西。** 原来的小面板只有三行链接，放大成整高就是一大片空玻璃。
      现在每个看板一张卡：名称 + 最新一期的两三个关键数（接口 /api/v1/board/overview，
      打开时才取）+ 直达子页。打开抽屉本身就是一次「扫一眼全局」。
   3. **有遮罩、可 Esc、点外面收起。** 整高抽屉会盖住左边 380px 的内容，
      不给遮罩的话看起来像页面坏了。遮罩只压暗、轻微模糊，不是全黑。

   胶囊本身：一枚竖向玻璃胶囊，与顶栏胶囊同一种材质；图形是 2×2 的四块圆角方格
   （每块代表一个看板），当前所在的看板那块是品牌蓝 —— 不用文字也知道「我在哪」。
   ============================================================ */
/* 2026-09-24 晚：用户反馈太小、不好找。宽 46 → 58、方格 7 → 10px、字 11.5 → 13px、
   字色 ink-3 → ink-2，并加一圈品牌蓝描边与淡光晕 —— 在深浅两种底上都能一眼看到 */
/* 2026-11-11 用户：半透明毛玻璃、等比放大（约 1.25 倍：宽 58 → 72，方格 10 → 12px，字 13 → 15px）、
   「看板」改「数据看板」四宫格排、轮廓辉光加强。毛玻璃 = 低不透明度底 + 背景模糊 + 顶边高光 */
.bdock-btn{
  position:fixed;left:16px;top:50%;z-index:280;transform:translateY(-50%);
  display:flex;flex-direction:column;align-items:center;gap:16px;cursor:pointer;
  width:72px;padding:24px 0 26px;border:0;border-radius:var(--r-pill);
  font:inherit;font-size:15px;font-weight:500;color:var(--ink-2);
  background:color-mix(in srgb,var(--glass) 70%,transparent);
  backdrop-filter:blur(22px) saturate(1.8);-webkit-backdrop-filter:blur(22px) saturate(1.8);
  box-shadow:var(--shadow-float),inset 0 1px 0 var(--rim-hi),inset 0 -1px 0 var(--rim-lo),
    0 0 0 1px var(--accent-line),0 0 22px -2px var(--accent-line),0 0 48px -8px var(--accent);
  transition:color .3s,opacity .35s,transform .5s var(--ease-spring),box-shadow .4s;
}
.bdock-btn:hover{box-shadow:var(--shadow-float),inset 0 1px 0 var(--rim-hi),inset 0 -1px 0 var(--rim-lo),
  0 0 0 1px var(--accent),0 0 28px 0 var(--accent-line),0 0 64px -6px var(--accent)}
/* 四个字排成 2×2，和上面的四块方格呼应 */
.bdock-btn .btxt{display:grid;grid-template-columns:repeat(2,1em);gap:5px 4px;line-height:1;letter-spacing:0;text-align:center}
.bdock-btn .btxt i{font-style:normal}
.bdock-btn:hover{color:var(--ink);transform:translate(2px,-50%)}
/* 四块方格：悬停时稍微散开一点，像是「要展开了」 */
.bgrid{display:grid;grid-template-columns:repeat(2,12px);gap:5px;transition:gap .45s var(--ease-spring)}
.bgrid i{width:12px;height:12px;border-radius:4px;background:currentColor;opacity:.7}
.bgrid i.cur{background:var(--accent);opacity:1;box-shadow:0 0 8px var(--accent-line)}
.bdock-btn:hover .bgrid{gap:7px}
.bdock.on .bdock-btn{opacity:0;pointer-events:none}

/* 遮罩：压暗 + 轻微模糊，点它收起 */
.bdock-scrim{
  position:fixed;inset:0;z-index:290;
  background:color-mix(in srgb,var(--bg) 38%,transparent);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
  opacity:0;visibility:hidden;transition:opacity .4s ease,visibility 0s linear .4s;
}
.bdock.on .bdock-scrim{opacity:1;visibility:visible;transition:opacity .4s ease,visibility 0s}

.bdock-drawer{
  position:fixed;z-index:300;left:12px;top:12px;bottom:12px;
  width:min(372px,calc(100vw - 24px));border-radius:var(--r-xl);
  display:flex;flex-direction:column;overflow:hidden;
  background:var(--glass-2);
  backdrop-filter:blur(34px) saturate(1.8);-webkit-backdrop-filter:blur(34px) saturate(1.8);
  transform:translateX(calc(-100% - 24px));visibility:hidden;
  transition:transform .6s var(--ease-spring),visibility 0s linear .6s;
}
.bdock.on .bdock-drawer{transform:none;visibility:visible;transition:transform .6s var(--ease-spring),visibility 0s}

.bd-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:24px 22px 14px}
.bd-head small{display:block;font-size:10.5px;letter-spacing:.22em;color:var(--ink-3);margin-bottom:6px}
.bd-head h3{margin:0;font-size:24px;font-weight:300;letter-spacing:-.01em}
.bd-x{
  flex:none;width:36px;height:36px;border-radius:50%;cursor:pointer;display:grid;place-items:center;
  color:var(--ink-2);background:var(--surface-2);border:1px solid var(--line);
  transition:color .25s,background-color .25s;
}
.bd-x:hover{color:var(--ink);background:var(--surface-3)}
.bd-x svg{width:14px;height:14px}

.bd-list{flex:1;overflow-y:auto;padding:4px 12px 12px;display:flex;flex-direction:column;gap:10px}
/* 条目依次滑入 —— 抽屉里唯一保留「逐个」的地方，因为它本来就是一次展开动作 */
.bd-item{
  border-radius:var(--r-lg);padding:6px;background:var(--surface);border:1px solid var(--line);
  opacity:0;transform:translateX(-12px);
  transition:opacity .35s ease,transform .55s var(--ease-spring),border-color .3s;
}
.bdock.on .bd-item{opacity:1;transform:none}
.bd-item.cur{border-color:var(--accent-line)}
.bd-main{display:flex;align-items:center;gap:12px;padding:10px;border-radius:var(--r-md);
  color:var(--ink);text-decoration:none;transition:background-color .25s}
a.bd-main:hover{background:var(--surface-2)}
.bd-ico{flex:none;width:36px;height:36px;border-radius:var(--r-sm);display:grid;place-items:center;
  background:var(--surface-2);border:1px solid var(--line);color:var(--ink-2)}
.bd-item.cur .bd-ico{background:var(--accent);color:var(--on-accent);border-color:transparent}
.bd-ico svg{width:17px;height:17px}
.bd-txt{display:flex;flex-direction:column;min-width:0;flex:1}
.bd-txt b{font-weight:500;font-size:14px}
.bd-txt em{font-style:normal;font-size:11.5px;color:var(--ink-3)}
.bd-item.off .bd-main{color:var(--ink-3)}
.bd-item.off u{text-decoration:none;font-size:10.5px;padding:3px 8px;border-radius:var(--r-pill);
  background:var(--surface-2);color:var(--ink-3);white-space:nowrap}

/* 关键数：细字重大数字，与看板卡同一种读法 */
.bd-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(90px,1fr));gap:1px;margin:2px 4px 4px;
  border-radius:var(--r-md);overflow:hidden;background:var(--line)}
.bd-kpis:empty{display:none}
.bd-kpis div{background:var(--surface);padding:10px 12px}
.bd-kpis small{display:block;font-size:10.5px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bd-kpis b{display:block;font-size:21px;font-weight:300;letter-spacing:-.02em;font-variant-numeric:tabular-nums;margin-top:2px}
.bd-kpis b u{text-decoration:none;font-size:11px;color:var(--ink-3);margin-left:2px;letter-spacing:0}
.bd-subs{display:flex;gap:4px;flex-wrap:wrap;padding:4px 6px 6px}
.bd-subs:empty{display:none}
.bd-subs a{font-size:12px;color:var(--ink-2);text-decoration:none;padding:6px 12px;border-radius:var(--r-pill);
  background:var(--surface-2);transition:color .25s,background-color .25s}
.bd-subs a:hover{color:var(--ink);background:var(--surface-3)}
.bd-subs a.cur{color:var(--accent-ink);background:var(--accent-soft)}
.bd-foot{padding:12px 22px 18px;font-size:11px;color:var(--ink-3);border-top:1px solid var(--line)}

@media(max-width:760px){
  .bdock-btn{width:52px;padding:16px 0 18px;left:6px}
  .bdock-btn .btxt{display:none}
}
@media(prefers-reduced-motion:reduce){.bdock-drawer,.bd-item{transition:none}}

/* ============================================================
   页内控制条（console 看板的日期 / 周次 / AI 平台选择）
   2026-09-24 用户要求：切日期、切平台做对比时，不用滚回顶部找选择器。
   所以它悬浮在页面右上（顶栏账号胶囊的正下方），右边缘对齐内容区；
   页头会按它的实际宽度给自己留出右边距（BoardHeader 量宽度），滚动前不压字。
   手机上移到屏幕底部居中 —— 拇指够得着，也不和顶栏抢位置。
   ============================================================ */
.ctl-rail{
  position:fixed;z-index:55;top:calc(var(--bar-h) + 27px);
  right:max(20px,calc((100% - 1320px) / 2 + 20px));
  display:flex;align-items:center;gap:4px;padding:5px;border-radius:var(--r-pill);
}
/* 数据还没到时槽里只有 v-if 留下的注释节点，:empty 会忽略注释 —— 不出一枚空胶囊 */
.ctl-rail:empty{display:none}
.ctl-rail .dpbtn{background:transparent;border-color:transparent;height:36px}
.ctl-rail .dpbtn:hover{background:var(--surface-2)}
.ctl-rail .sep{width:1px;height:20px;background:var(--line-2);margin:0 4px;flex:none}
/* 手机上控制条可横向滚动，里面的东西不许被挤窄 —— 不加时「豆包」「千问」会被压成竖排 */
.ctl-rail>*,.ctl-rail .chip{flex:none;white-space:nowrap}
.ctl-rail .chip{height:34px}
/* ── 吸附态：页面一离开顶端，控制条就从页头右侧「流」到屏幕右缘居中，横条变竖条 ──
   2026-09-24 用户反馈：停在原位的横条会压住卡片右上角的内容。竖条贴右缘，宽度只有 76px，
   在 1440 宽的屏幕上只压到内容区外沿。形变动画由 BoardHeader 做（量前后两个矩形再补间）。
   竖条里的读法：‹ › 转成 ︿ ﹀（上一个在上）；日期 / 周次拆成两行 —— 年份小字在上，
   月日或周次大字在下；日历图标单独一行。 */
/* 竖条态的统一排版（2026-09-30 用户要求：各页行距统一、字多的也不溢出）。全站一套规则，页面不再各写各的：
   - 宽度固定 88px；里面的字一律可以换行，行距统一 1.3
   - 主值（周次 / 日期 / 核心词，<b>）14px，最多 3 行；辅助信息（年份 / 日期跨度，<i> <em> <small>）10.5px，最多 2 行
   - 再长就省略号收尾，悬停看全文（组件给 title）；平台 chip 允许两行
   - 整条比可视区高时在条内滚动，不出屏（GEO 页一周次 + 六个平台就接近这个高度）
   页面里的值区域用 .dpval（日期 / 周次选择器自带）或 .rail-val（自定义的周次步进、小红书的「日期 · 核心词」）。
   这几条前面带 html：比页面自己的 scoped 样式高一级，竖条态时一定是这套生效（GEO 页实测被自己的 .wkv 盖过）。 */
.ctl-rail.docked{
  top:50%;right:14px;translate:0 -50%;
  flex-direction:column;gap:2px;padding:6px;border-radius:26px;width:88px;
  max-height:calc(100vh - 140px);overflow-y:auto;overflow-x:hidden;scrollbar-width:none;
}
.ctl-rail.docked::-webkit-scrollbar{display:none}
.ctl-rail.docked>*,.ctl-rail.docked .chip{white-space:normal}
.ctl-rail.docked .datebox,.ctl-rail.docked .wstep{flex-direction:column;gap:2px;width:100%}
.ctl-rail.docked .dpnav{rotate:90deg;width:34px;height:34px}
.ctl-rail.docked .dp{width:100%}
.ctl-rail.docked .dpbtn{
  flex-direction:column;gap:6px;height:auto;width:100%;padding:10px 0;border-radius:18px;justify-content:center;
}
html .ctl-rail.docked :is(.dpval,.rail-val){display:flex;flex-direction:column;align-items:center;gap:2px;
  width:100%;max-width:100%;padding:0 2px;text-align:center;line-height:1.3;white-space:normal}
html .ctl-rail.docked :is(.dpval,.rail-val) s{display:none}
html .ctl-rail.docked :is(.dpval,.rail-val) b{font-size:14px;font-weight:500;letter-spacing:0;line-height:1.3;
  overflow-wrap:anywhere;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden}
html .ctl-rail.docked :is(.dpval,.rail-val) :is(i,em,small){font-style:normal;font-size:10.5px;line-height:1.3;margin:0;
  color:var(--ink-3);letter-spacing:0;overflow-wrap:anywhere;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
.ctl-rail.docked .sep{width:28px;height:1px;margin:6px 0}
.ctl-rail.docked .chip{width:100%;height:auto;min-height:32px;padding:7px 4px;font-size:12px;line-height:1.3;overflow-wrap:anywhere;
  border-radius:20px}
/* 选中项（2026-11-11 用户：竖条里「周」的底块太大、离边缘不对称）：圆角与外框同心（26 − 6 = 20），四边离外框都是 6px；
   底块不描边、不加阴影，只用一层浅底 */
.ctl-rail.docked .chip[aria-pressed="true"]{border-color:transparent;box-shadow:none;background:var(--surface-3)}
/* 形变过程中内容先淡出、形状补间完再淡入，免得横竖两种排版在半路挤成一团 */
.ctl-rail.morph{overflow:hidden}
.ctl-rail>*{transition:opacity .16s ease}
.ctl-rail.morph>*{opacity:0}
.dpval i,.dpval s,.dpval b{font-style:normal;text-decoration:none;font-weight:inherit}

@media(max-width:760px){
  .ctl-rail{top:auto;bottom:calc(14px + env(safe-area-inset-bottom));right:50%;transform:translateX(50%);
    max-width:calc(100vw - 24px);overflow-x:auto}
}

/* ============================================================
   日期面板（app 的 ui.js 与 console 的 DatePicker / WeekPicker 共用同一套类名）
   ============================================================ */
.datebox{display:flex;align-items:center;gap:4px}
.dp,.sl{position:relative;display:inline-block;vertical-align:middle}
.dppop,.slpop{
  position:fixed;z-index:400;top:0;left:0;padding:10px;border-radius:var(--r-lg);
  background:var(--glass-2);
  backdrop-filter:blur(var(--blur)) saturate(1.7);-webkit-backdrop-filter:blur(var(--blur)) saturate(1.7);
  box-shadow:var(--shadow-float),inset 0 0 0 1px var(--line);
  opacity:0;transform:translateY(-6px) scale(.97);transform-origin:top left;
  pointer-events:none;transition:opacity .18s ease,transform .3s var(--ease-spring);
}
.dppop.open,.slpop.open{opacity:1;transform:none;pointer-events:auto}
/* 长列表的搜索框（ui.js：选项 > 12 时出现） */
.slsearch{font:inherit;font-size:13px;width:100%;height:34px;padding:0 12px;margin-bottom:6px;border-radius:var(--r-xs);
  border:1px solid var(--line-2);background:var(--surface);color:var(--ink);position:sticky;top:0;z-index:1}
.slsearch:focus{outline:none;border-color:var(--ink-3)}
/* 占位提示（<option value="" data-ph>请选择</option>）：按钮上淡色显示；弹层里只在已选值时出现「清空」 */
.slval.ph,.slopt.slclear{color:var(--ink-3)}
.dpbtn,.slbtn{
  font:inherit;display:inline-flex;align-items:center;gap:10px;cursor:pointer;
  color:var(--ink);border-radius:var(--r-pill);
  background:var(--surface);border:1px solid var(--line);
  transition:border-color .2s,background-color .2s,transform .12s;
}
.dpbtn{font-size:13.5px;padding:0 16px;height:38px}
.slbtn{font-size:14px;padding:9px 14px;width:100%;justify-content:space-between;border-radius:var(--r-sm)}
.dpbtn:hover,.slbtn:hover{border-color:var(--line-2)}
.dpbtn:active,.slbtn:active{transform:translateY(1px)}
.dpbtn.on,.slbtn.on{border-color:var(--ink-3)}
.dpval{font-variant-numeric:tabular-nums;letter-spacing:.02em}
.dpval.empty{color:var(--ink-3)}
.dpico,.slico{display:flex;color:var(--ink-3);transition:color .2s,transform .3s var(--ease-spring)}
.dpico svg{width:15px;height:15px}
.slico svg{width:15px;height:15px}
.slbtn.on .slico{transform:rotate(180deg);color:var(--ink)}

.dppop{width:296px}
.dphead{display:flex;align-items:center;gap:6px;margin-bottom:8px}
.dptitle{
  font:inherit;flex:1;font-size:13.5px;font-weight:500;color:var(--ink);cursor:pointer;
  background:transparent;border:0;border-radius:var(--r-xs);padding:7px 8px;transition:background-color .18s;
}
.dptitle:hover{background:var(--surface-2)}
.dpnav{
  font:inherit;width:38px;height:38px;flex:none;cursor:pointer;line-height:1;font-size:16px;
  color:var(--ink-2);background:var(--surface);border:1px solid var(--line);border-radius:50%;
  display:grid;place-items:center;transition:color .2s,border-color .2s,transform .12s;
}
.dppop .dpnav{width:32px;height:32px;background:transparent}
/* 箭头（2026-11-11 用户：圆钮里的箭头不居中，横竖两态都偏）。原来是字符 ‹ ›：字形不在字框正中，竖条态再转 90° 更偏。
   改成 CSS 画的折角，按几何中心放；按钮里的字符藏起来（font-size:0），读屏仍念 aria-label。
   方向按位置判断：一组里第一个 .dpnav 是「上一个」，后面那个是「下一个」（所有日期 / 周次 / 月份组件都是这个顺序） */
/* 折角绝对定位到圆钮正中（2026-11-11 二改）：第一版放在 grid 里，按钮里藏起来的字符还占着一行，
   折角被挤偏；竖条态按钮转 90°，这点偏移就成了「过于靠右」。translate(-50%,-50%) 后再沿箭头方向补 1.5px 视觉居中 */
.dpnav{font-size:0;position:relative}
.dpnav::before{content:"";position:absolute;left:50%;top:50%;width:7px;height:7px;
  border:solid currentColor;border-width:0 0 1.7px 1.7px;border-radius:1px;
  transform:translate(-50%,-50%) translateX(1.5px) rotate(45deg)}
.dpnav ~ .dpnav::before{transform:translate(-50%,-50%) translateX(-1.5px) rotate(-135deg)}
.dpnav:hover:not(:disabled){color:var(--ink);border-color:var(--line-2)}
.dpnav:active:not(:disabled){transform:scale(.92)}
.dpnav:disabled{opacity:.35;cursor:not-allowed}
.dpwd{display:grid;grid-template-columns:repeat(7,1fr);margin-bottom:3px}
.dpwd i{font-style:normal;text-align:center;font-size:11px;color:var(--ink-3);padding:5px 0}
.dpgrid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.dpday{
  font:inherit;font-size:12.5px;height:34px;cursor:pointer;color:var(--ink-2);
  background:transparent;border:0;border-radius:50%;font-variant-numeric:tabular-nums;
  transition:background-color .15s,color .15s,transform .1s;
  animation:dpin .26s var(--ease-out) backwards;animation-delay:calc(var(--i,0) * 10ms);   /* backwards：播完释放，按下的缩放才生效 */
}
@keyframes dpin{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
.dpday:hover:not(:disabled){background:var(--surface-2);color:var(--ink)}
.dpday:active:not(:disabled){transform:scale(.88)}
.dpday:disabled{opacity:.28;cursor:default}
.dpday.out{color:var(--ink-3);opacity:.45}
.dpday.today{box-shadow:inset 0 0 0 1px var(--line-2);color:var(--ink)}
.dpday.on{background:var(--accent);color:var(--on-accent);font-weight:600}
.dpfoot{display:flex;justify-content:space-between;margin-top:8px;padding-top:8px;border-top:1px solid var(--line)}
.dplink{
  font:inherit;font-size:12.5px;cursor:pointer;color:var(--ink-2);
  background:transparent;border:0;border-radius:var(--r-pill);padding:6px 11px;transition:.18s;
}
.dplink:hover{color:var(--ink);background:var(--surface-2)}
.dpmonths{display:none;position:absolute;inset:10px;border-radius:var(--r-md);
  background:var(--glass-2);padding:10px;flex-direction:column}
.dpmonths.show{display:flex;animation:dpin .2s backwards}
.dpyr{display:flex;align-items:center;gap:6px;margin-bottom:9px}
.dpyr b{flex:1;text-align:center;font-size:13.5px;color:var(--ink);font-weight:500}
.dpmg{flex:1;display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
.dpm{
  font:inherit;font-size:12.5px;cursor:pointer;color:var(--ink-2);
  background:var(--surface-2);border:0;border-radius:var(--r-sm);transition:.18s;
}
.dpm:hover{color:var(--ink);background:var(--surface-3)}
.dpm.on{background:var(--accent);color:var(--on-accent);font-weight:600}

/* ============================================================
   动效
   ============================================================ */
/* 逐个浮起（.rise）已删：用户反馈翻页时「先闪一下再完全加载」，就是它 ——
   十几个元素错开 45ms 从透明浮上来，整页要 0.5 秒才站稳。 */

/* 翻页：所有换页（app ↔ app、app ↔ 看板、前进后退）都是与切日期同一种整页叠化，0.42 秒。
   新页面「安定」之前，/static/transition.js 把过渡停在第 0 帧 —— 画面停在旧页面上，
   顶栏账号胶囊、左侧看板胶囊、看板数据都到位了才开始叠。所以顶栏和胶囊不再「闪一下才出来」。
   顶栏与看板胶囊各自单独一层：前后两页一样就纹丝不动。
   （曾经只给 app 页开、console 不开 —— 那时还没有「停在第 0 帧」，叠到的是 SPA 的空壳。）
   ⚠️ 选择加入的 @view-transition{navigation:auto} **不写在这里**，写在每个页面 <head> 的内联
   <style> 里（app 各页、console 的 nuxt.config）。只写在外链样式表里时，冷缓存下第一次从 app
   进看板，Chrome 在揭开新页面时没认到它，直接跳过过渡（2026-09-24 实测 0/5；内联后 5/5）。 */
/* 2026-11-11 起看板胶囊不再单独成层（原来 .bdock-btn{view-transition-name:bdock}）。
   原因（用户反馈「切页时左侧胶囊出现块状贴图 + 闪一下」）：单独成层的元素会被单独截图，截图里没有它背后的页面，
   毛玻璃（backdrop-filter）没东西可模糊，就成了一块实心色块；过渡结束换回真元素时毛玻璃恢复 → 闪一下。
   并进整页那一层后，截到的是带背景的样子；前后两页它在同一位置、同一个样子，叠化时看不出变化。顶栏同理（.appbar）。 */
/* 兜底（浏览器跳过了过渡时）：新页面安定前 body 透明、之后淡入。类名由 transition.js 加减 */
html.ray-hold body{opacity:0}
html.ray-fade body{transition:opacity .42s ease}
::view-transition-old(root),::view-transition-new(root){
  animation-duration:.42s;animation-timing-function:ease;
}

@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important}
}

/* ============================================================
   跳转链接 = 实体胶囊（2026-09-28 用户要求：所有可点击跳转的超链接都做成有实体质感的胶囊按钮）
   上亮下暗的面 + 顶边高光 + 落地阴影，悬停微微浮起、按下沉回去 —— 一眼看出「这是能按的」。
   用法：<a class="cap" href="…">文字</a>（页内动作用 <button class="cap">，同一个样子）；表格里的笔记标题用 .cap.sm（单行、超长省略）。
   菜单、返回键、入口卡片这些本来就是按钮形态的不用它。
   ============================================================ */
/* 2026-10-20 用户：全站透明小按钮改成与主按钮（button.primary，如「生成周报」）同一样式 —— 墨色实心、反白字、悬停上浮带阴影；
   只保留小号尺寸（32px），因为它常嵌在说明文字和表格行里。同日去掉了所有按钮上的箭头图标（.arw）。 */
a.cap,button.cap{
  display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 16px;max-width:100%;
  border-radius:var(--r-pill);font-size:12.5px;font-weight:500;line-height:1;white-space:nowrap;letter-spacing:.02em;
  color:var(--bg);background:var(--ink);text-decoration:none;vertical-align:middle;border:0;
  transition:transform .5s var(--ease-spring),box-shadow .4s var(--ease-out),opacity .2s;
}
a.cap:hover,button.cap:hover:not(:disabled){transform:translateY(-2px);box-shadow:var(--shadow-lift)}
a.cap:active,button.cap:active:not(:disabled){transform:translateY(0) scale(.98)}
/* 按钮形态的胶囊（2026-10-10 日例会「立即同步」「展开」：原来 <button class="cap"> 没吃到样式，显示成浏览器默认按钮） */
button.cap{font-family:inherit;cursor:pointer}
button.cap:disabled{background:var(--surface-3);color:var(--ink-3);cursor:not-allowed}
/* 数据胶囊（表格里的订单号、关联号码、笔记标题等，a.cap.sm）保留原来的白底样式（2026-10-20 用户：改成墨色喧宾夺主）。
   只有按钮形态的（button.cap.sm，如「编辑」）跟主按钮走墨色。 */
a.cap.sm{color:var(--ink);background:var(--surface);border:1px solid var(--line-2);
  box-shadow:inset 0 1px 0 var(--rim-hi),0 1px 2px rgba(0,0,0,.08),0 6px 14px -8px rgba(0,0,0,.28)}
a.cap.sm:hover{transform:translateY(-1px);border-color:var(--ink-3);
  box-shadow:inset 0 1px 0 var(--rim-hi),0 2px 4px rgba(0,0,0,.12),0 12px 24px -12px rgba(0,0,0,.45)}
a.cap.sm{display:inline-block;height:28px;line-height:26px;padding:0 12px;
  max-width:min(420px,100%);overflow:hidden;text-overflow:ellipsis}

/* ── 右侧悬浮编辑抽屉（2026-10-20，培训中心审核 / 知识库：不跳页面，在当前页改完回填）──
   形态照左侧「数据看板」抽屉（.bdock-drawer）镜像到右边：悬浮玻璃卡、弹簧滑入、背后轻微压暗。
   结构：.sdrawer-scrim + .sdrawer > .sd-head / .sd-body / .sd-foot。开关加 .on。 */
.sdrawer-scrim{position:fixed;inset:0;z-index:290;background:color-mix(in srgb,var(--bg) 38%,transparent);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
  opacity:0;visibility:hidden;transition:opacity .4s ease,visibility 0s linear .4s}
.sdrawer-scrim.on{opacity:1;visibility:visible;transition:opacity .4s ease,visibility 0s}
.sdrawer{position:fixed;z-index:300;right:12px;top:12px;bottom:12px;width:min(480px,calc(100vw - 24px));
  border-radius:var(--r-xl);display:flex;flex-direction:column;overflow:hidden;
  background:var(--glass-2);backdrop-filter:blur(34px) saturate(1.8);-webkit-backdrop-filter:blur(34px) saturate(1.8);
  box-shadow:var(--shadow-float);
  transform:translateX(calc(100% + 24px));visibility:hidden;
  transition:transform .6s var(--ease-spring),visibility 0s linear .6s}
.sdrawer.on{transform:none;visibility:visible;transition:transform .6s var(--ease-spring),visibility 0s}
.sd-head{display:flex;align-items:flex-start;gap:12px;padding:22px 22px 12px}
.sd-head small{display:block;font-size:10.5px;letter-spacing:.18em;color:var(--ink-3);margin-bottom:6px}
.sd-head h3{margin:0;font-size:20px;font-weight:400;letter-spacing:-.01em;line-height:1.3}
.sd-head .sd-x{margin-left:auto;flex:none;width:34px;height:34px;border-radius:50%;cursor:pointer;font:inherit;font-size:18px;line-height:1;
  color:var(--ink-2);background:var(--surface);border:1px solid var(--line)}
.sd-body{flex:1;overflow-y:auto;padding:4px 22px 16px;display:grid;gap:14px;align-content:start}
.sd-body label{display:grid;gap:6px;font-size:12.5px;color:var(--ink-3)}
.sd-body label em{font-style:normal;font-size:11.5px;color:var(--ink-3)}
.sd-body input,.sd-body textarea{font:inherit;font-size:13.5px;line-height:1.7;padding:9px 12px;border-radius:10px;
  color:var(--ink);background:var(--surface);border:1px solid var(--line)}
.sd-body textarea{min-height:96px}
.sd-body textarea.tall{min-height:180px}
.sd-body input:focus,.sd-body textarea:focus{outline:none;border-color:var(--ink-3)}
.sd-foot{display:flex;align-items:center;gap:12px;padding:14px 22px 20px;border-top:1px solid var(--line)}
.sd-foot .sd-msg{font-size:12.5px;color:var(--ink-3)}
.sd-foot .sd-msg.bad{color:var(--warn)}
@media(prefers-reduced-motion:reduce){.sdrawer,.sdrawer-scrim{transition:none}}
/* 宽抽屉：里面嵌一个页面（RayUI.frame，如业务台账一条记录的完整编辑） */
.sdrawer.wide{width:min(620px,calc(100vw - 24px))}
.sdrawer .sd-frame{flex:1;width:100%;border:0;background:transparent}

/* ── 放大阅读（RayUI.reader，2026-10-20）：知识类卡片点开后居中大字，培训时可直接投屏讲 ──
   字号由 --rd-fs 控制（A− / A+，记在本机）；要点拆成条目、原话拆成左右气泡，一眼抓到重点 */
.rd-mask{position:fixed;inset:0;z-index:700;display:flex;align-items:center;justify-content:center;gap:18px;padding:24px;
  background:var(--scrim);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  opacity:0;visibility:hidden;transition:opacity .3s ease,visibility 0s linear .3s;--rd-fs:20px}
.rd-mask.on{opacity:1;visibility:visible;transition:opacity .3s ease,visibility 0s}
.rd{width:min(920px,100%);max-height:calc(100vh - 48px);display:flex;flex-direction:column;border-radius:var(--r-xl);
  background:var(--surface);border:1px solid var(--line);box-shadow:var(--shadow-float);overflow:hidden;
  transform:translateY(12px) scale(.98);transition:transform .5s var(--ease-spring)}
.rd-mask.on .rd{transform:none}
.rd-top{display:flex;align-items:center;gap:12px;padding:18px 26px 0}
.rd-top small{font-size:12px;letter-spacing:.16em;color:var(--ink-3)}
.rd-tools{margin-left:auto;display:flex;gap:6px}
.rd-tools button{font:inherit;font-size:13px;min-width:34px;height:34px;padding:0 10px;border-radius:var(--r-pill);cursor:pointer;
  color:var(--ink-2);background:var(--surface-2);border:1px solid var(--line)}
.rd-tools button:hover{color:var(--ink);border-color:var(--line-2)}
.rd-body{flex:1;overflow-y:auto;padding:10px 40px 28px;font-size:var(--rd-fs);line-height:1.75;color:var(--ink)}
.rd-body h2{font-size:calc(var(--rd-fs) * 1.6);font-weight:500;line-height:1.3;margin:6px 0 14px;letter-spacing:-.01em}
.rd-tags{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:18px}
.rd-sec{margin-top:22px}
.rd-sec h4{margin:0 0 10px;font-size:calc(var(--rd-fs) * .62);font-weight:500;letter-spacing:.14em;color:var(--ink-3)}
.rd-sec p{margin:0;white-space:pre-line}
.rd-sec ul{margin:0;padding:0;list-style:none;display:grid;gap:10px}
.rd-sec li{position:relative;padding-left:1.1em}
.rd-sec li::before{content:"";position:absolute;left:.15em;top:.68em;width:.38em;height:.38em;border-radius:50%;background:var(--accent)}
.rd-bub{max-width:82%;padding:.55em .9em;border-radius:16px;margin-bottom:10px;background:var(--surface-2);white-space:pre-line}
.rd-bub.a{margin-left:auto;background:var(--accent-soft)}
.rd-bub i{display:block;font-style:normal;font-size:.62em;letter-spacing:.12em;color:var(--ink-3);margin-bottom:2px}
.rd-foot{display:flex;gap:12px;padding:12px 26px 18px;border-top:1px solid var(--line);font-size:12.5px;color:var(--ink-3)}
.rd-foot .rd-n{margin-left:auto;font-variant-numeric:tabular-nums}
.rd-nav{flex:none;width:52px;height:52px;border-radius:50%;cursor:pointer;font:inherit;font-size:28px;line-height:1;
  color:var(--ink-2);background:var(--surface);border:1px solid var(--line);box-shadow:var(--shadow-card)}
.rd-nav:disabled{opacity:.3;cursor:default}
@media(max-width:760px){.rd-nav{display:none}.rd-body{padding:8px 20px 22px}}
@media(prefers-reduced-motion:reduce){.rd-mask,.rd{transition:none}}
/* 编辑保存回填后闪一下：让人看到「这条换成了改好的内容」（培训中心、对象档案等共用） */
@keyframes rvflash{0%{box-shadow:0 0 0 2px var(--accent)}100%{box-shadow:0 0 0 2px transparent}}
.flash{animation:rvflash 1.6s ease-out}
@media(prefers-reduced-motion:reduce){.flash{animation:none}}
/* 可点开放大的卡片：鼠标指针 + 一点悬浮感 */
.zoomable{cursor:zoom-in;transition:border-color .25s,transform .45s var(--ease-spring)}
.zoomable:hover{border-color:var(--line-2);transform:translateY(-1px)}

/* ── 返回键吸附（2026-10-20 用户：往下滚动后返回键吸附到当前容器左上角，动效照看板日期控制条）──
   .docked 时固定在顶栏正下方、内容容器左外侧的留白里（脚本算好写进 --back-x）；原位置留 .back-ph 占位，页头不跳。
   形变用 FLIP（ui.js backDock / console BoardHeader）：量前后两个矩形再补间，带一点回弹。只在宽屏吸附，与 .ctl-rail 同一条件。 */
.back.docked{position:fixed;z-index:56;top:calc(var(--bar-h) + 16px);left:var(--back-x,20px);margin:0}
.back-ph{flex:none;width:44px;height:44px}
/* 历史表「更早的 N 条」折叠行（ui.js histFold）：统一的 .fxhd / .fx，默认只露最新一条 */
tr.histmore td{padding:8px 10px;border-bottom:0;background:none!important}
tr.histmore .fxt{font-size:12.5px;color:var(--ink-3)}
/* 推送前预览：多张卡片各一个折叠（ui.js pushBox），第一张展开 */
.pcfold{border-bottom:1px solid var(--line)}
.pcfold:last-child{border-bottom:0}
.pcfold > .fxhd{padding:12px 2px}
.pcfold > .fxhd .fxt{font-size:13.5px;font-weight:500}
.pcfold > .fxbody{padding-bottom:12px}

/* ============================================================
   展开 / 收起（2026-10-13 统一，照官网 /faq 问答框：my-raydiene pages/faq.vue）
   - 整行标题可点（.fxhd）；右侧一个圆形「+」（.fx，纯 CSS 画），展开时转 45° 成「×」，描边 / 底 / 字染品牌蓝；
   - 悬停时标题（.fxt）变品牌蓝；内容（.fxbody）出现时淡入上移，与 FAQ 列表的 fadeSlideIn 同一种动效。
   - 展开态三种写法都认：外层 .open / .is-open、标题 aria-expanded="true"、<details open>。
   app（static/*.html）与 console 共用这一份，新增折叠一律用这套，不再各写 ▸ 箭头或「展开 / 收起」文字按钮。
   ============================================================ */
:where(button.fxhd){font:inherit;color:inherit;background:none;border:0;padding:0;margin:0;width:100%;text-align:left}
.fxhd{display:flex;align-items:center;gap:12px;cursor:pointer;user-select:none;list-style:none}
.fxhd::-webkit-details-marker{display:none}
.fxt{transition:color .2s}
.fxhd:hover .fxt{color:var(--accent-ink)}
.fx{position:relative;flex:none;width:32px;height:32px;margin-left:auto;border-radius:50%;
  border:1px solid var(--line-2);color:var(--ink-3);
  transition:transform .3s ease,border-color .3s,background-color .3s,color .3s}
.fx::before,.fx::after{content:"";position:absolute;left:50%;top:50%;width:13px;height:1.7px;margin:-.85px 0 0 -6.5px;
  border-radius:2px;background:currentColor}
.fx::after{transform:rotate(90deg)}
.fx.sm{width:22px;height:22px}
.fx.sm::before,.fx.sm::after{width:9px;height:1.5px;margin:-.75px 0 0 -4.5px}
.fxhd:hover .fx{border-color:var(--ink-3);color:var(--ink-2)}
.open>.fxhd .fx,.is-open>.fxhd .fx,.fxhd[aria-expanded="true"] .fx,details[open]>summary.fxhd .fx{
  transform:rotate(45deg);border-color:var(--accent-line);background:var(--accent-soft);color:var(--accent-ink)}
@keyframes fxIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
/* 填充用 backwards 不用 both（2026-10-20 性能排查）：both 会让播完的动画一直「生效」，元素一直占着一个合成图层；
   展开过的折叠越多，残留图层越多。终点就是元素本来的样子，所以视觉上没有区别 */
.fxbody{animation:fxIn .5s ease backwards}
/* 折叠开合（2026-10-21 全站统一）：高度 + 内容淡入淡出由脚本播 —— app 在 ui.js foldMotion，console 在 FoldBody.vue / AgentTools.vue，
   参数一致（0.45s、--ease-out）。fxOut 只留给卡片离场（.ag-leave-active）用 */
@keyframes fxOut{from{opacity:1;transform:none}to{opacity:0;transform:translateY(-8px)}}
@media(prefers-reduced-motion:reduce){.fx,.fxt{transition:none}.fxbody{animation:none}}
/* 卡片排序 / 筛选的进出场（console AgentGrid，2026-10-21）：入场 fxIn、离场 fxOut（与折叠同一套），留下的卡用弹簧曲线挪到新位置 */
.ag-grid{position:relative}
.ag-enter-active{animation:fxIn .5s ease backwards}
.ag-leave-active{position:absolute;animation:fxOut .22s cubic-bezier(.4,0,.2,1) both;pointer-events:none;z-index:0}
.ag-move{transition:transform .5s var(--ease-spring)}
@media(prefers-reduced-motion:reduce){.ag-enter-active,.ag-leave-active{animation:none}.ag-move{transition:none}}

/* 输入框不给右下角的拖拽手柄（2026-09-28 用户要求）：高度由页面定好 */
textarea{resize:none}

/* ============================================================
   标签式输入（2026-09-28 用户要求防呆：多个词不用符号分隔，一个词一个标签）
   小红书占位分析、品牌监测共用。行为在 static/xhs_tags.js（品牌监测）/ xhs_rank.html。
   ============================================================ */
.kwbox{display:flex;flex-wrap:wrap;align-items:center;gap:6px;min-height:46px;padding:6px 6px 6px 8px;border-radius:10px;
  background:var(--surface-2);border:1px solid var(--line);cursor:text}
.kwbox:focus-within{border-color:var(--ink-3)}
.kwbox input[type=text]{flex:1;min-width:180px;border:0!important;background:transparent!important;padding:6px 4px!important;outline:none!important;box-shadow:none!important}
.kwtag{display:inline-flex;align-items:center;gap:4px;height:30px;padding:0 4px 0 12px;border-radius:99px;font-size:13.5px;
  color:var(--ink);background:var(--surface);border:1px solid var(--line-2)}
.kwtag i{font-style:normal;font-size:11px;color:var(--ink-3);margin-right:2px}
.kwtag button{width:22px;height:22px;border:0;border-radius:50%;background:transparent;color:var(--ink-3);cursor:pointer;font-size:14px;line-height:1}
.kwtag button:hover{background:var(--surface-3);color:var(--ink)}
.kwadd{height:32px;padding:0 14px;border-radius:99px;border:1px solid var(--line-2);background:var(--surface);color:var(--ink-2);
  font:inherit;font-size:12.5px;cursor:pointer}
.kwadd:hover{color:var(--ink)}
.kwhint{font-size:12px;color:var(--ink-3);line-height:1.6;min-height:19px}
.kwhint.warn{color:var(--warn)}
.kwhint button{margin-left:8px}

/* ---------- 功能板块授权（ui.js applyRoutes / toast，2026-10-07） ---------- */
.raytoast{position:fixed;left:50%;bottom:28px;z-index:900;max-width:min(560px,calc(100vw - 32px));
  transform:translate(-50%,12px);opacity:0;pointer-events:none;padding:11px 18px;border-radius:12px;
  background:var(--ink);color:var(--bg,#fff);font-size:13.5px;line-height:1.6;box-shadow:var(--shadow-lift);
  transition:opacity .3s var(--ease-out),transform .3s var(--ease-out)}
.raytoast.on{opacity:1;transform:translate(-50%,0)}
a.locked{opacity:.42;cursor:not-allowed;filter:grayscale(1)}
a.entry.locked:hover{transform:none;box-shadow:var(--shadow-card);border-color:var(--line)}
.robadge{font-size:11px;font-weight:500;padding:1px 8px;border-radius:99px;background:var(--warn-bg);color:var(--warn)}
.robar{margin:0 0 18px;padding:10px 14px;border-radius:12px;font-size:13px;line-height:1.6;
  background:var(--warn-bg);color:var(--warn);border:1px solid color-mix(in srgb,var(--warn) 30%,transparent)}
/* 只读页：主按钮、上传框不可点（服务器也会拒，这里只是不让人白点） */
body.ro button.primary,body.ro input[type=file],body.ro label:has(>input[type=file]),body.ro .zone:has(>input[type=file]){
  opacity:.4;pointer-events:none;filter:grayscale(1)}
