/* ============================================================================
   溪雨官网 · 流动效果 + 深色「墨玉·全息」主题
   2026-09-16 大副（总控师当晚交的活）

   为什么单开一个文件：app.css 里已有四层深色规则（约 40 / 1446 / 1718 / 1817 行起），
   再往里塞会变成"第五层"。这个文件**在 app.css 之后加载**，只做两件事：

     ① 流动效果 —— 浅色深色都用，靠"墨"的物理行为（洇开、落笔、划过）做隐喻，
        不用"所有元素都上浮 16px"那套（那已经是 AI 生成站点的标志性套路）。
     ② 深色主题层 —— 把深色重做成「墨玉 · 玉青 · 朱砂」：书法 logo 一个像素不动，
        科技感全部由它**周围的光**（粒子 / 全息网格 / 扫描线 / 投射光带）承载。

   硬约束（写在最前面，改之前先读）：
     · 浅色页的**静态外观一律不变**（他只让改深色）；浅色下新增的只有"进入时的动"
     · 大 logo 不做大改动 —— 书法本体不动，加的是 mask 裁出的扫描光带与外围光晕
     · `prefers-reduced-motion: reduce` 时全部关掉（文件末尾总闸）
     · 只动 transform / opacity（合成层）；粒子在 JS 里按屏宽限数量
   ========================================================================== */

/* ==========================================================================
   一 · 流动效果（浅色深色通用）
   ========================================================================== */

/* ---- 1. 首屏墨洇：logo 像墨落在宣纸上，先晕开、再收清 --------------------
   隐喻来自书法：墨接触纸面那一刻是"洇"的（边缘发虚），随后吃进纤维才清晰。
   blur 会触发重绘（不是合成层），所以只给这一个元素、且只播一次（1.5s）。 */
@keyframes fx-ink-spread {
  0%   { opacity: 0; filter: blur(11px); transform: scale(1.035); }
  40%  { opacity: 1; }
  100% { opacity: 1; filter: blur(0); transform: scale(1); }
}
html.fx-js .brand-logo,
html.fx-js .brand-row::after {
  /* fill-mode 用 backwards 而不是 both：动画结束**不留残留样式** ——
     both 会让元素永久带着 filter/transform，给浅色页带来亚像素级渲染差异（实测 0.3%）。
     无延时的那两个用 backwards 与 none 等价；有延时的必需 backwards（延时期间要压住起始帧）。 */
  animation: fx-ink-spread 1.5s cubic-bezier(.22, .61, .36, 1) backwards;
}

/* ---- 2. 宗旨落笔：三个词逐个"渗"出来 ------------------------------------
   不用位移（那会变成 fade-up 套路），用 **模糊→清晰** 做"墨渗"，
   逐个延后 0.28s —— 像一笔一笔写下来。 */
@keyframes fx-word-seep {
  0%   { opacity: 0; filter: blur(7px); }
  60%  { opacity: 1; }
  100% { opacity: 1; filter: blur(0); }
}
html.fx-js .brand .creed > .creed-word { animation: fx-word-seep .95s ease-out backwards; }
html.fx-js .brand .creed > .creed-word:nth-child(1) { animation-delay: .78s; }
html.fx-js .brand .creed > .creed-word:nth-child(2) { animation-delay: 1.06s; }
html.fx-js .brand .creed > .creed-word:nth-child(3) { animation-delay: 1.34s; }

/* 副标题与那行小字：跟着宗旨之后淡入（delay 排在宗旨之后，不抢戏） */
@keyframes fx-soft-in { from { opacity: 0; } to { opacity: 1; } }
html.fx-js .brand .subtitle { animation: fx-soft-in .9s ease-out 1.5s backwards; }
html.fx-js .brand .tip      { animation: fx-soft-in .9s ease-out 1.66s backwards; }

/* 收尾那道细线：从中间往两边"拉"开（scaleX），比淡入更像"画了一道" */
html.fx-js .brand::after {
  transform-origin: center;
  animation: fx-line-draw .9s cubic-bezier(.2, .7, .3, 1) 1.7s backwards;
}
@keyframes fx-line-draw { from { transform: scaleX(0); opacity: 0; } to { transform: scaleX(1); opacity: 1; } }

/* ---- 3. 滚动进入：只挑该动的元素，动作**各不相同** ----------------------
   JS 只负责在进入视口时加 .fx-in（一次），动作全部在这一层定义。
   刻意不用同一套（同一个位移+同一个 easing 铺满全站，是最 AI 味的那种做法）。 */

/* 服务卡：像纸片被"推"到位 —— 极轻的位移 + 边框细线从左划入。
   隐藏态挂在 .fx-pending（JS 逐元素加），不是"全局时间窗"：
   app.js 每 30 秒会重建一次首页卡片，时间窗方案会让重建出来的卡片变透明。 */
.fx-card.fx-pending { opacity: 0; transform: translate3d(0, 14px, 0); }
.fx-card.fx-in {
  opacity: 1; transform: none;
  transition: opacity .62s cubic-bezier(.2, .7, .3, 1), transform .62s cubic-bezier(.2, .7, .3, 1);
}
.fx-card::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, var(--accent), transparent 72%);
  /* 默认**不显示**：这条朱砂细线只在 hover（或入场那一下）出现 ——
     浅色页的静态外观必须与改版前逐像素一致（实测口径见台账）。 */
  transform: scaleX(0); transform-origin: left center;
  transition: transform .55s cubic-bezier(.2, .7, .3, 1);
  pointer-events: none;
}
.fx-card.fx-in::after { transform: scaleX(1); }
@media (hover: hover) {
  .fx-card:hover::after, .fx-card.fx-in:hover::after { transform: scaleX(1); }
}
.home-card { position: relative; }

/* 服务公告：从上方落下一点点（它是"今日状态"，该先被看到） */
.fx-notice.fx-pending { opacity: 0; transform: translate3d(0, -10px, 0); }
.fx-notice.fx-in {
  opacity: 1; transform: none;
  transition: opacity .7s ease-out, transform .7s cubic-bezier(.2, .7, .3, 1);
}

/* 反馈区标题：细线从中间展开（和 hero 收尾线同一套语言） */
.fx-title { position: relative; }
.fx-title::before {
  content: ''; position: absolute; left: 0; bottom: -6px; height: 1px; width: 100%;
  background: var(--line);
  transform: scaleX(0); transform-origin: center;      /* 默认不显示，见 .fx-card::after 的说明 */
  transition: transform .8s cubic-bezier(.2, .7, .3, 1);
}
.fx-title.fx-in::before { transform: scaleX(1); }

