
/* Admin */
.admin-layout { display: grid; grid-template-columns: 188px minmax(0, 1fr); gap: 16px; }
.admin-tabs { display: grid; align-content: start; gap: 2px; padding: 8px; height: fit-content; }
.admin-tab { gap: 8px; padding: 10px 10px; border: 0; border-radius: var(--radius-input); color: var(--muted); text-align: left; background: transparent; font-size: 11px; font-weight: 700; }
.admin-tab.active { color: var(--on-accent); background: var(--lime); }
.admin-tab svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.7; }
.admin-main { min-width: 0; }
.admin-panel-head { gap: 12px; margin-bottom: 16px; }
.admin-panel-head p { color: var(--muted); font-size: 11px; margin-top: 4px; }
.admin-search { max-width: 240px; }
.data-table { width: 100%; border-collapse: collapse; }
.data-table th { padding: 8px 8px; color: var(--muted-2); text-align: left; font: 10px "DM Mono", monospace; font-weight: 500; border-bottom: 1px solid var(--line); }
.data-table td { padding: 12px 8px; border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent); color: var(--text); font-size: 11px; vertical-align: middle; }
/* 首列与末列不留内边距。
   表格住在 `.admin-panel` 里，而那个面板已经有 20px 内边距；单元格再各留 8px，
   表头和内容就比面板里的标题（`.admin-panel-head h2`）右移 8px —— 表格看起来
   "整体偏了"。让第一列贴齐面板内容边缘之后，标题、表头、第一列文字在同一条竖线上。 */
.data-table th:first-child, .data-table td:first-child { padding-left: 0; }
.data-table th:last-child, .data-table td:last-child { padding-right: 0; }
.data-table tr:last-child td { border-bottom: 0; }
.table-player { gap: 8px; }
.table-player .avatar { width: 28px; height: 28px; }
.table-player-name { font-weight: 700; }
.table-player-id { color: var(--muted); font: 9px "DM Mono", monospace; margin-top: 2px; }
.role { display: inline-flex; padding: 4px 6px; border-radius: var(--radius-xs); background: var(--surface-role); }
/* 标签与状态胶囊用同一套语言：半透明底色 + 彩色文字。
   原先 .role.lime 是实心红底白字，看起来像一个主按钮，比旁边真正的按钮还抢眼。 */
.role.lime { color: var(--lime); background: color-mix(in srgb, var(--lime) 14%, transparent); }
.role.coral { color: var(--coral); background: color-mix(in srgb, var(--coral) 14%, transparent); }
.table-actions { text-align: right; }
.tiny-btn { border: 1px solid var(--line-light); border-radius: var(--radius-input); color: var(--muted); background: transparent; padding: 6px 8px; font-size: 10px; }
.tiny-btn:hover { color: var(--text); }
.danger-btn { border: 1px solid color-mix(in srgb, var(--danger) 55%, var(--line)); border-radius: var(--radius-input); color: var(--danger); background: transparent; padding: 8px 10px; font-size: 11px; }
.danger-btn:hover { color: var(--on-accent); background: var(--danger); }
.admin-series { display: grid; gap: 10px; }
/* 比赛长条：全站唯一一种。时间/标志固定，名称块占剩余空间并截断，
   对阵块固定宽度并靠右——固定宽度是让每一行的 VS/比分落在同一条竖线上的前提。 */
.match-strip { grid-template-columns: 92px 34px minmax(0, 1fr) 380px auto; gap: 14px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--panel); color: var(--text); text-align: left; }
.match-strip[data-match] { cursor: pointer; transition: border-color .16s ease; }
.match-strip[data-match]:hover { border-color: var(--line-light); }
.match-strip-mark { display: flex; }
/* 已分胜负：只有赢的那个数字变绿,输家队徽与队名变灰变淡。 */
.match-strip-score-num.is-win { color: var(--win); }
.match-strip-score-sep { color: var(--muted-2); }
.match-strip-side-loser { opacity: .45; filter: grayscale(1); }
/* 选手页/战队页的近期比赛：这一场的胜负。
   宽屏是卡片最左侧的一条装饰带（用 inset 阴影,不占布局、跟着圆角走）;
   窄屏由 8-responsive 换成右上角的胜/败徽章。 */
