/* ==========================================================================================
   screens/lobby.css — the hub (official entry backdrop, the emblem in its radar and the title, 成就统计 / 密钥加入 /
   作战提示 at the left, the light S.W.E.E.P.报告 / 干员调配 plates at the right, the 独立模拟 / 同盟模拟 entries at the
   bottom right), and the two full-screen dialogs (the project's Modal): 选择模拟协议 (official picture, difficulty cards
   with the 已选定 stamp, 开始独立模拟 — or the room's 确认 / read-only view) and 选择同盟方式 (radar, 创建同盟 and 加入同盟
   cards). Text follows 文字大小 (calc(k * var(--t))).
   ========================================================================================== */

/* ---- 我方定制（0.3.2 大厅重做后重新贴回）：.lobby-screen 顶栏的自有布局 --------------------------------
   上游在 css/components.css 里另有一套 .lobby-screen .topbar 网格（本次合并未采用，理由见该文件末尾的说明），
   这里保留我方实现：左右两组可横向滚动、中间标题限宽居中。 */
/* Balanced tool columns keep the heading at the viewport center and the profile on one row. */
.lobby-screen .topbar { height: auto; min-height: 1.1rem; padding-block: .1rem; gap: .16rem; }
.lobby-screen .topbar__left { justify-self: stretch; overflow-x: auto; gap: .08rem; }
.lobby-screen .topbar__left > * { flex: none; }
.lobby-screen .topbar__center { min-width: 0; max-width: 4rem; }
.lobby-screen .topbar__center > * { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lobby-screen .topbar__title { display: block; }
.lobby-screen .topbar__right { flex-wrap: nowrap; justify-self: stretch; max-width: 100%; overflow-x: auto; gap: .08rem; }
.lobby-screen .topbar__right > :first-child { margin-left: auto; }
.lobby-screen .topbar__right > * { flex: none; }
.lobby-screen .topbar > :is(.topbar__left, .topbar__right) > .btn { padding-inline: .1rem; }
.lobby-screen .me-chip__name { max-width: 1.6rem; }

/* ---- hub backdrop ------------------------------------------------------------------------------------- */
/* the entries' width follows 文字大小 (2.3rem at 小; §35.18 review: at a fixed 2.3rem the names had to stop at 小's size) */
.lobby-hub { --hub-entry-w: calc(2.3 * var(--t)); --hub-gap: .14rem; background: #050807; }
/* Korean breaks between words, not between the syllables of one (§35.18 review: 「독립 시뮬레이|션」 at 小); a word too
   long for its box still breaks rather than running out of it. The hub's own stage only: 选择模拟协议's button keeps its
   two lines (「독립 시뮬레이션 시작」 took three at 特大 in a 1024×600 window by words) */
.lobby-hub:lang(ko) .hub-stage { word-break: keep-all; overflow-wrap: break-word; }
/* Japanese never starts a line with a small kana, ー or a closing mark (§35.18 review: the tips' 「オペレ|ーター」 at 中 / 特大
   in a 1024×600 window; line-break: normal allows a break before them), as in the room */
.lobby-hub:lang(ja) .hub-stage { line-break: strict; }
/* a last line of one character: the hub's tips, the protocol dialog's paragraphs and its big button's label wrap `pretty`
   (§35.18 review of the text-fit fixes: 「比較的所要時間が短いシミュレーショ|ン」 on a phone at 特大, 「単独演算を開|始」,
   Korean 「독립 시뮬레이션 시|작」 on desktops). Scoped as in the room (room.css): WebKit's `pretty` adds lines to short
   labels, and the lobby's other dialogs were not measured with it. The dialog's button only (`.proto-foot`): the room's
   big button shares the label's class and wraps plainly — in Safari `pretty` broke its Japanese 「シミュレーション|開始」
   inside the word, 「シミュレー|ション開始」, at 小 on the phones (review of 6f34f380), as `balance` had. `pretty`:
   Chrome 117+, Safari 26+; Firefox wraps as before */
.tips__text, .proto-brief p, .proto-hint, .proto-foot .proto-start__label { text-wrap: pretty; }
/* 选择同盟方式's note breaks Japanese between phrases in Chrome 119+ (BudouX; review of 6f34f380: 「…教えてもらう|か、招待リンク…」
   at 特大 on the phones, now 「…教えて|もらうか、招待リンクを|直接開いてください」); Safari and Firefox ignore it and wrap as
   before */
.ally-recent:lang(ja) { word-break: auto-phrase; }
/* the top bar's ping pill grows with its text at 大 / 特大, as in the room (§35.18 review: its fixed .32rem cut it) */
.lobby-hub > .topbar .ping { height: auto; min-height: .32rem; padding-top: 1px; padding-bottom: 1px; }
.hub-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  background:
    radial-gradient(55% 60% at 50% 48%, rgba(96, 170, 186, .14), transparent 72%),
    linear-gradient(180deg, #08100f, #040606 82%);
}
/* the official layers are drawn on black: `screen` keeps only their light. Their place, size and opacity below are
   eyeballed from the event video [ASSUMED: no official layout data] */
.hub-bg__glow, .hub-bg__ship { position: absolute; left: 50%; height: auto; transform: translate(-50%, -50%); mix-blend-mode: screen; }
.hub-bg__glow { top: 46%; width: 9.6rem; opacity: .2; }
.hub-bg__ship { top: 54%; width: 13.4rem; opacity: .4; animation: hub-ship 18s ease-in-out infinite alternate; }
@keyframes hub-ship { to { transform: translate(-50%, calc(-50% - .1rem)); } }
.hub-bg__grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, .028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, .028) 1px, transparent 1px);
  background-size: .6rem .6rem;
  -webkit-mask-image: radial-gradient(70% 70% at 50% 50%, #000 30%, transparent 85%);
  mask-image: radial-gradient(70% 70% at 50% 50%, #000 30%, transparent 85%);
}
.lobby-hub .topbar { background: linear-gradient(180deg, rgba(4, 8, 8, .85), transparent); border-bottom: 0; }

/* ---- 大厅背景与音乐 (PR #643 split 8, ui/lobbyMedia.js): the player's own picture / video over the official layers,
   darkened by its 暗度 (--own-dim) so the title and the entries stay readable; the dialog reuses the settings rows ---- */
.hub-bg__own { position: absolute; inset: 0; background: #050807; animation: hub-own-in 400ms ease-out backwards; }
.hub-bg__own img, .hub-bg__own video, .hub-bg__own canvas { display: block; width: 100%; height: 100%; object-fit: cover; }
.hub-bg__own::after { content: ''; position: absolute; inset: 0; background: rgba(5, 8, 7, var(--own-dim, .35)); }
@keyframes hub-own-in { from { opacity: 0; } }
.lmedia .modal__body { display: flex; flex-direction: column; gap: .16rem; }
.lmedia__part { display: flex; flex-direction: column; gap: .1rem; padding: .14rem .16rem; border: 1px solid var(--line); background: rgba(0, 0, 0, .25); }
.lmedia__head { display: flex; align-items: baseline; gap: .1rem; font-size: calc(.18 * var(--t)); color: var(--text-hi); }
.lmedia__now { display: flex; align-items: center; gap: .08rem; min-width: 0; font-size: calc(.16 * var(--t)); color: var(--text-md); }
.lmedia__now .icon { flex: none; width: .2rem; height: .2rem; color: var(--mint-500); }
.lmedia__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lmedia__size { flex: none; font-size: calc(.14 * var(--t)); color: var(--text-lo); }
.lmedia__btns { display: flex; flex-wrap: wrap; align-items: center; gap: .1rem; }
.lmedia__btns .set-toggle { grid-column: auto; }
.lmedia__dim { padding: 0 .16rem; }
.lmedia__note { display: flex; gap: .06rem; margin: 0; font-size: calc(.15 * var(--t)); line-height: 1.6; color: var(--text-lo); }
.lmedia__note .icon { flex: none; width: .18rem; height: .18rem; margin-top: .04rem; }

/* 大厅场景 (ui/hubScene.js): four generated scenes over the official backdrop; colour tokens per scene ---------- */
[data-hub-theme="night"] {
  --sky-0: #03080a; --sky-1: #08141a; --sky-2: #12262a; --sky-3: #050909;
  --haze: rgba(92, 168, 156, .17); --cloud: rgba(140, 196, 186, .055);
  --ridge-far: #122022; --ridge-mid: #0b1516; --ridge-near: #060b0b;
  --rim: rgba(110, 226, 196, .34); --fog: rgba(54, 104, 98, .3); --beam: rgba(150, 240, 215, .1);
  --beacon: #59f4ca; --window: rgba(89, 244, 202, .7); --grid: rgba(89, 244, 202, .32);
  --mote: rgba(170, 245, 225, .7);
}
/* the official backdrop's swatch: its dark field and glow */
[data-hub-theme="official"] {
  --sky-0: #08100f; --sky-1: #0c1a1b; --sky-2: #1b3134; --sky-3: #040606;
  --ridge-far: transparent; --ridge-mid: transparent; --ridge-near: transparent; --beacon: rgba(150, 220, 230, .7);
}
[data-hub-theme="frost"] {
  --sky-0: #070c12; --sky-1: #142029; --sky-2: #34444f; --sky-3: #090d11;
  --haze: rgba(205, 226, 240, .2); --cloud: rgba(220, 236, 246, .08);
  --ridge-far: #3a4852; --ridge-mid: #212c34; --ridge-near: #0f1418;
  --rim: rgba(240, 248, 255, .62); --fog: rgba(180, 200, 214, .24); --beam: rgba(225, 240, 255, .12);
  --beacon: #9fd8ff; --window: rgba(170, 220, 255, .7); --grid: rgba(170, 215, 240, .26);
  --mote: rgba(240, 248, 255, .85);
}
[data-hub-theme="ember"] {
  --sky-0: #080605; --sky-1: #120d0b; --sky-2: #251913; --sky-3: #070505;
  --haze: rgba(196, 104, 52, .15); --cloud: rgba(130, 96, 76, .08);
  --ridge-far: #211814; --ridge-mid: #150f0c; --ridge-near: #090606;
  --rim: rgba(255, 150, 80, .28); --fog: rgba(84, 52, 38, .32); --beam: transparent;
  --beacon: #ffae48; --window: rgba(255, 168, 80, .75); --grid: rgba(255, 170, 90, .22);
  --mote: rgba(255, 150, 70, .85);
}
[data-hub-theme="calm"] {
  --sky-0: #040606; --sky-1: #070b0b; --sky-2: #0c1211; --sky-3: #040505;
  --haze: rgba(80, 120, 110, .07); --cloud: transparent;
  --ridge-far: #0e1514; --ridge-mid: #090e0e; --ridge-near: #050808;
  --rim: rgba(89, 244, 202, .14); --fog: rgba(30, 50, 46, .25); --beam: transparent;
  --beacon: #4ed8af; --window: rgba(78, 216, 175, .45); --grid: rgba(89, 244, 202, .22);
  --mote: transparent;
}

.hub-scene { position: absolute; inset: 0; pointer-events: none; overflow: hidden; background: var(--sky-3); }
.hub-bg__sky { position: absolute; inset: 0;
  background: linear-gradient(180deg, var(--sky-0) 0%, var(--sky-1) 36%, var(--sky-2) 63%, var(--sky-3) 100%); }
.hub-bg__stars { position: absolute; left: 0; top: 0; width: 1px; height: 1px; border-radius: 50%;
  animation: hub-twinkle 7s ease-in-out infinite alternate; }
.hub-bg__haze { position: absolute; inset: 0;
  background: radial-gradient(ellipse 80% 20% at 50% 64%, var(--haze), transparent 72%),
    radial-gradient(ellipse 130% 36% at 50% 72%, var(--haze), transparent 70%); }
.hub-bg__clouds { position: absolute; left: 0; top: 6%; width: 200%; height: 50%;
  background:
    radial-gradient(30% 10% at 15% 42%, var(--cloud), transparent 70%),
    radial-gradient(22% 7% at 38% 20%, var(--cloud), transparent 70%),
    radial-gradient(36% 11% at 66% 58%, var(--cloud), transparent 70%),
    radial-gradient(20% 6% at 88% 28%, var(--cloud), transparent 70%);
  background-size: 50% 100%; background-repeat: repeat-x; animation: hub-drift 180s linear infinite; }
.hub-bg__land { position: absolute; left: 0; bottom: 0; width: 100%; height: 64%; overflow: visible; }
.hub-bg__ridge--far { fill: var(--ridge-far); }
.hub-bg__ridge--mid, .hub-bg__fort { fill: var(--ridge-mid); }
.hub-bg__ridge--near { fill: var(--ridge-near); }
.hub-bg__rim { fill: none; stroke: var(--rim); stroke-width: 1.2; vector-effect: non-scaling-stroke; }
.hub-fog-0 { stop-color: var(--fog); stop-opacity: 0; }
.hub-fog-1 { stop-color: var(--fog); stop-opacity: 1; }
.hub-beam-0 { stop-color: var(--beam); }
.hub-beam-1 { stop-color: var(--beam); stop-opacity: 0; }
.hub-bg__beam { transform-origin: 791px 300px; animation: hub-beam 16s ease-in-out infinite alternate; }
.hub-bg__windows rect { fill: var(--window); animation: hub-window 9s steps(1) infinite; animation-delay: var(--dl); }
.hub-bg__beacons g { fill: var(--beacon); animation: hub-beacon 2.8s ease-in-out infinite; animation-delay: var(--dl); }
.hub-bg__beacon-glow { opacity: .22; }
.hub-bg__motes { position: absolute; inset: 0; }
.hub-bg__mote { position: absolute; border-radius: 50%; background: var(--mote); box-shadow: 0 0 6px var(--mote); opacity: 0;
  animation: hub-mote var(--d) linear infinite; animation-delay: var(--dl); }
[data-hub-theme="frost"] .hub-bg__mote { animation-name: hub-snow; }
@keyframes hub-twinkle { from { opacity: .5; } to { opacity: 1; } }
@keyframes hub-drift { to { transform: translateX(-50%); } }
@keyframes hub-beam { from { transform: rotate(-18deg); } to { transform: rotate(24deg); } }
@keyframes hub-window { 0%, 70% { opacity: .9; } 72%, 78% { opacity: .2; } 80%, 100% { opacity: .9; } }
@keyframes hub-beacon { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
@keyframes hub-mote { 0% { transform: translate3d(0, 0, 0); opacity: 0; } 15% { opacity: .8; } 85% { opacity: .45; } 100% { transform: translate3d(2vw, -18vh, 0); opacity: 0; } }
@keyframes hub-snow { 0% { transform: translate3d(0, -12vh, 0); opacity: 0; } 15% { opacity: .9; } 85% { opacity: .7; } 100% { transform: translate3d(-3vw, 14vh, 0); opacity: 0; } }
.bgset__swatch { position: relative; display: block; width: 100%; aspect-ratio: 16 / 9; overflow: hidden;
  background: linear-gradient(180deg, var(--sky-0), var(--sky-1) 40%, var(--sky-2) 66%, var(--sky-3)); }
.bgset__swatch svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.bgset__swatch .sw-far { fill: var(--ridge-far); }
.bgset__swatch .sw-mid { fill: var(--ridge-mid); }
.bgset__swatch .sw-near { fill: var(--ridge-near); }
.bgset__swatch .sw-beacon { fill: var(--beacon); }

/* the scene buttons of 大厅背景与音乐 */
.bgset__themes { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: .1rem; }
.bgset__theme {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .05rem;
  min-width: 0;
  padding: .06rem;
  font: inherit;
  text-align: left;
  color: var(--text-hi);
  cursor: pointer;
  background: rgba(223, 230, 226, .04);
  border: 1px solid rgba(223, 230, 226, .14);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.bgset__theme:hover { border-color: var(--mint-a35); }
.bgset__theme.is-selected { border-color: var(--mint-400); box-shadow: inset 0 0 0 1px var(--mint-400), 0 0 .14rem var(--mint-a20); }
.bgset__name { font-size: calc(.15 * var(--t)); font-weight: 800; white-space: nowrap; }
.bgset__en { font: 700 calc(.09 * var(--t)) / 1 ui-monospace, Consolas, monospace; letter-spacing: .14em; color: var(--text-dim); white-space: nowrap; }


/* ---- 我方定制（0.3.2 大厅重做后重新贴回）：模式卡片基线 + 折叠的「训练场」细条卡片 -------------------
   上游 0.3.2 把大厅改成了 hub，删掉了 .mode-cards / .mode-card 整套；我方 lobby.js 仍在用它们
   （mode-cards 容器、mode-card.is-compact 的细条、mode-card__badge「建设中」），故整套贴回。 */
/* ---- mode cards ------------------------------------------------------------------------------------ */
.mode-cards { display: grid; grid-template-columns: 1fr 1fr; gap: .24rem; margin-bottom: .34rem; }
.mode-card {
  --bk-c: transparent;
  --bk-l: .2rem;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .22rem;
  min-height: 4.3rem;
  padding: .34rem .32rem .3rem;
  overflow: hidden;
  text-align: left;
  background: linear-gradient(180deg, rgba(28, 34, 31, .92), rgba(13, 16, 15, .94));
  border: 1px solid var(--line);
  color: var(--text-hi);
  transition: border-color var(--t-med) var(--ease-out), box-shadow var(--t-med) var(--ease-out), transform var(--t-fast) var(--ease-out);
  animation: card-in var(--t-slow) var(--ease-out) backwards;
}
.mode-card:nth-child(2) { animation-delay: 60ms; }
.mode-card__bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(70% 55% at 100% 0%, rgba(78, 216, 175, .10), transparent 70%),
    repeating-linear-gradient(-45deg, rgba(255, 255, 255, .018) 0 2px, transparent 2px 12px),
    linear-gradient(transparent 70%, rgba(0, 0, 0, .35));
  transition: opacity var(--t-med);
}
.mode-card::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--mint-500), transparent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-slow) var(--ease-out);
}
.mode-card__icon {
  position: relative;
  width: .88rem;
  height: .88rem;
  display: grid;
  place-items: center;
  background: #0c0f0e;
  border: 1px solid var(--line-2);
  color: var(--text-md);
  clip-path: polygon(25% 0, 75% 0, 100% 50%, 75% 100%, 25% 100%, 0 50%);
  transition: background var(--t-med), color var(--t-med);
}
.mode-card__icon .icon { width: .44rem; height: .44rem; }
.mode-card__text { position: relative; display: flex; flex-direction: column; gap: .1rem; }
.mode-card__name { font-size: calc(.46 * var(--t)); font-weight: 900; letter-spacing: .08em; line-height: 1.1; }