/* 反馈卡片：一张张摞上来（延迟由 JS 写进 --fx-delay） */
.fx-rise.fx-pending { opacity: 0; transform: translate3d(0, 12px, 0); }
.fx-rise.fx-in {
  opacity: 1; transform: none;
  transition: opacity .55s ease-out var(--fx-delay, 0ms), transform .55s cubic-bezier(.2, .7, .3, 1) var(--fx-delay, 0ms);
}

/* ---- 4. 交互细节（浅色也吃） -------------------------------------------- */

/* 服务卡图标：hover 时轻轻"洇"开一点（像墨点落在纸上） */
.home-card .hc-icon { transition: transform .45s cubic-bezier(.2, .7, .3, 1), filter .45s ease; }
@media (hover: hover) {
  .home-card:hover .hc-icon { transform: scale(1.06); filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .10)); }
}

/* 箭头：hover 时往前走半步（方向暗示，不用缩放大动干戈） */
.home-card .hc-arrow { transition: transform .3s cubic-bezier(.2, .7, .3, 1), color .2s ease; }
@media (hover: hover) {
  .home-card:hover .hc-arrow { transform: translateX(4px); }
}

/* 提交按钮：按下时沉一下（真实按钮该有的手感） */
.submit-btn, .login-btn { transition: transform .12s ease, box-shadow .2s ease, background .2s ease; }
.submit-btn:active, .login-btn:active { transform: translateY(1px) scale(.995); }

/* "更多例子"折叠按钮：做得像一行小字，不像控件 —— 它只是"想不出来时可以看"的后路 */
.preset-toggle {
  display: inline-flex;
  align-items: center;
  min-height: 32px;                 /* 手指点得到（探针判据 ≥32px） */
  margin: 4px 0 0;
  padding: 6px 2px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12.5px;
  letter-spacing: .04em;
  color: var(--accent);
  opacity: .85;
  cursor: pointer;
}
.preset-toggle:hover { opacity: 1; text-decoration: underline; text-underline-offset: 3px; }

/* 填单/选档时把 hero 收一收（总控师 2026-09-16 夜："我自己都不愿意填"）：
   客户进来是干活的，不必每次先滚过整个招牌。logo 尺寸不动，只收上下留白。 */
body.fx-working .brand { padding-top: 2vh; margin-bottom: 26px; }

/* ---- 5. 宣纸的"物质感"（浅色为主） ---------------------------------------
   总控师 2026-09-16 夜反馈两条："明页啥也没有" + "网页有点素"。
   诊断成立：浅色原本只有「平色底 + 留白」，视觉上确实是空的 ——
   品牌要的"克制"不等于"什么都没有"。这里补的是**宣纸本身的质地**，不是贴装饰物：
   纸有纤维（噪点层）、墨会洇（hero 后方墨晕）、画有落款（印章）。
   注意：这几条写在深色段**之前**，深色主题有自己的对应版本（网格 / 玉青光晕），会正常覆盖。 */

/* 5a. 纸纹：极淡的纤维噪点（SVG feTurbulence 内联生成，无外部请求、可平铺） */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: .55;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='f'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='180' height='180' filter='url(%23f)' opacity='.085'/></svg>");
  background-size: 180px 180px;
}

/* 5b. hero 后方的一团墨晕：像纸上洇开的一块墨，极慢地"呼吸" */
.brand-row::before {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: min(96vw, 720px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  pointer-events: none;
  background: radial-gradient(circle,
    rgba(31, 26, 23, .062) 0%,
    rgba(31, 26, 23, .022) 40%,
    transparent 66%);
  animation: fx-breathe 9s ease-in-out infinite;
}

/* 5c. 落款印章：中式书画的收尾。进场时"盖"下去 —— 放大落下、压过头、微回弹、定住 */
.fx-seal {
  --seal-final: .45;
  display: block;
  width: 30px; height: 30px;
  margin: 20px auto 0;
  opacity: 0;
  animation: fx-seal-stamp 1.15s cubic-bezier(.2, .9, .3, 1) 1.85s both;
}
@media (min-width: 900px) {
  .fx-seal { margin: 20px max(6%, 44px) 0 auto; }   /* 宽屏靠右 —— 落款该在的位置 */
}
@keyframes fx-seal-stamp {
  0%   { opacity: 0;               transform: scale(1.9) rotate(-10deg); }
  55%  { opacity: .88;             transform: scale(.93) rotate(2.5deg); }
  76%  {                           transform: scale(1.02) rotate(-1deg); }
  100% { opacity: var(--seal-final); transform: scale(1) rotate(0deg); }
}

/* 5d. 卡片的"纸感"：顶部一道极细的高光边（纸有厚度），朱砂细线入场时划入 */
.fx-card.fx-in::after { transform: scaleX(1); }
.home-card { box-shadow: var(--shadow), inset 0 1px 0 rgba(255, 255, 255, .8); }

/* 5e. 明页的**持续**动效（总控师 2026-09-16 夜第 2 条反馈：
       "明面你只是加了出现的动态效果，而不是跟暗面一样的那种偏持续性的动态效果"）
       —— 暗面有粒子/网格/扫描线在持续跑，明面也该有东西一直在动。
       这里给的是**水墨在纸里缓慢流动**：三层极淡的墨晕，68 秒一轮、看不出循环。
       它不是"入场动画"，是背景本身在动 —— 像纸里吸了水，墨在慢慢走。 */
html[data-skin="paper"] body::after {
  content: '';
  position: fixed;
  left: -25%; top: -25%;
  width: 150%; height: 150%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(38% 30% at 22% 26%, rgba(31, 26, 23, .055) 0%, transparent 62%),
    radial-gradient(34% 26% at 76% 62%, rgba(31, 26, 23, .045) 0%, transparent 60%),
    radial-gradient(30% 22% at 46% 90%, rgba(31, 26, 23, .038) 0%, transparent 58%);
  animation: fx-ink-flow 68s ease-in-out infinite alternate;
}
@keyframes fx-ink-flow {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(-2.6%, 1.9%, 0) scale(1.07); }
  100% { transform: translate3d(2.3%, -1.6%, 0) scale(1.03); }
}

/* 5f. 云气：几团极淡的云影缓缓掠过（96 秒一轮）。宣纸白 + 轻微模糊，
   在纸上像"窗外有云走过"，也正好是后面主题轮换里"科技 → 宣纸"那一下的同族语言。 */
.fx-cloud {
  position: fixed;
  left: -60%; top: 0;
  width: 220%; height: 100%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(46% 17% at 16% 20%, rgba(255, 255, 255, .70) 0%, transparent 62%),
    radial-gradient(40% 13% at 60% 44%, rgba(255, 255, 255, .55) 0%, transparent 60%),
    radial-gradient(48% 19% at 28% 72%, rgba(255, 255, 255, .50) 0%, transparent 64%);
  filter: blur(7px);
  animation: fx-cloud-drift 96s linear infinite;
}
@keyframes fx-cloud-drift {
  from { transform: translate3d(-7%, 0, 0); }
  to   { transform: translate3d(19%, 0, 0); }
}
html[data-skin="cyber"] .fx-cloud { display: none; }