.match-strip-win { box-shadow: inset 3px 0 0 var(--win); }
.match-strip-loss { box-shadow: inset 3px 0 0 var(--danger); }
.match-strip-result { display: none; }
/* 网站管理：颜色用系统取色器,开关是一行可点区域。 */
.site-toggle { display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-card); }
.site-toggle span { display: grid; gap: 2px; }
.site-toggle small { color: var(--muted); font-size: 10px; }
.site-toggles { display: grid; gap: 12px; }
/* 网站管理的两个分组和外层 `.admin-panel` 是同一个面，所以不能再包一层 `.panel`：
   那会画出"卡片里的卡片"，而且分组内容的左边缘比标题深 20px —— 切到这个选项卡时
   整块看起来往右偏。分组只用一条 `.section-title` 带出来。 */
.site-group { display: grid; gap: 0; }
.site-group > .section-title { margin: 22px 0 14px; }
.site-group:first-of-type > .section-title { margin-top: 0; }
.match-strip-mark-img { width: 34px; height: 34px; border-radius: var(--radius-card); object-fit: cover; }
.match-strip-names { display: grid; gap: 2px; min-width: 0; }
.match-strip-names strong { font-size: 13px; font-weight: 700; }
.match-strip-names span { color: var(--muted); font-size: 10px; }
/* 三列对应三个子元素：左半、比分、右半。两半等宽，所以比分永远落在正中。 */
.match-strip-versus { grid-template-columns: minmax(0, 1fr) 56px minmax(0, 1fr); gap: 6px; }
.match-strip-side { min-width: 0; }
.match-strip-side-right { justify-content: flex-end; }
.match-strip-team { font-size: 12px; text-align: right; }
.match-strip-side-right .match-strip-team { text-align: left; }
/* VS 与比分：加粗、无衬线、字重更大，数字等宽以免跳动。 */
.match-strip-score { color: var(--text); font-family: Manrope, "Microsoft YaHei", sans-serif; font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; text-align: center; }
.match-strip-logo { width: 24px; height: 24px; border-radius: var(--radius-input); object-fit: cover; }
.series-row { grid-template-columns: 42px minmax(0, 1fr) 108px 80px; border: 1px solid var(--line); border-radius: var(--radius-card); }
.series-cover { width: 42px; height: 42px; border-radius: var(--radius-btn); object-fit: cover; }
.series-cover.avatar-fallback { font-size: 13px; }
.series-name { font-size: 12px; font-weight: 700; }
.series-detail { color: var(--muted); font-size: 10px; margin-top: 4px; }
.series-detail-page { display: grid; gap: 20px; max-width: 1100px; margin: 0 auto; }
/* 选手页与队伍页同一套排版，只是内容不同。 */
.player-detail-page { max-width: 1100px; }
/* 成员/队伍列表：与比赛长条同一套行语言，整行可点。 */
.member-list { display: grid; gap: 10px; }
.member-row { grid-template-columns: 34px minmax(0, 1fr) auto; gap: 12px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--panel); color: var(--text); font: inherit; text-align: left; cursor: pointer; transition: border-color .16s ease; }
.member-row:hover { border-color: var(--line-light); }
.member-avatar { width: 34px; height: 34px; border-radius: var(--radius-card); object-fit: cover; }
.member-row strong { font-size: 13px; }
.series-detail-page.public-series-detail { max-width: none; }
.topbar .back-link { display: inline-flex; align-items: center; gap: 0; padding: 8px 14px; border: 1px solid var(--line-light); border-radius: var(--radius-pill); background: var(--panel); color: var(--text); font-size: 0; font-weight: 700; }
.topbar .back-link::after { content: "返回"; font-size: 11px; }
.topbar .back-link svg { display: none; }
.series-detail-page > .back-link:hover { border-color: var(--lime); }

/* 只在没有图时用「默认队伍头像颜色」。
   这里必须按**语义**列类名,不能靠猜:
   - 队伍/对阵标志：.match-strip-logo（比赛长条两侧）、.bracket-team-avatar（赛程里）、
     .match-detail-team-logo（比赛详情两侧）、.match-roster-team-logo、.match-stat-team-logo
   - `.member-avatar` 是**选手**（队伍成员列表里那一个个选手）,不在这一列；
   - `.series-cover` 是赛事标志,既不是队伍也不是选手,也不在这一列。
   - `:not(.has-image)` 必须有：否则会盖掉 .avatar-fallback.has-image 的透明底
     （同优先级、后写的赢）,有标志的队伍会露出一个方块。 */