/* 折叠的模式卡片（训练场，服主 2026-10-16）：整行细条 —— 图标 + 标题 + 建设中标签一行放下，
   高度从 4.3rem 压到约 .6rem。选中后才展开成正常卡片（描述 + 要点）。功能不受影响。 */
.mode-card__badge {
  display: inline-block; margin-left: .1rem; padding: 0 .07rem; vertical-align: middle;
  border: 1px solid var(--warn-500, #e8a33d); color: var(--warn-500, #e8a33d);
  font-size: calc(.11 * var(--t)); font-weight: 700; letter-spacing: .06em; line-height: 1.5;
  border-radius: 2px; white-space: nowrap;
}
.mode-card.is-compact {
  min-height: 0 !important;         /* 压掉 .mode-card 的 4.3rem 与 .lobby-screen 的 3.2rem */
  height: calc(.56 * var(--t));     /* 定死细条高度，不再被内容/网格撑开（半宽，留在网格一列里） */
  max-height: calc(.56 * var(--t));
  flex-direction: row;
  align-items: center;
  gap: .14rem;
}
/* 上下边距必须相等。注意：.lobby-screen .mode-card 那条规则在文件更后面，会把 padding 改成 .24/.22
   （上大下小 → 内容看着往下偏），所以这里用「.lobby-screen + 两个类」提高优先级压过去。 */
.lobby-screen .mode-card.is-compact { padding: .1rem .2rem; }
.lobby-screen .mode-card.is-compact.is-selected { padding: .34rem .32rem .3rem; }
.mode-card.is-compact .mode-card__text {
  flex-direction: row; align-items: center; gap: .08rem;
  flex-wrap: nowrap; white-space: nowrap; min-width: 0;
}
/* 半宽里要塞下「图标 + 英文 + 训练场 + 建设中」，所以每一块都收一点；靠 nowrap 保证不换行 */
.mode-card.is-compact .mode-card__text .micro { font-size: calc(.11 * var(--t)); letter-spacing: .1em; }
.mode-card.is-compact .mode-card__icon { width: .3rem; height: .3rem; flex: none; }
.mode-card.is-compact .mode-card__icon .icon { width: .18rem; height: .18rem; }
.mode-card.is-compact .mode-card__name { font-size: calc(.26 * var(--t)); letter-spacing: .04em; white-space: nowrap; }
.mode-card.is-compact .mode-card__badge { font-size: calc(.1 * var(--t)); margin-left: .02rem; }
/* 未选中：只留"训练场 + 建设中"，其余隐藏 */
.mode-card.is-compact:not(.is-selected) .mode-card__desc,
.mode-card.is-compact:not(.is-selected) .mode-card__points { display: none; }
.mode-card.is-compact:not(.is-selected) .mode-card__check { position: static; margin-left: auto; }
/* 选中后恢复成正常卡片的纵向排布与留白（高度也要放开） */
.mode-card.is-compact.is-selected {
  height: auto; max-height: none; min-height: 4.3rem !important;
  flex-direction: column; align-items: flex-start; gap: .22rem; padding: .34rem .32rem .3rem;
}
.mode-card.is-compact.is-selected .mode-card__text { flex-direction: column; align-items: flex-start; gap: .1rem; }
.mode-card.is-compact.is-selected .mode-card__icon { width: .66rem; height: .66rem; }
.mode-card.is-compact.is-selected .mode-card__icon .icon { width: .34rem; height: .34rem; }
.mode-card.is-compact.is-selected .mode-card__name { font-size: calc(.46 * var(--t)); letter-spacing: .08em; }
.mode-card__desc { font-size: calc(.17 * var(--t)); color: var(--text-lo); line-height: 1.65; max-width: 3.6rem; }
.mode-card__points { display: flex; flex-direction: column; gap: .05rem; margin-top: .06rem; font-size: calc(.15 * var(--t)); color: var(--text-md); }
.mode-card__points span::before {
  content: '';
  display: inline-block;
  width: .06rem;
  height: .06rem;
  margin: 0 .1rem .02rem 0;
  background: var(--mint-700);
  transform: rotate(45deg);
  vertical-align: middle;
}
.mode-card__check {
  position: absolute;
  top: .2rem;
  right: .2rem;
  display: flex;
  align-items: center;
  gap: .05rem;
  padding: .04rem .12rem .04rem .08rem;
  background: var(--mint-500);
  color: var(--text-on-mint);
  font-size: calc(.14 * var(--t));
  font-weight: 700;
  opacity: 0;
  transform: translateY(-.06rem);
  transition: opacity var(--t-med), transform var(--t-med) var(--ease-out);
}
.mode-card__check .icon { width: .16rem; height: .16rem; }
.mode-card:hover { border-color: var(--line-3); --bk-c: var(--line-3); }
.mode-card:active { transform: translateY(1px); }
.mode-card.is-selected {
  --bk-c: var(--mint-400);
  border-color: var(--mint-700);
  box-shadow: 0 0 0 1px rgba(78, 216, 175, .22), 0 0 .44rem rgba(23, 249, 183, .13), inset 0 0 .7rem rgba(23, 249, 183, .05);
}
.mode-card.is-selected::before { transform: scaleX(1); }
.mode-card.is-selected .mode-card__icon { background: var(--mint-500); border-color: var(--mint-400); color: var(--text-on-mint); }
.mode-card.is-selected .mode-card__check { opacity: 1; transform: none; }

/* （.mode-card 用到的 @keyframes card-in 由上游在本文件下方定义，这里不重复。） */

/* ---- hub layout: the centre spans the first row; both columns lie above it -------------------------- */
.hub-stage {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 4rem) minmax(0, 1fr) minmax(0, calc(var(--hub-entry-w) * 2 + var(--hub-gap)));
  grid-template-rows: minmax(0, 1fr) auto;
  grid-template-areas: "side center right" "side entries entries";
  gap: .2rem .4rem;
  width: 100%;
  padding: .1rem .36rem .36rem;
}

.hub-center {
  grid-row: 1;
  grid-column: 1 / -1;
  align-self: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .1rem;
  min-width: 0;
  text-align: center;
  pointer-events: none;
  animation: card-in var(--t-slow) var(--ease-out) backwards;
}
.hub-center__mark { position: relative; display: grid; place-items: center; min-height: 1.4rem; margin-bottom: .1rem; }
.hub-center__logo { position: relative; width: 1.3rem; height: auto; filter: drop-shadow(0 0 .12rem rgba(210, 255, 240, .25)); }
.hub-center__mark .emblem { position: relative; margin-bottom: 0; }
.hub-center__en { position: relative; font-family: var(--font-display); font-size: calc(.17 * var(--t)); letter-spacing: .32em; color: rgba(223, 230, 226, .72); text-shadow: 0 1px .08rem rgba(0, 0, 0, .85); }
.hub-center__en b { color: var(--mint-400); font-weight: 700; }
.hub-center__title {
  position: relative;
  margin: 0;
  /* follows 文字大小 while it fits on one line beside the side columns (larger, it ran under the left column's tips —
     §35.18 review): the centre is the stage's width (100vw less its .72rem padding) and the title's box 8.8rem less (below);
     7 CJK characters with their spacing are 7.4–8em, so it stops at that box / 8.2 (never below .56rem at 小); the latin
     title below */
  font-size: min(calc(.56 * var(--t)), calc((100vw - 9.52rem) / 8.2));
  font-weight: 900;
  letter-spacing: .14em;
  line-height: 1.15;
  color: var(--text-hi);
  text-shadow: 0 .04rem .3rem rgba(0, 0, 0, .8);
  overflow-wrap: anywhere;
}
.hub-center__title em { font-style: normal; color: var(--mint-400); }
.hub-center__title--latin { font-family: var(--font-display); letter-spacing: .04em; text-transform: uppercase; }
/* the title is centred over the whole stage: it keeps clear of the side columns (4rem and its gap each side), and the
   latin one — 「STRONGHOLD PROTOCOL: ALLIANCE」, 20em of the display font — is .46 × --t while it fits on one line
   inside that, (100vw − 9.52rem) / 20.2 (§35.18 review: at .56rem it reached under the left column's tips in English, at
   大 / 特大 in 800–1280 px windows; pinned at .46rem it no longer followed 文字大小). [ASSUMED] the .46 */
