:root {
  --bg: #10130f;
  --bg-2: #171b16;
  --panel: #1c221c;
  --line: #2d362c;
  --text: #efe7d4;
  --muted: #9aa08a;
  --accent: #d9a441;
  --accent-2: #f2d389;
  --danger: #e06b5c;
  --ok: #8fbf6a;
  --warn: #d9a441;
  --shadow: 0 18px 40px rgba(0, 0, 0, 0.28);
  --panel-bg: #1a1f1a;
  --gap: clamp(12px, 1vw, 18px);
  --edge: clamp(14px, 1.6vw, 26px);
  font-family: "Avenir Next", "PingFang SC", "Hiragino Sans GB", sans-serif;
}

* { box-sizing: border-box; }
/* Keep inner scrollbars thin and dim instead of the chunky default ones. */
.log-view, .table-wrap, .ai-chat, .account-list {
  scrollbar-width: thin; scrollbar-color: var(--line) transparent;
}
.log-view::-webkit-scrollbar, .table-wrap::-webkit-scrollbar,
.ai-chat::-webkit-scrollbar, .account-list::-webkit-scrollbar { width: 8px; height: 8px; }
.log-view::-webkit-scrollbar-track, .table-wrap::-webkit-scrollbar-track,
.ai-chat::-webkit-scrollbar-track, .account-list::-webkit-scrollbar-track { background: transparent; }
.log-view::-webkit-scrollbar-thumb, .table-wrap::-webkit-scrollbar-thumb,
.ai-chat::-webkit-scrollbar-thumb, .account-list::-webkit-scrollbar-thumb {
  background: var(--line); border-radius: 999px;
}
.log-view::-webkit-scrollbar-thumb:hover, .table-wrap::-webkit-scrollbar-thumb:hover,
.ai-chat::-webkit-scrollbar-thumb:hover, .account-list::-webkit-scrollbar-thumb:hover { background: #46523f; }
/* The form card scrolls with the wheel only; its pinned footer already marks the
   bottom edge, so the bar itself is just noise. */
.form-panel { scrollbar-width: none; }
.form-panel::-webkit-scrollbar { display: none; }
html, body { margin: 0; min-height: 100%; background: radial-gradient(1200px 600px at 10% -10%, #2a2418 0%, var(--bg) 45%); color: var(--text); }
button, input, select { font: inherit; color: inherit; }
button { cursor: pointer; }
h1, h2, h3 { margin: 0; font-weight: 650; letter-spacing: 0.02em; }
p { margin: 0; }

.app {
  width: 100%; max-width: 1760px; margin: 0 auto; padding: var(--edge);
  display: flex; flex-direction: column;
  height: 100vh; height: 100dvh;
}
.topbar {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px 20px; align-items: center;
  margin-bottom: 18px; padding-bottom: 16px; border-bottom: 1px solid var(--line);
}
.brand { display: flex; gap: 14px; align-items: center; min-width: 0; }
.mark {
  flex: none; width: 46px; height: 46px; display: grid; place-items: center;
  background: var(--accent); color: #1a1408; font-weight: 800; border-radius: 12px;
}
.brand > div { min-width: 0; }
.brand h1 { font-size: clamp(18px, 1.4vw, 22px); }
.brand p { color: var(--muted); font-size: 13px; margin-top: 4px; max-width: 52ch; }
.account-bar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-left: auto; }
.account-bar label { color: var(--muted); font-size: 13px; }
.account-bar select { min-width: 0; width: clamp(170px, 17vw, 300px); }

.layout {
  display: grid; grid-template-columns: minmax(320px, 26%) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  gap: var(--gap); flex: 1; min-height: 0;
}
.panel {
  background: var(--panel-bg);
  border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow);
  min-width: 0;
}
/* Each column scrolls on its own so the toolbar and the result table stay put. */
.form-panel {
  /* No bottom padding: the pinned action bar supplies it, so nothing can peek
     out beneath the bar as the form scrolls. */
  padding: 18px 18px 0; min-height: 0;
  overflow: hidden auto; overscroll-behavior: contain;
}
.panel-head {
  display: flex; flex-wrap: wrap; justify-content: space-between;
  align-items: center; gap: 8px 12px; margin-bottom: 14px;
}
.head-actions { display: flex; align-items: center; gap: 6px; }
.hint, .muted { color: var(--muted); font-size: 13px; }
.grid { display: grid; gap: 10px; }
.grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--muted); min-width: 0; }
input, select {
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px;
  padding: 8px 10px; outline: none;
  width: 100%; min-width: 0; max-width: 100%;
}
select { text-overflow: ellipsis; }
input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
input:focus, select:focus { border-color: var(--accent); }
.wide { grid-column: 1 / -1; }
.toggles { display: flex; flex-direction: column; gap: 6px; margin: 12px 0; }
.check { flex-direction: row; align-items: center; gap: 8px; color: var(--text); }
.check input { width: 16px; height: 16px; flex: none; }
.proxy-box {
  margin: 12px 0; padding: 12px; border: 1px dashed var(--line); border-radius: 12px;
}
.proxy-box h3 { font-size: 14px; }
.proxy-box .panel-head { margin-bottom: 10px; }
.advanced summary { cursor: pointer; margin-bottom: 10px; }
.actions { display: flex; gap: 8px; margin-top: 16px; }
/* Pinned to the bottom of the form card so 开始创建 stays reachable without
   scrolling to the end of a long form. Negative margins bleed it to the edges. */
