This repository has been archived on 2026-09-13. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BPOS-TMP-REPO/activities/part-substitution-assessment/src/views/style.ts
T
xcsandClaude Fable 5 68faeb4f50 fix(w05): 互换动画提到与卡同级 —— 三列网格中间留实体动画道,卡片相应收窄
2026-08-31 用户:「不要把这个动画做到背景板上,会被卡片覆盖;和卡片做到一级,
可以压缩一点卡片的大小」—— 上一稿的对向穿行点走在卡后,只在缝里闪现,基本看不见。
.dossiers 改三列网格(minmax(0,1fr) 76px minmax(0,1fr)):卡片各占左右列自然收窄,
中间 76px 是**谁也盖不住的实体动画道** —— ⇄ 徽居中轻呼吸,两枚信号点绕徽轨道对转
(此上彼下绕圈 = 两颗料换位),底下的虚线总线在道里露出来把两张卡接起来。
窄屏(<620px)卡片竖排,动画道随之收起。浏览器两帧相位实证在转;
105 包内 + 2531 全仓;2.12.1 装库核过(orbit/lane)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
2026-08-31 17:53:31 +08:00

460 lines
34 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* ACT-WORK-05 三张工单件的设计系统(2026-08-31 视图层整体重设计。用户定:
* 「中间这一块不要搞的像后台管理端,要像给客户使用的 C 端界面;可以按主题加 SVG 图形,
* 可以有动画,加强交互 —— 只保留功能,视图层可以推翻重新设计」)。
*
* 设计语言:「精密检测报告」——
* · 题头是一块深色电路板夜景(hero):芯片封装、铜引脚、流动的走线信号,
* 三张件各有一幕对应自己职能的场景(建档台 / 对决量尺 / 落账席);
* · 正文回到瓷白纸面,报告化排版:丝印体小标(silkscreen)、mono 料号、
* 引脚号式的序号列 —— 用电子行业自己的版面语汇,不借后台管理端的灰表格;
* · 动画只做 transform / opacity(信号点流动、晶粒呼吸、印章环慢转、入场浮起),
* prefers-reduced-motion 下全部静止 —— 与工作台动画同一条纪律。
*
* 旧的 target-style.ts(逐字节抽自目标件的三段样式)随本次重设计退役:目标件是
* 「照着做」时代的锚,这一版是活动自己的设计,样式只此一处真源。
*
* **这一整段活在 TS 模板字符串里 —— 不许出现反引号**(一个反引号就把串截断,
* esbuild 报在几行之外;本仓踩过)。注释里也别写星号斜杠连排。
*
* 几条被包内测试钉死的**机制规则逐字保留**,别「顺手整理」:
* · 序号计数器五连(.jc-tbl-wrap table, .tbl-wrap table 成对出现);
* · table:not(.on) tr.jc-row-static { display: none; }(种子行只在编辑态露面);
* · .jc-gate-bar:has(.jc-gate-text:empty) 显隐(gate_reason 是中文自由文本,
* data-class-of 在它上面永远算不出 v-token,显隐只认 data-blank 出的空文本节点);
* · .jc-tbl-wrap 不许 overflow:hidden(表宽超出要能横着滑)。
*/
/** 件① 数据工单的强调色 —— 数据蓝(与治理台「数据」语义同族) */
export const ACCENT_DATA = `
:root{
--acc:#2e6bff; --acc-deep:#1f52d6; --acc-soft:#e3ecff; --acc-line:#c2d5ff; --acc-wash:#f3f7ff;
--glow:#6fa1ff; --glow-line:rgba(111,161,255,.36); --hero-tint:rgba(46,107,255,.34);
}
`;
/** 件②③ 验收工单的强调色 —— 验收绿 #0aa294(2026-08-27 用户定:与对话区验收卡同色) */
export const ACCENT_LEDGER = `
:root{
--acc:#0aa294; --acc-deep:#07857a; --acc-soft:#dcf5f1; --acc-line:#aee5dd; --acc-wash:#f0fbf9;
--glow:#2fd4c2; --glow-line:rgba(47,212,194,.34); --hero-tint:rgba(10,162,148,.32);
--ledger:#0aa294;
}
`;
export const SHELL_CSS = `
/* ================= 令牌与底 ================= */
:root{
--ink:#182430; --ink-2:#3d4c5c; --ink-3:#67788a; --ink-4:#97a5b3;
--line:#dbe3ea; --line-soft:#e8edf3; --soft:#f5f8fa; --paper:#edf1f5;
--board:#0e1b27; --board-2:#15263a;
--cu:#d99a5b; --cu-deep:#b57632;
--ok:#1e9e56; --ok-soft:#e4f7ec;
--danger:#dd4a3a; --danger-soft:#feecea;
--amber:#b07a10; --amber-soft:#fdf3d8;
--cond:#5661f0; --cond-soft:#e9ebfe;
--hero-ink:#f4f8fc; --hero-dim:rgba(226,238,248,.62);
--mono:"SF Mono",Menlo,Consolas,monospace;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;background:var(--paper);color:var(--ink);font-size:14px;line-height:1.7;-webkit-font-smoothing:antialiased}
.page{margin:0;padding:0}
.card{background:#fff;overflow:hidden;border:0;border-radius:0}
.mono{font-family:var(--mono)}
i{font-style:normal}
/* ================= 题头:电路板夜景 hero ================= */
.card-head{
position:relative;display:flex;flex-direction:column;gap:12px;padding:20px 22px 22px;color:var(--hero-ink);
background:
repeating-linear-gradient(0deg, rgba(255,255,255,.03) 0 1px, transparent 1px 28px),
repeating-linear-gradient(90deg, rgba(255,255,255,.03) 0 1px, transparent 1px 28px),
radial-gradient(900px 340px at 18% -40%, var(--hero-tint), transparent 62%),
linear-gradient(158deg, #13212f 0%, var(--board) 56%, #0f1d2b 100%);
}
.hero-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.hero-sys{flex:1 1 auto;min-width:0;font-size:10.5px;font-weight:800;letter-spacing:.17em;color:var(--hero-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hero-chips{flex:none;display:flex;gap:6px}
.hero-tag{font-size:11px;font-weight:800;padding:2px 11px;border-radius:999px;color:#fff;background:var(--acc);box-shadow:0 4px 14px var(--glow-line);white-space:nowrap}
.hero-step{font-size:11px;font-weight:700;padding:2px 11px;border-radius:999px;color:var(--hero-dim);border:1px solid rgba(255,255,255,.22);white-space:nowrap}
.hero-title{margin:0;font-size:23px;font-weight:800;line-height:1.25;letter-spacing:.01em;color:#fff}
.hero-meta{font-size:11.5px;color:var(--hero-dim)}
.hero-meta b{font-weight:700;color:#fff}
/* ── hero 舞台:芯片铭牌 + 信号走线 ── */
.stage{position:relative;display:flex;align-items:stretch;justify-content:center;gap:clamp(20px,7vw,72px);padding:14px 6px 6px}
.stage::before{content:"";position:absolute;left:5%;right:5%;top:52%;border-top:2px dashed var(--glow-line)}
.stage::after{content:"";position:absolute;top:52%;left:5%;width:9px;height:9px;margin-top:-4px;border-radius:999px;background:var(--glow);box-shadow:0 0 14px 3px var(--glow-line),0 0 4px 1px var(--glow);animation:sig 3.4s linear infinite}
.stage-lab{padding-bottom:8px}
.stage-duel{padding-top:28px}
.hchip{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;gap:6px;flex:0 1 176px;min-width:128px;padding:13px 12px 11px;border-radius:14px;background:rgba(255,255,255,.97);color:var(--ink);box-shadow:0 14px 30px rgba(3,10,18,.5),inset 0 1px 0 rgba(255,255,255,.7)}
.hchip.v-absent{background:rgba(255,252,246,.97);outline:2px dashed var(--cu);outline-offset:-6px}
.hchip-role{font-size:10.5px;font-weight:800;letter-spacing:.08em;color:var(--ink-4)}
.hchip-pn{font-size:14.5px;font-weight:800;color:var(--ink);overflow-wrap:anywhere;text-align:center;line-height:1.3}
.hchip-badges{display:flex;gap:6px;flex-wrap:wrap;justify-content:center}
.csvg{width:86px;height:auto;display:block}
.c-body{fill:var(--board-2);stroke:rgba(217,154,91,.55);stroke-width:1.4}
.c-pin{fill:var(--cu)}
.c-die{fill:var(--acc);opacity:.9;animation:breathe 2.8s ease-in-out infinite}
.c-dot{fill:rgba(255,255,255,.85)}
.duel-type{position:absolute;z-index:1;left:50%;top:-4px;transform:translateX(-50%);font-size:10.5px;font-weight:800;letter-spacing:.06em;color:var(--hero-dim);border:1px solid rgba(255,255,255,.2);border-radius:999px;padding:2px 12px;background:rgba(10,20,30,.55);white-space:nowrap}
.duel-type i{font-style:normal;color:#fff}
.hero-verdict{display:flex;justify-content:center;padding:2px 0 0}
/* ── hero 落账席(件③):印章 + 一句话结论 ── */
.stage-seal{position:relative;display:flex;align-items:center;justify-content:center;gap:22px;padding:12px 4px 4px;flex-wrap:wrap}
.seal{position:relative;flex:none;width:112px;height:112px;border-radius:999px;display:grid;place-items:center}
.seal::before{content:"";position:absolute;inset:0;border:1.6px dashed rgba(255,255,255,.34);border-radius:999px;animation:sealspin 16s linear infinite}
.seal-core{display:grid;place-items:center;padding:7px 11px;border-radius:999px;background:rgba(255,255,255,.97);box-shadow:0 12px 26px rgba(3,10,18,.5)}
.seal-sum{flex:1 1 240px;min-width:200px;max-width:420px;margin:0;font-size:13px;line-height:1.85;color:var(--hero-dim)}
.seal-sum:empty::after{content:"—"}
/* ── 浅色题头变体(件① 2026-08-31 用户:「标题背景还是改成之前的那种蓝色渐变」——
渐变取自原目标件 card-head 那一条,深色电路夜景只留给验收两件)── */
.hd-light .card-head{background:linear-gradient(120deg,#f0f5ff 0%,#fff 55%,#eef4ff 100%);color:var(--ink);border-bottom:2px solid var(--ink)}
.hd-light .hero-sys{color:var(--ink-4)}
.hd-light .hero-title{color:var(--ink)}
.hd-light .hero-step{color:var(--ink-3);border-color:var(--line)}
.hd-light .hero-meta{color:var(--ink-3)}
.hd-light .hero-meta b{color:var(--ink)}
/* ================= 正文分区 ================= */
.card-bd{padding:20px 22px 8px}
.sec{display:flex;align-items:baseline;gap:9px;margin:26px 0 10px;flex-wrap:wrap}
.sec:first-child{margin-top:4px}
.sec-pin{flex:none;align-self:center;width:24px;height:24px;border-radius:8px;display:grid;place-items:center;background:var(--acc-soft);color:var(--acc-deep)}
.zic{width:13px;height:13px;display:block}
.sec-t{font-size:13.5px;font-weight:800;color:var(--ink);letter-spacing:.02em}
.sec-d{flex:1 1 200px;min-width:0;font-size:11.5px;color:var(--ink-3)}
/* 简报卡(做什么 / 纪律…) */
.brief{border:1px solid var(--line-soft);border-left:3px solid var(--acc);border-radius:10px;background:var(--acc-wash);padding:13px 16px;margin:0 0 4px}
.brief p{margin:0 0 7px;font-size:12.5px;line-height:1.75;color:var(--ink-2)}
.brief p:last-child{margin-bottom:0}
.brief b{color:var(--ink)}
.done,.need{display:inline-block;font-size:10.5px;font-weight:800;padding:0 8px;border-radius:999px;vertical-align:1px;margin-right:2px}
.done{color:var(--ok);background:var(--ok-soft)}
.need{color:var(--acc-deep);background:var(--acc-soft)}
/* 收尾指引 */
.flow{margin:24px 0 14px;padding:12px 16px;border-radius:10px;border:1px dashed var(--acc-line);background:var(--acc-wash);font-size:12.5px;color:var(--ink-2);line-height:1.8}
.flow b{color:var(--acc-deep)}
/* 页脚:丝印条 */
.card-foot{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:12px 22px;border-top:1px solid var(--line-soft);background:var(--soft);font-size:11px;color:var(--ink-4);flex-wrap:wrap}
.foot-r{letter-spacing:.04em}
/* ================= 顶部「还差什么」红带(机制:显隐认 data-blank 的空文本节点) ================= */
.jc-gate-bar{display:flex;flex-direction:column;gap:5px;margin:0 0 16px;padding:11px 14px;border-radius:10px;background:var(--danger-soft);border:1px solid #f5c0ba;color:var(--danger);font-size:12.5px;line-height:1.7}
.jc-gate-bar b{font-weight:800}
.jc-gate-bar:has(.jc-gate-text:empty){display:none}
/* 逐块的缺项点名并进这一条(2026-08-31 用户:「页面上所有的问题都合并到最上面的还差什么」)——
与提交闸同源的基座读数,数值为 0 的那一行自己消失,只在待处理态出现 */
.jc-gate-sub{display:none;font-size:12px;color:#a03d34;padding-left:2px}
html.editable .jc-gate-sub{display:block}
html.editable .jc-gate-sub.v-0{display:none}
/* 缺项红带 —— 与提交闸同源的必填提示,只在待处理态出现 */
.jc-gapbar{display:none}
html.editable .jc-gapbar{display:flex;align-items:flex-start;gap:8px;margin:0 0 10px;padding:9px 13px;border-radius:9px;background:var(--danger-soft);border:1px solid #f5c0ba;color:var(--danger);font-size:12px;line-height:1.7}
.jc-gapbar b{font-weight:800}
.jc-gapbar span{color:#a03d34}
html.editable .jc-gapbar.v-0{display:none}
/* ================= 编辑闸与加行(只在待处理态露面) ================= */
html:not(.editable) .jc-editgate, html:not(.editable) .jc-addrow { display: none !important; }
.jc-editgate{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 10px;padding:8px 12px;border-radius:10px;background:var(--soft);border:1px solid var(--line-soft);font-size:12px;color:var(--ink-3)}
.jc-editgate-t{flex:1 1 auto;min-width:0}
.jc-editgate-t b{color:var(--ink-2);font-weight:700}
.jc-egbtn{flex:none;display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:1px solid var(--line);border-radius:999px;padding:6px 15px;font:inherit;font-size:12px;font-weight:700;color:var(--ink-2);background:#fff;transition:border-color .16s,color .16s,background .16s,box-shadow .16s}
.jc-egbtn:hover{border-color:var(--acc);color:var(--acc-deep);box-shadow:0 0 0 3px var(--acc-soft)}
.jc-egbtn:active{transform:scale(.96)}
.jc-egbtn.save{color:#fff;background:var(--acc);border-color:var(--acc)}
.jc-egbtn.save:hover{filter:brightness(1.06);color:#fff}
.jc-editgate .eg-cancel,.jc-editgate .eg-save{display:none}
.jc-editgate.on{background:var(--acc-wash);border-color:var(--acc-line);color:var(--acc-deep)}
.jc-editgate.on .eg-open{display:none}
.jc-editgate.on .eg-cancel,.jc-editgate.on .eg-save{display:inline-flex}
.jc-addrow{display:none;margin:8px 0 0}
.jc-tbl-wrap:has(table.on) + .jc-addrow { display: flex; align-items: center; gap: 8px; }
.jc-addrow button{cursor:pointer;border:1px dashed var(--acc-line);border-radius:999px;background:var(--acc-wash);color:var(--acc-deep);font:inherit;font-size:12px;font-weight:700;padding:6px 15px;transition:border-color .16s,box-shadow .16s}
.jc-addrow button:hover{border-color:var(--acc);box-shadow:0 0 0 3px var(--acc-soft)}
.jc-addrow button:active{transform:scale(.96)}
.jc-addrow em{font-style:normal;font-size:11px;color:var(--ink-4)}
/* ================= 报告表格 ================= */
.jc-tbl-wrap{border:1px solid var(--line-soft);border-radius:12px;background:#fff;overflow-x:auto;overflow-y:hidden}
.jc-tbl-wrap, .tbl-wrap { overflow-x: auto; overflow-y: hidden; }
table{width:100%;border-collapse:collapse;font-size:12.5px}
thead th{position:static;text-align:left;font-size:10.5px;font-weight:800;letter-spacing:.07em;color:var(--ink-4);background:var(--soft);padding:9px 12px;border-bottom:1px solid var(--line);white-space:nowrap}
th.req::after{content:" *";color:var(--danger);font-size:10px}
tbody td{padding:10px 12px;border-bottom:1px solid var(--line-soft);vertical-align:top;color:var(--ink-2)}
tbody tr:last-child td{border-bottom:0}
tbody tr:hover td{background:var(--acc-wash)}
td.rn,td.num{font-family:var(--mono);font-size:11px;color:var(--ink-4);white-space:nowrap}
td.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)}
td.cust{font-weight:700;color:var(--ink)}
td.desc,.desc{color:var(--ink-3);font-size:12px;line-height:1.6}
/* 序号列交给 CSS 计数器(沙箱零脚本,增删行后自己数对;两种列名、两种包装类都接) */
.jc-tbl-wrap table, .tbl-wrap table { counter-reset: rn; }
.jc-tbl-wrap table td.rn, .tbl-wrap table td.rn { counter-increment: rn; }
.jc-tbl-wrap table td.rn .jc-rn-num::before, .tbl-wrap table td.rn .jc-rn-num::before { content: counter(rn); }
.jc-tbl-wrap table td.num, .tbl-wrap table td.num { counter-increment: rn; }
.jc-tbl-wrap table td.num::before, .tbl-wrap table td.num::before { content: counter(rn); }
/* ── 看与改是两件事:只读份 / 输入孪生件由 .on 二选一 ── */
.jc-vcell{display:block;font-size:12.5px;color:var(--ink);line-height:1.55;overflow-wrap:anywhere}
.jc-vcell.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)}
.jc-vcell:empty::after{content:"—";color:var(--ink-4)}
.jc-cell{display:none;width:100%;min-width:72px;border:1px solid var(--line);border-radius:8px;padding:6px 9px;font:inherit;font-size:12.5px;color:var(--ink);background:#fff}
.jc-cell:focus{border-color:var(--acc);box-shadow:0 0 0 3px var(--acc-soft);outline:none}
.jc-cell.mono{font-family:var(--mono);font-size:12px}
input.jc-cell, select.jc-cell { height: 32px; box-sizing: border-box; padding-top: 0; padding-bottom: 0; vertical-align: middle; }
table.on td>.jc-vcell{display:none}
table.on td>.jc-vcell.ro{display:block}
table.on td>.jc-cell{display:block}
table.on td>.jc-vcell:empty::after{content:none}
/* 增删行的痕(取消还原三件套的可视面) */
table.on tr.jc-row-new td { background: #f0fbf5; }
table.on tr.jc-row-gone td { background: #fff6f5; opacity: .55; }
table.on tr.jc-row-gone .jc-cell { text-decoration: line-through; color: var(--ink-3); }
.jc-rowdel{display:none;cursor:pointer;border:1px solid var(--line);border-radius:999px;background:#fff;color:var(--ink-3);width:20px;height:20px;line-height:1;font-size:12px;padding:0;margin-left:5px;vertical-align:middle}
table.on .jc-rowdel{display:inline-grid;place-items:center}
.jc-rowdel:hover{border-color:var(--danger);color:var(--danger)}
table.on tr.jc-row-gone .jc-rowdel { border-color: var(--danger); color: var(--danger); background: #fff; }
/* 静态种子行:零行也加得出第一行 —— 只在编辑态露面(读态看见空壳子是界面撒谎) */
table:not(.on) tr.jc-row-static { display: none; }
table.on tr.jc-row-static td{background:var(--acc-wash);border-top:1px dashed var(--acc-line)}
/* 主键钥匙格:不给人看,但真挂 data-col(漏了钥匙,这一行凑不出主键) */
.rowkey{display:none}
/* ================= 徽标基座(取值上色一律 data-class-of 投影,选择器从值算) ================= */
.stx,.ct,.rl,.st,.risk-badge{display:inline-block;font-size:11px;font-weight:700;padding:1px 9px;border-radius:999px;border:1px solid transparent;white-space:nowrap}
.rl{background:var(--soft);border-color:var(--line-soft);color:var(--ink-3);font-size:10.5px;letter-spacing:.03em}
.rec{display:inline-block;font-size:11.5px;font-weight:800;padding:2px 13px;border-radius:999px;border:1px solid transparent;white-space:nowrap}
.rec.rec-lg{font-size:14.5px;padding:7px 20px;letter-spacing:.03em}
/* kv 行(收口结论 / 待验项共用的键值版式) */
.kv{display:flex;gap:12px;padding:10px 0;border-bottom:1px solid var(--line-soft);font-size:12.5px}
.kv:last-child{border-bottom:0}
.kv i{flex:0 0 84px;font-style:normal;color:var(--ink-4);font-size:11px;font-weight:700;letter-spacing:.05em;padding-top:2px}
.kv > span{flex:1 1 auto;color:var(--ink-2);line-height:1.7;overflow-wrap:anywhere}
.kv > span:empty::after{content:"—";color:var(--ink-4)}
.kv-box{border:1px solid var(--line-soft);border-radius:12px;background:var(--soft);padding:4px 16px;margin-bottom:4px}
/* ================= 动画(全部 transform / opacity;reduced-motion 全静) ================= */
@keyframes sig{0%{transform:translateX(0);opacity:0}7%{opacity:1}93%{opacity:1}100%{transform:translateX(min(86vw,760px));opacity:0}}
@keyframes breathe{0%,100%{opacity:.55}50%{opacity:1}}
@keyframes sealspin{to{transform:rotate(360deg)}}
@keyframes rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}
.hero-top{animation:rise .5s cubic-bezier(.2,.7,.3,1) both}
.hero-title{animation:rise .5s .06s cubic-bezier(.2,.7,.3,1) both}
.stage,.stage-seal{animation:rise .55s .14s cubic-bezier(.2,.7,.3,1) both}
.hero-verdict,.hero-meta{animation:rise .55s .22s cubic-bezier(.2,.7,.3,1) both}
@media (prefers-reduced-motion: reduce){
*{animation:none !important;transition:none !important}
}
/* ================= 电路蓝图工作台(件① 的两张档案卡)=================
2026-08-31 用户:「卡片下面那个容器黑色和页面背景不搭」—— 深色板底退场,换**浅色蓝图**:
底是强调色的极浅晕染 + 淡格线,走线与信号点用强调色 —— 电路语汇留着,纸面色阶不断裂。 */
.board{position:relative;margin:0 0 6px;padding:18px 14px 16px;border-radius:16px;border:1px solid var(--acc-line);
background:
repeating-linear-gradient(0deg, rgba(46,107,255,.045) 0 1px, transparent 1px 26px),
repeating-linear-gradient(90deg, rgba(46,107,255,.045) 0 1px, transparent 1px 26px),
linear-gradient(158deg, var(--acc-wash) 0%, #fff 62%, var(--acc-wash) 100%)}
.board::before{content:"";position:absolute;left:4%;right:4%;top:50%;border-top:2px dashed var(--acc-line)}
/* 「可替换」动画(2026-08-31 用户第二稿:「不要做到背景板上,背景板会被卡片覆盖;
和卡片做到一级,可以压缩一点卡片的大小」)—— .dossiers 改三列网格,中间留一条
**实体动画道**(卡片各占左右列、相应收窄,谁也盖不住它):中央 ⇄ 徽轻呼吸,
两枚信号点绕徽**轨道对转**(此上彼下地绕圈 = 两颗料换位),底下横穿的虚线总线
在道里露出来把两张卡接起来。 */
.swapfx{position:absolute;left:50%;top:50%;width:76px;height:76px;transform:translate(-50%,-50%);z-index:1;pointer-events:none}
.sw-ic{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:36px;height:36px;padding:8px;box-sizing:border-box;color:var(--acc);background:#fff;border:1px solid var(--acc-line);border-radius:999px;box-shadow:0 4px 12px rgba(18,38,63,.16);animation:swbreathe 2.8s ease-in-out infinite}
.sw-orbit{position:absolute;left:50%;top:50%;width:64px;height:64px;margin:-32px 0 0 -32px;animation:sworbit 4.5s linear infinite}
.sw-dot{position:absolute;left:50%;width:8px;height:8px;margin-left:-4px;border-radius:999px;background:var(--acc);box-shadow:0 0 8px 2px var(--acc-soft)}
.sw-d1{top:-4px}
.sw-d2{bottom:-4px}
@keyframes sworbit{to{transform:rotate(360deg)}}
@keyframes swbreathe{0%,100%{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.1)}}
/* 三列网格:左右两列给卡,中间 76px 是动画道 —— 与卡同级的真实空间,不被覆盖 */
.dossiers{position:relative;z-index:1;display:grid;grid-template-columns:minmax(0,1fr) 76px minmax(0,1fr);row-gap:16px}
.dossiers > .dossier:nth-of-type(odd){grid-column:1}
.dossiers > .dossier:nth-of-type(even){grid-column:3}
.dossier{display:flex;flex-direction:column;gap:11px;background:#fff;border:1px solid var(--line-soft);border-radius:16px;padding:15px 16px 14px;box-shadow:0 8px 22px rgba(18,38,63,.09);transition:box-shadow .18s,transform .18s}
.dossier:hover{transform:translateY(-2px);box-shadow:0 12px 28px rgba(18,38,63,.13)}
.dz-top{display:flex;align-items:center;gap:12px}
.dz-top .csvg{width:64px;flex:none}
.dz-id{display:flex;flex-direction:column;gap:4px;min-width:0}
.dz-role{display:flex;gap:6px;flex-wrap:wrap}
.dz-pn{font-size:15px;font-weight:800;overflow-wrap:anywhere;line-height:1.3}
.dz-pn .jc-vcell{font-size:15px;font-weight:800;color:var(--ink)}
.dz-type{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:8px 10px;border-radius:10px;background:var(--acc-wash);border:1px solid var(--acc-line)}
.dz-lb{flex:none;font-style:normal;font-size:10.5px;font-weight:800;letter-spacing:.05em;color:var(--ink-4)}
.dz-type .jc-cell{flex:1 1 140px;width:auto}
/* 类型名守卫:这一行的下拉真有选中项(selectCurrent 按行作用域写的 option[selected])才摆名 ——
行里没选,data-by 落回外层的名一个字都不摆,换「待选择」胶囊。
守卫挂在共同祖先 .dz-type 上、单层 :has —— :has() 里再嵌 :has() 是非法选择器,整条会被浏览器
静默丢弃(第一版就栽在这:守卫写了等于没写,XL 那张卡照样摆出它没有的类型)。 */
.tsel{flex:1 1 auto;min-width:0}
.tsel > span > i{display:inline-block;font-size:11.5px;font-weight:800;color:var(--acc-deep);background:var(--acc-soft);border-radius:999px;padding:1px 11px}
.dz-type:not(:has(option[selected])) .tsel > span{display:none}
.dz-type:not(:has(option[selected])) .tsel::after{content:"待选择 · 点「编辑」挑一个";display:inline-block;font-size:11px;font-weight:700;color:var(--amber);background:var(--amber-soft);border:1px dashed #eeda9e;border-radius:999px;padding:1px 10px}
.dz-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px 12px}
.fcell{display:flex;flex-direction:column;gap:3px;min-width:0}
.fcell.wide{grid-column:1 / -1}
.fcell > i{font-style:normal;font-size:10.5px;font-weight:800;letter-spacing:.05em;color:var(--ink-4)}
.fcell.req > i::after{content:" *";color:var(--danger)}
.fcell .jc-vcell{font-size:12.5px}
/* 三级占位:必填红 / 建议橘(空格子直说要不要填,不摆一枚含糊的破折号) */
.fcell.req .jc-vcell:empty::after{content:"必填";font-size:10.5px;font-weight:800;color:var(--danger);background:var(--danger-soft);border-radius:999px;padding:0 9px}
/* 徽标包装的必填格(如生命周期):没值时徽标 class 恰为裸 "stx"(class-of 没投出 v-*),
wrapper 不为 :empty,上一条够不着 —— 认裸 class 补同一枚胶囊(单层 :has) */
.fcell.req .jc-vcell:has(> [class="stx"])::after{content:"必填";font-size:10.5px;font-weight:800;color:var(--danger);background:var(--danger-soft);border-radius:999px;padding:0 9px}
.fcell.sug .jc-vcell:empty::after{content:"建议";font-size:10.5px;font-weight:800;color:var(--amber);background:var(--amber-soft);border-radius:999px;padding:0 9px}
/* 档案卡的编辑态 —— **按卡开,只点亮这张卡的正面**(2026-08-31 用户:「各自编辑各自的部分,
不要做联动」:.on 由 scopedTargets 落在被点那张卡的行 section 上,不再落整个宿主);
只圈 .front 是因为卡背住着另一地址的宿主,不圈的话参数输入会被主数据的编辑顺手点亮 */
.dossier.on .front .jc-vcell{display:none}
.dossier.on .front .jc-vcell.ro{display:block}
.dossier.on .front .jc-cell{display:block}
.dossier.on .front .jc-vcell:empty::after{content:none}
.dossier.on .dz-role{display:flex}
/* ── 翻面(纯 CSS:checkbox + :has,零脚本;reduced-motion 下瞬时切换)── */
.dossier{position:relative;perspective:1200px;padding:0;background:none;border:0;box-shadow:none}
.dossier:hover{transform:none;box-shadow:none}
.flip-in{display:grid;transform-style:preserve-3d;transition:transform .55s cubic-bezier(.3,.7,.3,1)}
.face{grid-area:1 / 1;display:flex;flex-direction:column;gap:11px;background:#fff;border:1px solid var(--line-soft);border-radius:16px;padding:15px 16px 14px;box-shadow:0 8px 22px rgba(18,38,63,.09);backface-visibility:hidden;min-width:0}
.face.back{transform:rotateY(180deg)}
.flip-tg{position:absolute;opacity:0;pointer-events:none}
.flip-hit{position:absolute;inset:0;z-index:3;cursor:pointer}
.flip-cue{position:absolute;z-index:4;bottom:10px;right:10px;pointer-events:none;opacity:.6;transition:opacity .16s,transform .16s}
.flip-cue i{font-style:normal;display:inline-block;font-size:10.5px;font-weight:800;color:var(--acc-deep);background:var(--acc-soft);border:1px solid var(--acc-line);border-radius:999px;padding:2px 10px}
.dossier:hover .flip-cue{opacity:1;transform:translateY(-2px)}
/* 两句提示按面切换 —— 选择器都写到 .flip-cue i 之下的同层级,别被基座那条特异度压回来(踩过) */
.flip-cue .cue-back{display:none}
/* 翻转三态,后写的赢:人点的 < 主数据编辑锁正面 < 参数编辑翻背面 */
.dossier:has(.flip-tg:checked) .flip-in{transform:rotateY(180deg)}
.dossier:has(.flip-tg:checked) .flip-cue .cue-front{display:none}
.dossier:has(.flip-tg:checked) .flip-cue .cue-back{display:inline-block}
.dossier.on .flip-in{transform:rotateY(0deg)}
.dossier:has(.pback.on) .flip-in{transform:rotateY(180deg)}
/* 编辑中的**这张卡**不许翻(哪面在编辑锁哪面),点击层与提示丸一起收;另一张卡不受影响 */
.dossier.on .flip-hit,.dossier:has(.pback.on) .flip-hit{display:none}
.dossier.on .flip-cue,.dossier:has(.pback.on) .flip-cue{display:none}
/* 悬浮侧倾:预告「这张卡点了会翻」—— 只在读态、只在真有悬浮的设备、且不嫌动画的人那里 */
@media (hover:hover) and (prefers-reduced-motion: no-preference){
.dossier:hover:not(.on):not(:has(.flip-tg:checked)):not(:has(.pback.on)) .flip-in{transform:rotateY(-12deg)}
.dossier:hover:not(.on):has(.flip-tg:checked):not(:has(.pback.on)) .flip-in{transform:rotateY(168deg)}
}
/* ── 卡角编辑钮:笔=编辑当前这一面,软盘=保存,叉=放弃(2026-08-31 用户定,顶掉两行编辑闸)──
笔只在待处理态露面(html.editable,与从前的闸同一条纪律);软盘/叉只在对应面的编辑态露面。 */
.fabs{position:absolute;top:10px;right:10px;z-index:5;display:flex;gap:6px}
.fab{display:none;width:32px;height:32px;border-radius:999px;border:1px solid var(--acc-line);background:#fff;color:var(--acc-deep);cursor:pointer;place-items:center;padding:0;box-shadow:0 4px 12px rgba(18,38,63,.14);transition:border-color .16s,color .16s,box-shadow .16s}
.fab:hover{border-color:var(--acc);box-shadow:0 6px 16px rgba(18,38,63,.22)}
.fab:active{transform:scale(.94)}
.fic{width:15px;height:15px;display:block;margin:auto}
.fab.pen{color:var(--acc-deep)}
.fab.disk{background:var(--acc);border-color:var(--acc);color:#fff}
.fab.xbtn{color:var(--ink-3)}
/* 笔:这张卡当下这一面、且这张卡没在编辑 —— 各卡各开,互不联动 */
html.editable .dossier:not(.on):not(:has(.pback.on)):not(:has(.flip-tg:checked)) .pen-f{display:grid}
html.editable .dossier:not(.on):not(:has(.pback.on)):has(.flip-tg:checked) .pen-b{display:grid}
.dossier.on .disk-f{display:grid}
.dossier.on .x-f{display:grid}
.dossier:has(.pback.on) .disk-b{display:grid}
.dossier:has(.pback.on) .x-b{display:grid}
/* ── 卡背:参数瓷贴 ── */
.pb-hd{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
.pb-hd b{font-size:14px;font-weight:800;color:var(--ink)}
.pb-lb{font-size:10.5px;font-weight:800;letter-spacing:.08em;color:var(--ink-4)}
.pback{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.ptile{display:flex;flex-direction:column;gap:2px;border:1px solid var(--line-soft);border-radius:10px;background:var(--soft);padding:8px 10px;min-width:0}
.pt-hd{display:flex;align-items:baseline;gap:6px;min-width:0}
.pt-hd .jc-vcell{font-size:11px;font-weight:800;color:var(--ink-3)}
.pt-unit{font-style:normal;font-size:10px;color:var(--ink-4);font-family:var(--mono)}
.pt-val .jc-vcell{font-size:14px;font-weight:800;color:var(--ink)}
.pt-note .jc-vcell{font-size:10.5px;color:var(--ink-3)}
/* 三级占位:值必填红 / 说明建议橘 */
.ptile .pv .jc-vcell:empty::after{content:"必填";font-size:10.5px;font-weight:800;color:var(--danger);background:var(--danger-soft);border-radius:999px;padding:0 9px}
/* 说明空着**什么都不摆**(2026-08-31 用户:「没写就什么都不要展示」)—— 连兜底破折号一起收 */
.ptile .sg .jc-vcell:empty{display:none}
/* 参数编辑态:值与说明换输入,参数名照旧当标签摆着;两枚主键孪生件藏死(钥匙不是编辑面)。
藏钥匙用包装类(.pt-name / .rowkey),不用「data-col 属性选择器」—— 那段选择器文本会原样
出现在共享样式表里,把「落账确认全只读」那类字面断言踩翻(2026-08-31 踩过,连注释也不许写)。 */
.pback.on .pv > .jc-vcell,.pback.on .sg > .jc-vcell{display:none}
.pback.on .pv > .jc-cell,.pback.on .sg > .jc-cell{display:block}
.pback .pt-name .jc-cell{display:none}
.pt-name{display:inline-flex;min-width:0}
/* ================= 比对基准卡(类型 + 字段合一,只读、跟手)================= */
.basis{display:block;margin:0 0 10px}
.basis:empty{border:1.5px dashed var(--line);border-radius:12px;padding:16px;display:block}
.basis:empty::after{content:"还没定比对基准 —— 先在上面任一张档案卡上挑一个芯片类型,或展开下面的抽屉新建一个。";font-size:12.5px;color:var(--ink-3)}
.basis-in{display:flex;flex-direction:column;gap:10px;border:1px solid var(--acc-line);border-radius:12px;background:var(--acc-wash);padding:12px 14px 14px}
.basis-hd{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.basis-lb{flex:none;font-size:10.5px;font-weight:800;letter-spacing:.08em;color:var(--acc-deep)}
.basis-chip b{display:inline-block;font-size:13px;font-weight:800;color:#fff;background:var(--acc);border-radius:999px;padding:2px 14px;margin-right:8px}
.basis-desc{font-style:normal;font-size:11.5px;color:var(--ink-3)}
.basis-hd:has(.basis-chip:empty)::after{content:"待选择";font-size:11px;font-weight:700;color:var(--amber);background:var(--amber-soft);border:1px dashed #eeda9e;border-radius:999px;padding:1px 10px}
.basis-hd .csvg{width:56px;flex:none}
/* 类型图:层叠双封装 —— 后面那枚是「同类的别的芯片」,淡出成剪影 */
.basis-hd .tsvg{width:60px;flex:none}
.tsvg{display:block}
.t-ghost{opacity:.32}
.basis-id{display:flex;flex-direction:column;gap:5px;min-width:0;flex:1 1 auto}
.basis-in:has(.ftiles:empty) .ftiles{display:none}
/* 降噪(2026-08-31 用户:「乱糟糟…没必要显示全就不要显示完全,鼠标指上去后再显示」):
字段收成一排丸(名 + 硬/软徽 + 单位),说明藏进悬浮气泡 —— 指上去才现身 */
.ftiles{display:flex;flex-wrap:wrap;gap:8px}
.ftile{position:relative;display:flex;flex-direction:row;align-items:center;gap:7px;border:1px solid var(--line-soft);border-radius:999px;background:#fff;padding:6px 13px;min-width:0;transition:border-color .16s,box-shadow .16s}
.ftile:hover{border-color:var(--acc-line);box-shadow:0 4px 12px rgba(18,38,63,.1)}
.ft-hd{display:flex;align-items:baseline;gap:7px;white-space:nowrap}
.ft-hd b{font-size:12px;font-weight:800;color:var(--ink)}
.ft-unit{font-style:normal;font-size:10px;color:var(--ink-4);font-family:var(--mono)}
.ft-desc{display:none;position:absolute;z-index:6;top:calc(100% + 7px);left:0;width:max-content;max-width:280px;margin:0;font-size:11px;line-height:1.65;color:var(--ink-2);background:#fff;border:1px solid var(--line);border-radius:9px;padding:8px 11px;box-shadow:0 10px 24px rgba(18,38,63,.16)}
.ftile:hover .ft-desc:not(:empty){display:block}
/* 类型说明:默认一行截断,悬浮题头才放开 */
.basis-desc{display:block;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.basis-hd:hover .basis-desc{white-space:normal}
/* ================= 新建类型工作抽屉(details,零脚本)================= */
.lab{margin:0 0 6px;border:1.5px dashed var(--line);border-radius:12px;background:var(--soft)}
.lab[open]{border-style:solid;background:#fff}
.lab-sm{cursor:pointer;list-style:none;display:flex;align-items:center;gap:8px;padding:11px 14px;font-size:12.5px;color:var(--ink-3);user-select:none}
.lab-sm::-webkit-details-marker{display:none}
.lab-sm b{color:var(--ink-2)}
.lab-sm:hover{color:var(--acc-deep)}
.lab-caret{margin-left:auto;flex:none;width:8px;height:8px;border-right:2px solid var(--ink-4);border-bottom:2px solid var(--ink-4);transform:rotate(45deg);transition:transform .16s}
.lab[open] .lab-caret{transform:rotate(-135deg)}
.lab-bd{padding:2px 14px 14px}
.lab-brief{margin:0 0 16px}
.lab-brief .brief{margin:2px 14px 14px;border-left-width:3px}
/* ================= 窄屏 ================= */
@media(max-width:620px){
.card-head{padding:16px 14px 18px}
.dz-grid{grid-template-columns:1fr}
.swapfx{display:none}
.dossiers{grid-template-columns:1fr}
.dossiers > .dossier:nth-of-type(odd),.dossiers > .dossier:nth-of-type(even){grid-column:1}
.pback{grid-template-columns:1fr}
.ftiles{grid-template-columns:1fr}
.card-bd{padding:16px 14px 6px}
.hero-title{font-size:19.5px}
.stage{gap:14px}
.hchip{min-width:108px;padding:10px 8px 9px}
.csvg{width:68px}
.kv i{flex-basis:72px}
.card-foot{padding:10px 14px}
}
`;