.hub-center__title { max-width: calc(100% - 8.8rem); }
.hub-center__title--latin { font-size: min(calc(.46 * var(--t)), calc((100vw - 9.52rem) / 20.2)); }
/* the radar rings around the emblem (original drawing) */
.hub-radar { position: absolute; left: 50%; top: 50%; width: 4.6rem; height: 4.6rem; transform: translate(-50%, -50%); }
.hub-radar svg { width: 100%; height: 100%; overflow: visible; fill: none; stroke: rgba(89, 244, 202, .15); stroke-width: 1; }
.hub-radar .hub-radar__ticks { stroke-width: 5; stroke-dasharray: 1.4 9.8; }
.hub-radar__sweep {
  position: absolute;
  inset: 5.4%;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 292deg, rgba(89, 244, 202, .15) 360deg);
  -webkit-mask-image: radial-gradient(circle, transparent 0 17%, #000 18%);
  mask-image: radial-gradient(circle, transparent 0 17%, #000 18%);
  animation: hub-sweep 9s linear infinite;
}
@keyframes hub-sweep { to { transform: rotate(1turn); } }

/* ---- left column: 成就统计, 密钥加入, 作战提示 ------------------------------------------------------------ */
.hub-side { grid-area: side; position: relative; z-index: 1; display: flex; flex-direction: column; gap: .14rem; min-width: 0; padding-top: .3rem; }
/* 成就统计 (#643's top-left card, from the event video): a dusk scene with the emblem and the trophy medal, the label strip
   with the LV under it */
.hub-ach {
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  padding: 0;
  font: inherit;
  text-align: left;
  color: #eef3f1;
  cursor: pointer;
  background: #0c1110;
  border: 1px solid rgba(220, 230, 226, .16);
  box-shadow: 0 .04rem .16rem rgba(0, 0, 0, .45);
  transition: border-color var(--t-fast), filter var(--t-fast);
}
.hub-ach:hover, .hub-ach:focus-visible { border-color: rgba(78, 216, 175, .35); filter: brightness(1.08); outline: none; }
.hub-ach:focus-visible { box-shadow: 0 0 0 2px var(--mint-400); }
.hub-ach__scene { position: relative; height: 1rem; overflow: hidden; display: grid; place-items: center; }
.hub-ach__land { position: absolute; inset: 0; width: 100%; height: 100%; }
.hub-ach__scene::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(0deg, rgba(0, 0, 0, .18) 0 1px, transparent 1px 3px), linear-gradient(90deg, rgba(8, 10, 10, .55), transparent 40%);
}
.hub-ach__mark { position: relative; z-index: 1; display: grid; place-items: center; }
.hub-ach__mark .emblem { margin: 0; gap: .06rem; animation: none; }
.hub-ach__mark .emblem__svg { width: .52rem; height: .56rem; filter: drop-shadow(0 0 .04rem rgba(0, 0, 0, .6)); }
.hub-ach__mark .emblem__svg circle { fill: #15110c; animation: none; }
.hub-ach__mark .emblem__svg circle.is-accent { fill: #2cf0b8; }
.hub-ach__mark .emblem__bracket { width: .07rem; height: .66rem; border-width: 1px; border-color: rgba(20, 16, 10, .55); }
.hub-ach__rank {
  position: absolute;
  left: .1rem;
  top: .1rem;
  z-index: 2;
  width: .6rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .01rem;
  padding: .04rem 0 .03rem;
  background: rgba(14, 18, 17, .55);
  border: 1px solid rgba(240, 244, 243, .4);
}
.hub-ach__medal { width: .44rem; height: .44rem; object-fit: contain; }
.hub-ach__rank > .icon { width: .3rem; height: .3rem; color: #eef3f1; }
.hub-ach__rank small { display: inline-flex; align-items: center; gap: .02rem; font-size: min(calc(.13 * var(--t)), .15rem); color: #e6ebe9; }
.hub-ach__rank small .icon { width: .12rem; height: .12rem; }
.hub-ach__label {
  position: relative;
  display: flex;
  align-items: center;
  gap: .08rem;
  flex-wrap: wrap;
  min-height: .46rem;
  padding: .02rem .16rem;
  font-size: calc(.21 * var(--t));
  font-weight: 700;
  background: linear-gradient(90deg, rgba(20, 26, 25, .96), rgba(14, 18, 17, .96));
  border-top: 1px solid rgba(220, 230, 226, .14);
}
.hub-ach__label::before, .hub-ach__label::after { content: ''; position: absolute; top: .06rem; bottom: .06rem; width: .06rem; border: 1px solid rgba(220, 230, 226, .3); }
.hub-ach__label::before { left: .04rem; border-right: 0; }
.hub-ach__label::after { right: .04rem; border-left: 0; }
.hub-ach__badge { flex: none; width: .24rem; height: .24rem; fill: #e8eeec; }
.hub-ach__lv { margin-left: auto; font-size: calc(.15 * var(--t)); font-weight: 600; color: var(--mint-400); }
.hub-tile {
  display: flex;
  align-items: center;
  gap: .14rem;
  width: 100%;
  min-height: .74rem;
  padding: .1rem .16rem;
  text-align: left;
  color: var(--text-hi);
  background: rgba(8, 14, 13, .8);
  border: 1px solid rgba(223, 230, 226, .2);
  border-left: 3px solid var(--mint-500);
  transition: background var(--t-fast), border-color var(--t-fast);
}
.hub-tile:hover, .hub-tile:focus-visible { background: rgba(24, 40, 36, .9); border-color: var(--mint-a35); }
.hub-tile__icon { flex: none; display: grid; place-items: center; width: .44rem; height: .44rem; border: 1px solid var(--mint-a35); color: var(--mint-400); }
.hub-tile__icon .icon { width: .24rem; height: .24rem; }
.hub-tile__text { display: flex; flex-direction: column; gap: .02rem; min-width: 0; }
.hub-tile__label { font-size: calc(.2 * var(--t)); font-weight: 800; }
.hub-tile__en { font-family: ui-monospace, Consolas, monospace; font-size: calc(.1 * var(--t)); font-weight: 600; letter-spacing: .18em; color: var(--text-dim); }
.hub-side .tips { margin-top: .04rem; background: rgba(8, 14, 13, .72); }

/* ---- right column: light plates with bracket marks (S.W.E.E.P.报告, 干员调配 = loadout.js's LoadoutButton) --------- */
.hub-right { grid-area: right; position: relative; z-index: 1; align-self: start; display: flex; flex-direction: column; gap: .12rem; min-width: 0; padding-top: .3rem; }
.lobby-hub .hub-plate {
  --pl-ink: #222b28;
  --bk-c: var(--mint-400);
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: .14rem;
  width: 100%;
  height: auto;
  min-height: .7rem;
  min-width: 0;
  padding: .04rem .22rem .04rem .2rem;
  font: inherit;
  font-size: calc(.2 * var(--t));
  letter-spacing: .04em;
  color: #111816;
  text-align: left;
  cursor: pointer;
  background:
    linear-gradient(var(--pl-ink), var(--pl-ink)) left .07rem center / 2px 54% no-repeat,
    linear-gradient(var(--pl-ink), var(--pl-ink)) left .07rem top 23% / .06rem 2px no-repeat,
    linear-gradient(var(--pl-ink), var(--pl-ink)) left .07rem bottom 23% / .06rem 2px no-repeat,
    linear-gradient(var(--pl-ink), var(--pl-ink)) right .07rem center / 2px 54% no-repeat,
    linear-gradient(var(--pl-ink), var(--pl-ink)) right .07rem top 23% / .06rem 2px no-repeat,
    linear-gradient(var(--pl-ink), var(--pl-ink)) right .07rem bottom 23% / .06rem 2px no-repeat,
    linear-gradient(180deg, #e8edea, #c6cfcb);
  border: 1px solid rgba(255, 255, 255, .5);
  box-shadow: 0 .05rem .18rem rgba(0, 0, 0, .5), inset 0 -2px 0 rgba(0, 0, 0, .14);
}
.lobby-hub .hub-plate:not(:disabled):hover { border-color: #fff; box-shadow: 0 .05rem .22rem rgba(0, 0, 0, .55), 0 0 .16rem rgba(78, 216, 175, .3); filter: brightness(1.05); }
.lobby-hub .hub-plate:focus-visible { outline: 2px solid var(--mint-400); outline-offset: 2px; }
.hub-plate__glyph, .lobby-hub .hub-plate .lo-entry__icon, .lobby-hub .hub-plate > .btn__icon {
  flex: none;
  display: grid;
  place-items: center;
  width: .46rem;
  height: .46rem;
  padding: .07rem;
  box-sizing: border-box;
  color: var(--mint-400);
  background: #182120;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08);
}
.hub-plate__glyph svg { width: 100%; height: 100%; }
/* (a label too long for its plate wraps beside its glyph and the plate grows, rather than an ellipsis — §35.18 review:
   Japanese S.W.E.E.P.レポート beside its tag at 特大 in 800–1280 px windows. It takes the row's free width, at least its
   longest word, so only the tag drops under it when even that does not fit) */
.hub-plate__label, .lobby-hub .hub-plate .btn__label { flex: 1 1 0; min-width: min-content; font-weight: 900; letter-spacing: .04em; line-height: 1.15; white-space: normal; color: #111816; }
.hub-plate__tag { margin-left: auto; padding: .03rem .07rem; font-size: calc(.11 * var(--t)); font-weight: 700; letter-spacing: .12em; color: rgba(17, 24, 22, .6); border: 1px solid rgba(17, 24, 22, .28); white-space: nowrap; }
.lobby-hub .hub-plate .lo-entry__n { margin-left: auto; }
/* 成就统计 as a plate: only on short screens, where the left column with its card gives way (see the media block) */
.lobby-hub .hub-plate--ach { display: none; }
.hub-plate--ach .hub-plate__glyph svg { fill: currentColor; }

/* ---- entries (独立模拟 / 同盟模拟), bottom right ----------------------------------------------------------- */
/* (the card, the line above it, the tips' head and the 成就统计 card's label grow or wrap rather than cut their text at
   大 / 特大 in a small window — §35.18 review; the trophy count under the medal stops at .15rem, 大's size [ASSUMED]) */
/* (the two cards share a height: the taller one's, their text at the bottom) */
.hub-entries { grid-area: entries; position: relative; z-index: 1; display: flex; align-items: stretch; justify-content: flex-end; gap: var(--hub-gap); min-width: 0; }
.hub-entry-wrap { display: flex; flex-direction: column; gap: .05rem; min-width: 0; animation: card-in var(--t-slow) var(--ease-out) backwards; }
.hub-entry-wrap:nth-child(2) { animation-delay: 60ms; }
.hub-entry__group { display: flex; align-items: center; gap: .06rem; min-height: .22rem; padding-left: .04rem; font-size: calc(.13 * var(--t)); color: rgba(223, 230, 226, .7); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hub-entry__group .icon { flex: none; width: .16rem; height: .16rem; color: var(--mint-400); }
.hub-entry__long { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.hub-entry__short { display: none; }
/* Narrow desktop windows keep the full descriptions (phones have their own short labels below).
   [ASSUMED] A shared two-line minimum keeps both cards level when only one description wraps. */

.hub-entry {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  flex: 1 0 auto;
  width: var(--hub-entry-w);
  max-width: 100%;
  min-height: calc(1.34 * var(--t));
  padding: .14rem .16rem;
  /* the icon's height kept above the text (below) */
  padding-top: calc(.12rem + .42 * var(--t) + .04rem);
  overflow: hidden;
  text-align: left;
  color: var(--text-hi);
  background: linear-gradient(160deg, rgba(30, 46, 42, .94), rgba(9, 15, 14, .96));
  border: 1px solid rgba(223, 230, 226, .26);
  box-shadow: 0 .06rem .24rem rgba(0, 0, 0, .5);
  transition: transform var(--t-fast), border-color var(--t-fast), box-shadow var(--t-fast);
}
.hub-entry:hover, .hub-entry:focus-visible { transform: translateY(-.04rem); border-color: var(--mint-400); box-shadow: 0 .08rem .3rem rgba(0, 0, 0, .55), 0 0 .2rem var(--mint-a20); }
.hub-entry:active { transform: translateY(1px); }
.hub-entry__icon { position: absolute; right: .14rem; top: .12rem; color: var(--mint-a35); }
.hub-entry__icon .icon { width: calc(.42 * var(--t)); height: calc(.42 * var(--t)); }
/* the card, its icon and its text follow 文字大小 together (2.3 × 1.34 --t, the icon .42 --t), as at 小; the text stays
   below the icon — the card's top padding is the icon's .12rem offset, its height and a gap — so a long name or the
   decorative line grows the card rather than running under it (§35.18 review: 「ALLIANCE SIMULATION」 ran under the
   people icon in English, Korean names under it at 大 / 特大; a padding beside it instead wrapped the line in every
   language, Chinese 「ALLIANCE / SIMULATION」 at 小, which never reached the icon). A short card keeps its min-height */
.hub-entry__en { font-family: ui-monospace, Consolas, monospace; font-size: calc(.11 * var(--t)); font-weight: 700; letter-spacing: .22em; color: var(--mint-400); }
/* the name wraps between words (§35.18 review: on one line English 「Solo Simulation」 / 「Team Simulation」 ran 25–40 px
   past the 2.3rem card at 小 in every window and 84–100 px at 特大, the card cutting it); 「Simulation」 alone is ~6.2em,
   and the card (2.3 × --t) keeps ~1.98 × --t inside for the .3 × --t name */
.hub-entry__name { margin-top: .04rem; font-size: calc(.3 * var(--t)); font-weight: 900; letter-spacing: .06em; line-height: 1.1; }
.hub-entry__corner { position: absolute; right: 0; bottom: 0; width: .3rem; height: .3rem; background: linear-gradient(135deg, transparent 50%, var(--mint-500) 50%); opacity: .8; }
/* 同盟模拟, the main way to play: bright */
.hub-entry--coop { background: linear-gradient(160deg, var(--mint-500), #1f8f72); color: #04140f; border-color: var(--mint-400); }
.hub-entry--coop .hub-entry__en { color: rgba(4, 20, 15, .75); }
.hub-entry--coop .hub-entry__icon { color: rgba(4, 20, 15, .25); }
.hub-entry--coop .hub-entry__corner { background: linear-gradient(135deg, transparent 50%, #e8fff7 50%); }
@keyframes card-in { from { opacity: 0; transform: translateY(.14rem); } }

/* ---- tips -------------------------------------------------------------------------------------------- */
.tips {
  --bk-c: var(--line-3);
  margin-top: .3rem;
  padding: .16rem .22rem .2rem;
  background: rgba(8, 10, 9, .55);
  border: 1px solid var(--line);
}
.tips__head { display: flex; flex-wrap: wrap; align-items: center; gap: .1rem; font-size: calc(.16 * var(--t)); font-weight: 700; color: var(--text-md); }
.tips__head > .icon { width: .2rem; height: .2rem; color: var(--mint-500); }
/* the count and its arrows move to a line of their own, together, when the head is too narrow for them (§35.18 review) */
.tips__pager { display: inline-flex; align-items: center; gap: .1rem; margin-left: auto; }
.tips__idx { font-size: calc(.16 * var(--t)); color: var(--text-md); }
.tips__nav {
  display: grid;
  place-items: center;
  width: .3rem;
  height: .3rem;
  padding: 0;
  border: 1px solid var(--line-2);
  background: transparent;
  color: var(--text-lo);
  transition: color var(--t-fast), border-color var(--t-fast);
}
.tips__nav:hover { color: var(--mint-400); border-color: var(--mint-700); }
.tips__nav .icon { width: .18rem; height: .18rem; }
.tips__text { margin-top: .1rem; font-size: calc(.17 * var(--t)); color: var(--text-lo); line-height: 1.6; animation: tip-in var(--t-slow) var(--ease-out); }
@keyframes tip-in { from { opacity: 0; transform: translateX(.1rem); } }

/* ---- the two full-screen dialogs (Modal .proto / .ally) --------------------------------------------- */
.modal.proto-veil { padding: 0; background: #0b0c0c; -webkit-backdrop-filter: none; backdrop-filter: none; }
.modal__box.proto, .modal__box.ally {
  position: fixed;
  inset: 0;
  width: auto;
  max-height: none;
  padding: var(--sa-t, 0px) var(--sa-r, 0px) var(--sa-b, 0px) var(--sa-l, 0px);
  color: #eef0ef;
  background: #0b0c0c;
  border: 0;
  box-shadow: none;
  overscroll-behavior: contain;
  animation: proto-in 200ms var(--ease-out) backwards;
}
.modal__box.proto::after, .modal__box.proto > .modal__stripe, .modal__box.ally::after, .modal__box.ally > .modal__stripe { display: none; }
.modal__box.proto > .modal__body, .modal__box.ally > .modal__body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; padding: 0; overflow: hidden; color: inherit; }
.proto__body, .ally__body { position: relative; flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
@keyframes proto-in { from { opacity: 0; } }
.proto__bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
  transition: background 400ms;
  background:
    radial-gradient(46% 60% at 30% 52%, rgba(255, 255, 255, .05), transparent 70%),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .022) 0 1px, transparent 1px 4px),
    linear-gradient(rgba(255, 255, 255, .03) 1px, transparent 1px) 0 0 / 1.1rem 1.1rem,
    linear-gradient(90deg, rgba(255, 255, 255, .03) 1px, transparent 1px) 0 0 / 1.1rem 1.1rem,
    radial-gradient(120% 90% at 50% 40%, #151616, #070808);
  background:
    radial-gradient(46% 60% at 30% 52%, color-mix(in srgb, var(--d-color, #4ed8af) 16%, transparent), transparent 70%),
    radial-gradient(40% 50% at 100% 50%, color-mix(in srgb, var(--d-color, #4ed8af) 10%, transparent), transparent 70%),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .022) 0 1px, transparent 1px 4px),
    linear-gradient(rgba(255, 255, 255, .03) 1px, transparent 1px) 0 0 / 1.1rem 1.1rem,
    linear-gradient(90deg, rgba(255, 255, 255, .03) 1px, transparent 1px) 0 0 / 1.1rem 1.1rem,
    radial-gradient(120% 90% at 50% 40%, #151616, #070808);
}
.proto-top, .proto-body { position: relative; }
.proto-top { flex: none; display: flex; align-items: flex-start; justify-content: space-between; gap: .2rem; padding: .18rem .34rem 0 .22rem; z-index: 2; }
.proto-back {
  display: inline-flex;
  align-items: center;
  height: max(.62rem, 32px, calc(36px * var(--sp-ui, 1)));
  padding: 0;
  font: inherit;
  color: #f2f4f3;
  background: linear-gradient(180deg, #2b2c2d, #1b1c1d);
  border: 1px solid rgba(255, 255, 255, .1);
  box-shadow: 0 .04rem .14rem rgba(0, 0, 0, .5);
}
.proto-back > .icon { width: max(.4rem, 22px); height: max(.4rem, 22px); margin: 0 .3rem 0 .14rem; }
.proto-back__home {
  display: grid;
  place-items: center;
  align-self: stretch;
  width: max(2rem, 32px, calc(96px * var(--sp-ui, 1)));
  border-left: 2px solid #0d0e0e;
  background: radial-gradient(circle, rgba(255, 255, 255, .22) 1px, transparent 1.6px) 0 0 / .14rem .14rem, linear-gradient(90deg, #2f3132, #3d3f40 50%, #2f3132);
}
.proto-back__home .icon { width: max(.32rem, 18px); height: max(.32rem, 18px); }
.proto-back:hover, .proto-back:focus-visible { border-color: rgba(255, 255, 255, .35); }
.proto-title { display: flex; flex-direction: column; align-items: flex-end; gap: .02rem; min-width: 0; padding-top: .06rem; text-align: right; }
.proto-title .modal__title { margin: 0; font-size: calc(.36 * var(--t)); font-weight: 900; letter-spacing: .06em; color: #eef0ef; }
.proto-title__mode { display: inline-flex; align-items: center; gap: .08rem; font-size: calc(.16 * var(--t)); font-weight: 700; color: var(--d-color, var(--mint-400)); }
.proto-title__mode .icon { width: 1.1em; height: 1.1em; }
.proto-title__mode i { font-style: normal; font-family: var(--font-display); font-size: calc(.13 * var(--t)); letter-spacing: .16em; color: #8b8f8e; }

/* the cards' column 5.6rem, at least 300 px (§35.18 review: in a window whose 1rem is under 54 px — 960×540, 1100×530,
   800×600 — the px floors of the glyph and the 文字大小 made 5.6rem too narrow for English 「Standard Simulation」 /
   「Ultimate Simulation」 on one line, and the unselected cards' names ended in an ellipsis), never past 46vw. [ASSUMED] the
   floor */
.proto-body { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) min(max(5.6rem, 32px, calc(300px * var(--sp-ui, 1))), 46vw); gap: .3rem; padding: 0 .34rem .26rem .22rem; }
.proto-stage { position: relative; min-width: 0; min-height: 0; display: grid; place-items: center; }

/* the official picture of the selected difficulty, with its brief at the bottom left */
/* the picture fills the column (as #643's drawn scene did: from a little above the cards down to the brief) */
.proto__pic { position: absolute; inset: -.5rem -1.8rem .9rem -.3rem; display: grid; place-items: center; min-height: 0; animation: proto-pic var(--t-slow) var(--ease-out); }
.proto__art {
  width: 100%;
  height: 100%;
  max-width: 9.4rem; /* the art is 427 × 332: up to about 2.2× before it turns soft */
  max-height: 7.3rem;
  object-fit: contain;
  filter: drop-shadow(0 0 .2rem var(--d-color));
  filter: drop-shadow(0 0 .2rem color-mix(in srgb, var(--d-color) 45%, transparent));
}
.proto__glyph { width: 2.2rem; height: 2.2rem; color: var(--d-color); opacity: .8; filter: drop-shadow(0 0 .2rem var(--d-color)); }
@keyframes proto-pic { from { opacity: 0; transform: translateX(-.14rem); } }

/* the scene (ui/protocolScene.js, PR #643 + video 5:00–5:16): the official ship on a survey grid between two squares of
   defenders, the cable with a light running down it; it reaches under the cards like the event's. A new difficulty
   remounts it: dark first, then up in the new colour. */
.proto-side { position: relative; z-index: 1; }

.ps { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; color: var(--d-color); animation: ps-in 640ms ease-out backwards; }
@keyframes ps-in { 0% { opacity: 0; filter: brightness(.15); } 35% { opacity: .35; filter: brightness(.3); } 100% { opacity: 1; filter: none; } }
.ps-grid line { stroke: currentColor; stroke-opacity: .12; stroke-width: 1; }
.ps-pad polygon { fill: currentColor; fill-opacity: .1; stroke: currentColor; stroke-opacity: .55; stroke-width: 1.2; }
.ps-pad__edge { fill: none; stroke: currentColor; stroke-opacity: .7; stroke-width: 2; stroke-dasharray: 26 8; }
.ps-hull { filter: drop-shadow(0 0 6px var(--d-color)); }
.ps-ship image { filter: drop-shadow(0 0 10px var(--d-color)); filter: drop-shadow(0 0 10px color-mix(in srgb, var(--d-color) 55%, transparent)); }
.ps-face { stroke: currentColor; stroke-width: 1.3; stroke-linejoin: round; fill: currentColor; }
.ps-face--top { fill-opacity: .42; }
.ps-face--front { fill-opacity: .26; }
.ps-face--side { fill-opacity: .16; }
.ps-seam { stroke: #fff; stroke-opacity: .35; stroke-width: 1; }
.ps-beacon { fill: #fff; animation: ps-blink 1.6s steps(2) infinite; }
@keyframes ps-blink { 50% { opacity: .2; } }
.ps-cable { fill: none; stroke: currentColor; stroke-width: 5; stroke-opacity: .7; stroke-linecap: round; }
.ps-cable__pulse { fill: none; stroke: #fff6d8; stroke-width: 6; stroke-linecap: round; stroke-dasharray: 90 1200; stroke-dashoffset: 90;
  filter: drop-shadow(0 0 6px var(--d-color)); animation: ps-pulse 2.6s cubic-bezier(.5, 0, .7, 1) 400ms infinite; }
@keyframes ps-pulse { from { stroke-dashoffset: 90; opacity: 1; } 85% { opacity: 1; } to { stroke-dashoffset: -1000; opacity: 0; } }
.ps-fig { animation: ps-fig 360ms var(--ease-out) backwards; animation-delay: calc(240ms + var(--i) * 18ms); }
@keyframes ps-fig { from { opacity: 0; transform: translateY(-6px); } }
.ps-fig__body, .ps-fig__head { fill: currentColor; fill-opacity: .88; stroke: rgba(0, 0, 0, .45); stroke-width: .8; }
.ps-fig__head { fill-opacity: 1; }
.ps-fig__shadow { fill: #000; opacity: .35; }
.ps-spike polygon { fill: currentColor; fill-opacity: .75; }
.ps-spike__x { stroke: currentColor; stroke-width: 2; stroke-opacity: .8; }
.ps-spike { animation: ps-fig 420ms var(--ease-out) backwards; animation-delay: calc(var(--i) * 60ms + 120ms); }
.ps-call rect { fill: rgba(0, 0, 0, .55); stroke: currentColor; stroke-width: 1.5; }
.ps-call line { stroke: currentColor; stroke-width: 1.5; stroke-opacity: .8; }
.ps-call rect.ps-call__icon { fill: currentColor; fill-opacity: .25; }
.ps-call__man { fill: currentColor; }
.ps-call { animation: ps-fig 420ms var(--ease-out) 420ms backwards; }
.ps-scan { stroke: currentColor; stroke-opacity: .2; stroke-width: 2; animation: ps-scan 7s linear infinite; }
@keyframes ps-scan { from { transform: translateY(40px); } to { transform: translateY(620px); } }
.proto-brief {
  position: absolute;
  left: .1rem;
  bottom: .1rem;
  max-width: min(6rem, 92%);
  padding: .12rem .2rem .14rem;
  background: linear-gradient(90deg, rgba(0, 0, 0, .7), rgba(0, 0, 0, .2));
  border-left: 3px solid var(--d-color);
}
.proto-brief__code { margin-right: .1rem; padding: 0 .08rem; font-size: calc(.14 * var(--t)); color: #111; background: var(--d-color); }
.proto-brief__name { font-size: calc(.26 * var(--t)); color: var(--d-color); }
.proto-brief p { margin: .04rem 0 0; font-size: calc(.16 * var(--t)); line-height: 1.5; color: #b7bcba; }

/* the difficulty cards: the chosen one slides out with a glow and the 已选定 stamp; centred while they fit (auto margins, so
   a list taller than the column still scrolls from its top). The gaps and pads a little tighter than #643's (.14rem, .1rem
   and .1 / .11rem) so the full cards fit at 小 in a 16:9 window (they were 2–26 px too tall at 1280x720 – 1920x1080:
   §35.18's leftover). [ASSUMED] the spacing */
.proto-side { min-height: 0; display: flex; flex-direction: column; gap: .14rem; }
.proto-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
  gap: .1rem;
  padding: .07rem .06rem .07rem .5rem;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, .25) transparent;
}
.proto-list > :first-child { margin-top: auto; }
.proto-list > :last-child { margin-bottom: auto; }
.pcard {
  position: relative;
  flex: none;
  display: flex;
  flex-direction: column;
  gap: .04rem;
  padding: .08rem .26rem .09rem;
  overflow: hidden;
  font: inherit;
  text-align: left;
  color: #e9eceb;
  background: linear-gradient(180deg, #252627, #1a1b1c);
  border: 2px solid #55585a;
  border-radius: .2rem;
  box-shadow: 0 .05rem .16rem rgba(0, 0, 0, .5);
  transition: transform 220ms var(--ease-out), border-color 220ms;
}
.pcard:hover:not(.is-on), .pcard:focus-visible:not(.is-on) { border-color: #7b7f81; }
/* the room's read-only view (another doctor's: the host chooses): shown, not chosen */
.pcard:disabled { cursor: default; }
.pcard:disabled:hover:not(.is-on) { border-color: #55585a; }
.pcard.is-on { transform: translateX(-.44rem); border-color: #8f9496; }
.pcard__glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 260ms;
  background: radial-gradient(70% 140% at 100% 50%, rgba(255, 255, 255, .12), transparent 72%);
  background: radial-gradient(70% 140% at 100% 50%, color-mix(in srgb, var(--d-color) 70%, transparent), transparent 72%);
}
.pcard.is-on .pcard__glow { opacity: 1; }
.pcard__head, .pcard__desc, .pcard__effects, .pcard__meta { position: relative; }
.pcard.is-on .pcard__head, .pcard.is-on .pcard__desc, .pcard.is-on .pcard__effects, .pcard.is-on .pcard__meta { padding-right: max(1.3rem, 32px, calc(70px * var(--sp-ui, 1))); }
.pcard__head { display: flex; align-items: center; gap: .08rem; }
.pcard__glyph { width: max(.3rem, 18px); height: max(.3rem, 18px); color: var(--d-color); }
.pcard__name { font-size: min(calc(.28 * var(--t)), .36rem); font-weight: 900; letter-spacing: .04em; color: var(--d-color); text-shadow: 0 0 .1rem rgba(0, 0, 0, .6); white-space: nowrap; }
.pcard__desc { padding-bottom: .05rem; font-size: calc(.16 * var(--t)); color: #9a9f9d; border-bottom: 1px solid rgba(255, 255, 255, .18); }
.pcard__effects { display: flex; flex-direction: column; padding-top: .04rem; font-size: calc(.17 * var(--t)); line-height: 1.4; }
.pcard__effects span::before { content: '·'; margin-right: .06rem; }
.pcard__meta { display: flex; flex-wrap: wrap; align-items: center; gap: .04rem .14rem; margin-top: .04rem; font-size: calc(.13 * var(--t)); color: #7f8583; }
.pcard__meta b { color: #cfd3d1; }
.pcard__stage { display: inline-flex; align-items: center; gap: .04rem; }
.pcard__stage .icon { width: 1.1em; height: 1.1em; }
.pcard__stamp {
  position: absolute;
  right: .2rem;
  top: 50%;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .04rem;
  width: max(1.3rem, 32px, calc(70px * var(--sp-ui, 1)));
  height: max(1.1rem, 32px, calc(60px * var(--sp-ui, 1)));
  transform: translateY(-50%) rotate(-6deg);
}
.pcard.is-on .pcard__stamp { display: flex; animation: proto-stamp 260ms var(--ease-out) backwards; }
@keyframes proto-stamp { from { opacity: 0; transform: translateY(-50%) rotate(-6deg) scale(1.4); } }
.pcard__ring { position: absolute; inset: -.1rem -.14rem; width: calc(100% + .28rem); height: calc(100% + .2rem); }
.pcard__ring path { fill: none; stroke: #fff; stroke-width: 3; stroke-linecap: round; opacity: .9; }
.pcard__tick { display: grid; place-items: center; width: max(.46rem, 26px); height: max(.46rem, 26px); color: #2a1712; background: #f5f5f5; border-radius: .06rem; box-shadow: 0 .02rem .08rem rgba(0, 0, 0, .5); }
.pcard__tick .icon { width: 78%; height: 78%; color: var(--d-color); filter: brightness(.7); }
.pcard__ok { font-size: calc(.18 * var(--t)); font-weight: 800; color: #fff; text-shadow: 0 1px 3px rgba(0, 0, 0, .6); white-space: nowrap; }

/* ---- co-op capacity ---------------------------------------------------------------------------------- */
.capacity-select { display: flex; align-items: center; justify-content: space-between; gap: .18rem; margin-top: .2rem; padding: .14rem .18rem; border: 1px solid var(--line-2); background: rgba(9, 13, 11, .7); }
.capacity-select__label { display: flex; flex-direction: column; flex: none; color: var(--text-md); font-size: calc(.19 * var(--t)); font-weight: 700; }
.capacity-select__options { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .06rem; }
.capacity-select__opt { min-width: .66rem; height: .42rem; padding: 0 .12rem; border: 1px solid var(--line-2); background: rgba(255, 255, 255, .03); color: var(--text-lo); font-size: calc(.16 * var(--t)); font-weight: 700; }
.capacity-select__opt:hover { color: var(--text-hi); border-color: var(--mint-600); }
.capacity-select__opt.is-active { color: var(--mint-400); border-color: var(--mint-500); background: var(--mint-a20); }

/* ---- create ------------------------------------------------------------------------------------------ */
.create-box { margin-top: .3rem; display: flex; flex-direction: column; gap: .12rem; }
/* the foot: the test-room box, the hint, 开始独立模拟 / 创建同盟 */
.proto-foot { flex: none; display: flex; flex-direction: column; gap: .08rem; padding-left: .5rem; }
.create-box__test {
  display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; gap: .04rem .1rem;
  color: #e8b84a; font-size: calc(.16 * var(--t));
}
.create-box__test input { width: .2rem; height: .2rem; margin: 0; flex: none; accent-color: #e8b84a; }
.create-box__test em { flex-basis: 100%; font-style: normal; }

.proto-hint { display: flex; align-items: center; gap: .08rem; min-height: .24rem; margin: 0; font-size: calc(.14 * var(--t)); color: #858b89; }
.proto-hint .icon { flex: none; width: 1.1em; height: 1.1em; }
.proto-hint--ro { min-height: max(.64rem, 32px, calc(38px * var(--sp-ui, 1))); font-size: calc(.18 * var(--t)); color: #b9bfbd; }
.proto-start {
  position: relative;
  display: flex;
  align-items: center;
  gap: .26rem;
  width: 100%;
  min-height: max(1.04rem, 32px, calc(54px * var(--sp-ui, 1)));
  padding: .03rem 0 .03rem .26rem;
  overflow: hidden;
  font: inherit;
  color: #0d2a23;
  text-align: left;
  background: linear-gradient(180deg, #4fe0bf, #34c8a6);
  border: 3px solid #121313;
  box-shadow: 0 0 0 1px rgba(79, 224, 191, .5), 0 .06rem .2rem rgba(0, 0, 0, .55);
  transition: filter var(--t-fast);
}
.proto-start:hover:not(:disabled), .proto-start:focus-visible { filter: brightness(1.07); }
.proto-start:focus-visible { outline: 2px solid #eef0ef; outline-offset: 2px; }
.proto-start:disabled { filter: grayscale(.8) brightness(.6); cursor: default; }
.proto-start__mark { flex: none; display: flex; flex-direction: column; align-items: center; gap: 1px; }
.proto-start__rook { display: inline-flex; align-items: center; gap: 2px; font-size: calc(.36 * var(--t)); font-weight: 300; line-height: 1; }
.proto-start__rook i { font-style: normal; }
.proto-start__rook .icon { width: max(.34rem, 19px); height: max(.34rem, 19px); }
.proto-start__mark small { font-family: var(--font-display); font-size: calc(.08 * var(--t)); font-weight: 800; letter-spacing: .06em; line-height: 1.1; text-align: center; }
.proto-start__label { position: relative; display: inline-flex; align-items: center; gap: .1rem; min-width: 0; font-size: calc(.4 * var(--t)); font-weight: 900; letter-spacing: .08em; white-space: nowrap; }
/* 选择模拟协议's own button (.proto-foot; the room's GoButton shares the rules above and makes its own choice in
   css/screens/room.css — §35.18 review: these rules once reached it too): the label wraps onto a second line (the button
   grows: min-height above) rather than being cut, and stops at .46rem — 大's size — on a screen taller than 520 px, the
   mark's rook at .4rem (§35.18's leftover: English 开始独立模拟 was cut at every desktop size, even at 小 at 1440x900;
   the short-screen block has its own caps). [ASSUMED] the label's caps */
.proto-foot .proto-start__label { flex: 1 1 auto; padding-right: 8%; font-size: min(calc(.4 * var(--t)), .46rem); white-space: normal; line-height: 1.1; }
.proto-foot .proto-start__rook { font-size: min(calc(.36 * var(--t)), .4rem); }
.proto-start__deco {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 26%;
  clip-path: polygon(18% 0, 100% 0, 100% 100%, 0 100%);
  background: repeating-linear-gradient(135deg, rgba(0, 0, 0, .28) 0 5px, transparent 5px 11px), linear-gradient(90deg, rgba(13, 42, 35, .2), rgba(13, 42, 35, .6));
}

/* ---- 选择同盟方式: the radar, the 创建同盟 / 加入同盟 cards -------------------------------------------------- */
.ally__bg {
  background:
    radial-gradient(40% 55% at 30% 52%, rgba(46, 210, 160, .12), transparent 70%),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .022) 0 1px, transparent 1px 4px),
    linear-gradient(rgba(255, 255, 255, .03) 1px, transparent 1px) 0 0 / 1.1rem 1.1rem,
    linear-gradient(90deg, rgba(255, 255, 255, .03) 1px, transparent 1px) 0 0 / 1.1rem 1.1rem,
    radial-gradient(120% 90% at 50% 40%, #141616, #070808);
}
.ally__mode { color: var(--mint-400); }
.ally-body { grid-template-columns: minmax(0, 1fr) min(7.4rem, 46vw); }
.ally-stage { position: relative; min-width: 0; min-height: 0; }
.mf-radar { position: absolute; inset: 0 0 .8rem; width: 100%; height: calc(100% - .8rem); }
.mf-radar__grid line { stroke: rgba(78, 216, 175, .08); stroke-width: 1; }
.mf-radar__land path { fill: rgba(150, 170, 165, .1); stroke: rgba(150, 170, 165, .2); stroke-width: 1; }
.mf-radar__ring { fill: none; stroke: rgba(78, 216, 175, .25); stroke-width: 1.5; }
.mf-radar__ring--far { fill: rgba(30, 140, 110, .1); }
.mf-radar__ring--core { stroke: rgba(78, 216, 175, .75); stroke-width: 3; filter: drop-shadow(0 0 6px rgba(78, 216, 175, .6)); }
.mf-radar__sweep { transform-origin: 270px 250px; animation: mf-sweep 4.5s linear infinite; }
.mf-radar__sweep path { fill: rgba(60, 230, 180, .22); }
.mf-radar__sweep line { stroke: #5df0c6; stroke-width: 3; filter: drop-shadow(0 0 6px #5df0c6); }
@keyframes mf-sweep { to { transform: rotate(360deg); } }
.mf-radar__blip { fill: #ffc53d; filter: drop-shadow(0 0 8px #ffc53d); animation: mf-blip 2.2s ease-in-out infinite; }
.mf-radar__blip--b { fill: #5df0c6; filter: drop-shadow(0 0 6px #5df0c6); animation-delay: 1.1s; }
@keyframes mf-blip { 50% { opacity: .2; } }
.mf-radar__cross { stroke: #5df0c6; stroke-width: 3; }
.mf-radar__read rect { fill: rgba(0, 0, 0, .5); stroke: rgba(78, 216, 175, .45); }
.mf-radar__read text { fill: #9fe9d3; font: 700 14px var(--font-num, monospace); }
.mf-radar__frame { fill: none; stroke: rgba(78, 216, 175, .35); stroke-width: 2; }
.ally-guide {
  position: absolute;
  left: .1rem;
  bottom: .1rem;
  display: inline-flex;
  align-items: center;
  gap: .14rem;
  height: max(.64rem, 32px, calc(38px * var(--sp-ui, 1)));
  padding: 0 .3rem 0 .1rem;
  font: inherit;
  font-size: calc(.22 * var(--t));
  font-weight: 800;
  color: #1a1d1c;
  background: linear-gradient(180deg, #e9edeb, #c3cac7);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow: 0 .04rem .14rem rgba(0, 0, 0, .5);
}
.ally-guide:hover, .ally-guide:focus-visible { filter: brightness(1.06); }
.ally-guide__icon { display: grid; place-items: center; width: max(.46rem, 28px); height: max(.4rem, 24px); color: #e9edeb; background: #2a2f2d; }
.ally-guide__icon .icon { width: 64%; height: 64%; }
/* centred safely: the auto margins give way when the column is taller than its space (justify-content: center would
   push it past both ends), so a short screen's scroll (below) starts at 创建同盟 */
.ally-side { min-height: 0; display: flex; flex-direction: column; gap: .2rem; padding: .1rem 0 .1rem .3rem; }
.ally-side > :first-child { margin-top: auto; }
.ally-side > :last-child { margin-bottom: auto; }
.ally-card {
  position: relative;
  flex: none;
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: 0;
  overflow: hidden;
  font: inherit;
  color: #eef0ef;
  text-align: left;
  background: radial-gradient(70% 90% at 50% 40%, #161a19, #090a0a);
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: .08rem;
  box-shadow: 0 .06rem .2rem rgba(0, 0, 0, .5);
}
button.ally-card:hover, button.ally-card:focus-visible { border-color: rgba(93, 240, 198, .6); }
.ally-card__art { display: block; padding: .1rem .2rem 0; }
.mf-art { display: block; width: 100%; height: auto; max-height: 1.3rem; }
.mf-art text { font: 700 8px var(--font-display, monospace); letter-spacing: 2px; fill: currentColor; opacity: .7; }
.mf-art--create { color: #5df0c6; }
.mf-art--create .mf-art__wire { fill: none; stroke: rgba(93, 240, 198, .45); stroke-width: 2; }
.mf-art--create .mf-art__oct { fill: #2fd6a6; filter: drop-shadow(0 0 10px rgba(93, 240, 198, .6)); }
.mf-art--create .mf-art__plus { stroke: #08221b; stroke-width: 7; stroke-linecap: square; }
.mf-art--create .mf-art__brk { fill: none; stroke: #5df0c6; stroke-width: 4; }
.mf-art--create .mf-art__dot { fill: #5df0c6; }
.mf-art--join { color: #ff9a3c; }
.mf-art--join .mf-art__wire { fill: none; stroke: rgba(255, 154, 60, .6); stroke-width: 2; }
.mf-art--join .mf-art__tri { fill: #ff9a3c; }
.mf-art--join .mf-art__target { fill: rgba(255, 154, 60, .15); stroke: #ff9a3c; stroke-width: 2; }
.mf-art--join .mf-art__x { stroke: #ff9a3c; stroke-width: 3; }
.mf-blk path { stroke: rgba(0, 0, 0, .5); stroke-width: 1; }
.mf-blk__top { fill: #3a3d3d; } .mf-blk__l { fill: #2a2c2c; } .mf-blk__r { fill: #1f2121; }
.mf-blk.is-lit .mf-blk__top { fill: #f0a35a; } .mf-blk.is-lit .mf-blk__l { fill: #c96b23; } .mf-blk.is-lit .mf-blk__r { fill: #a5541a; }
.mf-blk.is-lit { animation: mf-blk 2.4s ease-in-out infinite; animation-delay: calc(var(--k) * 120ms); }
@keyframes mf-blk { 50% { transform: translateY(-3px); } }
.ally-card__bar {
  position: relative;
  display: flex;
  align-items: center;
  gap: .14rem;
  height: max(.74rem, 32px, calc(42px * var(--sp-ui, 1)));
  padding: 0 .2rem;
  font-family: inherit;
  font-size: calc(.3 * var(--t));
  font-weight: 900;
  letter-spacing: .06em;
  white-space: nowrap;
  text-align: left;
  color: #08221b;
  background: linear-gradient(180deg, #4fe8c0, #2fcf9f);
  border: 0;
}
/* the difficulty line wraps at the bar's right rather than ending in an ellipsis (§35.51: English 「Difficulty: Standard
   Simulat…」 at 1280–1440 px, Japanese at 1024×600 特大). It keeps a column of at least 10em beside the name, else it
   takes a row of its own under the name and the bar grows (§35.51 review: squeezed into the 96 px the name left in
   English at 特大 on 1024×600, six lines ran out of the 42 px bar); Korean breaks between words only (the review:
   「시뮬레이|션」 once balanced), Japanese by its line-breaking rules */
.ally-card--create .ally-card__bar { flex-wrap: wrap; align-content: center; row-gap: 1px; height: auto; min-height: max(.74rem, 32px, calc(42px * var(--sp-ui, 1)));
  padding-top: 4px; padding-bottom: 4px; }
.ally-card__bar small { flex: 0 1 auto; margin-left: auto; min-width: min(100%, 10em); white-space: normal; text-align: right; text-wrap: balance;
  line-height: 1.2; font-size: calc(.14 * var(--t)); font-weight: 700; letter-spacing: 0; color: rgba(8, 34, 27, .75); }
.ally-card__bar small:lang(ko) { word-break: keep-all; overflow-wrap: break-word; }
.ally-card__bar small:lang(ja) { line-break: strict; }
button.ally-card:disabled { cursor: default; }
button.ally-card:disabled .ally-card__bar { filter: grayscale(.5) brightness(.8); }
/* the test-room box under 创建同盟 (test mode only) */
.ally-test { padding: 0 .2rem; }
.ally-card__bar--join { width: 100%; color: #2a1404; background: linear-gradient(180deg, #ffb24f, #f08a26); }
.ally-card__bar--join:disabled { filter: grayscale(.6) brightness(.75); cursor: default; }
.ally-card__bar--join:hover:not(:disabled), .ally-card__bar--join:focus-visible { filter: brightness(1.06); }
.ally-card__icon { flex: none; display: grid; place-items: center; width: max(.36rem, 22px); height: max(.36rem, 22px); color: currentColor; background: rgba(0, 0, 0, .14); border: 2px solid currentColor; border-radius: 4px; }
.ally-card__icon .icon { width: 74%; height: 74%; }
/* the key field: the project's TextField (.field / .field__box / .field__input) restyled as the event's grey bar, with
   观战 beside it inside the same bar */
.ally-key {
  display: flex;
  align-items: center;
  gap: .1rem;
  height: max(.56rem, 32px, calc(34px * var(--sp-ui, 1)));
  margin: .06rem .2rem .08rem;
  padding: 0 .06rem 0 .12rem;
  background: #262929;
  border: 1px solid rgba(255, 255, 255, .2);
  border-radius: .06rem;
}
.ally-key:focus-within { border-color: #ff9a3c; }
.ally-key .field { flex: 1 1 auto; height: 100%; gap: 0; }
.ally-key .field__box { height: 100%; padding: 0; gap: .1rem; background: none; border: 0; box-shadow: none; }
.ally-key .field__box::after { display: none; }
.ally-key .field__icon { flex: none; width: max(.24rem, 15px); height: max(.24rem, 15px); color: #c9cecc; }
.ally-key .field__box:focus-within .field__icon { color: #ff9a3c; }
.ally-key input {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  font: inherit;
  font-size: calc(.22 * var(--t));
  font-weight: 700;
  letter-spacing: .08em;
  text-align: center;
  text-transform: uppercase;
  text-overflow: ellipsis;
  color: #f2f4f3;
  background: none;
  border: 0;
  outline: none;
}
.ally-key input::placeholder { color: #8d9391; font-family: inherit; font-size: calc(.22 * var(--t)); font-weight: 500; letter-spacing: .04em; text-transform: none; }
.ally-key__spec {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: .04rem;
  height: 80%;
  padding: 0 .12rem;
  font: inherit;
  font-size: calc(.15 * var(--t));
  color: #eef0ef;
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .2);
  border-radius: 4px;
}
.ally-key__spec:hover:not(:disabled), .ally-key__spec:focus-visible { border-color: rgba(255, 255, 255, .5); }
.ally-key__spec:disabled { opacity: .45; cursor: default; }
.ally-key__spec .icon { width: 1.1em; height: 1.1em; }
.ally-recent { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .06rem .1rem; min-height: .3rem; margin: 0 .2rem .1rem; font-size: calc(.14 * var(--t)); text-align: center; }
.code-chip {
  padding: .03rem .12rem .03rem .16rem;
  border: 1px solid var(--line-2);
  background: rgba(0, 0, 0, .3);
  color: var(--amber);
  font-size: calc(.17 * var(--t));
  font-weight: 700;
  letter-spacing: .2em;
  transition: border-color var(--t-fast), background-color var(--t-fast);
}
.code-chip:hover { border-color: var(--amber); background: rgba(246, 163, 41, .08); }

/* ---- 选择模拟协议's cards when they do not fit their column (screens/lobby.js pickCardFit: data-fit), above 520 px tall --
   (§35.18's leftover there: at 大 / 特大, in a small window or a long language the list ran under 开始独立模拟 with 终极模拟
   out of view.) 'brief': the description only in the brief at the left, where the chosen difficulty's already is;
   'names': a line each, and the brief adds the chosen difficulty's effects and rounds. At both, the chosen card's name
   ends in an ellipsis beside the stamp should a long language need it (the brief names it in full); the names stop at
   .36rem (base rule: at 特大 in a 1024 px window English ran past the cards). The short-screen block below has its own
   one-line cards. [ASSUMED] the levels and the sizes */
.proto-brief__more { display: none; }


/* ---- narrow windows: the dialogs stack their halves ------------------------------------------------- */


/* ---- short landscape phones (≤ 520 CSS px tall) ---------------------------------------------------------- */
/* The hub drops its left column and the radar; the dialogs keep the four cards and the button in view without scrolling
   at every 文字大小 (the cards keep only their names, the selected difficulty's description moves to the brief). */

/* ---- 转场 (PR #643, the event's screen changes): a screen comes up from black, its panels slide in one after another ---- */
.lobby-hub, .modal__box.proto, .modal__box.ally { --tr-ease: cubic-bezier(.16, .84, .3, 1); }
@keyframes tr-fade { from { opacity: 0; } }
@keyframes tr-veil { from { background-color: transparent; } }
@keyframes tr-right { from { opacity: 0; transform: translateX(.36rem); } }
@keyframes tr-left { from { opacity: 0; transform: translateX(-.36rem); } }
@keyframes tr-rise { from { opacity: 0; transform: translateY(.22rem); } }
@keyframes tr-zoom { from { opacity: 0; transform: scale(1.04); } }
@keyframes tr-draw { to { stroke-dashoffset: 0; } }
@keyframes tr-diamond { 0% { opacity: 0; transform: translateX(-50%) rotate(45deg) scale(.5); } 30%, 72% { opacity: 1; transform: translateX(-50%) rotate(45deg) scale(1); }
  100% { opacity: 0; transform: translateX(-50%) rotate(45deg) scale(1.1); } }
/* the hub */
.lobby-hub .hub-bg { animation: tr-fade 560ms ease-out backwards; }
.lobby-hub > .topbar { animation: tr-fade 320ms ease-out 120ms backwards; } /* opacity only: its dialogs are fixed */
.lobby-hub .hub-center { animation: tr-zoom 600ms var(--tr-ease) 140ms backwards; }
.lobby-hub .hub-side { animation: tr-left 480ms var(--tr-ease) 220ms backwards; }
.lobby-hub .hub-right { animation: tr-right 480ms var(--tr-ease) 260ms backwards; }
.hub-entries .hub-entry-wrap { animation: tr-rise 440ms var(--tr-ease) 300ms backwards; }
.hub-entries .hub-entry-wrap:nth-child(2) { animation-delay: 360ms; }
.hub-entries .hub-entry-wrap:nth-child(3) { animation-delay: 420ms; }
.hub-entries .hub-entry-wrap:nth-child(4) { animation-delay: 480ms; }
/* 选择模拟协议 / 选择同盟方式: from black, then the title, the stage and the cards */
.modal__box.proto, .modal__box.ally { animation: tr-veil 150ms linear backwards; }
.proto__bg { animation: tr-fade 340ms ease-out 140ms backwards; }
.proto-top { animation: tr-fade 260ms ease-out 170ms backwards; }
.proto-title { animation: tr-right 400ms var(--tr-ease) 200ms backwards; }
.proto-stage, .ally-stage { animation: tr-zoom 480ms var(--tr-ease) 190ms backwards; }
.proto-list .pcard { animation: tr-right 400ms var(--tr-ease) backwards; animation-delay: calc(240ms + var(--n, 0) * 60ms); }
.proto-list .pcard:nth-child(2) { --n: 1; }
.proto-list .pcard:nth-child(3) { --n: 2; }
.proto-list .pcard:nth-child(4) { --n: 3; }
.proto-list .pcard:nth-child(5) { --n: 4; }
.proto-foot { animation: tr-rise 400ms var(--tr-ease) 440ms backwards; }
.ally-card--create { animation: tr-right 420ms var(--tr-ease) 240ms backwards; }
.ally-card--join { animation: tr-right 420ms var(--tr-ease) 380ms backwards; }
.ally-guide { animation: tr-rise 380ms var(--tr-ease) 450ms backwards; }
/* the diamond at the bottom while it comes up */
.proto__body::after, .ally__body::after { content: ''; position: absolute; left: 50%; bottom: .5rem; z-index: 9; width: .3rem; height: .3rem; pointer-events: none; opacity: 0;
  border: 2px solid rgba(223, 230, 226, .55); box-shadow: inset 0 0 0 3px #0a0b0b, inset 0 0 0 5px rgba(223, 230, 226, .3); animation: tr-diamond 720ms ease-out 60ms both; }
/* the stamp's ring is drawn each time a difficulty is chosen */
.pcard.is-on .pcard__ring path { stroke-dasharray: 1; stroke-dashoffset: 1; animation: tr-draw 380ms ease-out 90ms forwards; }
.pcard.is-on .pcard__ring path + path { animation-delay: 260ms; }



/* official versions (DESIGN §35.23): the version under the title, the cards' wait while a version's data loads */
.hub-center__ver { position: relative; margin-top: .04rem; font-size: calc(.22 * var(--t)); font-weight: 700; letter-spacing: .08em; color: #9fd3ff; text-shadow: 0 1px .08rem rgba(0, 0, 0, .85); overflow-wrap: anywhere; }
.proto-list__wait { display: flex; align-items: center; gap: .08rem; margin: 0; color: var(--text-lo); font-size: calc(.15 * var(--t)); }
.proto-list__wait.is-failed { flex-wrap: wrap; color: var(--amber); }
.proto-list__wait.is-failed .icon { flex: none; width: 1.1em; height: 1.1em; }
.create-box .btn--xl { height: .92rem; font-size: calc(.32 * var(--t)); letter-spacing: .3em; }
.create-box__hint { display: flex; align-items: center; justify-content: center; min-height: .3rem; font-size: calc(.14 * var(--t)); color: var(--text-lo); }

/* ---- public lobby discovery ------------------------------------------------------------------------ */
.lobby-screen .mode-cards { margin-bottom: .2rem; }
.lobby-screen .mode-card { min-height: 3.2rem; gap: .14rem; padding-top: .24rem; padding-bottom: .22rem; }
.lobby-screen .mode-card__icon { width: .66rem; height: .66rem; }
.lobby-screen .mode-card__icon .icon { width: .34rem; height: .34rem; }
.lobby-online { display: inline-flex; align-items: center; gap: .05rem; min-width: .86rem; height: .34rem; padding: 0 .1rem; border: 1px solid var(--mint-800); background: rgba(20, 84, 67, .28); color: var(--mint-400); font-size: calc(.14 * var(--t)); white-space: nowrap; }
.lobby-online .icon { width: .17rem; height: .17rem; }
.lobby-online.is-offline { color: var(--text-dim); border-color: var(--line-2); background: rgba(0, 0, 0, .25); }
.lobby-discovery { margin: .02rem 0 .28rem; padding: .16rem .18rem .14rem; border: 1px solid var(--mint-800); background: linear-gradient(100deg, rgba(13, 44, 36, .68), rgba(10, 14, 12, .8)); box-shadow: inset 0 0 .55rem rgba(23, 249, 183, .03); }
.lobby-discovery__overview { display: flex; align-items: center; justify-content: space-between; gap: .16rem; min-width: 0; }
.lobby-discovery__heading { display: flex; flex-direction: column; gap: .04rem; min-width: 0; }
.lobby-discovery__heading strong { display: flex; align-items: center; gap: .06rem; font-size: calc(.22 * var(--t)); color: var(--text-hi); white-space: nowrap; }
.lobby-discovery__heading strong .icon { width: .19rem; height: .19rem; color: var(--mint-400); }
.lobby-discovery__stats { display: flex; flex: none; align-items: center; gap: .1rem; min-width: 0; }
.lobby-discovery__stats > span { display: flex; flex-direction: column; align-items: center; min-width: .44rem; border-left: 1px solid var(--line-2); padding-left: .09rem; }
.lobby-discovery__stats b { color: var(--mint-400); font-size: calc(.23 * var(--t)); line-height: 1; }
.lobby-discovery__stats small { margin-top: .04rem; color: var(--text-lo); font-size: calc(.13 * var(--t)); white-space: nowrap; }
.lobby-discovery__actions { display: flex; align-items: center; gap: .08rem; margin-top: .12rem; }
.lobby-discovery__actions .btn { flex: none; }
.lobby-discovery__preference { display: inline-flex; align-items: center; gap: .05rem; min-width: 0; height: .42rem; padding: 0 .06rem 0 .1rem; border: 1px solid var(--line-2); background: rgba(0, 0, 0, .24); color: var(--text-lo); font-size: calc(.13 * var(--t)); }
.lobby-discovery__preference select { min-width: 1.15rem; height: .34rem; padding: 0 .08rem; border: 0; background: var(--bg-2); color: var(--text-hi); font-size: calc(.15 * var(--t)); }
.lobby-directory { background: #101713; }
.lobby-directory .modal__body { padding: .12rem .18rem .08rem; }
.lobby-directory__note { display: flex; align-items: center; justify-content: space-between; margin-bottom: .08rem; color: var(--text-lo); font-size: calc(.13 * var(--t)); }
.lobby-directory__note .btn { height: .34rem; padding: 0 .1rem; font-size: calc(.13 * var(--t)); }
.lobby-directory__rooms { display: flex; flex-direction: column; gap: .05rem; max-height: 5.8rem; overflow-y: auto; padding-right: .03rem; }
.lobby-directory__room { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: .1rem; align-items: center; min-height: .54rem; padding: .07rem .08rem; border: 1px solid var(--line); background: rgba(255, 255, 255, .025); }
.lobby-directory__room:hover { border-color: var(--line-3); background: var(--mint-a10); }
.lobby-directory__room.is-match { opacity: .78; }
.lobby-directory__room-main, .lobby-directory__room-meta { display: flex; align-items: center; gap: .09rem; min-width: 0; }
.lobby-directory__room-main { flex-wrap: wrap; }
.lobby-directory__room-code { min-width: .62rem; color: var(--amber); font-size: calc(.19 * var(--t)); font-weight: 800; letter-spacing: .08em; }
.lobby-directory__hidden-code { color: var(--text-dim); font-size: calc(.13 * var(--t)); }
.lobby-directory__room-mode { color: var(--text-md); font-size: calc(.14 * var(--t)); white-space: nowrap; }
.lobby-directory__room-meta { flex-wrap: wrap; color: var(--text-lo); font-size: calc(.13 * var(--t)); white-space: nowrap; }
.lobby-directory__status { padding: .02rem .07rem; border: 1px solid var(--mint-700); color: var(--mint-400); font-size: calc(.12 * var(--t)); }
.lobby-directory__status.is-match { border-color: var(--line-2); color: var(--text-dim); }
.lobby-directory__room.is-retained { background: rgba(255, 180, 80, .025); }
.lobby-directory__retained-note { margin: 0 0 .08rem; color: var(--text-lo); font-size: calc(.13 * var(--t)); line-height: 1.5; }
.lobby-directory__offline { color: var(--amber); font-size: calc(.12 * var(--t)); }
.lobby-directory__private { color: var(--amber); font-size: calc(.12 * var(--t)); }
.lobby-directory__actions { display: flex; align-items: center; justify-content: flex-end; gap: .08rem; }
.lobby-directory__actions .btn { height: .34rem; padding: 0 .1rem; white-space: nowrap; }
/* Adjacent join/spectate controls must not borrow each other's horizontal touch area. */
.sp-coarse .lobby-directory .lobby-directory__actions .btn::before { width: calc(100% + .08rem); }
.lobby-directory__empty { display: grid; place-items: center; min-height: 1.7rem; color: var(--text-lo); font-size: calc(.16 * var(--t)); text-align: center; }
.lobby-directory__empty.is-error { color: var(--amber); }
.lobby-directory__footer { display: flex; align-items: center; justify-content: space-between; gap: .12rem; width: 100%; }
.lobby-directory__pager { display: flex; align-items: center; gap: .1rem; color: var(--text-lo); font-size: calc(.14 * var(--t)); }



/* 服主策略（2026-10-13）：16 / 20 人房暂不开放 —— 灰显，点击给提示 */
.capacity-select__opt.is-closed { opacity: .35; cursor: not-allowed; }
.capacity-select__opt.is-closed:hover { color: var(--text-lo); border-color: var(--line-2); }

/* ---- 「我的」页面（2026-10-13）------------------------------------------------------------------ */
.profile-entry { display: inline-flex; align-items: center; gap: .06rem; }
.me-chip__label { font-size: calc(.14 * var(--t)); }
.profile__body { display: flex; flex-direction: column; gap: .14rem; }
.profile__card { display: flex; flex-direction: column; gap: .1rem; padding: .16rem; border: 1px solid var(--line-2); background: rgba(255,255,255,.02); }
.profile__who { display: flex; flex-direction: column; gap: .04rem; }
.profile__who b { font-size: calc(.24 * var(--t)); color: var(--text-hi); }
.profile__who .num { color: var(--mint-400); font-family: var(--font-num); }
.profile__meta { display: flex; flex-wrap: wrap; gap: .08rem .18rem; color: var(--text-lo); font-size: calc(.14 * var(--t)); }
.profile__meta b { color: var(--text-hi); }
.profile__hint { margin: 0; color: var(--text-lo); font-size: calc(.14 * var(--t)); line-height: 1.6; }
.profile__actions { display: flex; gap: .08rem; align-items: center; justify-content: flex-end; width: 100%; }

.profile__uid { display: flex; align-items: center; flex-wrap: wrap; gap: .08rem; padding: .1rem .12rem; border: 1px solid var(--mint-700); background: var(--mint-a10); }
.profile__uid-label { color: var(--text-lo); font-size: calc(.14 * var(--t)); }
.profile__uid b { font-family: var(--font-num); font-size: calc(.2 * var(--t)); color: var(--mint-400); letter-spacing: .06em; }
.profile__uid-hint { color: var(--text-dim); font-size: calc(.13 * var(--t)); }

.profile__count { color: var(--mint-400); font-size: calc(.13 * var(--t)); }
.profile__friend-add { display: flex; align-items: flex-end; gap: .08rem; }
.profile__friend-add > *:first-child { flex: 1 1 auto; }
.profile__friends { display: flex; flex-direction: column; gap: .06rem; max-height: 3.2rem; overflow-y: auto; }
.profile__friend { display: flex; align-items: center; gap: .08rem; padding: .08rem .1rem; border: 1px solid var(--line); background: rgba(255,255,255,.02); }
.profile__dot { width: .1rem; height: .1rem; border-radius: 50%; background: var(--text-dim); flex: none; }
.profile__dot.is-on { background: var(--mint-400); box-shadow: 0 0 6px var(--mint-glow); }
.profile__friend-name { flex: 1 1 auto; color: var(--text-hi); font-size: calc(.15 * var(--t)); }
.profile__friend-name .num { color: var(--text-lo); }
.profile__friend-state { color: var(--text-dim); font-size: calc(.13 * var(--t)); }
.profile__friend-state.is-on { color: var(--mint-400); }

/* ---- 头像（「我的」页面，2026-10-17 定制）----------------------------------------------------------- */
.prof-ava { gap: .12rem; }
/* 换行兜底：译文比中文长（英/日/韩的「清除头像」）时按钮整颗掉到下一行，不会被右边缘裁掉 */
.prof-ava__head { display: flex; align-items: center; flex-wrap: wrap; gap: .14rem; }
.prof-ava__now { display: flex; flex-direction: column; gap: .04rem; flex: 1 1 2.2rem; min-width: 0; }
.prof-ava__head > .btn { margin-left: auto; }
.prof-ava__now-name { color: var(--text-hi); font-size: calc(.18 * var(--t)); }
.prof-ava__tools { display: flex; align-items: center; gap: .1rem; }
.prof-ava__search { flex: 1 1 auto; min-width: 0; }
.prof-ava__count { color: var(--text-dim); font-size: calc(.13 * var(--t)); white-space: nowrap; }
.prof-ava__grid {
  display: grid;
  /* 固定方格子（和 .skins__item 一样）：网格行高必须由 CSS 定死 —— 让图片或 aspect-ratio 决定行高时，
     Chrome 在图片还没到齐的那一帧会把行高算成 0，整排格子互相压实（联调时踩过）。 */
  grid-template-columns: repeat(auto-fill, .54rem);
  grid-auto-rows: .54rem;
  gap: .06rem;
  max-height: 3.2rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: .06rem;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, .015);
}
/* 触屏：格子至少 --tap-min 见方（和别处的小按钮同一规矩） */
.sp-coarse .prof-ava__grid { grid-template-columns: repeat(auto-fill, var(--tap-min)); grid-auto-rows: var(--tap-min); }
.prof-ava__tile {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--line-2);
  background: #0a0d0c;
  cursor: pointer;
  transition: border-color 120ms ease;
}
.prof-ava__tile:hover { border-color: var(--mint-600); }
.prof-ava__tile.is-on { border-color: var(--mint-400); box-shadow: inset 0 0 0 1px var(--mint-500), 0 0 .16rem var(--mint-a35); }
.prof-ava__tile:focus-visible { outline: 2px solid var(--mint-400); outline-offset: -2px; }
.prof-ava__img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.prof-ava__ph { display: grid; place-items: center; width: 100%; height: 100%; color: var(--text-dim); font-size: calc(.1 * var(--t)); }
.prof-ava__tag {
  position: absolute;
  left: 0;
  bottom: 0;
  padding: 0 .04rem;
  background: rgba(10, 13, 12, .82);
  color: var(--mint-400);
  font-size: calc(.09 * var(--t));
  font-weight: 700;
  letter-spacing: .04em;
  line-height: 1.5;
}
.prof-ava__check {
  position: absolute;
  right: .02rem;
  top: .02rem;
  width: .16rem;
  height: .16rem;
  padding: .02rem;
  border-radius: 50%;
  background: var(--mint-400);
  color: var(--text-on-mint);
}
.prof-ava__wait { display: grid; place-items: center; padding: .2rem; }
/* 自定义上传（2026-10-21）：按钮 + 隐藏的 file input + 进度 */
.prof-ava__upload { display: flex; align-items: center; flex-wrap: wrap; gap: .08rem; }
.prof-ava__upload-hint { flex: 1 1 auto; min-width: 0; color: var(--text-dim); font-size: calc(.12 * var(--t)); }
/* 原生 file input 隐藏但保留可点击（puppeteer / 无障碍都能拿到它） */
.prof-ava__file { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); border: 0; }
.prof-ava__progress {
  display: flex;
  align-items: center;
  gap: .06rem;
  color: var(--mint-400);
  font-size: calc(.13 * var(--t));
}

/* ---- 排行榜（2026-10-13）------------------------------------------------------------------------ */
.lb-entry { display: inline-flex; align-items: center; gap: .06rem; }
.lb { display: flex; flex-direction: column; gap: .12rem; }
.lb__tabs { display: flex; flex-wrap: wrap; gap: .06rem; }
.lb__tab { padding: .08rem .14rem; border: 1px solid var(--line-2); background: rgba(255,255,255,.03); color: var(--text-lo); font-size: calc(.14 * var(--t)); font-weight: 700; cursor: pointer; }
.lb__tab:hover { color: var(--text-hi); border-color: var(--mint-600); }
.lb__tab.is-active { color: var(--mint-400); border-color: var(--mint-500); background: var(--mint-a20); }
.lb__loading { display: flex; justify-content: center; padding: .3rem; }
.lb__list { display: flex; flex-direction: column; gap: .05rem; max-height: 6.4rem; overflow-y: auto; }
.lb__row { display: flex; align-items: center; gap: .12rem; padding: .1rem .12rem; border: 1px solid var(--line); background: rgba(255,255,255,.02); }
.lb__rank { width: .34rem; text-align: center; font-family: var(--font-num); font-size: calc(.18 * var(--t)); color: var(--text-dim); }
.lb__row.is-top1 { border-color: var(--mint-400); background: var(--mint-a10); }
.lb__row.is-top2, .lb__row.is-top3 { border-color: var(--mint-700); }
.lb__row.is-top1 .lb__rank, .lb__row.is-top2 .lb__rank, .lb__row.is-top3 .lb__rank { color: var(--mint-400); }
.lb__name { flex: 1 1 auto; color: var(--text-hi); font-size: calc(.16 * var(--t)); }
.lb__name .num { color: var(--text-lo); font-size: calc(.13 * var(--t)); }
.lb__sub { color: var(--text-dim); font-size: calc(.13 * var(--t)); }
.lb__value { color: var(--mint-400); font-family: var(--font-num); font-size: calc(.2 * var(--t)); }
.lb__value small { margin-left: .04rem; color: var(--text-lo); font-size: calc(.12 * var(--t)); }

/* ---- 设置按钮：只要图标，但图标要和别的按钮一样大（覆盖 .btn--square 的 50% 规则）---- */
.lobby-settings .btn__icon { width: 1.15em; height: 1.15em; }
.lobby-settings svg { width: 1.15em; height: 1.15em; }
/* 房间列表计时（2026-10-14）：开局多久 + 第几回合 / 已开多久 */
.lobby-directory__timer { color: var(--mint-300, var(--mint-400)); font-size: calc(.13 * var(--t)); font-weight: 700; white-space: nowrap; }

/* ==========================================================================================
   整页「联机大厅」（2026-10-19 定制）—— 房间标签页的卡片网格、筛选条、空位条。
   外壳完全复用统计页/排行榜那套 .st / .st-top / .st-tabs / .st-tab / .st-body，
   这里只加房间卡片自己的东西。
   ========================================================================================== */

/* 标签栏：与排行榜第二行 .lbp-boards 完全同一套「条」视觉（2026-10-18 统一）——
   上下 .1rem 留白 + 1px 底部分隔线，标签底边的 active 下划线（.st-tab）就成了一条连续的标签条。
   position: relative 是必须的：.st__bg 绝对定位铺满整页，没有定位的区块会被它盖住（标签栏会整个消失，
   和 leaderboard.css 里 .lbp-boards 踩的是同一个坑）。 */
.hall-tabs {
  position: relative;
  flex: none;
  padding: .1rem .36rem;
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  flex-wrap: wrap;
  row-gap: .08rem;
}
.hall-tab .lbp-n { margin-left: .06rem; }

.hall-body { padding: .12rem .36rem .2rem; }

/* 筛选条 + 本页计数 */
.hall-bar {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: .1rem; padding: 0 0 .12rem;
}
.hall-filters { display: flex; flex-wrap: wrap; gap: .06rem; }
.hall-chip {
  font: inherit; font-size: max(.15rem, 11px); font-weight: 700; letter-spacing: .06em;
  color: var(--text-lo); background: rgba(255, 255, 255, .04);
  border: 1px solid var(--line); border-radius: 2px; padding: .04rem .12rem;
  cursor: pointer; white-space: nowrap; touch-action: manipulation;
}
.hall-chip:hover { color: var(--text-hi); border-color: var(--line-2); }
.hall-chip.is-on { color: var(--bg-0); background: var(--mint-500); border-color: var(--mint-500); }
.hall-counts { display: flex; flex-wrap: wrap; gap: .16rem; font-size: max(.15rem, 11px); color: var(--text-lo); }

/* 卡片网格：够宽就多列，窄屏自动一列 */
.rh-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(max(2.9rem, 260px), 1fr));
  gap: .12rem;
}

.rh-card {
  position: relative; display: flex; flex-direction: column; gap: .07rem;
  padding: .12rem .14rem;
  border: 1px solid var(--line); border-radius: 2px;
  background: rgba(255, 255, 255, .025);
}
.rh-card.is-open { border-color: rgba(78, 216, 175, .34); background: rgba(78, 216, 175, .05); }
.rh-card.is-match { opacity: .8; }

.rh-card__top { display: flex; align-items: center; gap: .08rem; min-width: 0; }
.rh-card__code {
  font-family: var(--font-num); font-size: max(.24rem, 15px); font-weight: 900;
  letter-spacing: .06em; color: var(--mint-400); white-space: nowrap;
}
.rh-card__code.is-hidden { font-family: inherit; font-size: max(.15rem, 11px); font-weight: 600; color: var(--text-lo); letter-spacing: .04em; }
.rh-card__mode { font-size: max(.15rem, 11px); color: var(--text-md); letter-spacing: .04em; white-space: nowrap; }
.rh-card__state {
  margin-left: auto; font-size: max(.14rem, 10px); font-weight: 700; letter-spacing: .06em;
  padding: .02rem .08rem; border: 1px solid var(--line); border-radius: 2px;
  color: var(--text-lo); white-space: nowrap;
}
.rh-card__state.is-match { color: var(--mint-500); border-color: rgba(78, 216, 175, .4); }
.rh-card__state.is-full { color: var(--text-dim); border-color: var(--line-2); }

/* 卡片第二行：版本标签 + 难度 + 已开时长（2026-10-26 服主：格子视图要和列表一样看得到这些） */
.rh-card__facts {
  display: flex; flex-wrap: wrap; align-items: center; gap: .06rem;
  min-width: 0; font-size: max(.13rem, 10px); color: var(--text-lo);
}
.rh-card__facts .lobby-directory__room-ver { height: max(18px, calc(.18 * var(--t))); font-size: max(10px, calc(.11 * var(--t))); padding: 0 .06rem; }
.rh-card__diff { flex: none; }
.rh-card__timer { margin-left: auto; color: var(--mint-400); font-weight: 700; font-size: max(.13rem, 10px); white-space: nowrap; }

/* 席位与空位 */
.rh-card__seats { display: flex; align-items: baseline; gap: .06rem; }
.rh-card__seatnum { font-family: var(--font-num); font-size: max(.3rem, 18px); font-weight: 900; color: var(--text-hi); }
.rh-card__seatnum i { font-style: normal; font-size: max(.2rem, 13px); color: var(--text-dim); font-weight: 700; }
.rh-card__seatlbl { font-size: max(.14rem, 10px); color: var(--text-lo); }
.rh-card__free {
  margin-left: auto; font-size: max(.16rem, 12px); font-weight: 700; letter-spacing: .04em;
}
.rh-card__free.is-open { color: var(--mint-400); }
.rh-card__free.is-full { color: var(--text-dim); }

/* 一排小格子表示每个座位：占用亮、空位暗 */
.rh-card__bar { display: flex; gap: 2px; }
.rh-card__bar i {
  flex: 1 1 0; height: 4px; border-radius: 1px;
  background: rgba(255, 255, 255, .07);
}
.rh-card__bar i.is-used { background: var(--mint-500); opacity: .85; }

.rh-card__meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: .1rem;
  font-size: max(.14rem, 10px); color: var(--text-lo);
}
.rh-card__warn { color: #e8b96a; }

.rh-card__tags { display: flex; flex-wrap: wrap; gap: .04rem; min-height: .18rem; }

.rh-card__actions { display: flex; gap: .06rem; margin-top: auto; padding-top: .04rem; }
.rh-card__actions .rh-card__btn { flex: 1 1 0; justify-content: center; }

.hall-pager { display: flex; align-items: center; gap: .1rem; padding-top: .14rem; }
.hall-pager__spacer { flex: 1 1 auto; }


/* 房间行标签错位（2026-10-19 定制，服主此前反馈）：行是 flex 子项，被压缩后行内 grid 不再撑开，
   标签就会互相压住；hidden-code 也要禁止换行。两行解决，根因已用样机复现过。 */
.lobby-directory__rooms .lobby-directory__room { flex: none; }
.lobby-directory__hidden-code { white-space: nowrap; }

/* 排列方式切换（2026-10-19 服主）：紧跟在筛选条右侧，和筛选 chip 同一套外观 */
.hall-view { display: inline-flex; gap: .04rem; margin-left: .08rem; }
/* 整页里的房间列表不再按弹窗那样限高滚动，交给页面自己滚 */
.hall-body .lobby-directory__rooms.hall-rows { max-height: none; overflow: visible; }

/* ==========================================================================================
   固定定位；四个入口全部 disabled（灰、not-allowed、无 hover）；关卡清单在面板内部滚动。
   为了不压住大厅的难度卡 / 创建同盟按钮，.lobby-body 在右侧让出 4.95rem：
   面板宽 4.05rem + 右距 .3rem + 与内容之间约 .6rem。
   ========================================================================================== */

/* 合并 0.3.3 说明：上面这段「关卡清单」固定面板的样式，在 ours 分支提交时就已经丢了 14 行选择器
   （ours 的 lobby.css 本身是 299 个 { 对 313 个 }），任何分支都没有原文，JS 里也查不到对应的类。
   为让样式表语法有效（大括号成对、不散落顶层属性），下面给每段属性补一条 merge-lost-xl-* 占位选择器：
   属性原样保留，占位名不会命中任何标记；将来找到真名，把选择器换回去即可恢复。 */

.merge-lost-xl-panel {
  --bk-c: var(--mint-700);
  --bk-l: .18rem;
  position: fixed;
  right: .3rem;
  bottom: .3rem;
  z-index: 30;
  display: flex;
  flex-direction: column;
  width: 4.05rem;
  max-height: calc(100vh - 1.2rem);
  padding: .17rem .2rem .14rem;
  background:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, .016) 0 1px, transparent 1px 3px),
    linear-gradient(180deg, rgba(26, 33, 30, .97), rgba(10, 13, 12, .98));
  border: 1px solid var(--line-2);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .45), 0 .16rem .44rem rgba(0, 0, 0, .55), inset 0 0 .7rem rgba(23, 249, 183, .035);
}

.merge-lost-xl-panel__micro {
  padding-top: .02rem;
  font-family: var(--font-display);
  font-size: max(calc(.1 * var(--t)), 8px);
  letter-spacing: .2em;
  color: var(--mint-700);
  white-space: nowrap;
}
.merge-lost-xl-panel__tag {
  display: inline-flex;
  align-items: center;
  gap: .06rem;
  padding: .02rem .09rem;
  border: 1px solid var(--line-2);
  background: rgba(255, 255, 255, .045);
  color: var(--text-md);
  font-size: max(calc(.12 * var(--t)), 9px);
  font-weight: 700;
  letter-spacing: .12em;
  white-space: nowrap;
}
.merge-lost-xl-panel__en {
  font-family: var(--font-display);
  font-size: max(calc(.085 * var(--t)), 7px);
  letter-spacing: .16em;
  color: var(--text-dim);
  white-space: nowrap;
}

.merge-lost-xl-panel__title {
  margin-top: .1rem;
  padding-bottom: .1rem;
  border-bottom: 1px solid var(--line);
  color: var(--text-hi);
  font-size: max(calc(.24 * var(--t)), 15px);
  font-weight: 900;
  line-height: 1.25;
  letter-spacing: .05em;
  white-space: nowrap;
}

.merge-lost-xl-entry {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .06rem;
  height: max(.42rem, 30px);
  padding: 0 .08rem;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, .026);
  color: var(--text-dim);
  font-size: max(calc(.15 * var(--t)), 10px);
  font-weight: 700;
  letter-spacing: .05em;
  white-space: nowrap;
  cursor: not-allowed;
  filter: grayscale(1);
  opacity: .8;
}

.merge-lost-xl-entry__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .1rem;
  margin-top: .15rem;
  padding-top: .11rem;
  border-top: 1px solid var(--line);
  color: var(--text-md);
  font-size: max(calc(.14 * var(--t)), 10px);
  font-weight: 700;
  letter-spacing: .04em;
}
.merge-lost-xl-entry__en {
  margin-left: .08rem;
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: max(calc(.09 * var(--t)), 7px);
  font-weight: 400;
  letter-spacing: .16em;
}

.merge-lost-xl-panel__list {
  flex: 0 1 auto;
  min-height: 0;
  max-height: calc(7 * .32rem);
  margin: .06rem 0 0;
  padding: 0 .04rem 0 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  list-style: none;
}
.merge-lost-xl-item {
  display: grid;
  grid-template-columns: 1.06rem minmax(0, 1fr);
  align-items: center;
  gap: .1rem;
  height: .32rem;
  padding: 0 .05rem;
  border-bottom: 1px solid rgba(47, 58, 53, .45);
}
.merge-lost-xl-item__label {
  color: var(--mint-500);
  font-size: max(calc(.135 * var(--t)), 9px);
  font-weight: 700;
  letter-spacing: .02em;
  white-space: nowrap;
}
.merge-lost-xl-item__desc {
  min-width: 0;
  color: var(--text-md);
  font-size: max(calc(.15 * var(--t)), 10px);
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.merge-lost-xl-panel__foot {
  display: flex;
  align-items: center;
  gap: .05rem;
  margin-top: .1rem;
  padding-top: .07rem;
  border-top: 1px solid rgba(47, 58, 53, .6);
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: max(calc(.085 * var(--t)), 7px);
  letter-spacing: .12em;
  white-space: nowrap;
}

/* 窄屏：不再固定悬浮（会盖住单列大厅），改为大厅内容末尾的一整行，入口仍可用。 */




/* 2026-10-25 合并后适配：上游大厅侧栏变窄，联机大厅卡片需要纵向换行，
   否则统计行会被压成竖排、三个按钮会溢出卡片（见截图 _merge-matchmaking.png 之前的 hub）。 */
.lobby-discovery { container-type: inline-size; }
.lobby-discovery__overview { flex-wrap: wrap; row-gap: .06rem; }
.lobby-discovery__stats { flex: 1 1 100%; justify-content: space-between; gap: .04rem; }
.lobby-discovery__stats > span { flex: 1 1 0; min-width: 0; padding-left: .06rem; }
.lobby-discovery__stats > span:first-child { border-left: 0; padding-left: 0; }
.lobby-discovery__stats b { font-size: calc(.2 * var(--t)); }
.lobby-discovery__stats small { font-size: calc(.11 * var(--t)); }
.lobby-discovery__actions { flex-wrap: wrap; row-gap: .06rem; }
.lobby-discovery__actions .btn { flex: 1 1 auto; min-width: 0; }
.lobby-discovery__preference { flex: 1 1 100%; justify-content: space-between; }
.lobby-discovery__preference span { white-space: nowrap; }

/* ==== 2026-10-25 服主反馈：顶栏铺满、按钮统一、右下两张模式卡别拉那么高 ==== */
.lobby-screen .topbar { display: flex; align-items: center; justify-content: space-between; gap: .1rem; width: 100%; }
.lobby-screen .topbar__left, .lobby-screen .topbar__right { min-width: 0; align-items: center; }
.lobby-screen .topbar__tools { display: flex; align-items: center; gap: .05rem; flex-wrap: nowrap; }
.lobby-screen .topbar .btn,
.lobby-screen .topbar .me-chip,
.lobby-screen .topbar .ping { height: .4rem; min-height: .4rem; box-sizing: border-box; }
.lobby-screen .topbar .btn--square { width: .4rem; padding: 0; }
.lobby-screen .topbar .btn:not(.btn--square) { padding-inline: .1rem; }
.lobby-screen .topbar__right { margin-left: auto; }

/* 右下两张模式卡：按内容高度贴底，不随网格行拉伸 */
.hub-entries { align-items: flex-end; }
.hub-entry-wrap { flex: none; align-self: flex-end; }
.hub-entries .mode-card.hub-entry,
.hub-entries .hub-entry {
  flex: 0 0 auto;
  width: calc(2.3 * var(--t));
  height: calc(1.85 * var(--t)) !important;
  min-height: 0 !important;
  aspect-ratio: auto;
}
.hub-entry__desc, .hub-entry .hub-entry__en { font-size: calc(.1 * var(--t)); }

/* ==== 2026-10-25：顶栏按线上版快捷菜单排布 + 去掉整页滚动条 ==== */
html:has(.lobby-hub), body:has(.lobby-hub) { overflow: hidden; }
.lobby-screen.lobby-hub { overflow: hidden; }
.hub-stage { overflow: hidden; }
.lobby-screen .topbar { display: flex; align-items: center; justify-content: space-between; gap: .12rem; padding-inline: .12rem; }
.lobby-screen .topbar__right { display: flex; align-items: center; gap: .05rem; min-width: 0; overflow: hidden; }
.lobby-screen .topbar__left { display: flex; align-items: center; gap: .06rem; min-width: 0; overflow: hidden; }
.lobby-screen .topbar .btn,
.lobby-screen .topbar .ping { height: .4rem; min-height: .4rem; }
.lobby-screen .topbar .btn--square { width: .4rem; padding: 0; }
.lobby-screen .topbar__sep { flex: none; }

/* 2026-10-25：me-chip 不要被顶栏的固定高度压扁，按内容自然撑开 */
.lobby-screen .topbar .me-chip {
  height: auto;
  min-height: .72rem;
  padding: .03rem .1rem .03rem .04rem;
  align-items: center;
  gap: .06rem;
}
.lobby-screen .topbar .me-chip .avatar {
  width: .58rem;
  height: .58rem;
  flex: none;
}
.lobby-screen .topbar .me-chip__text { display: flex; flex-direction: column; justify-content: center; gap: .01rem; line-height: 1.1; }
.lobby-screen .topbar .me-chip__name { font-size: max(.2rem, 14px); }
/* 长名字不要撑破 chip */
.lobby-screen .topbar .me-chip__name { max-width: 2.4rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lobby-screen .topbar .me-chip__text { min-width: 0; }

/* 房间列表的版本标签（2026-10-25 服主需求：每个房间显示它在跑哪个版本） */
.lobby-directory__room-ver {
  flex: none;
  display: inline-flex;
  align-items: center;
  height: .24rem;
  padding: 0 .08rem;
  border: 1px solid var(--mint-700);
  background: var(--mint-a10);
  color: var(--mint-400);
  font-size: max(.12rem, 11px);
  white-space: nowrap;
}

/* ==== 2026-10-25 服主反馈：



/* 2026-10-25 服主：顶栏右侧这排按钮改半透明，露出背景 */
.lobby-screen .topbar__right .btn,
.lobby-screen .topbar__left .btn {
  background-color: rgba(7, 13, 12, .55);
  backdrop-filter: blur(3px);
}
.lobby-screen .topbar__right .btn:hover,
.lobby-screen .topbar__left .btn:hover {
  background-color: rgba(12, 22, 20, .78);
  backdrop-filter: blur(3px);
}
.lobby-screen .topbar .me-chip { background-color: rgba(7, 13, 12, .55); backdrop-filter: blur(3px); }

/* 2026-10-25 服主：手机横屏也要接近电脑的三列布局，只做等比缩小，不改成单列 */
@media (max-width: 1100px) {
  .lobby-screen .topbar { flex-wrap: nowrap; gap: .06rem; }
  .lobby-screen .topbar__left, .lobby-screen .topbar__right { overflow: hidden; }
  .hub-stage {
    display: grid;
    grid-template-columns: minmax(0, 3.1rem) minmax(0, 1fr) minmax(0, 2.1rem);
    grid-template-rows: minmax(0, 1fr) auto;
    grid-template-areas: "side center right" "side entries entries";
    gap: .1rem .18rem;
    padding: .06rem .16rem .12rem;
    overflow: hidden;
  }
  .hub-side { padding-top: .1rem; gap: .08rem; }
  .hub-right { padding-top: .1rem; gap: .08rem; }
  .hub-entries { justify-content: flex-end; gap: .08rem; }
  .hub-entries .mode-card.hub-entry,
  .hub-entries .hub-entry { width: auto !important; height: 64px !important; min-height: 64px !important; }
  .hub-center__title { font-size: min(calc(.42 * var(--t)), 40px); }
}

/* 2026-10-25 服主：手机横屏右栏被压扁（S.W.E.E.P./干员调配 挤在一起），按比例给右栏更多宽度 */
@media (max-width: 1100px) {
  .hub-stage {
    grid-template-columns: minmax(0, 23%) minmax(0, 1fr) minmax(0, 30%);
    gap: .08rem .12rem;
  }
  .hub-right { gap: .06rem; }
  .hub-right .hub-plate,
  .hub-right .hub-plate--loadout,
  .hub-right .lo-entry { min-width: 0; }
  .hub-right .hub-plate { padding-inline: .1rem; }
  .hub-right .hub-plate .lo-entry__label,
  .hub-right .hub-plate__label { font-size: max(12px, .15rem); white-space: nowrap; }
}

/* 2026-10-25 服主：手机横屏右栏别拉太长，板子给个上限 */
@media (max-width: 1100px) {
  .hub-stage { grid-template-columns: minmax(0, 23%) minmax(0, 1fr) minmax(0, 26%); }
  .hub-right .hub-plate, .hub-right .lo-entry { max-width: 210px; margin-left: auto; }
}

/* 2026-10-26：按版本播放的大厅背景视频（/media/bg/phaseN.mp4）。
   铺满窗口且不拉伸：object-fit: cover，等比裁切；最底层，静态光效/场景仍在上面。 */
.hub-bg__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity .6s ease;
  background: #050807;
}
.hub-bg__video.is-visible { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .hub-bg__video { transition: none; } }

/* 2026-10-26 服主需求：视频背景出现时，隐藏原本的静态背景层（光晕 / 舰船 / 网格 / 生成场景）。
   玩家自定义背景（OwnBackdrop）仍保留在最上层，玩家自己的选择优先。 */
.hub-bg.has-video .hub-bg__glow,
.hub-bg.has-video .hub-bg__ship,
.hub-bg.has-video .hub-bg__grid,
.hub-bg.has-video .hub-scene { display: none; }

/* 2026-10-26 服主：顶栏「切换版本」胶囊和「大厅背景」按钮要和其它按钮同高同风格 */
.lobby-screen .topbar .verchip-wrap { display: inline-flex; align-items: center; }
.lobby-screen .topbar .verchip {
  height: .4rem;
  min-height: .4rem;
  padding: 0 .12rem;
  display: inline-flex;
  align-items: center;
  gap: .06rem;
  font-size: calc(.14 * var(--t));
  line-height: 1;
}
.lobby-screen .topbar .verchip__label { font-size: calc(.14 * var(--t)); }
.lobby-screen .topbar .verchip__k { font-size: calc(.13 * var(--t)); }
.lobby-screen .topbar .lobby-media { height: .4rem; min-height: .4rem; }

/* 2026-10-26 修复：顶栏「按钮半透明」规则是按后代选择器写的，
   弹窗渲染在 .topbar__right 内部时会把弹窗里的实心按钮（完成/关闭）也刷成半透明深色，
   文字仍是深色 → 看起来像坏掉。这里让实心变体在顶栏子树里保持原色。 */
.lobby-screen .topbar .btn--primary,
.lobby-screen .topbar .btn--amber,
.lobby-screen .topbar .btn--ice,
.lobby-screen .topbar .btn--danger {
  background-color: var(--btn-bg);
  color: var(--btn-fg);
}
.lobby-screen .topbar .btn--primary:hover,
.lobby-screen .topbar .btn--amber:hover,
.lobby-screen .topbar .btn--ice:hover,
.lobby-screen .topbar .btn--danger:hover {
  background-color: var(--btn-bg-hover);
}

