:root{
  --bg:#12141a; --panel:#1a1d25; --panel2:#222633; --line:#2e3342;
  --fg:#e6e9f0; --dim:#8b93a7;
  --sig:#7aa2ff; --model:#4ea3ff; --human:#39d98a; --coach:#ffb454; --warn:#ff6b6b;
  --accent:#5b8cff;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%;background:var(--bg);color:var(--fg);
  font:13px/1.45 -apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}
.grow{flex:1}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.dim{color:var(--dim)}

header{display:flex;align-items:center;gap:14px;padding:8px 14px;background:var(--panel);
  border-bottom:1px solid var(--line);flex-wrap:wrap}
.brand{font-weight:700;letter-spacing:.3px}
header label{color:var(--dim);display:flex;align-items:center;gap:5px}
input,select{background:var(--panel2);color:var(--fg);border:1px solid var(--line);
  border-radius:5px;padding:4px 7px;font:inherit}
input[type=checkbox]{accent-color:var(--accent)}
button{background:var(--panel2);color:var(--fg);border:1px solid var(--line);border-radius:5px;
  padding:5px 10px;cursor:pointer;font:inherit}
button:hover{border-color:#4a536b}
button.primary{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:600}
button.primary:hover{filter:brightness(1.1)}
button.wide{width:100%}
kbd{background:#0d0f14;border:1px solid var(--line);border-bottom-width:2px;border-radius:3px;
  padding:0 4px;margin-left:5px;font:11px/1.4 ui-monospace,monospace;color:var(--dim)}
.pill{background:var(--panel2);border:1px solid var(--line);border-radius:99px;padding:3px 11px}

#app{display:flex;height:calc(100vh - 45px);overflow:hidden}

/* ---------- segment list ---------- */
#list{width:262px;min-width:262px;overflow-y:auto;background:var(--panel);
  border-right:1px solid var(--line)}
.vidHead{padding:5px 10px;background:#151821;color:var(--dim);font-weight:600;
  position:sticky;top:0;border-bottom:1px solid var(--line);font-size:12px}
.seg{padding:6px 10px;border-bottom:1px solid #23283400;border-left:3px solid transparent;
  cursor:pointer;display:flex;gap:6px;align-items:baseline}
.seg:hover{background:#20242f}
.seg.sel{background:#263049;border-left-color:var(--accent)}
.seg .ex{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.seg .n{color:var(--dim);font-family:ui-monospace,monospace;font-size:12px}
.seg .st{width:14px;text-align:center}
.seg.suspect .n{color:var(--warn);font-weight:700}
.seg.novid{opacity:.4}

/* ---------- main ---------- */
main{flex:1;display:flex;flex-direction:column;overflow:hidden;padding:0 12px 10px}
#segbar{display:flex;align-items:center;gap:10px;padding:8px 2px;font-weight:600}
#coachHint{color:var(--coach);font-weight:600}
#coachHint.bad{color:var(--warn)}

#stage{display:flex;gap:12px;min-height:0;flex:1}
#videoWrap{position:relative;background:#000;border-radius:8px;overflow:hidden;
  display:flex;align-items:center;justify-content:center;flex:1;min-width:0}
#v{max-width:100%;max-height:100%;display:block}
/* HUD 是压在画面上的浮层：不封宽度它就跟着最长那行一直长，把人挡住（竖屏尤其明显）。
   封了宽度长句子自己折行，宁可多几行也别横着盖过去。 */
#hud{position:absolute;top:10px;left:12px;background:#000a;border-radius:8px;padding:6px 12px;
  text-align:center;pointer-events:none;max-width:min(36%,380px)}
#hudSub,#hudMix,#hudExec{white-space:normal;overflow-wrap:anywhere}
#hudCount{font:700 30px/1 ui-monospace,monospace;color:var(--human)}
#hudSub{font-size:10px;color:var(--dim);letter-spacing:.5px}
#hudMix{font:12px/1.4 ui-monospace,monospace;color:#7fc4ff}
#hudExec{font:700 13px/1.35 ui-monospace,monospace;color:#ffb454;min-height:0;margin-top:2px}
.repnow{font-size:14px;color:var(--human);font-family:ui-monospace,monospace}
#execCard .row kbd{margin-left:3px}
#tapFlash{position:absolute;inset:0;background:var(--human);opacity:0;pointer-events:none;
  transition:opacity .12s}
#tapFlash.on{opacity:.16;transition:none}

