/* ==========================================================================
   PPT 智能生成助手 — 共享样式
   三屏共用一套 token 与外壳，改这里就是三屏一起改。

   视觉方向：冷灰底 + 白卡 + 朱砂主色，全站无衬线。
   两条硬规矩：
   1. 中文界面不用衬线体做标题。Songti SC 只有 macOS 有，Windows 回落到
      SimSun，30px 的 SimSun 标题是整套界面最显廉价的地方。字重和字号
      拉层级，不靠换字族。
   2. 主色只给主操作。以前主按钮是黑的、朱砂只出现在 11px 小字里，
      所以整体没有品牌感。
   ========================================================================== */

/* ---------- 1. token ---------- */
:root{
  /* 墨色阶。12–13px 的说明文字全用 --ink-4，所以它必须两种底都过 AA：
     #666D77 对白底 5.22:1，对 --field 冷灰底 4.83:1。
     选色时按 --field 算，不能只按白底算——右栏和页脚都是灰底，
     只按白底挑的灰放到灰底上就掉到 4.3 不合格了。
     --ink-5 只给占位符和禁用态，不承载信息。 */
  --ink:#14161A; --ink-2:#3A4149; --ink-3:#575E68; --ink-4:#666D77; --ink-5:#A3AAB4;

  /* 描边 1px，不用 0.5px——半像素在不同缩放下时粗时细，还发灰。 */
  --line:#E3E6EA; --line-2:#EDEFF2;

  /* 三个面：页底冷灰 → 白卡 → 冷灰输入框。层级靠明度差 + 投影，不靠边框堆叠。 */
  --paper:#F0F1F4; --card:#FFFFFF; --field:#F5F6F8;

  /* 朱砂＝主色，给主按钮、当前步骤、焦点环。5.10:1，白字压得住。 */
  --cinnabar:#C8372B; --cinnabar-d:#A82A20; --cinnabar-l:#FDF2F1; --cinnabar-b:#F2D5D1;
  /* 玉色＝成功态。原 #3E8F6F 在白底只有 3.2:1，压到 #12805C 拿到 4.92:1。 */
  --jade:#12805C; --jade-l:#F0F9F5; --jade-b:#C7E5D8;

  /* 一套无衬线走全场。Windows 落 Segoe UI + 微软雅黑 UI，macOS 落苹方。 */
  --sans:-apple-system,BlinkMacSystemFont,'Segoe UI Variable Text','Segoe UI',
         'PingFang SC','Hiragino Sans GB','Microsoft YaHei UI','Microsoft YaHei',sans-serif;
  /* 制作码、倒计时、页码用等宽，等宽数字对齐才不跳。 */
  --mono:ui-monospace,'SF Mono','Cascadia Mono',Consolas,Menlo,monospace;

  /* 间距刻度。所有留白都从这里取，不要再写零散数值。
     --s8 是卡片之间的距离：卡与卡的间隙必须明显大于卡内部的最大间隙，
     不然两张卡看着就像一张卡里的两段，层级立刻塌掉。 */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:22px; --s6:30px; --s7:44px; --s8:20px;

  /* 字号刻度。中文界面 12px 是下限，再小就糊。 */
  --f-micro:12px; --f-small:13px; --f-body:14px; --f-lead:15px; --f-title:17px;
  /* 标题靠字号 + 字重 + 收紧字距，不换字族。 */
  --f-h3:20px; --f-h1:34px;

  /* 中文正文行距给足，密排最容易显得憋。 */
  --lh-tight:1.5; --lh-body:1.75; --lh-loose:1.9;

  /* 圆角与投影 */
  --r-lg:12px; --r-md:8px; --r-sm:5px;
  --sh-card:0 1px 2px rgba(16,18,22,.05), 0 12px 32px -16px rgba(16,18,22,.16);
  --sh-btn:0 1px 2px rgba(16,18,22,.08);
  --sh-brand:0 2px 10px -3px rgba(200,55,43,.42);

  /* 舞台宽度。--stage 是上限不是死值，窄窗口按 100% 收。 */
  --stage:1240px; --rail:312px;
}

/* ---------- 2. base ---------- */
*{box-sizing:border-box}
body{
  margin:0;padding:var(--s7) var(--s6);background:var(--paper);
  font-family:var(--sans);font-size:var(--f-body);color:var(--ink);
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  min-width:0;
}
p{margin:0}
button{font:inherit;color:inherit;background:none;border:0;padding:0;margin:0;cursor:pointer;text-align:inherit}
button:disabled{cursor:not-allowed}
input,textarea,select{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--cinnabar);outline-offset:2px;border-radius:2px}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
[hidden]{display:none !important}

/* 页底 → 白卡。
   以前整页是一张大白卡（.shell）把所有东西包在里面，所有内容平铺在同一个面上，
   全靠标题文字分段——这就是「层级感不强」的根因：没有一处物理边界告诉眼睛
   「这里是一件事，那里是另一件事」。
   现在改成：外壳只管页头 + 步骤条（导航），内容拆成一叠独立的卡，
   卡与卡之间留 --s8 的空隙让页底灰透出来。层级靠「卡的边界」，不靠标题。 */
.stage{max-width:var(--stage);margin:0 auto}
.frame{padding:0;background:none}
/* 导航壳：页头和步骤条。圆角只留上面两个，下面接着内容卡。 */
.shell{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
       overflow:hidden;box-shadow:var(--sh-card)}

/* 内容卡。屏 1 的每一段、屏 2/3 的每一块都是一张。 */
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
      box-shadow:var(--sh-card);padding:var(--s6);margin-top:var(--s8)}
.card.tight{padding:var(--s5) var(--s6)}
/* 第一张卡的上缝已经由 .body 的 margin-top 给了，这里不能再加一份——
   否则外壳到第一张卡是 40px，而右栏是 20px，两列顶不齐。 */
.main>.card:first-child{margin-top:0}

/* ---------- 3. topbar ---------- */
/* 页头右边只放制作码，一个信号。
   之前这里并排三样：制作码 + 「服务可用」绿点 + 「换个制作码」链接。
   问题不是每一样都没用，是它们抢同一个位置——「服务可用」是常态，
   常态不需要一直报告；「换个制作码」是低频操作，不配站在页头。
   服务不可用时会出横幅（checkHealth 里 U.banner），异常照样看得到，
   所以撤掉那个绿点不丢信息。换码入口挪到码本身：点制作码就能换。 */
.topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--s5);
        padding:var(--s4) var(--s6);background:var(--card);border-bottom:1px solid var(--line)}
.brand{display:flex;align-items:baseline;gap:var(--s3);min-width:0}
.brand-n{font-size:var(--f-title);font-weight:600;color:var(--ink);letter-spacing:-.01em;white-space:nowrap}
.brand-s{font-size:var(--f-micro);color:var(--ink-4);white-space:nowrap}
.topbar-r{display:flex;align-items:center;gap:var(--s4)}
/* 服务状态不再常驻页头，但 checkHealth 还要往这里写状态给读屏用 */
.svc{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}

/* 制作码常驻。这是付过钱的凭证，一个码一份 PPT，换设备也靠它——
   所以它一直摆在最显眼的地方，没有码的时候也占着位子并且可以点。 */
.code-chip{display:inline-flex;align-items:center;gap:var(--s2);
           background:var(--field);border:1px solid var(--line);border-radius:var(--r-md);
           padding:5px var(--s2) 5px var(--s3);transition:border-color .14s,background .14s}
.code-chip-k{font-size:var(--f-micro);color:var(--ink-4);white-space:nowrap}
.code-v{font-family:var(--mono);font-size:var(--f-small);color:var(--ink);
        letter-spacing:.08em;font-variant-numeric:tabular-nums;white-space:nowrap}
.code-chip button{display:flex;align-items:center;padding:2px;border-radius:3px}
.code-chip i{font-size:15px;color:var(--ink-4);transition:color .14s}
.code-chip button:hover i{color:var(--ink)}
/* 填了码之后整条也可点＝换个码。hover 才提示，不常态占视觉。 */
.code-chip.can{cursor:pointer}
.code-chip.can:hover{border-color:var(--ink-5);background:var(--card)}
/* 还没填码：朱砂描边 + 整条可点，直接开兑换栏 */
.code-chip.empty{background:var(--cinnabar-l);border-color:var(--cinnabar-b);cursor:pointer}
.code-chip.empty .code-v{color:var(--cinnabar-d);letter-spacing:0;font-family:var(--sans)}
.code-chip.empty .code-chip-k{color:var(--cinnabar-d);opacity:.75}
.code-chip.empty:hover{border-color:var(--cinnabar)}

/* ---------- 4. stepper（三屏完全一致） ---------- */
/* 数字要看得清：圆点从 22px 提到 30px，字号从 12 提到 15，等宽加粗。
   之前 22px 的圆点里塞 12px 数字，等于没有数字——用户第一条抱怨就是这个。 */
.stepper{display:flex;align-items:center;justify-content:center;gap:0;padding:0 var(--s5);
         height:74px;background:var(--card);border-bottom:1px solid var(--line)}
/* 还没走到的步骤用 --ink-4 不用 --ink-5：「生成中」「下载」是步骤名，
   是信息不是禁用控件，得看得清。层级靠当前步的加粗和朱砂圆点拉开。 */
.step{display:flex;align-items:center;gap:var(--s3);font-size:var(--f-body);
      color:var(--ink-4);flex-shrink:0;white-space:nowrap}
.step-n{width:30px;height:30px;border-radius:50%;border:1.5px solid var(--line);
        display:flex;align-items:center;justify-content:center;font-size:var(--f-lead);
        font-family:var(--mono);font-weight:600;color:var(--ink-4);flex-shrink:0;background:var(--card)}
.step.now{color:var(--ink);font-weight:600}
.step.now .step-n{background:var(--cinnabar);border-color:var(--cinnabar);color:#fff;
                  box-shadow:0 0 0 4px var(--cinnabar-l)}
.step.done{color:var(--ink-3)}
.step.done .step-n{background:var(--cinnabar);border-color:var(--cinnabar);color:#fff}
.rule{width:76px;height:2px;background:var(--line-2);margin:0 var(--s5);flex-shrink:0;border-radius:1px}
.rule.done{background:var(--cinnabar-b)}

/* 制作码 / 找回订单：屏 1 内联展开的一条，不是单独页面。
   还在外壳里（紧贴步骤条下面），因为它是「进这一单」的前置动作，不是内容。 */
.redeem{background:var(--field);border-top:1px solid var(--line)}
.redeem-in{padding:var(--s5) var(--s6)}
.redeem-h{font-size:var(--f-small);color:var(--ink-2);margin:0 0 var(--s3);font-weight:600}
.redeem-row{display:flex;gap:var(--s2);max-width:640px}
.redeem-i{flex:1;border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s3) var(--s4);
          font-size:var(--f-small);color:var(--ink);min-width:0;background:var(--card);
          font-family:var(--mono);transition:border-color .14s,box-shadow .14s}
.redeem-i::placeholder{color:var(--ink-5);font-family:var(--sans)}
.redeem-i:focus{outline:none;border-color:var(--cinnabar);box-shadow:0 0 0 3px var(--cinnabar-l)}
.redeem-b{border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s3) var(--s5);
          flex-shrink:0;background:var(--card);box-shadow:var(--sh-btn);transition:border-color .14s,background .14s}
.redeem-b span{font-size:var(--f-small);color:var(--ink-2);font-weight:500}
.redeem-b:hover{border-color:var(--ink-5);background:var(--field)}
.redeem-b:disabled{box-shadow:none}
.redeem-b:disabled span{color:var(--ink-5)}
.redeem-n{font-size:var(--f-micro);color:var(--ink-4);margin:var(--s3) 0 0;line-height:var(--lh-body);max-width:640px}
.redeem-n.ok{color:var(--jade)}
.redeem-n.bad{color:var(--cinnabar-d)}

/* ---------- 5. body + 常驻右栏 ---------- */
/* 左右两栏不再是同一张卡里的两半，各自成卡，中间留缝。 */
.body{display:grid;grid-template-columns:minmax(0,1fr) var(--rail);
      gap:var(--s8);align-items:start;margin-top:var(--s8)}