/* ---- 6. 深色「墨玉 · 全息」 ---------------------------------------------
   --------------------------------------------------------------------------
   设计判断（写下来，免得下次自己推翻自己）：
   溪雨的科技感**不是**霓虹夜雨，是**暗室里运转的精密仪器** —— 冷光、秩序、留白。
   他的原话是"让用户知道溪雨在看不到的地方也有硬核实力"：硬核靠**精密**表达，
   不靠喧闹。所以这里不用紫蓝霓虹、不堆满屏故障感，改用：

     墨玉黑（冷）  #0A0E11   夜里的墨
     玉  青        #5FD3BE   主科技光（青瓷/玉的色，不是电子蓝）
     朱  砂        #E0554A   点睛与"行动"，一个色号都不改（中式符号的锚）

   朱青本就是中国传统配色（朱印 + 青瓷），又恰好是色差(RGB split)的经典对色 ——
   中式审美与现代光学的重合点就在这里，整套配色从这一条长出来。
   ========================================================================== */

/* ---- 5. 变量重声明：换底、换光、留朱砂 --------------------------------- */
html[data-skin="cyber"][data-theme="light"] {
  /* 「中式科技 · 明」—— 2026-09-17 重做。
     上一版被总控师一眼判"很乱而且敷衍"：网格、扫描线、角标、玉青文字、青边框全在抢存在感。
     重做的原则是**技术图纸**而不是**发光屏幕**：
       · 底：接近白的冷灰（干净、亮），不是发灰的实验室墙
       · 线：网格压到"只在留白处隐约看见"的程度，扫描线与四角标**直接去掉**（浅底上用不着）
       · 字：一律深墨青 —— 玉青**不写字**，只做结构线、状态点、hover 这点睛
       · 朱砂：保留（价格/印章），浅底上它是唯一的暖色
     一句话：让内容当主角，线条做秩序，玉青做那一点点光。 */
  --paper:     #F2F5F7;
  --paper-2:   #FAFCFD;
  --paper-dim: #E8EEF0;

  --bg:    var(--paper);
  --card:  #FFFFFF;
  --block: #EBF1F3;

  --ink:       #0C1E24;
  --ink-sub:   #35505A;
  --ink-soft:  #5E7883;
  --ink-faint: #7C949C;

  --line:   #DCE5E8;
  --border: #CBD8DC;
  --hover:  #EAF1F3;

  --accent:      #C4161C;
  --accent-dark: #9E1016;
  --cta:         #C4161C;
  --cta-dark:    #9E1016;
  --accent-bg:   #F5E9EA;
  --accent-bg-2: #EAD4D5;

  --fx-jade:      #0E9C86;
  --fx-jade-soft: rgba(14, 156, 134, .13);
  --fx-jade-line: rgba(14, 156, 134, .17);
  --fx-jade-glow: rgba(14, 156, 134, .38);
  --fx-ice:       #08262E;

  --ok: #1F7A52;      --ok-dark: #166040;    --ok-bg: #E4F1EA;
  --warning: #9A6410; --warning-dark: #7C4F0C; --warn-bg: #F8EFDD; --warn-line: #E6D2AC;
  --violet: #43606B;  --violet-dark: #33505B; --violet-bg: #E8EFF1;
  --indigo: #43606B;

  --shadow: 0 1px 2px rgba(15, 32, 39, .04);
  --shadow-hover: 0 10px 28px rgba(15, 32, 39, .09);

  --fx-panel-1: rgba(255, 255, 255, .94);
  --fx-panel-2: rgba(243, 248, 249, .96);
  --fx-panel-h1: rgba(255, 255, 255, 1);
  --fx-panel-h2: rgba(238, 245, 247, 1);
  --fx-ink-bg: rgba(255, 255, 255, .78);
  --fx-ink-solid: rgba(12, 34, 40, .94);
  --fx-mask: rgba(20, 40, 46, .40);
  --fx-scan-line: transparent;
}

/* 浅底上不需要扫描线与四角标：那是"屏幕"的语言，图纸上只会显乱 */
html[data-skin="cyber"][data-theme="light"] body::after { display: none; }
html[data-skin="cyber"][data-theme="light"] .fx-hud { display: none; }
/* 网格也压下去：只在留白处隐约成格（.16 太淡等于没有，.22 是"看得出是图纸、又不抢内容"） */
html[data-skin="cyber"][data-theme="light"] body::before { opacity: .22; }
/* 宗旨的词回到墨色（玉青写字在浅底上最显花） */
html[data-skin="cyber"][data-theme="light"] .brand .creed > .creed-word > i {
  color: var(--ink-sub);
  text-shadow: none;
}
/* 面板与卡片：只留极淡的冷边，不要"青光边框" */
html[data-skin="cyber"][data-theme="light"] .home-card,
html[data-skin="cyber"][data-theme="light"] .notice,
html[data-skin="cyber"][data-theme="light"] .tier-card,
html[data-skin="cyber"][data-theme="light"] .template-card {
  border-color: var(--border);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), 0 1px 3px rgba(15, 32, 39, .05);
}
html[data-skin="cyber"][data-theme="light"] .home-card .hc-price { color: var(--accent); text-shadow: none; }
html[data-skin="cyber"][data-theme="light"] .home-card .hc-icon { color: var(--fx-jade); }
html[data-skin="cyber"][data-theme="light"] .home-card .hc-arrow {
  color: var(--fx-jade);
  border-color: var(--fx-jade-line);
  background: rgba(14, 156, 134, .04);
}
html[data-skin="cyber"][data-theme="light"] .modal { border-color: var(--border); box-shadow: 0 22px 60px rgba(15, 32, 39, .16); }
html[data-skin="cyber"][data-theme="light"] .order-table th { color: var(--ink-sub); border-bottom-color: var(--line); }
html[data-skin="cyber"][data-theme="light"] .brand::after { background: linear-gradient(90deg, transparent, var(--fx-jade-line), transparent); box-shadow: none; }