#side{width:298px;min-width:298px;overflow-y:auto;display:flex;flex-direction:column;gap:8px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:9px}
.cardTitle{color:var(--dim);font-size:11px;margin-bottom:6px;font-weight:600}
.row{display:flex;gap:6px;margin-bottom:6px;align-items:center}
.row:last-child{margin-bottom:0}
.row button{flex:1}
.row.big{justify-content:space-between;text-align:center}
.row.big>div{flex:1}
.row.big label{display:block;color:var(--dim);font-size:11px}
.row.big b{font:700 24px/1.2 ui-monospace,monospace}
.hnum{color:var(--human)}
#dCount.off{color:var(--warn)}
label.inline{display:flex;align-items:center;gap:6px;color:var(--dim);flex:1}
label.inline input[type=number]{flex:1;width:100%}
.verdicts button{font-size:12px}
button.v.on{outline:2px solid currentColor}
.v.agree{color:var(--human)} .v.corr{color:var(--sig)} .v.bad{color:var(--warn)}
#note{width:100%}
#savedMsg{color:var(--human);font-size:11px;min-height:14px}
#coachList{max-height:190px;overflow-y:auto;font-size:12px}
.cs{display:flex;gap:7px;padding:2px 0;border-bottom:1px solid #22273300;cursor:pointer}
.cs:hover{background:#20242f}
.cs .t{color:var(--coach);font-family:ui-monospace,monospace;min-width:44px}
.cs.num .x{color:var(--coach);font-weight:700}

#ctrls{display:flex;gap:6px;align-items:center;padding:8px 0 6px;flex-wrap:wrap}
#ctrls .sp{color:var(--dim);margin-left:8px}
button.rate.active{background:var(--accent);border-color:var(--accent);color:#fff}
#tl{width:100%;background:var(--panel);border:1px solid var(--line);border-radius:8px;
  display:block;cursor:crosshair}
.legendBar{display:flex;gap:10px;align-items:center;padding:4px 2px}
#legendBtn{font-size:11px;padding:3px 9px;color:var(--dim)}
#legendBtn.on{color:var(--fg);border-color:#4a536b}
#legendHint{font-size:11px}
.legend{display:flex;gap:14px;align-items:center;color:var(--dim);font-size:11px;padding:5px 2px;
  flex-wrap:wrap;border-top:1px solid var(--line);margin-top:2px}
.legend[hidden]{display:none}   /* display:flex 会盖过 hidden 属性，跟 .modal 一个坑 */
.sw{display:inline-block;width:10px;height:10px;border-radius:2px;margin-right:4px;
  vertical-align:-1px}
.sw.sig{background:var(--sig)} .sw.model{background:var(--model)}
.sw.human{background:var(--human)} .sw.coach{background:var(--coach)}

/* ---------- modals ---------- */
.modal{position:fixed;inset:0;background:#000b;display:flex;align-items:center;
  justify-content:center;z-index:50}
.modal[hidden]{display:none}   /* display:flex would otherwise beat the hidden attribute
                                  and leave an invisible full-screen click blocker */
.modalBox{background:var(--panel);border:1px solid var(--line);border-radius:10px;
  width:min(880px,92vw);max-height:86vh;overflow:auto;padding:14px}
.modalHead{display:flex;align-items:center;margin-bottom:10px}
table{border-collapse:collapse;width:100%;font-size:12px;margin-bottom:14px}
th,td{border-bottom:1px solid var(--line);padding:4px 8px;text-align:right}
th:first-child,td:first-child{text-align:left}
th{color:var(--dim);font-weight:600}
table.kv td{text-align:left;border:none;padding:3px 8px}

#toast{position:fixed;bottom:18px;left:50%;transform:translateX(-50%) translateY(14px);
  background:#1f6b45;border:1px solid #39d98a;color:#eafff3;padding:8px 16px;border-radius:8px;
  opacity:0;pointer-events:none;transition:opacity .18s,transform .18s;z-index:60;font-weight:600}
#toast.on{opacity:1;transform:translateX(-50%) translateY(0)}
h4{margin:12px 0 6px;font-size:13px}

a.lnk{color:var(--accent);text-decoration:none;font-size:12px}
a.lnk:hover{text-decoration:underline}

.kinds button{font-size:12px;opacity:.55;flex:1}
.kinds button.on{opacity:1;outline:2px solid currentColor}
.kinds button[data-kind=intro]{color:#8b93a7}
.kinds button[data-kind=set]{color:#4ea3ff}
.kinds button[data-kind=rest]{color:#ff6b6b}
.kinds button[data-kind=transition]{color:#1fb8ab}
#clsRng{font-family:ui-monospace,monospace;font-weight:400}

#blockList{margin-top:6px;font-size:12px}
#blockList .sr{display:flex;gap:8px;padding:2px 0;border-bottom:1px solid #23283340;cursor:pointer}
#blockList .sr:hover{background:#20242f}
#blockList .sr.on{background:#263049}
#blockList .sr.empty .c{color:#ff6b6b;font-weight:400}
#execSrc.bad{color:#ff6b6b}
#blockList .sr .no{color:#4ea3ff;font-weight:600;min-width:96px;max-width:120px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#blockList .sr .t{color:var(--dim);font-family:ui-monospace,monospace;flex:1}
#blockList .sr .c{color:var(--human);font-weight:700;font-family:ui-monospace,monospace}
#blockList .tot{color:var(--dim);padding-top:4px}
#blockList .tot.warn{color:#ff6b6b;cursor:pointer;text-decoration:underline dotted #ff6b6b66}
#blockList .tot.warn:hover{background:#2a1a1a}
#newSetBtn small{color:var(--dim);font-weight:400;margin-left:4px}

.warnpill{background:#4a2020;border-color:var(--warn);color:#ffd7d7;font-weight:600}
/* 定稿：整页进入只读态，一眼看得出「这段不能改了」 */
.lockpill{background:#2b3a24;border-color:#7ac74f;color:#d8f5c4;font-weight:600}
body.locked #tl{opacity:.72}
body.locked #commitMsg{color:#9fd77a}
#commitBtn{border-color:#7ac74f;color:#d8f5c4}
#whoFile{font-variant-numeric:tabular-nums}

#list .n.done{color:var(--human);font-weight:600}
/* 判定那一遍的进度，直接写在段列表行里 */
.seg .jn{color:var(--coach);font-family:ui-monospace,monospace;font-size:11px;
  white-space:nowrap}
.seg .jn.ok{color:var(--human)}
/* 标注里混了别的动作的段:名字写成 a + b,和语料原名区分开 */
.seg .ex.mixed{color:#4ea3ff}

/* 「这一段是什么动作、多少组」——混进别的动作时逐个列出,不同名的用粉色(和时间轴同色) */
#segSum{display:flex;flex-wrap:wrap;gap:3px 7px;align-items:baseline;
  padding:1px 2px 7px;border-bottom:1px solid var(--line);margin-bottom:8px;font-size:12px}
#segSum .act{color:#4ea3ff;font-weight:600;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;max-width:210px}
#segSum .act.alt{color:#ff9ad2}
#segSum .cnt{color:var(--human);font-weight:700;font-family:ui-monospace,monospace}
#segSum .sep{color:#4a5265}

/* ---------- 逐次判断 ---------- */
/* 进判定模式就把判定卡拉到侧栏最上面（flex order，不动 DOM 顺序）——
   第二遍要用的卡片本来排在第三张、在折叠线以下，滚不到就等于没有。 */
body.judging #jgCard{order:-1}
#jgEnter{border-color:#ffd47955;color:#ffd479}
body.judging #jgEnter{background:#3a3115;border-color:#ffd479}
#jgCard.on{border-color:#ffd47955}
body.judging #jgCard{border-color:#ffd479;box-shadow:0 0 0 1px #ffd47933}
#jgNow{font-size:13px}
#jgNow.warn{color:var(--warn)}
.jgQ{display:flex;gap:4px;margin-bottom:6px}
.jgQ button{flex:1;min-width:0;padding:5px 2px;font-size:12px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.jgQ button kbd{margin-left:3px}
.jgQ button.on{outline:2px solid currentColor}
.jgQ button[data-q=aborted]{color:var(--coach)}
.jgQ button[data-q=below_basic]{color:var(--warn)}
.jgQ button[data-q=suboptimal]{color:#ff9ad2}
/* 方向按钮不禁用（直接按就能一步判成「不好」），但没在「不好」上时压暗，
   免得看着像四类之外还有别的选项 */
.jgAxis button.dimmed{opacity:.45}
/* 判定卡片的说明文字默认收起（同图例）：看懂一次之后它们只是在挤地方 */
.jgTitle{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
#jgHintBtn{font-size:10px;padding:1px 6px;color:var(--dim);margin-left:auto}
#jgHintBtn.on{color:var(--fg);border-color:#4a536b}
#jgCard.nohint .jgHint{display:none}
/* 判定层三层,每层一个小标题 —— 不分开的话「跟谁比」会糊成一片(§9.1) */
.jgSec{font-size:11px;font-weight:600;color:var(--fg);margin:8px 0 4px;
  border-top:1px solid var(--line);padding-top:6px}
.jgQ + .jgSec, .jgAxis + .jgSec{margin-top:8px}
/* 整段的原话都列出来了（教练说一次管好几组），给足高度免得老要滚 */
#jgCmt{max-height:230px;overflow-y:auto;margin-bottom:5px}
.cmt{display:flex;gap:6px;align-items:baseline;padding:3px 4px;border-radius:4px;
  cursor:pointer;font-size:11px;border:1px solid transparent}
.cmt:hover{background:#20242f}
.cmt.on{background:#1d3a2a;border-color:var(--human)}
.cmt .mk{color:var(--dim);width:11px;flex:none}
.cmt.on .mk{color:var(--human)}
.cmt.far{opacity:.62}
.cmt.far.on{opacity:1}
.cmtDiv{color:var(--dim);font-size:10px;margin:5px 0 2px;border-top:1px dashed var(--line);
  padding-top:4px}
.cmt .x{flex:1;color:var(--fg)}
.cmt.own{background:#2a2540;border-color:#a98bff}
.cmt.own .mk{color:#a98bff}
.cmt .del{color:var(--dim);flex:none;padding:0 3px}
.cmt .del:hover{color:var(--warn)}
.cmtAdd{gap:4px;margin-top:2px}
.cmtAdd #jgCmtOwn{flex:1;min-width:0}
.cmtAdd button{flex:none;font-size:11px;padding:3px 8px}
.cmt kbd{flex:none}
#jgAtt{margin-bottom:5px}       /* 挂上的那几条:可改、可拖、可删,不进会滚的候选框 */
.cmt.att{cursor:default}
.cmt.att .x{cursor:text}
.cmt .grip{color:var(--dim);flex:none;cursor:grab;font-size:10px}
.cmt.att.over{outline:2px solid var(--accent)}
.cmt .ed{color:var(--dim);flex:none;padding:0 3px;cursor:pointer}
.cmt .ed:hover{color:var(--fg)}
/* 定稿(🔒)之后 comment 照样列出来,只是只读 —— 看得见、hover 还能看到改自哪句原话,
   但不给任何「能点」的暗示(没有 ⠿ / ✎ / ✕,也没有 text 光标) */
.cmt.att.ro{opacity:.8}
.cmt.att.ro .x{cursor:default}
.cmtEdit{flex:1;min-width:0;font-size:11px;padding:1px 4px}
#jgCmtOwn{width:100%;font-size:11px}
/* 参照系写在轴的头上,不写在按钮里 —— 「跟谁比」是这一层最容易标歪的地方(§9.1) */
.jgQ button .qsub{display:block;font-size:9px;color:var(--dim);line-height:1.1}
.jgAxisHead{font-size:11px;color:var(--fg);margin:6px 0 3px}
.jgAxis{display:flex;gap:3px;align-items:center;margin-bottom:6px}
.jgAxis .ax{color:var(--dim);font-size:11px;min-width:26px;flex:none}
/* 键位竖排在标签下面。一行放不下「明显慢 ⇧5」,而挤掉的必定是键位（宽度靠右）——
   竖排以后两样都完整,代价只是这一栏高一点。 */
.jgAxis button{flex:1;min-width:0;padding:3px 1px;font-size:11px;line-height:1.25;
  display:flex;flex-direction:column;align-items:center;gap:1px}
.jgAxis button kbd{margin:0;padding:0 3px;font-size:10px}
.jgHint{font-size:10px;margin:-2px 0 6px 28px}
.jgHint code{font-size:10px}
.jgAxis button.on{outline:2px solid var(--coach);color:var(--coach)}
#jgOkAll.on{outline:2px solid #fff}
#jgAbort.on{outline:2px solid var(--coach);color:var(--coach)}
#jgBad.on{outline:2px solid #ff9ad2;color:#ff9ad2}
#jgRef{font-size:11px;margin-top:2px}
#jgProg{font-size:11px;margin-top:3px;font-variant-numeric:tabular-nums}
#jgProg.okmsg{color:var(--human);font-weight:600}
#hudJg{font:12px/1.35 ui-monospace,monospace;color:#ffd479;white-space:normal;
  overflow-wrap:anywhere;margin-top:2px}

/* ---------------------------------------------------------------- v3 ---- */
/* 示范页:一条横幅 + 全局只读。只读本身走的是「已定稿🔒」那条路(锁上什么都改不了),
   这里只是把「存盘/定稿/解锁」这些没意义的入口藏掉,免得点了报错。 */
#demoBar{background:#2a2540;border-bottom:1px solid #a98bff;color:var(--fg);
  padding:6px 14px;font-size:12px}
#demoBar[hidden]{display:none}
body.demo #saveBtn, body.demo #commitBtn, body.demo #unlockBtn,
body.demo #dirty, body.demo #dsLabel{display:none}
body.demo #lockPill{background:#2a2540;border-color:#a98bff}
header #whoName{color:var(--human)}
/* 锁着的时候按钮是 disabled 的,但样式上看不出来 —— 示范页整页都锁着,一排亮蓝的按钮
   点了没反应,新人只会以为坏了。灰下去就一目了然。 */
button:disabled{opacity:.4;cursor:not-allowed}
/* 图例里两种语言各一块（长文分块写才看得清）。块本身不参与布局:
   display:contents 让里面的 <span> 照旧当 flex 子项,布局一个字不用改。 */
.legend > .lang-en, .legend > .lang-zh{display:contents}
.legend > [hidden]{display:none}