.main{min-width:0}
.main.pad{padding:0}
/* 右栏：粘顶跟随，而且高度封在视口里。
   只写 position:sticky 是不够的——右栏内容能长到 877px，
   视口只有 800 出头，sticky 把顶端粘住之后底部就溢出到视口下面，
   提交按钮在往下滚的大半程里根本看不见（实测 5 个位置里 4 个看不见）。
   所以：max-height 封到视口，回显放进 .rail-scroll 自己滚，
   .rail-act 用 margin-top:auto 钉在底部。视口够高时 .rail-scroll
   撑不满，一切照旧，看不出区别。 */
.rail{position:sticky;top:var(--s8);display:flex;flex-direction:column;
      max-height:calc(100vh - var(--s8) * 2);
      background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
      box-shadow:var(--sh-card);padding:var(--s5)}
/* 只有真的装不下才滚，装得下就不出滚动条 */
.rail-scroll{min-height:0;overflow-y:auto;display:flex;flex-direction:column;
             scrollbar-width:thin}
/* 动作区永远在底部：上面有剩余空间就把它推到底，没有就紧跟着滚动区 */
.rail-act{margin-top:auto;flex-shrink:0;padding-top:var(--s5)}

/* 栏内小标题 */
.rail-h{font-size:var(--f-micro);color:var(--ink-4);margin:0 0 var(--s4);
        letter-spacing:.1em;font-weight:600}
.rail-h .opt{color:var(--ink-5);letter-spacing:0;font-weight:400}

/* 本单回显：换掉左键右值的两列表格。
   旧写法是 13 行 key 左 value 右，中间挤出一条锯齿状的空白河，
   每行权重还一样重——用户说「太影响观感」指的就是这个。
   新写法：标签做小号说明压在上面，值在下面用正文级字号顶格左对齐。
   两边都左对齐，河没了；值比标签大一号，一眼扫过去先看到「选了什么」。 */
.spec{display:flex;flex-direction:column;gap:var(--s4)}
.kv{display:flex;flex-direction:column;gap:2px;min-width:0}
.k{font-size:var(--f-micro);color:var(--ink-4);letter-spacing:.02em}
.v{font-size:var(--f-body);color:var(--ink);min-width:0;line-height:var(--lh-tight);
   font-weight:500;overflow-wrap:anywhere}
.v.mono{font-family:var(--mono);font-variant-numeric:tabular-nums;letter-spacing:.06em}
/* 没选的值降一档＝不假装「已经填了」，但仍然是信息，得看得清。
   这里不能用 --ink-5：那是占位符和禁用态的灰，「未上传」是状态不是占位符，
   放白卡上只有 2.34:1。用 --ink-4，5.22:1 过 AA，靠字重和字号跟已填值区分。 */
.v.none{color:var(--ink-4);font-weight:400}

/* 思考等级是花钱买到的档位，不跟普通回显平级——单独做成一枚徽章顶在最上面 */
.tierbox{display:flex;align-items:center;gap:var(--s2);margin-bottom:var(--s5);
         background:var(--cinnabar-l);border:1px solid var(--cinnabar-b);
         border-radius:var(--r-md);padding:var(--s3) var(--s4)}
.tierbox i{font-size:16px;color:var(--cinnabar);flex-shrink:0}
.v.tier{font-size:var(--f-small);color:var(--cinnabar-d);font-weight:600;letter-spacing:.02em}

.rail-div{border-top:1px solid var(--line-2);margin:var(--s5) 0}
.rail-note{font-size:var(--f-micro);color:var(--ink-4);margin:var(--s3) 0 0;line-height:var(--lh-body)}
.rail-body{font-size:var(--f-small);color:var(--ink-2);margin:0;line-height:var(--lh-body)}
.autofill{display:flex;align-items:center;gap:var(--s1);font-size:var(--f-micro);color:var(--jade);
          margin:0 0 var(--s4)}
.autofill i{font-size:13px}

/* 「预计」从三行表格压成一句话。
   用时、出页、含几次生成——这三条是固定事实，不是用户的选择，
   却在旧版里跟「用途」「模板」并排占了三行同等分量。
   现在合成一段贴在提交按钮上方：该说的都在，占的地方少一半。 */
.est{background:var(--field);border:1px solid var(--line-2);border-radius:var(--r-md);
     padding:var(--s3) var(--s4);margin-bottom:var(--s4)}
.est p{font-size:var(--f-micro);color:var(--ink-3);margin:0;line-height:var(--lh-body)}
.est b{color:var(--ink);font-weight:600;font-variant-numeric:tabular-nums}

/* ---------- 6. 按钮 ---------- */
/* 主操作＝朱砂。以前是黑的，导致全站没有主色。 */
.btn-primary{display:block;width:100%;background:var(--cinnabar);border-radius:var(--r-md);
             padding:var(--s4) 0;text-align:center;box-shadow:var(--sh-brand);
             transition:background .14s,box-shadow .14s}