.match-strip-logo.avatar-fallback:not(.has-image), .bracket-team-avatar.avatar-fallback:not(.has-image),
.match-detail-team-logo.avatar-fallback:not(.has-image), .match-roster-team-logo.avatar-fallback:not(.has-image),
.match-stat-team-logo.avatar-fallback:not(.has-image) {
  background: var(--avatar-team, var(--lime));
}
/* 搜索框与卡片之间用同一个 10px,不再出现上面比下面宽。 */
.series-directory-page { display: grid; gap: 10px; }
.series-directory { display: grid; gap: 10px; width: 100%; }
.series-directory-card { grid-template-columns: 56px minmax(0,1fr); width: 100%; color: var(--text); text-align: left; cursor: pointer; transition: border-color .16s, transform .16s; }
.series-directory-card:hover { border-color: var(--coral); transform: translateY(-1px); }
.series-directory-avatar .series-avatar { width: 56px; height: 56px; border-radius: var(--radius-lg); }
.series-directory-copy { display: grid; gap: 4px; min-width: 0; }
.series-directory-copy strong { font-size: 15px; }
.series-directory-copy span, .series-directory-copy small { color: var(--muted); font-size: 10px; }

/* 头像与名字同一行居中。父级 .series-detail-head 是 flex-end（底对齐）,
   所以这里必须显式居中,并把标题那 6px 上边距去掉——它就是"名字看着偏低"的来源。 */