html[data-skin="cyber"][data-theme="dark"] {
  --paper:     #0A0E11;
  --paper-2:   #0E1418;
  --paper-dim: #131A1F;

  --bg:    var(--paper);
  --card:  #0E1418;
  --block: #131A1F;

  --ink:       #E7EFF0;
  --ink-sub:   #B5C4C8;
  --ink-soft:  #8E9FA4;
  --ink-faint: #76878F;

  --line:   #1B242A;
  --border: #22303A;
  --hover:  #111920;

  /* 强调色的"浅底"在冷墨底上不能是暖红（原来 #2E1A17）：色相一跳就显脏。
     改成冷中性高亮底 —— hover / 标签 / 状态条靠**明度**区分，朱砂只留在文字与细线上点睛。 */
  --accent-bg:   #16202A;
  --accent-bg-2: #24313B;
  /* 同理：朱砂的"最浅底"（档位回显、文件标签、状态徽标都用它）在深色下也走冷调。
     朱砂本身（--vermilion）一个像素没改 —— 它仍然是这个主题里唯一的暖色点睛。 */
  --vermilion-l: #171D24;

  /* 色差对色：青（全息光）与朱（印章） */
  --fx-jade:        #63DCC6;
  --fx-jade-soft:   rgba(99, 220, 198, .16);
  --fx-jade-line:   rgba(99, 220, 198, .30);
  --fx-jade-glow:   rgba(99, 220, 198, .42);
  --fx-ice:         #E9F4F4;

  /* 语义色随玉青走（原来那几个蓝紫在冷墨底上会显得"外来"） */
  --ok: #5BC79A;      --ok-dark: #7BDCB2;     --ok-bg: #0F2420;
  --violet: #8AA6AE;  --violet-dark: #A7C2C9; --violet-bg: #14202A;
  --indigo: #8AA6AE;
  /* 科技皮肤的结构色（明/暗各一套，组件样式共用） */
  --fx-panel-1: rgba(19, 27, 33, .92);
  --fx-panel-2: rgba(11, 16, 20, .94);
  --fx-panel-h1: rgba(22, 32, 38, .94);
  --fx-panel-h2: rgba(13, 19, 24, .96);
  --fx-ink-bg: rgba(10, 16, 20, .62);
  --fx-ink-solid: rgba(8, 12, 15, .95);
  --fx-mask: rgba(6, 9, 11, .72);
  --fx-scan-line: rgba(233, 244, 244, .05);
  --shadow: 0 1px 2px rgba(0, 0, 0, .5);
  --shadow-hover: 0 10px 28px rgba(0, 0, 0, .55);
}

/* ---- 6. 装饰层的层序：让粒子/网格待在内容**之下**、扫描线之上 ----------
   做法：给 body 建一个层叠上下文，装饰层用 z-index:-1（绘制在 body 背景之上、
   内容之下）；扫描线用 z-index:2 —— 它是要"盖住整屏"的，那才是投影的感觉。 */
html[data-skin="cyber"] body { position: relative; z-index: 0; }

/* 全息网格：极淡、缓慢平移、边缘用 mask 淡出（硬边网格很廉价） */
html[data-skin="cyber"] body::before {
  content: '';
  position: fixed;
  left: -60%; top: -60%;
  width: 220%; height: 220%;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(var(--fx-jade-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--fx-jade-line) 1px, transparent 1px);
  background-size: 56px 56px;
  /* 铺满整屏、均匀极淡 —— 一开始用了 mask 做"中心亮边缘淡"，
     手机上结果变成"只有左上角一小块看得见网格"，像瑕疵而不是氛围。
     它本来就该是**基底层**：均匀铺开，被卡片盖住的地方自然看不见。 */
  opacity: .30;
  animation: fx-grid-drift 46s linear infinite;
}
@keyframes fx-grid-drift { to { transform: translate3d(56px, 56px, 0); } }

/* 扫描线：整屏 CRT 质感（3px 一条，极淡），用 transform 上移 —— 合成层，不重绘 */
html[data-skin="cyber"] body::after {
  content: '';
  position: fixed;
  left: 0; top: -100%;
  width: 100%; height: 200%;
  z-index: 2;
  pointer-events: none;
  background: repeating-linear-gradient(
    0deg,
    var(--fx-scan-line) 0 1px,
    transparent 1px 3px
  );
  animation: fx-scan-drift 9s linear infinite;
}
@keyframes fx-scan-drift { to { transform: translate3d(0, 50%, 0); } }

/* 尘粒画布：两种主题都有 —— 深色是玉青的"墨尘"，浅色是宣纸上的"浮尘"（颜色/密度由 JS 按主题给）。
   内容层在 canvas 之上，所以粒子只在留白处透出来。 */
#fxDust {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

/* ---- 7. Hero：书法不动，光在它周围 ------------------------------------- */

/* 全息光晕（缓慢呼吸）—— 挂在 .brand-row 上，logo 本体不碰 */
html[data-skin="cyber"] .brand-row { position: relative; }
html[data-skin="cyber"] .brand-row::before {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: min(92vw, 660px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  pointer-events: none;
  background: radial-gradient(circle,
    rgba(99, 220, 198, .115) 0%,
    rgba(99, 220, 198, .038) 40%,
    transparent 66%);
  animation: fx-breathe 7.5s ease-in-out infinite;
}
@keyframes fx-breathe {
  0%, 100% { opacity: .72; transform: translate(-50%, -50%) scale(1); }
  50%      { opacity: 1;   transform: translate(-50%, -50%) scale(1.035); }
}

/* 投射底座：logo 正下方一片扁光斑（"这幅字是被投出来的"）——单独一个元素，
   因为 .brand-row::before/::after 已经分别给了光晕和深色 logo，不能再占。 */
.fx-pedestal {
  display: none;                 /* 同 .fx-sweep：浅色下不参与渲染 */
  position: absolute;
  left: 50%; bottom: -14%;
  width: min(88vw, 580px); height: 96px;
  transform: translateX(-50%);
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 0%,
    rgba(99, 220, 198, .22) 0%,
    rgba(99, 220, 198, .06) 42%,
    transparent 74%);
  filter: blur(3px);
  animation: fx-pedestal-breathe 7.5s ease-in-out infinite;
}
html[data-skin="cyber"] .fx-pedestal { display: block; }
@keyframes fx-pedestal-breathe {
  0%, 100% { opacity: .78; }
  50%      { opacity: 1; }
}

/* 投射光带：用**白色书法图当 mask**，光只在笔画里走 —— 所以它看着像
   "这幅字被一束光扫过"，而不是"页面上飘过一条白带"。
   外层负责对齐与 mask（静止），内层负责平移（合成层）。 */