.btn-primary span{font-size:var(--f-lead);color:#fff;letter-spacing:.06em;font-weight:600}
.btn-primary:hover{background:var(--cinnabar-d);box-shadow:0 3px 14px -3px rgba(200,55,43,.5)}
.btn-primary:disabled{background:var(--ink-5);box-shadow:none}
.btn-primary:disabled span{color:#fff}
.btn-ghost{display:block;width:100%;border:1px solid var(--line);background:var(--card);
           border-radius:var(--r-md);padding:var(--s3) 0;text-align:center;transition:border-color .14s}
.btn-ghost span{font-size:var(--f-small);color:var(--ink-2);font-weight:500}
.btn-ghost:hover{border-color:var(--ink-5)}
.act{border:1px solid var(--line);background:var(--card);border-radius:var(--r-md);
     padding:var(--s3) var(--s5);box-shadow:var(--sh-btn);transition:border-color .14s,background .14s}
.act span{font-size:var(--f-small);color:var(--ink-2);font-weight:500}
.act:hover{border-color:var(--ink-5);background:var(--field)}
.act:disabled{box-shadow:none}
.act:disabled span{color:var(--ink-5)}
.btn-sub{font-size:var(--f-small);color:#fff;background:var(--ink);border-radius:var(--r-md);
         padding:var(--s3) var(--s5);flex-shrink:0;font-weight:500;transition:background .14s}
.btn-sub:hover{background:#000}
.btn-sub:disabled{background:var(--ink-5)}

/* ---------- 7. footer ---------- */
/* 页脚不再是卡里的一条，直接躺在页底灰上——它不是内容，不该占一张卡。 */
.footer{padding:var(--s5) var(--s2) 0}
.footer p{font-size:var(--f-micro);color:var(--ink-4);margin:0}

/* ---------- 8. 通知条 ---------- */
/* 横幅现在在外壳外面，自己是一张卡宽的条 */
.banner{display:flex;align-items:flex-start;gap:var(--s3);padding:var(--s4) var(--s5);
        margin-top:var(--s8);border:1px solid var(--cinnabar-b);border-radius:var(--r-md);
        background:var(--cinnabar-l)}
.banner i{font-size:16px;color:var(--cinnabar);flex-shrink:0;margin-top:1px}
.banner p{font-size:var(--f-small);color:var(--cinnabar-d);margin:0;line-height:var(--lh-body);flex:1}
.banner button{font-size:var(--f-micro);color:var(--cinnabar-d);text-decoration:underline;flex-shrink:0}
.banner.info{background:var(--card);border-color:var(--line)}
.banner.info i,.banner.info p,.banner.info button{color:var(--ink-3)}

.toast{position:fixed;left:50%;bottom:var(--s7);transform:translateX(-50%);background:var(--ink);
       color:#fff;font-size:var(--f-small);padding:var(--s3) var(--s5);border-radius:var(--r-md);
       z-index:50;box-shadow:0 6px 24px rgba(16,18,22,.28)}

/* ==========================================================================
   屏 1 · 填写需求
   ========================================================================== */
/* 段标题。
   之前我把段号删了，理由是「顶上已经有 1/2/3 进度条，两套编号会打架」。
   这个判断是错的：顶上的 1/2/3 是跨屏的大流程（填写→生成→下载），
   段号是这一屏里面的操作顺序，两者不是同一个尺度，用户要的是后者——
   一屏三件事，得让人知道先做哪件。
   为了不跟顶上的阿拉伯数字混，段号用带圈数字 + 朱砂，形态和位置都不一样。 */
.sec{display:flex;align-items:baseline;gap:var(--s3);font-size:var(--f-title);color:var(--ink);
     margin:0 0 var(--s5);font-weight:600;letter-spacing:-.01em}
.sec-n{display:flex;align-items:center;justify-content:center;flex-shrink:0;
       width:26px;height:26px;border-radius:50%;background:var(--cinnabar-l);
       border:1px solid var(--cinnabar-b);color:var(--cinnabar-d);
       font-family:var(--mono);font-size:var(--f-body);font-weight:700;
       align-self:center}
/* 段标题右边的补充说明（「42 套可选」这类），不参与层级 */
.sec i,.sec .sec-s{color:var(--ink-4);font-style:normal;font-weight:400;
                   font-size:var(--f-small);letter-spacing:0}
.sec .sec-s{margin-left:auto;text-align:right}
/* 卡内的次级小标题：没有编号，比 .sec 低一级 */
.sub{font-size:var(--f-small);color:var(--ink);margin:0 0 var(--s4);font-weight:600;letter-spacing:-.005em}
.sub i{color:var(--ink-4);font-style:normal;font-weight:400;font-size:var(--f-micro);margin-left:var(--s2)}

/* 用途 chip 现在是卡里最后一件东西，底部留白交给卡的 padding */
.chips{display:flex;flex-wrap:wrap;gap:var(--s2)}
.chip{font-size:var(--f-small);color:var(--ink-2);background:var(--card);border:1px solid var(--line);
      border-radius:var(--r-md);padding:var(--s3) var(--s5);transition:border-color .14s,background .14s,color .14s}
.chip:hover{border-color:var(--ink-5);background:var(--field)}
.chip.on{color:#fff;background:var(--ink);border-color:var(--ink);font-weight:500}

.two{display:grid;grid-template-columns:minmax(0,1.62fr) minmax(0,1fr);gap:var(--s4)}
.ta{background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s4);
    min-height:140px;display:flex;flex-direction:column;justify-content:space-between;transition:border-color .14s,box-shadow .14s}
.ta:focus-within{border-color:var(--cinnabar);box-shadow:0 0 0 3px var(--cinnabar-l)}
.ta textarea{width:100%;border:0;background:none;resize:none;font-size:var(--f-body);
             color:var(--ink);line-height:var(--lh-body);min-height:64px;padding:0}
.ta textarea::placeholder{color:var(--ink-5)}
.ta textarea:focus{outline:none}
.ta-f{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
      margin-top:var(--s4);padding-top:var(--s3);border-top:1px solid var(--line-2)}
.ta-h{font-size:var(--f-micro);color:var(--ink-4)}

.up{background:var(--field);border:1.5px dashed var(--line);border-radius:var(--r-md);padding:var(--s4);
    min-height:140px;display:flex;flex-direction:column;align-items:center;justify-content:center;
    text-align:center;transition:border-color .14s,background .14s}
.up:hover{border-color:var(--ink-5)}
.up.drag{border-color:var(--cinnabar);background:var(--cinnabar-l)}
.up-t{font-size:var(--f-small);color:var(--ink-2);margin:var(--s3) 0 var(--s1);font-weight:500}
.up-s{font-size:var(--f-micro);color:var(--ink-4);margin:0;line-height:var(--lh-body)}
.up.has{border-style:solid;border-color:var(--line);background:var(--card);align-items:stretch;
        justify-content:flex-start;text-align:left;gap:var(--s2);padding:var(--s4)}
.up-h{font-size:var(--f-micro);color:var(--ink-4);margin:0 0 var(--s1)}
.file{display:flex;align-items:center;gap:var(--s2)}
.file-n{font-size:var(--f-small);color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;
        white-space:nowrap;flex:1;min-width:0}
.file .rm{font-size:14px;color:var(--ink-5);flex-shrink:0;transition:color .14s}
.file .rm:hover{color:var(--cinnabar)}
.file.bad .file-n{color:var(--cinnabar-d)}
.up-add{margin-top:auto;font-size:var(--f-micro);color:var(--ink-4);border-top:1px dashed var(--line);
        padding-top:var(--s3);width:100%;text-align:left;transition:color .14s}
.up-add:hover{color:var(--ink-2)}

/* ---- 补全结果 ---- */
/* 左边一条朱砂：这是 AI 写的，需要你核一遍再放行。
   这块本身就是一张卡（.card），所以这里只加那条朱砂边和上下留白，
   不再重复画边框/圆角/投影——套两层框是上一版层级糊掉的原因之一。 */
.res{border-left:3px solid var(--cinnabar)}
.res-h{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s4);
       margin-bottom:var(--s5);padding-bottom:var(--s4);border-bottom:1px solid var(--line-2)}
.res-t{font-size:var(--f-small);color:var(--ink);margin:0;font-weight:600}
.res-s{font-size:var(--f-micro);color:var(--ink-4);margin:0}
.res-hr{flex-shrink:0;text-align:right}
.btn-wand{font-size:var(--f-small);color:var(--ink-2);border:1px solid var(--line);background:var(--card);
          border-radius:var(--r-md);padding:var(--s2) var(--s4);flex-shrink:0;font-weight:500;
          box-shadow:var(--sh-btn);transition:border-color .14s,background .14s,color .14s}
.btn-wand:hover{border-color:var(--cinnabar);color:var(--cinnabar-d);background:var(--cinnabar-l)}
.btn-wand:disabled{color:var(--ink-5);border-color:var(--line);background:var(--card);box-shadow:none}
.wand-note{font-size:var(--f-micro);color:var(--ink-4);margin:var(--s2) 0 0;text-align:right;line-height:var(--lh-tight)}

/* 一行一个字段。标签列给足宽度，别让「核心结论」四个字挤成两行 */
.row{display:grid;grid-template-columns:80px minmax(0,1fr);gap:var(--s4);align-items:start;margin-bottom:var(--s5)}
.row:last-child{margin-bottom:0}
.row-k{font-size:var(--f-small);color:var(--ink-4);padding-top:var(--s3)}
.row-k.tall{padding-top:var(--s2)}
.ed{border:1px solid var(--line);background:var(--field);border-radius:var(--r-md);padding:var(--s3) var(--s4);
    display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s3);transition:border-color .14s,background .14s,box-shadow .14s}
.ed:focus-within{border-color:var(--cinnabar);background:var(--card);box-shadow:0 0 0 3px var(--cinnabar-l)}
.ed-in{flex:1;min-width:0;border:0;background:none;font-size:var(--f-body);color:var(--ink);
       line-height:var(--lh-body);resize:none;overflow:hidden;padding:0}
.ed-in:focus{outline:none}
/* 核心结论是整页的论点，给它最大的字号和字重——但还是同一个字族。 */
.ed-in.big{font-size:var(--f-h3);font-weight:600;line-height:1.55;letter-spacing:-.01em}
.ed>i{font-size:14px;color:var(--ink-5);flex-shrink:0;margin-top:4px}
.ro{font-size:var(--f-body);color:var(--ink-2);padding:var(--s3) 0;line-height:var(--lh-body)}
.tag-kept{display:inline-flex;align-items:center;gap:var(--s1);font-size:var(--f-micro);color:var(--ink-3);
          border:1px solid var(--line);background:var(--card);border-radius:var(--r-sm);padding:3px var(--s2);
          flex-shrink:0;margin-top:2px;white-space:nowrap}
.tag-kept i{font-size:12px;color:var(--ink-4)}

.outline{display:flex;flex-wrap:wrap;gap:var(--s3);padding-top:var(--s1)}
.oi{display:flex;align-items:center;gap:var(--s2);font-size:var(--f-small);color:var(--ink-2);
    background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);
    padding:var(--s2) var(--s2) var(--s2) var(--s3)}