.series-detail-brand { gap: 14px; align-items: center; }
/* 特异性要压过下面的 `.series-detail-head h1 { margin-top: 6px }`（同优先级、它更靠后）。 */
.series-detail-head .series-detail-brand h1 { margin-top: 0; }
.series-avatar-large { width: 64px; height: 64px; border-radius: var(--radius-lg); font-size: 20px; }
.room-player-slots { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.series-detail-head { gap: 16px; margin-top: 8px; }
.series-detail-head h1 { margin-top: 6px; }
.series-detail-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.series-detail-stats > div { display: grid; gap: 6px; border-right: 1px solid var(--line); }
.series-detail-stats > div:last-child { border-right: 0; }
.series-match-list { display: grid; gap: 8px; }

.bracket-panel { overflow-x: auto; }

.bracket-panel .section-title { margin: 0 0 16px; }

/* 阶段与分组用标签页切换(与原设计一致):一次只看一个阶段的一个分组。
   只有一行可选时调用方不渲染这一行——见 renderBracket 的 hasChoice。 */
.bracket-tabs { gap: 12px; margin-bottom: 16px; overflow-x: auto; padding-bottom: 2px; }
.bracket-stage-tabs, .bracket-group-tabs { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.bracket-group-tabs { padding-left: 12px; border-left: 1px solid var(--line); }
.bracket-tab, .bracket-group-tab, .bracket-tab-add { padding: 4px 10px; border: 1px solid var(--line); border-radius: var(--radius-pill); background: transparent; color: var(--muted); font-size: 10px; }
.bracket-tab.active, .bracket-group-tab.active { border-color: var(--lime); background: color-mix(in srgb, var(--lime) 12%, transparent); color: var(--text); }
.bracket-tab-add { border-style: dashed; }
.bracket-tab-slot { display: inline-flex; align-items: center; gap: 4px; }
.bracket-tab-name { width: 96px; padding: 4px 10px; border: 1px solid var(--lime); border-radius: var(--radius-pill); background: color-mix(in srgb, var(--lime) 12%, transparent); color: var(--text); font-family: inherit; font-size: 10px; }

/* 视口像地图软件:一块占满面板的深灰底衬,赛程默认按"铺满它"的比例显示(100%),
   可以放大到 250%、缩到 60%;拖动平移。没有滚动条——画布是"一张图",不是一份文档。 */
.bracket-viewport { position: relative; overflow: hidden; height: clamp(460px, 76vh, 900px); background: var(--panel-raised); border-radius: var(--radius); cursor: grab; touch-action: none; user-select: none; }
/* 拖动视口时文字会被选成蓝色——那是拖动的副作用,不是内容。整个赛程都不可选,
   但输入类控件必须恢复可选,否则没法编辑。 */
.bracket-panel { user-select: none; }
.bracket-panel input, .bracket-panel select, .bracket-panel textarea { user-select: text; }
.bracket-viewport.is-panning { cursor: grabbing; }
/* 管理模式仍用滚动条:编辑时拖背景会和点选控件打架,而且滚动位置更容易保持;
   缩放条在管理态没有意义,隐藏。 */
.bracket-editable .bracket-viewport { overflow: auto; cursor: default; touch-action: auto; }
.bracket-editable .bracket-zoom { display: none; }
.bracket-zoom { position: absolute; z-index: 3; top: 10px; right: 10px; gap: 6px; padding: 4px 8px; border: 1px solid var(--line); border-radius: var(--radius-pill); background: color-mix(in srgb, var(--panel) 88%, transparent); }
.bracket-zoom-btn { width: 20px; height: 20px; padding: 0; border: 1px solid var(--line-light); border-radius: 50%; background: transparent; color: var(--muted); font: 12px/18px Arial, sans-serif; }
.bracket-zoom-range { width: 96px; accent-color: var(--lime); }
.bracket-zoom-value { min-width: 34px; text-align: right; }
/* width: max-content 是适配的前提:否则画布宽度等于容器宽度,固定列宽的网格会溢出画布,
   自适应也会以容器宽度为基准算错比例。 */
.bracket-canvas { position: relative; display: grid; gap: 18px; width: max-content; padding: 4px 4px 12px; }
/* 底板(可拖动的那块深灰背景)比它装的内容大一圈,而且**不随内容或窄屏收缩**:
   给一个固定的最小尺寸,赛程居中放在里面。窄屏时它保持这个尺寸,靠拖动查看。 */
.bracket-band { display: grid; gap: 8px; align-content: center; justify-content: center; min-width: 960px; min-height: 560px; padding: 24px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel-soft); }
.bracket-band-trees { display: grid; gap: 12px; min-width: 0; }
.bracket-tree { display: grid; gap: 8px; min-width: 0; }
.bracket-tree + .bracket-tree { padding-top: 12px; border-top: 1px solid var(--line); }
.bracket-tree-head { min-width: 0; }
.bracket-tree-head h5 { margin: 0; color: var(--text); font-size: 12px; font-weight: 700; }
.bracket-tree-name { min-width: 0; max-width: 220px; padding: 4px 6px; border: 1px solid var(--line); border-radius: var(--radius-input); background: var(--panel-raised); color: var(--text); font: 11px Manrope, "Microsoft YaHei", sans-serif; }
/* 列宽固定,而不是 1fr:内容要有"自然尺寸",视口才能把它缩放到刚好合适
/* 列宽固定，而不是 1fr:内容要有"自然尺寸"，视口才能把它缩放到刚好合适。 */
.bracket-band-grid { display: grid; grid-template-columns: repeat(var(--bracket-rounds), 200px); gap: 36px; }

.bracket-round { position: relative; z-index: 1; }
.bracket-links { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; overflow: visible; color: var(--line-light); pointer-events: none; }
.bracket-links path { fill: none; stroke: currentColor; stroke-width: 1.2; vector-effect: non-scaling-stroke; }
.bracket-links .winner-link { color: var(--lime); }
.bracket-round-title { gap: 8px; margin-bottom: 10px; }
.bracket-round-title h3 { margin: 0; }

.bracket-remove-btn { width: 18px; height: 18px; padding: 0; border: 1px solid var(--line-light); border-radius: 50%; background: transparent; color: var(--muted); font: 14px/15px Arial, sans-serif; }
.bracket-remove-btn:hover { color: var(--danger); border-color: var(--danger); }
.bracket-round h3 { margin: 0 0 10px; color: var(--muted); font-size: 11px; font-weight: 700; }
.bracket-round-matches { display: flex; flex-direction: column; justify-content: space-around; min-height: var(--bracket-height, 380px); gap: 10px; }
.bracket-match { display: grid; gap: 6px; padding: 10px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--panel-raised); box-shadow: 0 5px 14px color-mix(in srgb, var(--ink) 5%, transparent); }
.bracket-match-head { gap: 8px; color: var(--muted); font: 9px "DM Mono", monospace; }
.bracket-match select { width: 100%; min-width: 0; padding: 6px 6px; border: 1px solid var(--line); border-radius: var(--radius-input); background: var(--panel); color: var(--text); font-size: 10px; }
.bracket-time-field { display: grid; gap: 4px; }
.bracket-time-field span { color: var(--muted); font-size: 9px; }
.bracket-time-field input { width: 100%; min-width: 0; padding: 6px 6px; border: 1px solid var(--line); border-radius: var(--radius-input); outline: 0; background: var(--panel); color: var(--text); font-size: 10px; color-scheme: inherit; }
.bracket-time-field input:focus { border-color: var(--lime); }
.bracket-match-head select { width: auto; padding: 2px 4px; font-size: 9px; }
.bracket-match-head [data-bracket-field="group"] { display: none; }
/* 轮空。公开页的轮空节点是一张**说明卡**而不是比赛卡：没有对手就没有比分、没有可点的
   进入点，两个下拉也只是两条"轮空/待定"。
   卡片风格和其它卡片**一致**（实线边框、同样的底色、同样的圆角）：它也是赛程里的一格，
   画成虚线会读成"这里坏了/还没填"，而它其实是一个填好的结论。区别只由「轮空」标签和
   「直接晋级」表达。编辑器里仍然保留完整下拉（否则改成轮空就改不回来了），只多一个标签。 */
