/* ============================================================
   A/B 桥接控制台 · 样式
   设计取向：干净、留白够、信息层级靠「字重 + 灰度」而不是靠框线。
   品牌色沿用瓶子的靛蓝 #4F46E5，两个端看起来是同一套东西。

   v4：整体压缩纵向节奏 —— 顶栏 56px、卡片 padding 16px、
       任务表一页 8 条，桌面上一屏半就能看完所有内容。
   ============================================================ */

:root {
    --brand: #4F46E5;
    --brand-2: #6366F1;
    --brand-ink: #3730A3;
    --brand-soft: #EEF0FF;

    --bg: #F5F6FA;
    --surface: #FFFFFF;
    --surface-2: #FAFBFD;

    --ink: #0F172A;
    --ink-2: #475569;
    --ink-3: #94A3B8;

    --line: #E9ECF3;
    --line-2: #F1F3F9;

    --ok: #12B76A;
    --ok-soft: #E7F8F0;
    --warn: #F79009;
    --warn-soft: #FFF6E6;
    --bad: #F04438;
    --bad-soft: #FEECEB;

    --r-lg: 16px;
    --r-md: 12px;
    --r-sm: 9px;

    --shadow-1: 0 1px 2px rgba(16, 24, 40, .04), 0 1px 3px rgba(16, 24, 40, .06);
    --shadow-2: 0 4px 12px rgba(16, 24, 40, .06), 0 12px 32px rgba(16, 24, 40, .06);
    --shadow-3: 0 24px 64px rgba(16, 24, 40, .18);

    --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

/* ⚠️ 必须放在所有 display 规则之前/最高优先级。
   浏览器对 [hidden] 的默认样式是 `display:none`，但那只是**UA 样式**，
   任何作者样式里的 `display: grid/flex` 都会把它盖掉 ——
   结果就是"设了 hidden 却还显示"。弹窗遮罩一开始就中招：
   登录页上直接盖了一层灰色的空弹窗。 */
[hidden] { display: none !important; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
        "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
    font-size: 14px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { margin: 0; font-weight: 650; letter-spacing: -.01em; }
h2 { font-size: 14.5px; }
h3 { font-size: 15px; }

code { font-family: var(--mono); }

/* ============================================================ 按钮 */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    padding: 9px 15px;
    font-family: inherit;
    font-size: 13px;
    font-weight: 550;
    cursor: pointer;
    transition: background .15s, border-color .15s, box-shadow .15s,
        transform .08s, color .15s;
    white-space: nowrap;
    user-select: none;
}

.btn:active:not(:disabled) { transform: translateY(.5px); }
.btn:disabled { opacity: .55; cursor: not-allowed; }

.btn-sm { padding: 6px 11px; font-size: 12.5px; border-radius: 8px; }
.btn-block { width: 100%; }

.btn-primary {
    background: var(--brand);
    color: #fff;
    box-shadow: 0 1px 2px rgba(79, 70, 229, .24), 0 4px 12px rgba(79, 70, 229, .18);
}
.btn-primary:hover:not(:disabled) { background: #4338CA; }

.btn-ghost {
    background: var(--surface);
    border-color: var(--line);
    color: var(--ink-2);
}
.btn-ghost:hover:not(:disabled) {
    border-color: #D8DDEA;
    color: var(--ink);
    background: var(--surface-2);
}

.btn-warn {
    background: var(--warn);
    color: #fff;
}
.btn-warn:hover { background: #DD7A06; }

.btn-danger-ghost {
    background: var(--surface);
    border-color: #FBD5D2;
    color: var(--bad);
}
.btn-danger-ghost:hover { background: var(--bad-soft); }

.btn svg { width: 15px; height: 15px; flex: none; }

/* 表格里的小按钮 */
.mini {
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--ink-2);
    border-radius: 6px;
    padding: 3px 8px;
    font-family: inherit;
    font-size: 11.5px;
    cursor: pointer;
    transition: all .14s;
}
.mini:hover { border-color: #CFD6E6; color: var(--brand); background: var(--brand-soft); }

/* ============================================================ 表单 */

.field { display: block; margin-bottom: 12px; min-width: 0; }
.field > span {
    display: block;
    font-size: 12px;
    font-weight: 550;
    color: var(--ink-2);
    margin-bottom: 5px;
}

/* ⚠️ 必须包含 `input:not([type])`。
   HTML 里漏写 type 的 <input> 匹配不到 input[type=text]，
   于是没有 width:100%，浏览器给个默认 170px —— 在窄网格列里会
   直接顶出卡片边界（金额输入框就中过这个招）。 */
input:not([type]), input[type=text], input[type=password], input[type=number],
textarea, select {
    width: 100%;
    font-family: inherit;
    font-size: 13.5px;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    padding: 9px 11px;
    outline: none;
    transition: border-color .15s, box-shadow .15s, background .15s;
}

textarea { resize: vertical; font-family: var(--mono); font-size: 12.5px; line-height: 1.6; }

input:focus, textarea:focus, select:focus {
    border-color: var(--brand-2);
    box-shadow: 0 0 0 3px rgba(99, 102, 241, .13);
}

input::placeholder, textarea::placeholder { color: #B4BBCB; }

select {
    appearance: none;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394A3B8' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 11px center;
    padding-right: 30px;
    cursor: pointer;
}

/* ⚠️ 列宽必须写 minmax(0, 1fr) 而不是 1fr。
   1fr 的最小尺寸是 auto —— select 里一个长节点名就能把整列撑过
   卡片边界，视觉上输入框会压到右边的卡片上。 */
.row2 { display: grid; grid-template-columns: minmax(0, 1fr) 104px; gap: 10px; }

.check-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 12px;
    font-size: 12.5px;
    color: var(--ink-2);
    cursor: pointer;
}
.check-row input[type=checkbox] { width: auto; }

.meta-line {
    font-size: 11.5px;
    color: var(--ink-3);
    min-height: 16px;
    margin: -4px 0 10px;
    font-family: var(--mono);
}

.hint {
    font-size: 12px;
    color: var(--ink-3);
    line-height: 1.65;
    margin: 10px 0 0;
}
.hint code {
    background: var(--line-2);
    padding: 1px 5px;
    border-radius: 4px;
    font-size: 11.5px;
    color: var(--ink-2);
}

/* ============================================================ 登录 */

.screen { min-height: 100vh; }

#screenLogin {
    display: grid;
    place-items: center;
    padding: 24px;
    position: relative;
    overflow: hidden;
    background: #0B1020;
}

.login-bg { position: absolute; inset: 0; overflow: hidden; }

.glow {
    position: absolute;
    border-radius: 50%;
    filter: blur(90px);
    opacity: .55;
}
.g1 {
    width: 520px; height: 520px;
    background: #4F46E5;
    top: -160px; left: -120px;
}
.g2 {
    width: 460px; height: 460px;
    background: #7C3AED;
    bottom: -180px; right: -100px;
    opacity: .4;
}

.login-card {
    position: relative;
    width: 100%;
    max-width: 372px;
    background: var(--surface);
    border-radius: 20px;
    padding: 32px 28px 26px;
    box-shadow: var(--shadow-3);
    text-align: center;
}

.brand-mark {
    width: 46px; height: 46px;
    margin: 0 auto 14px;
    border-radius: 13px;
    display: grid;
    place-items: center;
    background: linear-gradient(145deg, var(--brand-2), var(--brand));
    color: #fff;
    box-shadow: 0 6px 18px rgba(79, 70, 229, .32);
}
.brand-mark svg { width: 23px; height: 23px; }

.brand-mark.sm {
    width: 32px; height: 32px;
    margin: 0;
    border-radius: 9px;
    box-shadow: 0 2px 8px rgba(79, 70, 229, .26);
}
.brand-mark.sm svg { width: 17px; height: 17px; }

.login-card h1 { font-size: 19px; margin-bottom: 4px; }
.login-card .sub {
    margin: 0 0 22px;
    font-size: 12.5px;
    color: var(--ink-3);
}
.login-card .field { text-align: left; }

.login-msg {
    min-height: 18px;
    margin-top: 10px;
    font-size: 12.5px;
    color: var(--bad);
}

.login-foot {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--line-2);
    font-size: 11.5px;
    color: var(--ink-3);
}

/* ============================================================ 顶栏 */

.topbar {
    position: sticky;
    top: 0;
    z-index: 30;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 0 20px;
    background: rgba(255, 255, 255, .86);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--line);
}