.oi-n{font-size:var(--f-micro);color:var(--ink-4);font-family:var(--mono)}
.oi.edited{border-color:var(--ink-4);background:var(--field)}
.lk{font-size:12px;color:var(--ink-4);flex-shrink:0}
.x{font-size:13px;color:var(--ink-5);flex-shrink:0;transition:color .14s}
.x:hover{color:var(--cinnabar)}

.res-div{border-top:1px solid var(--line-2);margin:var(--s5) 0}
.nums-h{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s4);margin-bottom:var(--s4)}
.nums-h p{margin:0}
.nums-legend{font-size:var(--f-micro);color:var(--ink-4)}
.nums-legend i{font-size:12px;vertical-align:-1px;margin-right:3px}
.nums-legend b{color:var(--cinnabar-d);font-weight:500}
/* 事实清单：一条一行。整句 + 来源，不是短标签，所以竖排不横排。
   条内 padding 从 12/16 提到 16/16，条间距从 8 提到 12——
   之前 6 条挨在一起像一坨，行与行之间分不开。 */
.nums{display:flex;flex-direction:column;gap:var(--s3)}
.num{border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s4);
     background:var(--card);min-width:0;transition:border-color .14s,background .14s}
.num-t{display:flex;align-items:flex-start;gap:var(--s2)}
.num-v{font-size:var(--f-body);line-height:var(--lh-body);color:var(--ink);border:0;background:none;
       padding:0;flex:1;min-width:0;font-family:inherit;resize:none;overflow:hidden}
.num-v:focus{outline:none}
.num-s{font-size:var(--f-micro);color:var(--ink-4);margin-top:var(--s1);overflow:hidden;text-overflow:ellipsis}
/* 原文摘录：默认收起，点「看原文」展开 */
.num-q{font-size:var(--f-micro);line-height:var(--lh-body);color:var(--ink-3);margin:var(--s2) 0 0;
       padding:var(--s2) var(--s3);background:var(--field);border-left:2px solid var(--line);
       border-radius:0 var(--r-sm) var(--r-sm) 0}
.num-more{font-size:var(--f-micro);color:var(--ink-4);background:none;border:0;padding:0;cursor:pointer;
          text-decoration:underline;text-decoration-color:var(--ink-5);margin-top:var(--s1);transition:color .14s}
.num-more:hover{color:var(--ink-2)}
.num.edited{border-color:var(--ink-4);background:var(--field)}
.num.warn{border-color:var(--cinnabar-b);background:var(--cinnabar-l)}
.num.warn .num-v{color:var(--cinnabar-d)}
.num.warn .num-s{color:var(--cinnabar-d)}
.warn-i{font-size:14px;color:var(--cinnabar);flex-shrink:0;margin-top:3px}