.fx-sweep {
  display: none;                 /* 浅色下彻底不渲染：光是"透明"仍会进渲染管线，
                                    实测给浅色页带来 0.3% 的亚像素差异（见台账的负向对照） */
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  overflow: hidden;
  -webkit-mask-image: url("/assets/brand/logo-hero-white.png");
  -webkit-mask-image: -webkit-image-set(url("/assets/brand/logo-hero-white.webp") 1x type("image/webp"),
                                        url("/assets/brand/logo-hero-white.png") 1x type("image/png"));
  mask-image: url("/assets/brand/logo-hero-white.png");
  mask-image: image-set(url("/assets/brand/logo-hero-white.webp") type("image/webp"),
                        url("/assets/brand/logo-hero-white.png") type("image/png"));
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
html[data-skin="cyber"] .fx-sweep { display: block; }
.fx-sweep > i {
  position: absolute;
  top: -10%; left: -120%;
  width: 240%; height: 120%;
  display: block;
  background: linear-gradient(100deg,
    transparent 40%,
    rgba(233, 244, 244, .38) 47%,
    rgba(99, 220, 198, .85) 52%,
    rgba(233, 244, 244, .30) 57%,
    transparent 64%);
  animation: fx-sweep-run 7s cubic-bezier(.45, 0, .3, 1) infinite;
}
@keyframes fx-sweep-run {
  0%, 52%   { transform: translate3d(0, 0, 0); }
  88%, 100% { transform: translate3d(96%, 0, 0); }
}

/* 底部"投射底座"：一道贴着 logo 的光，暗示它是被投出来的 */
html[data-skin="cyber"] .brand::after {
  background: linear-gradient(90deg, transparent, var(--fx-jade-glow), transparent);
  box-shadow: 0 0 12px var(--fx-jade-soft);
  height: 1px;
}

/* 系统状态行：**四套皮肤结构完全一致**（总控师 2026-09-17："不能出现布局差距"）。
   宽度与高度**锁死** —— 两套皮肤用的字体不同（衬线 vs 等宽），不锁字宽就会一边宽 268、
   另一边 234，居中位置差 17px。锁住尺寸后，只有字体与颜色随皮肤变，几何一模一样。 */
.fx-status {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  /* 2026-09-19：宽度原来是 min(340px,88vw)，但状态条后来多了第三段「· 最近交付 X月X日 18:00」，
     两套皮肤实测需要 357px(默认) / 383px(本地 cyber) / 423px(线上 cyber，字体渲染略有不同) ——
     340 装不下就硬裁，桌面访客第一屏看到一截断句（走查发现）。放宽到 440 并继续锁死：
     锁死是为了两套皮肤几何一致（见上面注释），不是必须 340。 */
  width: min(440px, 92vw);
  height: 30px;
  margin: 24px auto 0;
  padding: 0 13px;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: rgba(255, 255, 255, .55);
  font-size: 11px;
  letter-spacing: .08em;
  line-height: 1.7;
  color: var(--ink-faint);
  white-space: nowrap;
  overflow: hidden;
}
.fx-status b {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 9px rgba(196, 22, 28, .30);
  animation: fx-pulse 2.4s ease-in-out infinite;
}
/* 宣纸皮肤下**不显示**状态行 —— 总控师第 3 条："宣纸页你也在中间放那个'系统在线'是不是有点莫名其妙"。
   他指的是信息不对（那是仪表盘的语言，宣纸页上是外来物）。
   但布局占位必须留（否则切换时下面内容会跳 52px），所以用 visibility:hidden ——
   空间照占、位置留白，视觉上只是 hero 与公告之间多一点留白（宣纸页本来就该有留白）。
   科技皮肤（暗页）照常显示，那里它才是对的。 */
html[data-skin="paper"] .fx-status { visibility: hidden; }
html[data-skin="cyber"] .fx-status {
  background: var(--fx-ink-bg);
  border-color: var(--fx-jade-soft);
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  color: var(--ink-soft);
}
html[data-skin="cyber"] .fx-status b {
  background: var(--fx-jade);
  box-shadow: 0 0 9px var(--fx-jade-glow);
}
@keyframes fx-pulse { 0%, 100% { opacity: .4; } 50% { opacity: 1; } }
/* 状态行要占满一行（.brand 里其它都是块级居中），否则会跟副标题挤在一行 */
html[data-skin="cyber"] .brand,
html[data-skin="paper"] .brand { text-align: center; }
/* 按屏宽逐级藏掉半句 —— 上一版只藏了最后半句，主文案里"溪雨 · 系统在线 · 今日承接 0/20 单"
   加起来还是超出 268px，被 overflow:hidden 从中间截断（总控师截图里看到的"9月1"就是这么来的）。 */
@media (max-width: 900px) {
  .fx-status .fx-status-sub { display: none; }
}
@media (max-width: 560px) {
  .fx-status .fx-brand { display: none; }
  .fx-status { font-size: 10.5px; letter-spacing: .04em; }
}

/* ---- 8. 文字与数字：等宽 + 微光（"仪器读数"的质感） -------------------
   ⚠️ 注意：**公告块里的数字不用等宽**。等宽字比正文宽，会把那一行挤到折行，
   于是科技皮肤的公告块比宣纸的高 4px —— 这正是总控师说的"布局有轻微差距"。
   等宽只留在状态行与订单时间这些"纯数字且独占一行"的地方。 */
html[data-skin="cyber"] .ho-list .status-pill,
html[data-skin="cyber"] .order-table .td-time {
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  letter-spacing: .02em;
}
html[data-skin="cyber"] .notice-live b {
  color: var(--fx-jade);
  text-shadow: 0 0 14px var(--fx-jade-soft);
}
html[data-skin="cyber"] .brand .creed > .creed-word > i { color: var(--fx-jade); text-shadow: 0 0 10px var(--fx-jade-soft); }
html[data-skin="cyber"] .brand .tip { color: var(--ink-soft); }

/* 副标题后挂一个脉冲光标（终端/投影机在待机的感觉）—— 极克制，2.6s 一次 */
html[data-skin="cyber"] .brand .subtitle::after {
  content: '';
  display: inline-block;
  width: .5em; height: 1em;
  margin-left: .18em;
  vertical-align: -.14em;
  background: var(--fx-jade);
  box-shadow: 0 0 10px var(--fx-jade-glow);
  animation: fx-caret 2.6s steps(1, end) infinite;
}
@keyframes fx-caret {
  0%, 46%  { opacity: .9; }
  47%, 100% { opacity: 0; }
}

/* ---- 9. 卡片与面板：全息边缘（边框比中心亮 —— 投影的边缘才聚光） ------- */
html[data-skin="cyber"] .home-card {
  background: linear-gradient(180deg, var(--fx-panel-1), var(--fx-panel-2));
  border: 1px solid var(--fx-jade-soft);
  box-shadow:
    inset 0 1px 0 rgba(233, 244, 244, .07),
    0 0 0 1px rgba(0, 0, 0, .35),
    0 8px 26px rgba(0, 0, 0, .35);
  position: relative;
  overflow: hidden;
}
/* hover 时一道扫描光带从卡片上掠过（一次，不是常驻闪烁） */
html[data-skin="cyber"] .home-card::before {
  content: '';
  position: absolute;
  left: -60%; top: 0;
  width: 45%; height: 100%;
  pointer-events: none;
  background: linear-gradient(100deg, transparent, var(--fx-jade-soft), transparent);
  opacity: 0;
  transform: skewX(-12deg);
}
@media (hover: hover) {
  html[data-skin="cyber"] .home-card:hover::before {
    animation: fx-card-sweep .95s ease-out;
  }
}
@keyframes fx-card-sweep {
  0%   { left: -60%; opacity: 0; }
  18%  { opacity: 1; }
  100% { left: 122%; opacity: 0; }
}
html[data-skin="cyber"] .home-card:hover {
  background: linear-gradient(180deg, var(--fx-panel-h1), var(--fx-panel-h2));
  border-color: var(--fx-jade-glow);
  box-shadow:
    inset 0 1px 0 rgba(233, 244, 244, .11),
    0 0 26px rgba(99, 220, 198, .13),
    0 12px 30px rgba(0, 0, 0, .5);
}
html[data-skin="cyber"] .home-card .hc-price { color: var(--fx-jade); text-shadow: 0 0 16px var(--fx-jade-soft); }
html[data-skin="cyber"] .home-card .hc-price.tidy-leads,
html[data-skin="cyber"] .home-card .hc-price.tidy-leads b { text-shadow: none; }
html[data-skin="cyber"] .home-card .hc-price.tidy-leads b { color: var(--fx-jade); }
html[data-skin="cyber"] .home-card .hc-arrow {
  color: var(--fx-jade);
  border-color: var(--fx-jade-line);
  background: rgba(99, 220, 198, .05);
}
html[data-skin="cyber"] .home-card:hover .hc-arrow { color: var(--paper); background: var(--fx-jade); border-color: var(--fx-jade); }
html[data-skin="cyber"] .home-card .hc-icon { color: var(--fx-jade); }

/* 服务公告：像一块仪表面板 */
html[data-skin="cyber"] .notice {
  background: linear-gradient(180deg, var(--fx-panel-1), var(--fx-panel-2));
  border: 1px solid var(--fx-jade-soft);
  box-shadow: inset 0 1px 0 rgba(233, 244, 244, .06), 0 6px 20px rgba(0, 0, 0, .3);
}
html[data-skin="cyber"] .notice-head { border-bottom-color: var(--fx-jade-line); color: var(--fx-ice); }
html[data-skin="cyber"] .notice-head .ico { color: var(--fx-jade); }
html[data-skin="cyber"] .notice-list li::before { background: var(--fx-jade-line); }
html[data-skin="cyber"] .notice-live::before { background: var(--fx-jade); box-shadow: 0 0 8px var(--fx-jade-glow); }

/* 面板 / 弹窗 / 表格：跟着换底，但保持"纸"的克制（不加发光） */
html[data-skin="cyber"] .modal {
  background: var(--card);
  border: 1px solid var(--fx-jade-line);
  box-shadow: 0 22px 60px rgba(0, 0, 0, .65), 0 0 40px rgba(99, 220, 198, .05);
}
html[data-skin="cyber"] .modal-mask { background: var(--fx-mask); -webkit-backdrop-filter: saturate(.9); backdrop-filter: saturate(.9); }
html[data-skin="cyber"] .table-card,
html[data-skin="cyber"] .profile-nav,
html[data-skin="cyber"] .list-view .table-wrap { border-color: var(--fx-jade-soft); }
html[data-skin="cyber"] .order-table th { color: var(--fx-jade); border-bottom-color: var(--fx-jade-line); }
html[data-skin="cyber"] .order-table tbody tr.row-unpaid td { background: rgba(224, 85, 74, .07); }
html[data-skin="cyber"] .order-table tbody tr.row-unpaid td:first-child { box-shadow: inset 2px 0 0 var(--vermilion); }

/* 输入框：聚焦时是一道青光（原来是朱砂光晕） */
html[data-skin="cyber"] .name-input:focus,
html[data-skin="cyber"] textarea.req-input:focus,
html[data-skin="cyber"] .form-row input:focus {
  border-color: var(--fx-jade-glow);
  box-shadow: 0 0 0 3px rgba(99, 220, 198, .12), 0 0 18px rgba(99, 220, 198, .08);
}

/* 主按钮：全息边缘 + hover 时的极轻色差（2px，克制） */
html[data-skin="cyber"] .submit-btn,
html[data-skin="cyber"] .login-btn {
  background: linear-gradient(180deg, var(--vermilion), var(--vermilion-d));
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .3), 0 6px 20px rgba(224, 85, 74, .18);
}
@media (hover: hover) {
  html[data-skin="cyber"] .submit-btn:hover,
  html[data-skin="cyber"] .login-btn:hover {
    box-shadow:
      -2px 0 0 rgba(99, 220, 198, .35),
      2px 0 0 rgba(224, 85, 74, .35),
      0 8px 26px rgba(224, 85, 74, .26);
  }
}