.tb-left { display: flex; align-items: center; gap: 10px; min-width: 0; }

.tb-title { display: flex; flex-direction: column; min-width: 0; }
.tb-title b { font-size: 14px; letter-spacing: -.01em; }
.tb-title span {
    font-size: 11.5px;
    color: var(--ink-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tb-right { display: flex; align-items: center; gap: 8px; }

/* ============================================================ 横幅 */

.warn-banner {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: 12px auto 0;
    max-width: 1180px;
    padding: 10px 14px;
    border-radius: var(--r-md);
    background: var(--warn-soft);
    border: 1px solid #FCE3B8;
    font-size: 12.5px;
    color: #8A5300;
}
.warn-banner b { font-weight: 650; }
.warn-banner span { color: #A0661A; }

/* ============================================================ 布局 */

.wrap {
    max-width: 1180px;
    margin: 0 auto;
    padding: 14px 20px 28px;
}

/* 概览条：四个数字，横向一行，高度 66px */
.stats {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 10px;
    margin-bottom: 14px;
}

.stat {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    padding: 11px 14px;
    display: flex;
    flex-direction: column;
    gap: 1px;
    position: relative;
    overflow: hidden;
}
.stat::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--line);
}
.stat.st-ok::before { background: var(--ok); }
.stat.st-bad::before { background: var(--bad); }
.stat.st-live::before { background: var(--warn); }

.stat em {
    font-style: normal;
    font-size: 19px;
    font-weight: 680;
    letter-spacing: -.02em;
    line-height: 1.2;
}
.stat.st-ok em { color: var(--ok); }
.stat.st-bad em { color: var(--bad); }
.stat.st-live em { color: var(--warn); }

.stat span { font-size: 11.5px; color: var(--ink-3); }

.grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.22fr);
    gap: 14px;
    align-items: start;
}