.drop{display:flex;align-items:baseline;gap:var(--s3);margin-top:var(--s5);padding-top:var(--s4);
      border-top:1px solid var(--line-2)}
.drop-k{font-size:var(--f-small);color:var(--ink-4);flex-shrink:0;padding-top:var(--s1)}
.drop-list{display:flex;flex-wrap:wrap;gap:var(--s2);min-width:0}
/* 已排除项。带删除线，但删除线不等于可以看不清——
   之前 <s> 里的字是 --ink-5，在灰底上只有 2.17:1。
   「已排除什么」是用户要核对的信息（漏排/错排都得看出来），用 --ink-4。 */
.di{display:flex;align-items:center;gap:var(--s2);font-size:var(--f-small);color:var(--ink-4);
    background:var(--field);border:1px solid var(--line-2);border-radius:var(--r-sm);padding:var(--s1) var(--s3)}
.di s{text-decoration:line-through;text-decoration-color:var(--ink-5)}
.di i{font-size:13px;color:var(--ink-4);transition:color .14s}
.di:hover i{color:var(--ink-2)}
.res-f{font-size:var(--f-micro);color:var(--ink-4);margin:var(--s5) 0 0;line-height:var(--lh-body)}

/* 补全提醒：后端 plan.warnings 一直在返回（「未提供资料，数字需自行核对」
   「核心结论由 AI 补全，建议确认立场」），以前前端没渲染，等于白扔。
   放在补全结果卡片顶部、字段上面——这些话是「读下面之前先知道」，
   摆到卡片末尾就没人看了。
   用朱砂淡底而不是 .banner：.banner 是页头级降级提示（margin-top:s8、
   padding 到 s5），塞进卡片里太重，会压过下面真正要看的字段。 */
/* 不用朱砂淡底：事实清单里「没找到来源」那条已经是 cinnabar-l + cinnabar-b 了
   （量出来底色边框完全一样）。两处语义不同——这里是整份的前置提醒，
   那里是单条数据待核——同色会被读成同一类。
   所以这里走中性底 + 左侧朱砂色条：仍然是警示，但层级和归属都区分开。 */
.pw{display:flex;flex-direction:column;gap:var(--s2);margin:0 0 var(--s5);
    padding:var(--s3) var(--s4);border:1px solid var(--line-2);
    border-left:3px solid var(--cinnabar);
    border-radius:var(--r-md);background:var(--field)}
.pw-i{display:flex;align-items:flex-start;gap:var(--s2)}
.pw-i i{font-size:14px;color:var(--cinnabar);flex-shrink:0;margin-top:1px}
/* 正文用 ink-3 不用 cinnabar-d：这段是要读的信息，不是要惊动人的告警。
   ink-5 是占位/禁用专用，信息性文字不能用。 */
.pw-i span{font-size:var(--f-micro);color:var(--ink-3);line-height:var(--lh-body)}

/* 把握度：low 的时候才值得说话。medium/high 不显示——
   每次都挂个「中」是噪音，用户学会忽略之后 low 也一起被忽略了。 */
.conf{display:inline-flex;align-items:center;gap:var(--s1);font-size:var(--f-micro);
      color:var(--cinnabar-d);background:var(--cinnabar-l);
      border:1px solid var(--cinnabar-b);border-radius:var(--r-sm);
      padding:1px var(--s2);white-space:nowrap}
.conf i{font-size:12px;vertical-align:-1px}

/* ---- 模板 ---- */
.tpl-h{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--s5);gap:var(--s4)}
.pages-w{display:flex;align-items:center;gap:var(--s3)}
.pages-w>span,.pages-w>label{font-size:var(--f-small);color:var(--ink-4)}
.sel{border:1px solid var(--line);background:var(--card);border-radius:var(--r-md);
     padding:var(--s2) var(--s3);font-size:var(--f-small);color:var(--ink);box-shadow:var(--sh-btn)}
.grid5{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:var(--s3)}
.tpl{border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s1);background:var(--card);
     position:relative;display:block;width:100%;transition:border-color .14s,box-shadow .14s,transform .14s}
.tpl:hover{border-color:var(--ink-5);box-shadow:var(--sh-btn)}
.tpl.on{border:2px solid var(--cinnabar);padding:3px;box-shadow:0 0 0 3px var(--cinnabar-l)}
.tpl-c{background:var(--card);border:1px solid var(--line-2);border-radius:var(--r-sm);padding:var(--s2);
       display:flex;flex-direction:column;gap:3px;height:80px;overflow:hidden}
.tpl-n{font-size:var(--f-small);color:var(--ink-3);margin:var(--s2) 0 var(--s1);text-align:center}
.tpl.on .tpl-n{color:var(--ink);font-weight:600}
.tick{position:absolute;top:var(--s2);right:var(--s2);width:17px;height:17px;background:var(--cinnabar);
      border-radius:50%;color:#fff;font-size:10px;display:flex;align-items:center;justify-content:center;
      box-shadow:0 1px 3px rgba(200,55,43,.5)}
.more{border:1px dashed var(--line);border-radius:var(--r-md);background:var(--field);display:flex;
       align-items:center;justify-content:center;flex-direction:column;padding:var(--s1);transition:border-color .14s}
.more:hover{border-color:var(--ink-5)}
.more-in{height:80px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s1)}
.more-n{font-size:var(--f-h3);color:var(--ink-3);font-weight:600;font-variant-numeric:tabular-nums}
.more-s{font-size:var(--f-micro);color:var(--ink-4)}
.more-pad{font-size:var(--f-small);margin:var(--s2) 0 var(--s1);visibility:hidden}

/* ==========================================================================
   屏 2 · 生成中
   ========================================================================== */
/* 生成中：整块自成一卡，padding 走卡的规矩 */
.main.gen{padding:0}
.gen-card{padding:var(--s7) var(--s6)}
.live{display:flex;align-items:center;gap:var(--s2);font-size:var(--f-small);color:var(--cinnabar-d);
      margin:0 0 var(--s4);letter-spacing:.04em;font-weight:500}
.live.stalled{color:var(--ink-3)}
.dot{width:8px;height:8px;border-radius:50%;background:var(--cinnabar);display:inline-block;
     animation:pulse 1.6s ease-in-out infinite}
.live.stalled .dot{background:var(--ink-4);animation:none}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.25}}