/* 提示条：深色下改成"投影通告"（原实现是米白底墨字，在冷墨底上太跳） */
html[data-skin="cyber"] .toast {
  background: var(--fx-ink-solid);
  color: var(--fx-ice);
  border: 1px solid var(--fx-jade-line);
  box-shadow: 0 0 24px rgba(99, 220, 198, .12);
}
/* 付款说明条：原来是硬编码的暖黄（#FEF3C7/#B45309），在冷墨底上像贴了张便签。
   深色下改成冷底 + 玉青竖线 —— 它是"流程说明"，不是警告。 */
html[data-skin="cyber"] .pay-note {
  background: var(--vermilion-l);
  color: var(--ink-sub);
  border-left: 3px solid var(--fx-jade);
  padding-left: 10px;
}
/* 控制台的大按钮：纯朱砂实心块在冷墨底上太重，给它一层"投影"质感（同主按钮） */
html[data-skin="cyber"] .ctrl-btn.primary {
  background: linear-gradient(180deg, var(--vermilion), var(--vermilion-d));
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .35), 0 5px 18px rgba(224, 85, 74, .20);
}
html[data-skin="cyber"] .ctrl-btn.primary:hover {
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .35), 0 7px 24px rgba(224, 85, 74, .30);
}

/* ---- 10. HUD 角标：四角细线（"这台仪器在运行"的暗示，极淡） ----------- */
html[data-skin="cyber"] .fx-hud {
  position: fixed;
  inset: 12px;
  z-index: 3;
  pointer-events: none;
}
.fx-hud { display: none; }          /* 浅色下不渲染（理由同 .fx-sweep） */
html[data-skin="cyber"] .fx-hud { display: block; }
html[data-skin="cyber"] .fx-hud i {
  position: absolute;
  width: 18px; height: 18px;
  border: 1px solid rgba(99, 220, 198, .42);
  opacity: 1;
}
html[data-skin="cyber"] .fx-hud i:nth-child(1) { left: 0; top: 0; border-right: 0; border-bottom: 0; }
html[data-skin="cyber"] .fx-hud i:nth-child(2) { right: 0; top: 0; border-left: 0; border-bottom: 0; }
html[data-skin="cyber"] .fx-hud i:nth-child(3) { left: 0; bottom: 0; border-right: 0; border-top: 0; }
html[data-skin="cyber"] .fx-hud i:nth-child(4) { right: 0; bottom: 0; border-left: 0; border-top: 0; }