.form-actions {
  position: sticky; bottom: 0; z-index: 2; flex-wrap: wrap; align-items: center;
  margin: 16px -18px 0; padding: 12px 18px 18px;
  background: var(--panel-bg); border-top: 1px solid var(--line);
  border-radius: 0 0 15px 15px;
}
.primary, .ghost {
  border-radius: 10px; padding: 10px 14px; border: 1px solid transparent;
}
.primary { background: var(--accent); color: #1a1408; font-weight: 700; }
.primary:disabled, .ghost:disabled { opacity: 0.45; cursor: not-allowed; }
.ghost { background: transparent; border-color: var(--line); color: var(--text); }
.small { padding: 6px 9px; font-size: 12px; }

.workspace {
  display: grid; grid-template-rows: clamp(150px, 24vh, 300px) minmax(0, 1fr);
  gap: var(--gap); min-height: 0;
}
.log-panel, .result-panel { padding: 16px; min-height: 0; display: flex; flex-direction: column; }
.log-view {
  flex: 1; margin: 0; overflow: auto; background: #0c0f0b; border-radius: 12px;
  padding: 12px; font: 12px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap; color: #d7d2c3;
}
.log-view .info { color: #d7d2c3; }
.log-view .success { color: var(--ok); }
.log-view .warn { color: var(--warn); }
.log-view .error { color: var(--danger); }
/* 全局流里别人的动作，用名字打头才分得清是谁在建机 */
.log-view .log-actor { color: var(--accent); }
.table-wrap { overflow: auto; flex: 1; min-height: 0; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
#resultWrap table { min-width: 780px; }
#poolWrap table { min-width: 660px; }
/* 九列表格，挤一点才能在 1440 宽度下不出横向滚动条 */
#onlineWrap table { min-width: 940px; }
#onlineWrap th, #onlineWrap td { padding: 6px 8px; }
/* 实例 ID 有 16 位，任其自然会独占名称列半边；截断显示，完整值放 title，
   复制按钮取的是内存里的原值，不受这里影响 */
#onlineWrap td .id-line {
  max-width: 118px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* 聚合视图的盒子列。两台盒子上的实例同名，这一列是唯一能分辨的地方，所以不许被挤掉 */
#onlineWrap td.host-cell {
  white-space: nowrap; color: var(--muted); font-size: 12px;
}
th, td {
  text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--line);
  vertical-align: top; white-space: nowrap;
}
th {
  position: sticky; top: 0; z-index: 1;
  background: var(--panel-bg); color: var(--muted); font-weight: 600;
  /* border-collapse drops the border on sticky cells, so paint it inline. */
  border-bottom: none; box-shadow: inset 0 -1px 0 var(--line);
}
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
.status-success { color: var(--ok); }
.status-fail { color: var(--danger); }
.result-actions { display: flex; gap: 6px; flex-wrap: wrap; }

.traffic-chip {
  border-radius: 999px; padding: 7px 13px; font-size: 12px; font-weight: 700;
  border: 1px solid var(--line); background: var(--bg-2); color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap;
}
.traffic-chip.level-ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
.traffic-chip.level-warn { color: var(--warn); border-color: var(--warn); }
.traffic-chip.level-critical {
  color: #1a1408; background: var(--danger); border-color: var(--danger);
  animation: traffic-pulse 1.8s ease-in-out infinite;
}
@keyframes traffic-pulse { 50% { opacity: 0.62; } }
@media (prefers-reduced-motion: reduce) { .traffic-chip.level-critical { animation: none; } }

/* 容量胶囊：盒子内存是硬约束，超了建机会直接失败，所以放在顶栏常驻 */
.capacity-chip {
  border-radius: 999px; padding: 7px 13px; font-size: 12px; font-weight: 700;
  border: 1px solid var(--line); background: var(--bg-2); color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap;
}
.capacity-chip.level-ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
.capacity-chip.level-warn { color: var(--warn); border-color: var(--warn); }
.capacity-chip.level-critical {
  color: #1a1408; background: var(--danger); border-color: var(--danger);
}

/* ── 自动登录页签 ───────────────────────────────────────────────
   这个页签里塞了四张表，跟其它页签「一屏一张表」的布局不一样：整块一起纵向滚动，
   免得每张表各自出一个内滚动条，鼠标滚到哪一张全靠运气。 */
.al-wrap { overflow: auto; flex: 1; min-height: 0; }
.al-wrap[hidden] { display: none; }
.al-section { margin-top: 14px; }
.al-section .panel-head { margin-bottom: 6px; }
.al-section h3 { font-size: 14px; }
/* 表格自己不滚，交给 .al-wrap 统一滚 */
.al-table { overflow: visible; flex: none; }
.al-table table { min-width: 720px; }
.al-table th, .al-table td { padding: 6px 8px; }
/* 全局 th 是 sticky top:0 的，那是给「一屏一张表」用的。四张表共用一个滚动容器时
   每张表的表头都会粘到容器顶端叠在一起（滚到云机表还挂着任务表的表头），所以这里
   退回普通定位，让表头跟着自己那张表滚走。 */
.al-table th { position: static; }

.al-settings {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 10px;
  background: rgba(255, 255, 255, 0.02);
}
.al-settings-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: flex-end;
  margin-bottom: 6px;
}
.al-settings-row .inline-label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  color: var(--muted);
}
.al-settings-row input,
.al-settings-row select { min-width: 200px; }
.al-table tbody:empty::after { content: "暂无"; color: var(--muted); font-size: 13px; }