.h1{font-size:var(--f-h1);font-weight:600;color:var(--ink);margin:0 0 var(--s6);
    line-height:1.32;letter-spacing:-.02em}
.clock{display:flex;align-items:baseline;gap:var(--s4);padding-bottom:var(--s6);border-bottom:1px solid var(--line)}
.clock-v{font-size:52px;color:var(--ink);font-family:var(--mono);line-height:1;
         font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.clock-l{font-size:var(--f-small);color:var(--ink-3)}

.proc{margin:var(--s6) 0 0;max-width:580px}
.proc-h{font-size:var(--f-micro);color:var(--ink-4);letter-spacing:.1em;margin:0 0 var(--s5);font-weight:600}
.stg{display:flex;align-items:flex-start;gap:var(--s4);position:relative;padding-bottom:var(--s5)}
.stg:last-child{padding-bottom:0}
.stg::before{content:"";position:absolute;left:9px;top:24px;bottom:0;width:2px;background:var(--line-2);border-radius:1px}
.stg:last-child::before{display:none}
.stg.done::before{background:var(--cinnabar-b)}
.stg-m{width:20px;height:20px;border-radius:50%;border:1.5px solid var(--line);background:var(--card);
       display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;z-index:1;margin-top:1px}
.stg.done .stg-m{background:var(--cinnabar);border-color:var(--cinnabar);color:#fff}
.stg.now .stg-m{border-color:var(--cinnabar);background:var(--cinnabar-l);box-shadow:0 0 0 4px var(--cinnabar-l)}
.stg.now .stg-m::after{content:"";width:8px;height:8px;border-radius:50%;background:var(--cinnabar);
                       animation:pulse 1.6s ease-in-out infinite}
.stg.failed .stg-m{border-color:var(--cinnabar);background:var(--cinnabar);color:#fff}
.stg-in{flex:1;min-width:0}
.stg-t{display:flex;justify-content:space-between;gap:var(--s4);align-items:baseline;
       font-size:var(--f-body);color:var(--ink-4);line-height:var(--lh-tight)}
.stg.done .stg-t{color:var(--ink-2)}
.stg.now .stg-t{color:var(--ink);font-weight:600}
.stg-d{font-size:var(--f-micro);color:var(--ink-4);font-family:var(--mono);flex-shrink:0;font-variant-numeric:tabular-nums}

.note{font-size:var(--f-small);color:var(--ink-3);margin:var(--s6) 0 0;line-height:var(--lh-loose);max-width:580px}
.note b{color:var(--ink);font-weight:600}
.acts{display:flex;gap:var(--s3);margin-top:var(--s6)}
.acts i{font-size:16px;vertical-align:-3px;margin-right:var(--s2)}

/* ==========================================================================
   屏 3 · 下载
   ========================================================================== */
/* 成果区自成一卡，下载按钮在这张卡里；重做是另一张卡。
   两件事分两张卡：一个是「拿走成品」，一个是「不满意就重来」，
   挤在同一张卡里的时候，下载和重做的份量看着一样重。 */
.hero{padding:var(--s7) var(--s6)}
.hero-row{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s6)}
/* 「已完成」做成一枚玉色徽章。全站只有这一处用玉色底，
   走到这里就是钱花到东西了，值得一个明确的落点。 */
.ok{display:inline-flex;align-items:center;gap:5px;font-size:var(--f-micro);color:var(--jade);
    margin:0 0 var(--s4);letter-spacing:.02em;font-weight:600;
    background:var(--jade-l);border:1px solid var(--jade-b);border-radius:999px;padding:4px var(--s3)}
.ok i{font-size:15px}
.h1.tight{margin:0 0 var(--s3)}
.h1-s{font-size:var(--f-small);color:var(--ink-3);margin:0;line-height:var(--lh-body)}
.dl-col{display:flex;flex-direction:column;align-items:flex-end;gap:var(--s3);flex-shrink:0}
.btn-dl{background:var(--cinnabar);border-radius:var(--r-md);padding:var(--s4) var(--s7);
        box-shadow:var(--sh-brand);transition:background .14s,box-shadow .14s}
.btn-dl span{font-size:var(--f-lead);color:#fff;letter-spacing:.04em;font-weight:600}
.btn-dl i{font-size:18px;vertical-align:-3px;margin-right:var(--s2)}
.btn-dl:hover{background:var(--cinnabar-d);box-shadow:0 3px 14px -3px rgba(200,55,43,.5)}
.btn-dl:disabled{background:var(--ink-5);box-shadow:none}
.dl-note{font-size:var(--f-micro);color:var(--ink-4);margin:0}
.dl-note b{font-family:var(--mono);color:var(--ink-3);font-weight:400}
.quality-note{border-top:1px solid var(--line-2);margin-top:var(--s6);padding-top:var(--s4)}
.quality-head{display:flex;align-items:center;gap:var(--s2);font-size:var(--f-small);font-weight:600;color:var(--ink-2);margin-bottom:var(--s2)}
.quality-head i{font-size:16px;color:var(--jade)}
.quality-list{display:grid;gap:var(--s2)}
.quality-item{display:flex;align-items:flex-start;gap:var(--s2);font-size:var(--f-small);line-height:var(--lh-body);color:var(--ink-3)}
/* 默认走墨色＝排版规范提示；.q-fact 才上朱砂＝数字要回材料核对。
   六类全上朱砂等于都不强调，扫视时反而分不出该先看哪条。 */
.quality-item i{font-size:15px;color:var(--ink-4);flex-shrink:0;margin-top:3px}
.quality-item.q-fact i{color:var(--cinnabar-d)}
.request-copy{padding:var(--s6)}
.request-copy-head{display:flex;align-items:center;justify-content:space-between;gap:var(--s4);margin-bottom:var(--s3)}
.request-copy-head p{font-size:var(--f-lead);color:var(--ink);font-weight:600;margin:0}
.request-copy-head button{width:34px;height:34px;display:grid;place-items:center;border:1px solid var(--line);
                          border-radius:var(--r-md);background:var(--card);color:var(--ink-3)}
.request-copy-head button:hover{border-color:var(--ink-5);color:var(--cinnabar-d);background:var(--field)}
.request-copy-head i{font-size:17px}
.request-copy pre{max-height:240px;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere;margin:0;
                  padding:var(--s4);border:1px solid var(--line-2);border-radius:var(--r-md);
                  background:var(--field);font:var(--f-small)/var(--lh-body) var(--font);color:var(--ink-2)}
.done-recovery{display:flex;align-items:center;justify-content:space-between;gap:var(--s5);border-top:1px solid var(--line-2);margin-top:var(--s6);padding-top:var(--s4)}
.done-recovery strong{display:block;font-size:var(--f-small);color:var(--ink-2);margin-bottom:var(--s1)}
.done-recovery p{font-size:var(--f-small);color:var(--ink-4);line-height:var(--lh-body)}

.rev{padding:var(--s6)}
.rev-h{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--s3)}
.rev-t{font-size:var(--f-lead);color:var(--ink);font-weight:600}
.rev-t i{font-size:17px;vertical-align:-3px;margin-right:var(--s2);color:var(--cinnabar)}
.rev-timer{font-size:var(--f-small);color:var(--cinnabar-d);font-family:var(--mono);background:var(--cinnabar-l);
           border:1px solid var(--cinnabar-b);border-radius:var(--r-sm);padding:3px var(--s3);
           font-variant-numeric:tabular-nums}
.rev-timer.off{color:var(--ink-4);background:var(--field);border-color:var(--line)}
.rev-p{font-size:var(--f-small);color:var(--ink-3);margin:0 0 var(--s5);line-height:var(--lh-body)}
.rev-p b{color:var(--ink);font-weight:600}
.rev-in{border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s4);margin-bottom:var(--s4);
        background:var(--field);transition:border-color .14s,background .14s,box-shadow .14s}
.rev-in textarea{width:100%;border:0;background:none;resize:none;font-size:var(--f-body);color:var(--ink);
                 line-height:var(--lh-body);min-height:48px;padding:0}
.rev-in textarea::placeholder{color:var(--ink-5)}
.rev-in textarea:focus{outline:none}
.rev-in:focus-within{border-color:var(--cinnabar);background:var(--card);box-shadow:0 0 0 3px var(--cinnabar-l)}
.rev-warn{display:flex;align-items:flex-start;gap:var(--s2);background:var(--cinnabar-l);
          border:1px solid var(--cinnabar-b);border-radius:var(--r-md);padding:var(--s3) var(--s4);margin-bottom:var(--s4)}
.rev-warn i{font-size:15px;color:var(--cinnabar);flex-shrink:0;margin-top:1px}
.rev-warn p{font-size:var(--f-small);color:var(--cinnabar-d);margin:0;line-height:var(--lh-body)}
.rev-f{display:flex;align-items:center;justify-content:space-between;gap:var(--s4)}
.tagrow{display:flex;gap:var(--s2)}
.tag{font-size:var(--f-small);color:var(--ink-2);border:1px solid var(--line);border-radius:var(--r-md);
     padding:var(--s2) var(--s3);background:var(--card);transition:border-color .14s,background .14s}
.tag:hover{border-color:var(--ink-5);background:var(--field)}
.rev.used{opacity:.6}

.mail-row{display:flex;gap:var(--s2)}
.mail-in{flex:1;border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s3);
         font-size:var(--f-small);color:var(--ink);min-width:0;background:var(--card);transition:border-color .14s,box-shadow .14s}