.col { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

/* ============================================================ 卡片 */

.card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: 15px 16px 16px;
    box-shadow: var(--shadow-1);
}

/* 入场动画只播一次。
   ⚠️ 不要用 `animation: ... both` 挂在常驻元素上：fill-mode:both 会让
      元素在动画结束前保持 opacity:0，低性能设备 / 截图 / 页面切后台
      都可能让动画不推进，结果卡片是**看不见的**。 */
.card.enter {
    animation: fadeUp .32s cubic-bezier(.16, 1, .3, 1);
}

@keyframes fadeUp {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: none; }
}

.card-h {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 13px;
}

.card-h-right { display: flex; align-items: center; gap: 8px; }

/* ============================================================ 徽章 */

.pill {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 550;
    line-height: 1.6;
    white-space: nowrap;
}
.pill-soft { background: var(--brand-soft); color: var(--brand-ink); }
.pill-ok { background: var(--ok-soft); color: #067647; }
.pill-warn { background: var(--warn-soft); color: #B54708; }
.pill-bad { background: var(--bad-soft); color: #B42318; }
.pill-gray { background: #F2F4F9; color: var(--ink-3); }

.dot {
    width: 9px; height: 9px;
    border-radius: 50%;
    flex: none;
    display: inline-block;
}
.dot-on { background: var(--ok); box-shadow: 0 0 0 3px rgba(18, 183, 106, .18); }
.dot-off { background: #AEB7C9; box-shadow: 0 0 0 3px rgba(174, 183, 201, .18); }
.dot-busy { background: var(--warn); box-shadow: 0 0 0 3px rgba(247, 144, 9, .18); }

/* ============================================================ 密钥框 */

.key-box {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    padding: 8px 10px;
}

.key-box code {
    flex: 1;
    min-width: 0;
    font-size: 12px;
    color: var(--ink-2);
    word-break: break-all;
    line-height: 1.5;
}

.key-box.big { padding: 12px; }
.key-box.big code { font-size: 13.5px; color: var(--brand-ink); font-weight: 550; }

.key-acts { display: flex; gap: 6px; flex: none; }

/* ============================================================ 付款机列表 */

.node-list { display: flex; flex-direction: column; gap: 8px; }

.node {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 11px;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--surface-2);
    transition: border-color .15s, background .15s;
}
.node:hover { border-color: #DDE3F0; background: var(--surface); }

.node > .dot { margin-top: 6px; }

.node-main { flex: 1; min-width: 0; }

.node-title {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.node-title b { font-size: 13.5px; font-weight: 600; }

.node-key {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-top: 5px;
    flex-wrap: wrap;
}
.node-key code {
    font-size: 11px;
    color: var(--ink-3);
    background: #F0F2F8;
    padding: 1px 6px;
    border-radius: 4px;
    letter-spacing: .02em;
}
.node-base {
    font-size: 11px;
    color: var(--ink-3);
    font-family: var(--mono);
}

.node-acts { flex: none; padding-top: 1px; }

/* ============================================================ 表格 */

.table-wrap { width: 100%; overflow-x: auto; }

.tbl {
    width: 100%;
    border-collapse: collapse;
    font-size: 12.5px;
}

.tbl th {
    text-align: left;
    font-weight: 550;
    font-size: 11.5px;
    color: var(--ink-3);
    padding: 0 8px 6px;
    border-bottom: 1px solid var(--line);
    white-space: nowrap;
}

.tbl td {
    padding: 6px 8px;
    border-bottom: 1px solid var(--line-2);
    vertical-align: middle;
    white-space: nowrap;
}
/* 说明列允许省略号，但不参与撑宽 */
.tbl td.td-msg { white-space: nowrap; }
.tbl tr:last-child td { border-bottom: none; }
.tbl tr:hover td { background: var(--surface-2); }

.td-time { font-family: var(--mono); font-size: 11.5px; color: var(--ink-3); white-space: nowrap; }
.td-msg {
    color: var(--ink-2);
    max-width: 190px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.td-act { text-align: right; }
/* ⚠️ 不要给 td-act 设 width:1% —— 浏览器会把它压到极限，
   里面"详情"两个字就被拆成竖排了。用 nowrap 保证按钮不被压。 */
.td-act .mini { white-space: nowrap; }

/* ============================================================ 分页 */

.pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 12px;
    padding-top: 11px;
    border-top: 1px solid var(--line-2);
}

.pager-info { font-size: 11.5px; color: var(--ink-3); }

.pager-btns { display: flex; align-items: center; gap: 5px; }

.pager-num {
    font-size: 12px;
    color: var(--ink-2);
    padding: 0 6px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ============================================================ 空状态 */

.empty {
    padding: 22px 12px;
    text-align: center;
    font-size: 12.5px;
    color: var(--ink-3);
    line-height: 1.7;
}

/* ============================================================ 弹窗 */

.modal-mask {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(15, 23, 42, .42);
    backdrop-filter: blur(3px);
    animation: maskIn .16s ease;
}

@keyframes maskIn { from { opacity: 0; } to { opacity: 1; } }

.modal {
    width: 100%;
    max-width: 430px;
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border-radius: 17px;
    box-shadow: var(--shadow-3);
    animation: modalIn .2s cubic-bezier(.16, 1, .3, 1);
}

@keyframes modalIn {
    from { opacity: 0; transform: translateY(10px) scale(.985); }
    to { opacity: 1; transform: none; }
}

.modal-h {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 18px 12px;
}

.modal-h .x {
    border: none;
    background: none;
    font-size: 21px;
    line-height: 1;
    color: var(--ink-3);
    cursor: pointer;
    padding: 0 2px;
    border-radius: 6px;
}
.modal-h .x:hover { color: var(--ink); background: var(--line-2); }

.modal-b {
    padding: 0 18px 4px;
    overflow-y: auto;
    flex: 1;
}

.modal-f {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 14px 18px 16px;
    border-top: 1px solid var(--line-2);
    margin-top: 8px;
}

/* 键值行（任务详情 / 节点信息） */
.kv {
    display: flex;
    gap: 12px;
    padding: 6px 0;
    border-bottom: 1px solid var(--line-2);
    font-size: 12.5px;
}
.kv:last-child { border-bottom: none; }
.kv-k { flex: none; width: 82px; color: var(--ink-3); }
.kv-v { flex: 1; min-width: 0; word-break: break-all; color: var(--ink); }

/* ============================================================ Toast */

.toasts {
    position: fixed;
    left: 50%;
    bottom: 26px;
    transform: translateX(-50%);
    z-index: 200;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    pointer-events: none;
}

.toast {
    padding: 9px 16px;
    border-radius: 999px;
    background: #101828;
    color: #fff;
    font-size: 12.5px;
    font-weight: 500;
    box-shadow: 0 8px 24px rgba(16, 24, 40, .24);
    transition: opacity .25s, transform .25s;
    max-width: 78vw;
}
.toast.ok { background: #067647; }
.toast.bad { background: #B42318; }

/* ============================================================ 页脚 */

.foot {
    margin-top: 18px;
    text-align: center;
    font-size: 11.5px;
    color: var(--ink-3);
}

/* ============================================================ 响应式 */

@media (max-width: 900px) {
    .grid { grid-template-columns: minmax(0, 1fr); }
    .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 7px; }
    .stat { padding: 9px 10px; }
    .stat em { font-size: 16px; }
    .stat span { font-size: 10.5px; }
    .wrap { padding: 12px 13px 24px; }
    .topbar { padding: 0 13px; }
    .tb-title span { display: none; }
    .td-msg { max-width: 110px; }
}

@media (max-width: 560px) {
    .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .row2 { grid-template-columns: minmax(0, 1fr); }
    .modal { max-width: 100%; }
    .tbl th:nth-child(4), .tbl td:nth-child(4) { display: none; }
    .pager { justify-content: center; }
    .pager-info { width: 100%; text-align: center; }
}