.bracket-bye-tag { padding: 1px 6px; border-radius: var(--radius-pill); color: var(--muted); background: var(--surface-role); font: 9px "DM Mono", monospace; letter-spacing: .08em; }
.bracket-bye-body { display: grid; justify-items: center; gap: 4px; padding: 6px 0 2px; text-align: center; }
.bracket-bye-avatar { width: 24px; height: 24px; border-radius: var(--radius-tile); font-size: 10px; }
.bracket-bye-body strong { font-size: 12px; font-weight: 700; }
.bracket-bye-body small { color: var(--muted); font-size: 9px; }
.bracket-readonly .bracket-match select:disabled { opacity: 1; pointer-events: none; cursor: default; color: var(--text); -webkit-text-fill-color: var(--text); background: transparent; }
.bracket-readonly .bracket-match > select:disabled { appearance: none; padding: 4px 2px; border: 0; border-bottom: 1px solid var(--line); border-radius: 0; font-weight: 700; }
.bracket-readonly .bracket-match-head select:disabled { appearance: none; padding: 0; border: 0; font-size: 9px; }
.bracket-readonly .bracket-route { display: none; }
.bracket-readonly .bracket-round-matches { min-height: var(--bracket-height, 280px); }
.bracket-team-display, .bracket-team-select { display: flex; align-items: center; gap: 6px; min-width: 0; }
.bracket-team-display { min-height: 29px; padding: 4px 2px; border-bottom: 1px solid var(--line); }
.bracket-team-display strong { min-width: 0; font-size: 10px; }
.bracket-team-score { min-width: 18px; margin-left: auto; color: var(--text); font: 10px/1 "DM Mono", monospace; text-align: right; }
.bracket-team-winner strong, .bracket-team-winner .bracket-team-score { color: var(--lime); }
.bracket-team-avatar { width: 22px; height: 22px; border-radius: var(--radius-input); flex: 0 0 22px; font-size: 9px; }
.bracket-tbd { display: inline-grid; place-items: center; color: var(--muted); background: var(--panel); border: 1px dashed var(--line-light); font-weight: 800; }
.bracket-team-select select { flex: 1; }
.bracket-readonly { padding: 12px; overflow: hidden; }
.bracket-readonly .section-title { margin-bottom: 10px; }

/* 公开页保留"可滚动的盒子 + 每轮固定宽度",但列宽规则要落在分组网格上,不再是画布。 */
.bracket-readonly .bracket-round-title { justify-content: center; margin-bottom: 2px; text-align: center; }
.bracket-readonly .bracket-round h4 { margin-bottom: 8px; font-size: 10px; }
.bracket-readonly .bracket-round-matches { position: relative; display: block; }
.bracket-readonly .bracket-match { position: absolute; top: var(--match-y); left: 50%; width: 100%; gap: 2px; padding: 6px; border-radius: var(--radius-input); transform: translate(-50%, -50%); }
.bracket-readonly .bracket-match-head { gap: 6px; font-size: 9px; }
.bracket-readonly .bracket-team-display { min-height: 26px; gap: 6px; padding: 2px 2px; }
.bracket-readonly .bracket-team-display strong { font-size: 10px; }
.bracket-readonly .bracket-team-avatar { width: 20px; height: 20px; border-radius: var(--radius-xs); flex-basis: 20px; font-size: 9px; }
.bracket-readonly .bracket-match-linked { cursor: pointer; transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease; }
.bracket-readonly .bracket-match-linked:hover, .bracket-readonly .bracket-match-linked:focus-visible { z-index: 2; border-color: var(--lime); box-shadow: 0 7px 20px color-mix(in srgb, var(--ink) 12%, transparent); outline: 0; transform: translate(-50%, -50%) translateY(-1px); }
.bracket-route { display: grid; gap: 4px; padding-top: 2px; border-top: 1px solid var(--line); }
.bracket-route label { grid-template-columns: 48px minmax(0,1fr); gap: 4px; color: var(--muted); font-size: 9px; }
.bracket-route select { padding: 4px 4px; font-size: 9px; }
.bracket-actions { display: flex; gap: 6px; }
.bracket-empty { grid-column: 1 / -1; display: grid; place-items: center; min-height: 150px; color: var(--muted); font-size: 10px; }