.mail-in::placeholder{color:var(--ink-5)}
.mail-in:focus{outline:none;border-color:var(--cinnabar);box-shadow:0 0 0 3px var(--cinnabar-l)}
.mail-btn{border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s3) var(--s4);
          flex-shrink:0;background:var(--card);transition:border-color .14s}
.mail-btn span{font-size:var(--f-small);color:var(--ink-2);font-weight:500}
.mail-btn:hover{border-color:var(--ink-5)}
.mail-btn:disabled span{color:var(--ink-5)}
.again{border-top:1px solid var(--line-2);margin-top:var(--s4);padding-top:var(--s4);text-align:center;
       display:block;width:100%}
.again span{font-size:var(--f-small);color:var(--ink-2);transition:color .14s}
.again i{font-size:16px;vertical-align:-3px;margin-right:var(--s2)}
.again:hover span{color:var(--cinnabar-d)}

/* ---------- 骨架屏 ---------- */
.sk{background:var(--line-2);border-radius:var(--r-sm);animation:sk 1.4s ease-in-out infinite}
@keyframes sk{0%,100%{opacity:1}50%{opacity:.5}}

/* ---------- 窄屏 ---------- */
@media (max-width:760px){
  :root{--s6:20px;--s7:24px;--f-h1:30px}
  body{padding:var(--s3);min-width:0}
  .topbar{padding:var(--s3) var(--s4);flex-wrap:wrap}
  .brand{flex:1 1 auto}
  .brand-s{display:none}
  .topbar-r,.code-chip{max-width:100%}
  .stepper{height:64px;padding:0 var(--s2)}
  .step{gap:6px;font-size:var(--f-micro)}
  .step-n{width:26px;height:26px;font-size:var(--f-small)}
  .rule{width:18px;margin:0 6px}
  .body{grid-template-columns:minmax(0,1fr)}
  .rail{position:static;max-height:none}
  .rail-scroll{overflow:visible}
  .card,.card.tight{padding:var(--s5) var(--s4)}
  .two{grid-template-columns:minmax(0,1fr)}
  .row{grid-template-columns:minmax(0,1fr);gap:var(--s2)}
  .row-k,.row-k.tall{padding-top:0}
  .grid5{grid-template-columns:repeat(2,minmax(0,1fr))}
  .tpl-h,.res-h{align-items:flex-start;flex-direction:column}
  .pages-w{width:100%;justify-content:space-between}
  .hero{padding:var(--s5) var(--s4)}
  .hero-row{align-items:stretch;flex-direction:column}
  .dl-col{align-items:stretch}
  .btn-dl{width:100%;padding:var(--s4);text-align:center}
  .request-copy pre{max-height:320px}
  .done-recovery,.rev-f{align-items:stretch;flex-direction:column}
  .tagrow{flex-wrap:wrap}
  .rev-f>.btn-sub{width:100%;text-align:center}
  .acts{flex-wrap:wrap}
}

/* 关掉动效偏好：脉冲、骨架屏、所有过渡一起停。 */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition:none !important;animation:none !important}
}