/* 云机集群一览：哪台能接活、余量多少、不能接是为什么（hover 看 title） */
.al-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 6px; }
.al-cluster-title { font-size: 12px; color: var(--muted); }
.al-cluster-boxes { display: flex; flex-wrap: wrap; gap: 6px; }
.al-box {
  font-size: 12px; padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--muted); cursor: default;
}
.al-box em { font-style: normal; opacity: 0.75; margin-left: 2px; }
.al-box.ok { border-color: #2f7d4f; color: #7fd6a2; }
.al-box.bad { border-color: #7d3030; color: #e39b9b; }
.al-box.off { opacity: 0.5; }

.al-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.al-chips .capacity-chip { padding: 5px 11px; }

.al-config-actions { display: flex; align-items: center; gap: 8px; grid-column: 1 / -1; }
#alConfigBox summary { font-size: 13px; color: var(--muted); cursor: pointer; margin-bottom: 8px; }
#alConfigBox[open] summary { margin-bottom: 12px; }

/* critical 告警顶条：熔断、盒子连不上这类事故不能只躺在表里等人翻 */
.al-banner {
  margin-bottom: 12px; padding: 9px 12px; border-radius: 10px; font-size: 13px;
  color: #1a1408; background: var(--danger); border: 1px solid var(--danger);
}
.al-banner[hidden] { display: none; }

/* 页签上的未读徽标 */
.al-badge {
  display: inline-block; margin-left: 5px; padding: 0 5px; min-width: 16px;
  border-radius: 999px; font-size: 11px; font-weight: 700; line-height: 16px;
  color: #1a1408; background: var(--danger);
}
.al-badge[hidden] { display: none; }

.al-lvl-critical { color: var(--danger); font-weight: 700; }
.al-lvl-warn { color: var(--warn); }
.al-lvl-info { color: var(--muted); }

.apk-box { margin: 12px 0; padding: 12px; border: 1px dashed var(--line); border-radius: 12px; }
.apk-box h3 { font-size: 14px; }
.apk-box .panel-head { margin-bottom: 8px; }
.apk-list { display: flex; flex-direction: column; gap: 6px; max-height: 168px; overflow: auto; }
.apk-list .check { font-size: 13px; }

.bulk-bar {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin-bottom: 10px; padding: 8px 12px;
  background: var(--bg-2); border: 1px solid var(--accent); border-radius: 12px;
}
.bulk-bar[hidden] { display: none; }
.bulk-bar b { font-size: 13px; }
.bulk-bar .spacer { flex: 1; }
.ghost.danger { border-color: color-mix(in srgb, var(--danger) 60%, var(--line)); color: var(--danger); }

td.pick, th.pick { width: 30px; padding-right: 0; }
td.pick input { width: 15px; height: 15px; }
/* 六个操作按钮必须挤在一行：允许换行的话每行会涨到 116px，一屏就只剩五台看得见。
   宁可让表格横向滚动，也不能让行高失控。 */
.row-actions { display: flex; gap: 3px; flex-wrap: nowrap; }
.row-actions .small { padding: 4px 7px; }
.link-cell {
  background: none; border: none; padding: 0; font-size: 12px;
  color: var(--accent-2); text-decoration: underline dotted; text-underline-offset: 3px;
}
.state-on { color: var(--ok); }
.state-off { color: var(--muted); }
/* 备注框平时几乎隐形，聚焦才显出边框——一列输入框全画上框会把表格搞得很吵 */
.remark-input {
  width: 150px; padding: 4px 6px; font-size: 12px;
  color: var(--fg); background: transparent;
  border: 1px solid transparent; border-radius: 5px;
}
.remark-input:hover:not(:disabled) { border-color: var(--line); }
.remark-input:focus { outline: none; border-color: var(--accent-2); background: #0c0f0b; }
.remark-input:disabled { color: var(--muted); }
.remark-input[data-status="saving"] { border-color: var(--muted); }
.remark-input[data-status="saved"] { border-color: var(--ok); }
.remark-input[data-status="error"] { border-color: var(--danger); }
/* 缩略图挂在名字左边，60px 宽度够看清楚开的是哪个 app，又不至于把行撑高太多 */
.thumb {
  float: left; width: 40px; height: 71px; margin-right: 8px;
  object-fit: cover; border-radius: 5px; border: 1px solid var(--line); background: #0c0f0b;
}

.score {
  border-radius: 999px; padding: 3px 9px; font-size: 12px; font-weight: 700;
  border: 1px solid var(--line); background: var(--bg-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.score-ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
.score-warn { color: var(--warn); border-color: var(--warn); }
.score-bad { color: var(--danger); border-color: var(--danger); }

.wide-dialog { width: min(720px, 94vw); }

/* 投屏面板。画面是竖屏的，宽度让给右边的按键列，高度尽量吃满视口。 */
.mirror-dialog { width: min(840px, 96vw); }
.mirror-body { display: flex; gap: var(--gap); margin-top: 12px; align-items: flex-start; }
.mirror-stage {
  position: relative; flex: none;
  /* 手机是 1080x2424 的比例，按高度定尺寸，宽度自己跟着算，免得留黑边 */
  height: min(70vh, 720px); aspect-ratio: 1080 / 2424;
  background: #000; border: 1px solid var(--line); border-radius: 12px; overflow: hidden;
}
/* 没出画面时给个提示。出画面后 .live 把它撤掉，否则文字会压在画面上 */
.mirror-stage::after {
  content: attr(data-hint);
  position: absolute; inset: 0; display: grid; place-items: center;
  color: var(--muted); font-size: 13px; pointer-events: none;
}
.mirror-stage.live::after { content: none; }
.mirror-stage canvas { display: block; width: 100%; height: 100%; }
.mirror-screen { flex: none; display: flex; flex-direction: column; gap: 8px; }
.mirror-side { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
/* 仿 Android 导航栏：等分三格、图形化、贴着画面底边 */
.mirror-nav {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px;
  padding: 5px; border: 1px solid var(--line); border-radius: 12px; background: var(--bg-2);
}
.mirror-nav button {
  display: grid; place-items: center; padding: 9px 0;
  border: 0; border-radius: 8px; background: none; color: var(--muted); cursor: pointer;
}
.mirror-nav button:hover { background: var(--panel); color: var(--text); }
.mirror-nav button:active { background: var(--line); }
.mirror-nav svg { width: 17px; height: 17px; fill: currentColor; }
.mirror-quality { flex-direction: row; align-items: center; gap: 8px; }
.mirror-quality select { flex: 1; }
.mirror-text { display: flex; gap: 6px; }
.mirror-text input { flex: 1; min-width: 0; }
/* 群控默认收起：多数时候是单机投屏，别让它占着地方 */
.mirror-group { border: 1px solid var(--line); border-radius: 10px; padding: 8px 10px; }
.mirror-group summary { cursor: pointer; font-weight: 600; }
.mirror-group > p { margin: 8px 0; }
/* 名单可能有几十台，给个上限自己滚，别把右栏撑长 */
.mirror-group-list { display: flex; flex-direction: column; gap: 2px; max-height: 190px; overflow: auto; }
.mirror-group-item {
  display: flex; align-items: center; gap: 7px;
  padding: 4px 6px; border-radius: 7px; cursor: pointer;
}
.mirror-group-item:hover { background: var(--bg-2); }
.mirror-group-item input { margin: 0; }
.hint.ok { color: var(--ok); }
.hint.warn { color: var(--warn); }
.hint.bad { color: var(--danger); }

@media (max-width: 720px) {
  .mirror-body { flex-direction: column; align-items: stretch; }
  .mirror-screen { align-self: center; }
  .mirror-stage { height: min(60vh, 560px); }
}
.disguise-body { display: flex; flex-direction: column; gap: 6px; max-height: 58vh; overflow: auto; margin: 12px 0; }
.disguise-score { font-size: 30px; font-weight: 800; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.disguise-score.score-ok { color: var(--ok); }
.disguise-score.score-warn { color: var(--warn); }
.disguise-score.score-bad { color: var(--danger); }
.disguise-row {
  display: grid; grid-template-columns: 130px minmax(0, 1fr) 92px; gap: 10px; align-items: baseline;
  padding: 7px 10px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg-2); font-size: 13px;
}
.disguise-row span { color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; word-break: break-all; }
.disguise-row em { font-style: normal; text-align: right; font-size: 12px; }
.disguise-row.level-ok em { color: var(--ok); }
.disguise-row.level-warn { border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); }
.disguise-row.level-warn em { color: var(--warn); }
.disguise-row.level-bad { border-color: color-mix(in srgb, var(--danger) 45%, var(--line)); }
.disguise-row.level-bad em { color: var(--danger); }

/* 终端：命令回显和输出用等宽，和实时日志一套配色 */
.shell-output {
  height: 46vh; overflow: auto; background: #0c0f0b; border-radius: 12px; padding: 12px; margin: 12px 0;
  font: 12px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre-wrap; color: #d7d2c3;
}
.shell-output .log-info { color: var(--accent-2); }
.shell-output .log-warn { color: var(--warn); }
.shell-output .log-error { color: var(--danger); }
.shell-output .log-hint { color: var(--muted); }
.shell-form { display: flex; gap: 8px; align-items: center; }
.shell-form input { flex: 1; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

.jobs-bar { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.jobs-bar[hidden] { display: none; }
.job-chip {
  display: flex; align-items: center; gap: 10px; font-size: 12px;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px;
}
.job-chip.mine { border-color: var(--accent); }
.job-who { font-weight: 700; color: var(--accent-2); }
.job-target { color: var(--muted); }
.job-progress { width: 90px; height: 5px; border-radius: 999px; background: var(--line); overflow: hidden; }
.job-progress i { display: block; height: 100%; background: var(--accent); transition: width 0.3s ease; }
.job-count, .job-time { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--muted); }

.tabs { display: flex; gap: 4px; }
.tab {
  background: transparent; border: 1px solid transparent; border-radius: 9px;
  padding: 6px 12px; color: var(--muted); font-weight: 600; font-size: 15px;
}
.tab.active { color: var(--text); border-color: var(--line); background: var(--bg-2); }
.history-tools { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
.history-tools[hidden] { display: none; }
.history-tools input[type="search"] { flex: 1; min-width: 180px; }
.pager { display: flex; gap: 10px; align-items: center; justify-content: flex-end; padding-top: 10px; }
.pager[hidden] { display: none; }
.pager button:disabled { opacity: 0.4; cursor: not-allowed; }

dialog {
  width: min(560px, 92vw); border: 1px solid var(--line); border-radius: 16px;
  background: var(--panel); color: var(--text); padding: 18px; box-shadow: var(--shadow);
}
/* 显式钉在视口正中。浏览器默认也是居中，但那是靠 UA 样式的 margin:auto，页面上任何
   一条 dialog 的 margin 规则都能把它顶到左上角去，写死更省心。 */
dialog:modal {
  margin: auto;
  max-height: 88vh;
}
dialog::backdrop { background: rgba(0, 0, 0, 0.55); }

/* 提示 / 确认 / 输入，替代浏览器原生那三个 */
.ask-dialog { width: min(420px, 90vw); }
.ask-dialog h2 { font-size: 16px; margin: 0 0 10px; }
/* 消息里的 \n 要保留成换行，所以内容走 textContent + pre-line，不拼 HTML */
.ask-message { white-space: pre-line; margin: 0 0 14px; line-height: 1.6; color: var(--text); }
.ask-message:empty { display: none; }
.ask-input {
  width: 100%; margin-bottom: 14px; padding: 9px 11px;
  border: 1px solid var(--line); border-radius: 9px;
  background: var(--bg-2); color: var(--text); font-size: 14px;
}
.ask-input:focus { outline: none; border-color: var(--accent-2); }
.ask-input[hidden] { display: none; }
.dialog-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.account-list { display: flex; flex-direction: column; gap: 8px; margin: 14px 0; max-height: 240px; overflow: auto; }
.account-card {
  display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: center;
  border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; background: var(--bg-2);
}
.account-card b { display: block; }
.account-card span { color: var(--muted); font-size: 12px; }
.team-app { display: inline-block; margin-top: 3px; font-size: 12px; }
.team-app.ok { color: var(--ok); }
.team-app.warn { color: var(--warn); }
.team-app.bad { color: var(--danger); }
.team-app.muted { color: var(--muted); }

/* 体检结果。每项一行，缺口后面直接跟能点的修复按钮 */
.readiness {
  margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--line);
  display: flex; flex-direction: column; gap: 4px;
}
/* 项名固定一列，详情一列。用 grid 而不是 flex 是因为详情长短不一，
   flex 换行后项名就对不齐了，四行看下来像四种缩进 */
.readiness-row { display: grid; grid-template-columns: 60px 1fr; gap: 3px 8px; align-items: baseline; }
.readiness-row > .team-app { margin-top: 0; }
.readiness-row > span:not(.team-app) { color: var(--muted); font-size: 12px; }
/* 修复按钮跟详情左对齐，另起一行，免得把说明文字挤成一条窄缝 */
.readiness-fix { grid-column: 2; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }

.add-form { display: flex; flex-direction: column; gap: 10px; border-top: 1px solid var(--line); padding-top: 14px; }
.add-form h3 { font-size: 15px; }

.login-gate {
  min-height: 100vh; display: grid; place-items: center; padding: 24px;
}
.login-card {
  width: min(420px, 92vw); padding: 22px; display: flex; flex-direction: column; gap: 12px;
}
.login-card .brand { margin-bottom: 6px; }
.login-error { color: var(--danger); font-size: 13px; }
.app[hidden], .login-gate[hidden] { display: none !important; }

.ai-backdrop {
  position: fixed; inset: 0; background: rgba(0, 0, 0, 0.45); z-index: 40;
}
.ai-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 41;
  width: min(440px, 100vw); padding: 18px;
  background: var(--panel); border-left: 1px solid var(--line);
  box-shadow: var(--shadow); display: flex; flex-direction: column; gap: 12px;
}
.ai-drawer[hidden], .ai-backdrop[hidden] { display: none !important; }
.ai-tabs { margin-bottom: 2px; }
.ai-pane { display: flex; flex-direction: column; gap: 10px; flex: 1; min-height: 0; }
.ai-pane[hidden] { display: none !important; }
.ai-langs { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 8px; align-items: end; }
.ai-quick { display: flex; flex-wrap: wrap; gap: 6px; }
.ai-drawer textarea {
  width: 100%; resize: vertical; background: var(--bg-2);
  border: 1px solid var(--line); border-radius: 10px; padding: 10px;
  outline: none; color: inherit;
}
.ai-drawer textarea:focus { border-color: var(--accent); }
.ai-chat {
  flex: 1; min-height: 220px; overflow: auto; background: #0c0f0b;
  border-radius: 12px; padding: 12px; display: flex; flex-direction: column; gap: 10px;
}
.ai-msg { max-width: 92%; padding: 8px 10px; border-radius: 12px; font-size: 13px; line-height: 1.5; }
.ai-msg.user { align-self: flex-end; background: color-mix(in srgb, var(--accent) 22%, var(--bg-2)); }
.ai-msg.assistant { align-self: flex-start; background: var(--bg-2); border: 1px solid var(--line); }
.ai-msg.pending .ai-msg-text { color: var(--muted); }
.ai-msg-text { white-space: pre-wrap; }
.ai-msg-thumbs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.ai-msg-thumbs img { max-width: 168px; max-height: 120px; border-radius: 8px; object-fit: cover; display: block; }
.ai-composer {
  position: relative; display: flex; flex-direction: column; gap: 8px;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 14px; padding: 8px;
}
.ai-composer:focus-within { border-color: var(--accent); }
.ai-composer.drop-active { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--bg-2)); }
.ai-composer textarea { resize: none; border: none; background: transparent; padding: 6px 8px; }
.ai-composer textarea:focus { border-color: transparent; }
.ai-composer-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ai-attach-list { display: flex; flex-wrap: wrap; gap: 8px; padding: 2px 4px 0; }
.ai-attach {
  position: relative; width: 64px; height: 64px; border-radius: 10px; overflow: hidden;
  border: 1px solid var(--line); background: #0c0f0b;
}
.ai-attach img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ai-attach button {
  position: absolute; top: 3px; right: 3px; width: 18px; height: 18px; padding: 0;
  border: none; border-radius: 999px; background: rgba(0, 0, 0, 0.72); color: #fff;
  font-size: 12px; line-height: 18px;
}
.ai-drop-hint {
  position: absolute; inset: 0; z-index: 2; display: grid; place-items: center;
  border-radius: 13px; background: color-mix(in srgb, var(--accent) 22%, var(--bg-2));
  color: var(--accent-2); font-weight: 700; letter-spacing: 0.04em;
}
.ai-drop-hint[hidden] { display: none !important; }
#aiTransStatus, #aiChatStatus { min-height: 18px; }

@media (min-width: 1600px) {
  .layout { grid-template-columns: 400px minmax(0, 1fr); }
}

@media (max-width: 1180px) {
  .layout { grid-template-columns: minmax(290px, 33%) minmax(0, 1fr); }
  .brand p { display: none; }
}

/* Narrow or short viewports can't host two full-height scroll panes, so let the
   page scroll normally instead of trapping content in inner scrollers. */
@media (max-width: 900px), (max-height: 620px) {
  .app { height: auto; min-height: 0; }
  .layout { grid-template-rows: auto; flex: none; }
  .form-panel { padding-bottom: 18px; overflow: visible; }
  /* The whole page scrolls here, so a floating CTA would just cover content. */
  .form-actions { position: static; margin: 16px 0 0; padding: 12px 0 0; border-radius: 0; }
  .workspace { grid-template-rows: auto auto; }
  .log-view { height: 220px; flex: none; }
  .result-panel { min-height: 460px; }
}

@media (max-width: 900px) {
  .layout { grid-template-columns: minmax(0, 1fr); }
  .account-bar { width: 100%; margin-left: 0; }
  .account-bar select { flex: 1; width: auto; }
}

@media (max-width: 600px) {
  .grid.two { grid-template-columns: minmax(0, 1fr); }
  /* The select shows the account name already, so drop the label and give the
     dropdown its own row instead of letting the buttons crush it. */
  .account-bar label { display: none; }
  .account-bar select { flex: 1 1 100%; }
  .ai-langs { grid-template-columns: minmax(0, 1fr) auto; }
  .ai-langs label:last-of-type { grid-column: 1 / -1; }
  .topbar { gap: 10px; }
  .brand h1 { font-size: 18px; }
  .result-actions, .tabs { width: 100%; }
  .result-actions button { flex: 1; }
}