/* 赛程编辑是草稿式的：改动只留在内存里，点右上角「保存赛程」才写入，
   所以按钮旁边必须一直显示当前是「已保存」还是「有未保存的改动」。 */
.bracket-save-state { color: var(--muted-2); font-size: 10px; }
.bracket-save-state.is-dirty { color: var(--yellow); }
/* 就地改名：平时看不出是输入框，悬停/聚焦才显出边框，避免满屏控件。 */
.bracket-round-name { flex: 1; min-width: 0; padding: 4px 8px; border: 1px solid transparent; border-radius: var(--radius-input); background: var(--panel-soft); color: var(--text); font-family: inherit; font-size: 12px; font-weight: 600; }
.bracket-round-name:hover { border-color: var(--line); }
.bracket-round-name:focus { border-color: var(--lime); }

/* 批量导入选手：粘贴框 + 逐行预览。
   粘贴的文字里既有昵称也有 id，所以预览行按「行号 昵称 id 备注」四列排，
   昵称列是 minmax(0,1fr) 并可截断 —— 长昵称不能把备注挤出去。 */
.import-samples { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; }
.import-samples code { padding: 4px 6px; border: 1px solid var(--line); border-radius: var(--radius-xs); background: var(--panel-soft); color: var(--muted); font: 10px "DM Mono", monospace; }
.import-field textarea { min-height: 132px; resize: vertical; line-height: 1.6; }
.import-tools { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.import-summary { margin-top: 4px; color: var(--muted); font: 10px "DM Mono", monospace; }
.import-preview, .import-failures { display: grid; gap: 4px; max-height: 216px; margin-top: 8px; overflow-y: auto; overscroll-behavior: contain; }
.import-row, .import-failure { display: grid; grid-template-columns: 22px minmax(0, 1fr) 134px minmax(0, 1fr); gap: 8px; align-items: center; padding: 6px 8px; border: 1px solid var(--line); border-radius: var(--radius-input); background: var(--panel-soft); font-size: 11px; }
.import-row-line, .import-failure-line { color: var(--muted-2); font: 10px "DM Mono", monospace; text-align: right; }
.import-row-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.import-row-id, .import-failure-id { color: var(--muted); font: 10px "DM Mono", monospace; }
.import-row-note, .import-failure-note { min-width: 0; color: var(--muted-2); font-size: 10px; overflow-wrap: anywhere; }
/* 三态里只有两种需要上色：能导入的行保持中性，跳过的是信息态，读不出来的是错误态。 */
.import-row.is-skip { border-color: color-mix(in srgb, var(--sky) 40%, var(--line)); }
.import-row.is-skip .import-row-note { color: var(--sky); }
.import-row.is-error { border-color: color-mix(in srgb, var(--coral) 45%, var(--line)); }
.import-row.is-error .import-row-note { color: var(--coral); }
/* 导入是一次性的写入：结果只说一次，所以失败条目要在弹层里留到人看完为止。 */
.import-preview-more { color: var(--muted-2); font-size: 10px; text-align: center; }
.import-done p { margin-bottom: 8px; }
.import-done b { color: var(--lime); font: 12px "DM Mono", monospace; }
.import-done .import-done-warn { color: var(--coral); }
/* 次要的一句（来源、或者"没有需要处理的选手"）：和结论同一段，但比结论轻。 */
.import-done .import-done-note { color: var(--muted); font-size: 10px; }
/* Steam 密钥：状态胶囊 + 一只只写输入框。输入框是等宽的 —— 密钥看着像一串随机字符，
   等宽字体里少一位、多一位一眼就看得出来。 */
.steam-key { display: grid; gap: 10px; justify-items: start; }
.steam-key .field { width: 100%; max-width: 460px; }
.steam-key .field input { font: 12px "DM Mono", monospace; letter-spacing: 0.4px; }
.steam-key .form-actions { margin: 0; }
/* 邮件服务：字段比密钥多，用 form-row 排两列；状态胶囊单独一行放在最上面。 */
.mail-config { display: grid; gap: 12px; }
.mail-config .form-row { align-items: start; }
.mail-config > .status-pill { justify-self: start; }
.mail-config .form-actions { margin: 0; }