/* ---- 11. 深色下的既有细节：清掉暖色残留 --------------------------------- */
/* 深色原本是"暖墨 + 米白"，换成冷玉青之后，几处写死的暖色要跟着走 */
/* 档位回显条：底色已随 --vermilion-l 转冷，左边那道竖线改玉青 ——
   "系统状态"用青、"钱与行动"用朱砂，两色分工在全站保持一致 */
html[data-skin="cyber"] .tier-echo {
  background: var(--vermilion-l);
  border: 1px solid var(--fx-jade-line);
  border-left: 3px solid var(--fx-jade);
}
html[data-skin="cyber"] .tier-echo .echo-text { color: var(--fx-ice); }
html[data-skin="cyber"] .tier-echo .echo-text b { color: var(--fx-jade); }
html[data-skin="cyber"] .file-chip { color: var(--ink-sub); border-color: var(--border); }
html[data-skin="cyber"] .home-card .hc-desc { color: var(--ink-soft); }
html[data-skin="cyber"] .home-hint,
html[data-skin="cyber"] .tier-foot,
html[data-skin="cyber"] .fb-hint,
html[data-skin="cyber"] .upload-hint { color: var(--ink-faint); }
html[data-skin="cyber"] .tier-card { background: var(--fx-panel-1); border-color: var(--fx-jade-soft); }
html[data-skin="cyber"] .tier-card:hover { border-color: var(--fx-jade-glow); background: var(--fx-panel-h1); }
html[data-skin="cyber"] .template-card { background: var(--fx-panel-1); border-color: var(--fx-jade-soft); }
html[data-skin="cyber"] .template-card.on { border-color: var(--fx-jade-glow); box-shadow: 0 0 0 2px var(--fx-jade-soft); }
html[data-skin="cyber"] .preset-chip { border-color: var(--fx-jade-soft); }
html[data-skin="cyber"] .preset-chip.on { background: var(--fx-jade-soft); border-color: var(--fx-jade-glow); color: var(--fx-ice); }
html[data-skin="cyber"] .upload-doc,
html[data-skin="cyber"] .upload-zone { border-color: var(--fx-jade-soft); background: var(--fx-ink-bg); }
html[data-skin="cyber"] .urgent-row { border-color: var(--warn-line); }
html[data-skin="cyber"] .tidy-plan { border-color: var(--fx-jade-soft); background: var(--fx-panel-1); }
html[data-skin="cyber"] .tidy-plan.on { border-color: var(--fx-jade-glow); }
html[data-skin="cyber"] .z-footer { background: rgba(8, 11, 14, .92) !important; border-top-color: var(--fx-jade-soft) !important; }

/* 右上角那组按钮：原来 position:fixed，会一直浮在屏幕右上角挡住内容
   —— 总控师 2026-09-17 第 5 条。改成随页面滚动的绝对定位："固定在页面上"，而不是"固定在屏幕上"。 */
.user-zone { position: absolute; }

/* 窄屏再收一步：竖排会往下伸、压到 logo 右侧（截图实测重叠 60 多像素）。
   手机上是横排一行贴在页顶，让开 hero。 */
@media (max-width: 640px) {
  .user-zone {
    flex-direction: row;
    align-items: center;
    gap: 8px;
    top: 10px;
    right: 12px;
  }
}

/* ==========================================================================
   13 · logo 里那片波纹的流动（2026-09-17 第三次修正 · 看懂了）
   --------------------------------------------------------------------------
   前两次我都做错了，错在"没看清图里有什么"：
     · 第一次：以为波纹在字的下半部 → 用整块下半部做 mask，亮纹盖到了字上
     · 第二次：按行数像素（字与波纹在 y 上是重叠的）→ 误判"图里没有波纹"，
              于是在 logo 外面另画了一条线
   放大看过才明白：**波纹确实在** —— 在字的下方，而且从字的笔画之间穿过。
   所以正解是：从**原图里把那片波纹抠出来**（形态学：纵向薄 + 横向长 + 连通域是长条），
   只在这些波纹线条上放流动的光。字一个像素都不碰。

     · 宣纸皮肤：一道温润的水光缓缓流过波纹 —— 像溪水在流
     · 科技皮肤：一截亮脉冲沿线跑（带辉光）—— 像通了电
   ========================================================================== */

.fx-wave {
  position: absolute;
  left: 50%; top: 0;
  transform: translateX(-50%);
  height: 100%;
  aspect-ratio: 768 / 411;
  z-index: 4;
  pointer-events: none;
  overflow: hidden;
  /* 遮罩原图是 768×411 RGBA PNG（186KB）—— 它只是**透明度**在用，
     转成无损 WebP 后 7KB（解码后逐像素一致，实测 difference bbox = None），
     首访直接省掉 179KB。图不会破：图在就有效果，图丢了只是这道光不出现。 */
  -webkit-mask-image: url("/assets/brand/logo-wave.webp");
  mask-image: url("/assets/brand/logo-wave.webp");
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;          /* mask 与原图同尺寸(768×411)，直接铺满即严丝合缝 */
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
.fx-wave > i {
  position: absolute;
  top: 0; left: -70%;
  width: 60%; height: 100%;
  display: block;
}

html[data-skin="paper"] .fx-wave > i {
  background: linear-gradient(92deg,
    transparent,
    rgba(255, 255, 255, .92) 44%,
    rgba(244, 232, 214, .96) 58%,
    transparent);
  filter: blur(2px);
  animation: fx-wave-flow 7.5s cubic-bezier(.45, .05, .55, .95) infinite;
}
@keyframes fx-wave-flow {
  0%   { transform: translate3d(0, 0, 0); opacity: 0; }
  10%  { opacity: 1; }
  90%  { opacity: 1; }
  100% { transform: translate3d(290%, 0, 0); opacity: 0; }
}

html[data-skin="cyber"] .fx-wave > i {
  width: 30%;
  background: linear-gradient(90deg,
    transparent,
    var(--fx-jade) 42%,
    #EAFBFF 52%,
    var(--fx-jade) 62%,
    transparent);
  box-shadow: 0 0 14px var(--fx-jade-glow);
  animation: fx-wave-current 2.3s linear infinite;
}
@keyframes fx-wave-current {
  0%   { transform: translate3d(0, 0, 0); opacity: 0; }
  6%   { opacity: 1; }
  94%  { opacity: 1; }
  100% { transform: translate3d(560%, 0, 0); opacity: 0; }
}

/* ==========================================================================
   14 · 明暗切换：从 logo 那里"揭幕"（2026-09-17 第二次重做）
   --------------------------------------------------------------------------
   总控师："暗页切明页的时候那个过场是覆盖的，我不太喜欢，
            我想要那种随着那个图案出现或者消失，明页一点点出来的那种感觉"

   所以不再用"一整块东西盖过去"（书卷 / 方粒），改成**揭幕**：
   一层「旧皮肤颜色」的幕布先盖满全屏，然后**从 logo 所在的位置**开始收拢成一个小圆 ——
   新皮肤就像从 logo 里一点点漫出来。是"揭"不是"盖"。
   揭幕圆心由 JS 按 logo 实际位置写进 --fx-rx / --fx-ry，幕布颜色写进 --fx-veil-bg。
   ========================================================================== */

/* ⚠️ 默认必须**完全不显示**：这层幕布没有动画时就是一块盖满全屏的纯色。
   上一版忘了这一步 —— 过场结束我把 class 重置，动画一撤，幕布立刻回到"盖满屏"，
   整个页面的内容就被它挡死了（总控师两张截图里的"空白页 / 内容不见"就是这个）。 */
.fx-trans { display: none; }
.fx-trans.reveal { display: block; }

.fx-veil2 {
  position: absolute;
  inset: 0;
  background: var(--fx-veil-bg, #F6F1E7);
  will-change: clip-path;
}
.fx-trans.reveal .fx-veil2 {
  animation: fx-reveal 1.25s cubic-bezier(.55, 0, .25, 1) forwards;
}
@keyframes fx-reveal {
  from { clip-path: circle(170% at var(--fx-rx, 50%) var(--fx-ry, 16%)); }
  to   { clip-path: circle(0% at var(--fx-rx, 50%) var(--fx-ry, 16%)); }
}

/* 减少动态效果时：过场直接不播（皮肤照切，只是没有过程动画） */
@media (prefers-reduced-motion: reduce) {
  .fx-trans, .fx-trans > * { display: none !important; }
}

/* ==========================================================================
   15 · 两套皮肤各自的设计语言（2026-09-17 · 总控师第 1、4 条）
   --------------------------------------------------------------------------
   总控师："科技明页给我一种就是宣纸明页加了滤镜的感觉，感觉非常敷衍"
            "虽然都是溪雨的页面、都是一个布局，但仍然需要好好设计，而不是简单换皮"

   他说到根上了：上一版我只是把颜色变量换了一遍 —— 结构、圆角、字体、分隔方式全没动，
   那不叫两种皮肤，那叫滤镜。这一节给科技皮肤**结构层面**的差异化：

     科技（数据面板 / 工程图）      宣纸（纸与墨 / 文人）
     ─────────────────────────      ─────────────────────
     卡片切角（clip-path 斜切）      卡片圆角（纸的柔和）
     直角按钮（2px）                圆角按钮（999px 胶囊）
     等宽字 + 字母间距（读数）       衬线字 + 宽字距（题识）
     收尾线是带刻度的标尺            收尾线只是一道细线
     网格基底                        纸纹基底

   关键：这些差异全在"形状与字体"上，**不占布局** —— 所以四套皮肤的元素几何仍然一致。
   ========================================================================== */

/* ---- 科技：卡片与面板 = 数据面板（切角 + 直角） ---- */
html[data-skin="cyber"] .home-card,
html[data-skin="cyber"] .notice,
html[data-skin="cyber"] .tier-card,
html[data-skin="cyber"] .template-card,
html[data-skin="cyber"] .table-card,
html[data-skin="cyber"] .profile-nav {
  border-radius: 0;
  clip-path: polygon(0 0, calc(100% - 15px) 0, 100% 15px, 100% 100%, 0 100%);
}
/* 按钮与胶囊一律方角 */
html[data-skin="cyber"] .home-card .hc-arrow,
html[data-skin="cyber"] .back-link,
html[data-skin="cyber"] .submit-btn,
html[data-skin="cyber"] .login-btn,
html[data-skin="cyber"] .mini-btn,
html[data-skin="cyber"] .ctrl-btn,
html[data-skin="cyber"] .preset-chip,
html[data-skin="cyber"] .user-chip,
html[data-skin="cyber"] .status-pill,
html[data-skin="cyber"] .code-btn,
html[data-skin="cyber"] .add-file-btn,
html[data-skin="cyber"] .theme-toggle,
html[data-skin="cyber"] .round-btn {
  border-radius: 2px;
}
html[data-skin="cyber"] .modal { border-radius: 0; }
/* 科技页的"读数"文字：等宽 + 字母间距。
   ⚠️ 只替换**不会改变父级折行**的元素 —— 价格、箭头、状态徽标。
   教训：上一版把公告标题、卡片名、各种 hint 也换成等宽，等宽字更宽 →
   卡片高 1px、公告块高 1px、hero 高 3px，四套皮肤的几何立刻不一致（实测抓到的）。 */
html[data-skin="cyber"] .home-card .hc-price,
html[data-skin="cyber"] .home-card .hc-arrow,
html[data-skin="cyber"] .status-pill {
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  letter-spacing: .04em;
}
/* 收尾线：科技页是一条带刻度的标尺（宽度变了，高度不变 → 不影响布局） */
html[data-skin="cyber"] .brand::after {
  width: 170px;
  background: repeating-linear-gradient(90deg, var(--fx-jade-line) 0 1px, transparent 1px 9px);
  box-shadow: 0 0 0 1px var(--fx-jade-soft);
}
html[data-skin="cyber"] .brand .creed { letter-spacing: .22em; }

/* ---- 宣纸：把这些"工程味"明确挡回去（并给纸一点重量） ---- */
html[data-skin="paper"] .brand::after { width: 56px; }
html[data-skin="paper"] .home-card,
html[data-skin="paper"] .notice { border-radius: var(--radius, 10px); }
@media (prefers-reduced-motion: reduce) {
  html.fx-js .brand-logo,
  html.fx-js .brand-row::after,
  html.fx-js .brand .creed > .creed-word,
  html.fx-js .brand .subtitle,
  html.fx-js .brand .tip,
  html.fx-js .brand::after,
  .fx-sweep > i,
  html[data-skin="cyber"] body::before,
  html[data-skin="cyber"] body::after,
  html[data-skin="cyber"] .brand-row::before,
  html[data-skin="cyber"] .brand .subtitle::after,
  html[data-skin="cyber"] .home-card::before {
    animation: none !important;
  }
  .fx-card, .fx-notice, .fx-rise, .fx-title { opacity: 1 !important; transform: none !important; }
  .fx-card::after, .fx-title::before { transform: none !important; }
  html[data-theme="dark"] .brand .subtitle::after { display: none; }
  #fxDust { display: none; }
  html[data-skin="paper"] body::after { animation: none !important; }
  .fx-cloud { animation: none !important; }
}