/**

 * 全站样式：列表页 / 详情页 / SM 控制台 / 登录页 / 上传页共用
 * 分节顺序见文件里的 ---------------- xxx ---------------- 标记
 */


/** 带 hidden 属性的元素必须真的隐藏：[hidden] 默认是 display:none，但只要有任何一条规则给它设了 display（比如 .alert-here{display:flex}），它就会失效 */

[hidden] { display: none !important; }

:root {
    --bg:            #0e141b;
    --bg-2:          #151d26;
    --bg-3:          #1b2632;
    --bg-hover:      #1e2a38;
    --border:        #2a3846;
    --border-soft:   #223040;
    --text:          #d6e0ea;
    --text-dim:      #8b9bab;
    --text-faint:    #61717f;
    --accent:        #4c91d4;
    --accent-2:      #66c0f4;
    --green:         #7cc576;
    --lime:          #a4d007;
    --yellow:        #e0b74a;
    --orange:        #e08a3c;
    --red:           #d9534f;
    --radius:        6px;
    --shadow:        0 8px 28px rgba(0, 0, 0, .5);
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--bg);
    color: var(--text);
    font-family: "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB",
                 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

body {
    background-image:
        radial-gradient(1200px 500px at 15% -10%, rgba(76, 145, 212, .13), transparent 70%),
        radial-gradient(900px 420px at 95% 0%, rgba(124, 197, 118, .07), transparent 70%);
    background-attachment: fixed;
    min-height: 100vh;
}

.app {
    max-width: 1320px;
    margin: 0 auto;
    padding: 22px 20px 40px;
}

/* ---------------- 顶部 ---------------- */

.topbar {
    /** 固定两行：第一行标题，第二行统计。 ★ 故意不用"能挤下就并排" —— 那样拖动窗口时会在 一行/两行之间反复切换，看着就是"布局乱跳"。 */

    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 14px;
    margin-bottom: 18px;
}

.brand { display: flex; align-items: center; gap: 14px; }

/* 标题那一块允许被压缩：长服务器名先折行，而不是把右边的主题下拉框顶出屏幕 */
.brand-text { flex: 1 1 auto; min-width: 0; }

/** ★ 主题下拉框（lib/Theme.php 的 theme_select()）挂在 **.brand 这一行的行尾**。
    .brand 是页头第一行、宽度铺满 .app（和下面的统计块 / 服务器表格 / .qq-card 同宽），
    所以"行尾"就是**页面右上角** —— 不用 position 定位（那种容易和别的东西打架），
    也不新包一层容器（#qqCard 的前一个兄弟元素仍然是 .brand，结构不动）。 */
.brand > .theme-pick { margin-left: auto; }

.brand-logo {
    width: 52px; height: 52px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 10px;
    background: linear-gradient(145deg, #2b3f52, #16202b);
    border: 1px solid var(--border);
    color: var(--accent-2);
    font-weight: 700;
    font-size: 15px;
    letter-spacing: .5px;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06);
    flex: none;
}

.brand-text h1 {
    margin: 0;
    font-size: 21px;
    font-weight: 600;
    letter-spacing: .3px;
}

.brand-text p {
    margin: 2px 0 0;
    font-size: 12.5px;
    color: var(--text-dim);
}

.stats {
    /** 五块等宽铺满整行。 */
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 10px;
}

.stat {
    min-width: 104px;
    padding: 9px 12px;
    background: linear-gradient(180deg, rgba(38, 54, 70, .75), rgba(24, 34, 45, .75));
    border: 1px solid var(--border);
    border-radius: var(--radius);
    text-align: center;

    /** 用 flex + 居中，这样折线图那块把整行撑高之后， */
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.stat-num {
    display: block;
    font-size: 20px;
    font-weight: 700;
    color: var(--accent-2);
    font-variant-numeric: tabular-nums;
}

.stat-label {
    display: block;
    font-size: 11px;
    color: var(--text-dim);
    margin-top: 1px;
    white-space: nowrap;       /* 标签不换行，宽度靠块本身撑开 */
}

/* ---------- 当前时间 ---------- */

.stat-clock .stat-num {
    letter-spacing: .5px;      /* 秒数跳动时数字宽度不抖 */
}

.stat-clock .stat-label {
    font-variant-numeric: tabular-nums;
}

/* ---------------- 统计区 ---------------- */

/** 四块统一结构：上面一个大数字，下面一行小标签，内容整体居中。 */


.stat-peak {
    /* 它其实是个 button，这里把按钮默认样式清掉，看起来和旁边的统计一样 */
    font: inherit;
    color: inherit;
    cursor: pointer;
    text-align: center;
    transition: border-color .15s, background .15s;
}

.stat-peak:hover {
    border-color: var(--accent);
    background: linear-gradient(180deg, rgba(48, 70, 92, .85), rgba(28, 40, 53, .85));
}

.stat-peak:active { transform: translateY(1px); }

/* 标签里的"今日/当月/今年"，用主题色标出来 */

.stat-peak .stat-label em {
    font-style: normal;
    color: var(--accent-2);
}

.stat-peak .stat-label em::after {
    content: '▸';            /* 提示可以点 */
    font-size: 9px;
    margin: 0 2px 0 1px;
    opacity: .6;
}

/* ---------------- 网站访问人数折线图（页面底部整块） ---------------- */

.chart-card {
    margin-top: 16px;
}

.chart-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding-bottom: 10px;
    margin-bottom: 10px;
    border-bottom: 1px solid var(--border-soft);
}

.chart-head h2 {
    margin: 0;
    padding: 0;
    border: none;
    font-size: 15px;
    font-weight: 600;
}

.chart-head .chart-sub {
    font-size: 12px;
    color: var(--accent-2);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.sp-plot {
    position: relative;
    height: 150px;
    margin-bottom: 8px;
}

.sp-plot svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.sp-empty {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    color: var(--text-faint);
}

/* 图下面的横轴：两端日期 + 中间图例 */
.chart-axis {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    font-size: 11px;
    color: var(--text-faint);
    font-variant-numeric: tabular-nums;
}

.chart-axis .chart-legend {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--text-dim);
}

.chart-axis .chart-legend .dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    flex: none;
}

.chart-axis .chart-legend em {
    font-style: normal;
    color: var(--text-faint);
}

/* ---------------- 工具条 ---------------- */

.toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 12px 14px;
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    margin-bottom: 14px;
}

.field {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0 10px;
    height: 34px;
}

.field.inline {
    border: none;
    background: none;
    padding: 0;
    height: auto;
    gap: 7px;
    font-size: 12.5px;
    color: var(--text-dim);
}

.search-field { flex: 1 1 260px; min-width: 200px; }

.search-field svg {
    width: 15px; height: 15px;
    fill: var(--text-faint);
    flex: none;
}

.search-field input {
    flex: 1;
    background: none;
    border: none;
    outline: none;
    color: var(--text);
    font-size: 13.5px;
    font-family: inherit;
    height: 100%;
    min-width: 0;
}

.search-field input::placeholder { color: var(--text-faint); }

.search-field:focus-within { border-color: var(--accent); }

.select {
    height: 34px;
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0 8px;
    font-size: 13px;
    font-family: inherit;
    outline: none;
    cursor: pointer;
}

.select:focus { border-color: var(--accent); }

.btn {
    display: inline-flex;
    align-items: center;

    /** inline-flex 的默认主轴对齐是 flex-start —— 按钮一旦被拉宽（比如登录页的 width:100%），里面的文字就会贴在左边，这行不能少 */
    justify-content: center;

    gap: 7px;
    height: 34px;
    padding: 0 15px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: linear-gradient(180deg, #2a3a4a, #1d2937);
    color: var(--text);
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
    text-decoration: none;     /* .btn 也用在 <a> 上，不加这行会带下划线 */
    transition: background .15s, border-color .15s, transform .05s;
    white-space: nowrap;
}

.btn:hover { background: linear-gradient(180deg, #33475b, #22303f); border-color: #3a4c5e; }
.btn:active { transform: translateY(1px); }
.btn:disabled,
.btn:disabled:hover,
.btn:disabled:active {
    opacity: .45;
    cursor: not-allowed;          /* 鼠标变"禁止"符号，一眼看出不能按 */
    transform: none;
    box-shadow: none;
}

.btn svg { width: 14px; height: 14px; fill: currentColor; }

.btn-primary {
    background: linear-gradient(180deg, #3d7fbf, #2c5f92);
    border-color: #3d7fbf;
    color: #fff;
}

.btn-primary:hover { background: linear-gradient(180deg, #4a90d6, #356ea6); border-color: #4a90d6; }

.updated {
    margin-left: auto;
    font-size: 12px;
    color: var(--text-faint);
    font-variant-numeric: tabular-nums;
}

/* ---------------- 表格 ---------------- */

.table-wrap {
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow-x: auto;
}

.server-table {
    width: 100%;
    border-collapse: collapse;
    min-width: 900px;
}

.server-table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: #1a2532;
    color: var(--text-dim);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .4px;
    text-align: left;
    padding: 11px 14px;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
    user-select: none;
}

.server-table thead th.sortable { cursor: pointer; }
.server-table thead th.sortable:hover { color: var(--text); }

.server-table thead th.sort-asc::after,
.server-table thead th.sort-desc::after {
    content: "";
    display: inline-block;
    margin-left: 6px;
    border: 4px solid transparent;
    vertical-align: middle;
}

.server-table thead th.sort-asc::after  { border-bottom-color: var(--accent-2); margin-bottom: 3px; }
.server-table thead th.sort-desc::after { border-top-color: var(--accent-2); margin-top: 3px; }

.server-table tbody tr {
    border-bottom: 1px solid var(--border-soft);
    transition: background .12s;
}

.server-table tbody tr:last-child { border-bottom: none; }
.server-table tbody tr:hover { background: var(--bg-hover); }
.server-table tbody tr.is-offline { opacity: .62; }
.server-table tbody tr.is-offline:hover { opacity: .85; }
/** 查询中：别整行压暗（它不是离线），但要能一眼看出"这行还没结果" */
.server-table tbody tr.is-querying { opacity: .85; }

.server-table td {
    padding: 9px 14px;
    vertical-align: middle;
    /* 固定行高：名字再长也不会把这一行撑高，所有行高度完全一致 */
    height: 64px;
}

.col-players { width: 130px; }
.col-ping    { width: 92px; }
.col-status  { width: 120px; }
.col-act     { width: 200px; }
th.col-act   { text-align: center !important; }

.srv-name {
    display: flex;
    align-items: center;
    gap: 6px;
    /* 不换行，否则长名字会把这一行撑高、破坏整列的行高一致 */
    flex-wrap: nowrap;
    min-width: 0;
}

.srv-title {
    font-weight: 600;
    color: #e8f0f8;
    flex: 0 1 auto;
    min-width: 0;
    max-width: 320px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* 名字本身就是进入管理页面的链接 */
a.srv-title { text-decoration: none; }
a.srv-title:hover { color: var(--accent-2); text-decoration: underline; }

/* 标签不允许被压缩 */
.srv-name .tag { flex: none; }

.srv-addr {
    display: block;
    font-size: 11.5px;
    color: var(--text-faint);
    font-family: Consolas, "Courier New", monospace;
    margin-top: 2px;
}

.tag {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 3px;
    font-size: 10.5px;
    line-height: 16px;
    border: 1px solid transparent;
    white-space: nowrap;
}

.tag-group { background: #26333f; color: #9fb3c6; border-color: #33455a; }
.tag-region{ background: #1e2f3d; color: #7fb4d8; border-color: #2d4a61; }
.tag-vac   { background: #1f3a26; color: #7cc576; border-color: #2c5133; }
.tag-bot   { background: #3a3020; color: #d8b45c; border-color: #57492a; }

.srv-mode { color: #b6c6d6; font-size: 13px; }
.srv-diff { display: block; font-size: 11.5px; color: var(--text-faint); margin-top: 2px; }

.players-num {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: #e8f0f8;
}

.players-num .sep { color: var(--text-faint); font-weight: 400; }
.players-num .max { color: var(--text-dim); font-weight: 400; }

.players-bar {
    height: 4px;
    border-radius: 2px;
    background: #22303d;
    margin-top: 6px;
    overflow: hidden;
}

.players-bar span {
    display: block;
    height: 100%;
    border-radius: 2px;
    background: linear-gradient(90deg, #4c91d4, #66c0f4);
    transition: width .3s;
}

.players-bar.is-busy span { background: linear-gradient(90deg, #c96a3a, #e0b74a); }
.players-bar.is-full span { background: linear-gradient(90deg, #b3453f, #d9534f); }

.srv-map { color: #cfdbe6; line-height: 1.45; }

/* 地图名：这一列的主标题 */
.srv-map .map-campaign {
    display: inline;
    font-weight: 600;
    color: #e8f0f8;
    word-break: break-word;
}

/* 官图 / 三方图 标签，紧跟在地图名后面 */

.map-tag {
    display: inline-block;
    margin-left: 6px;
    padding: 0 6px;
    font-size: 10.5px;
    line-height: 16px;
    border-radius: 3px;
    border: 1px solid transparent;
    white-space: nowrap;
    vertical-align: 1px;
    font-weight: 400;
}

.map-tag-official { background: #1f3a26; color: #7cc576; border-color: #2c5133; }
.map-tag-custom   { background: #1b2f42; color: #66c0f4; border-color: #2a4a66; }
.map-tag-unknown  { background: #3a3020; color: #d8b45c; border-color: #57492a; cursor: help; }

.srv-map code {
    display: block;
    font-size: 11.5px;
    color: var(--text-faint);
    font-family: Consolas, "Courier New", monospace;
    margin-top: 2px;
}

/* 没收录的三方图：显示代码 + 一个提示标签 */
.srv-map .map-unknown-code {
    display: inline;
    font-family: Consolas, "Courier New", monospace;
    font-size: 12.5px;
    color: #b6c6d6;
    word-break: break-all;
}

/* 游戏模式徽章：不同模式不同颜色，和游戏里的模式标签一个意思 */
.mode-badge {
    display: inline-block;
    padding: 2px 9px;
    border-radius: 3px;
    font-size: 12px;
    line-height: 17px;
    border: 1px solid transparent;
    white-space: nowrap;
}

.mode-coop          { background: #1b2f42; color: #66c0f4; border-color: #2a4a66; }
.mode-versus        { background: #3a2620; color: #e08a3c; border-color: #5a3a2a; }
.mode-realism       { background: #2c2440; color: #a98fe0; border-color: #443862; }
.mode-realism-versus{ background: #3a2028; color: #e0708a; border-color: #5a3040; }
.mode-survival      { background: #1e3330; color: #5fc9b0; border-color: #2e504a; }
.mode-scavenge      { background: #3a3020; color: #d8b45c; border-color: #57492a; }
.mode-mutation      { background: #33243a; color: #c98fd8; border-color: #4d3657; }
.mode-unknown       { background: #26333f; color: #8b9bab; border-color: #33455a; }

.ping {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.ping::before {
    content: "";
    width: 7px; height: 7px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
    box-shadow: 0 0 6px currentColor;
}

.ping-good { color: #7cc576; }
.ping-ok   { color: #a4d007; }
.ping-mid  { color: #e0b74a; }
.ping-bad  { color: #d9534f; }
.ping-none { color: var(--text-faint); font-weight: 400; }
.ping-none::before { box-shadow: none; }

.status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
}

.status::before {
    content: "";
    width: 8px; height: 8px;
    border-radius: 50%;
    flex: none;
}

.status-online  { color: #7cc576; }
.status-online::before  { background: #7cc576; box-shadow: 0 0 7px rgba(124, 197, 118, .8); }

/** 响应慢：黄色。 ★ 和"离线"分开 —— 灰色那个是"真的没了"， 黄色这个是"刚才还在，这次没回话，可能在忙"。 */
.status-slow { color: #ffd77a; }
.status-slow::before {
    background: #ffd77a;
    animation: slowBlink 1.6s ease-in-out infinite;
}

@keyframes slowBlink {
    0%, 100% { opacity: 1; }
    50%      { opacity: .35; }
}

/** 查询中：蓝灰。 ★ 也和"离线"分开 —— 这只是"这一轮还没问到"，不是"服务器没了"。 */
.status-querying { color: #7fa8c9; }
.status-querying::before {
    background: #7fa8c9;
    animation: slowBlink 1.6s ease-in-out infinite;
}

.status-offline { color: #8b9bab; }
.status-offline::before { background: #61717f; }

.srv-last {
    display: block;
    font-size: 11px;
    color: var(--text-faint);
    margin-top: 2px;
}

.row-actions { display: flex; gap: 6px; justify-content: flex-end; }

.btn-mini {
    height: 27px;
    padding: 0 10px;
    font-size: 12px;
    border-radius: 4px;
    border: 1px solid var(--border);
    background: #22303d;
    color: #b6c6d6;
    cursor: pointer;
    font-family: inherit;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    transition: background .15s, color .15s, border-color .15s;
}

.btn-mini:hover { background: #2d3f50; color: #e8f0f8; border-color: #3d5268; }
.btn-mini.is-connect:hover { background: #2c5f92; border-color: #3d7fbf; color: #fff; }
.btn-mini:disabled { opacity: .4; cursor: default; }
.btn-mini:disabled:hover { background: #22303d; color: #b6c6d6; border-color: var(--border); }

.row-loading td { padding: 46px 14px; }

.loading {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    color: var(--text-dim);
    font-size: 13.5px;
}

.spinner {
    /** .spinner 是 <span>，默认 display:inline，而 width/height 对 inline 元素无效 —— display 必须显式写 */

    display: inline-block;
    box-sizing: border-box;
    vertical-align: -2px;

    width: 15px; height: 15px;
    border: 2px solid rgba(102, 192, 244, .25);
    border-top-color: var(--accent-2);
    border-radius: 50%;
    animation: spin .7s linear infinite;
    flex: none;
}

@keyframes spin { to { transform: rotate(360deg); } }

.empty {
    text-align: center;
    padding: 54px 20px;
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.empty h3 { margin: 0 0 6px; font-size: 16px; font-weight: 600; }
.empty p  { margin: 0; color: var(--text-dim); font-size: 13px; }

.foot {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 14px;
    font-size: 12px;
    color: var(--text-faint);
}

/* ---------------- 弹窗 ---------------- */

.modal { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; }
.modal[hidden] { display: none; }

.modal-mask {
    position: absolute;
    inset: 0;
    background: rgba(4, 8, 12, .72);
    backdrop-filter: blur(2px);
}

.modal-box {
    position: relative;
    width: min(560px, calc(100vw - 32px));
    max-height: min(76vh, 620px);
    display: flex;
    flex-direction: column;
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: var(--shadow);
    overflow: hidden;
}

.modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 13px 16px;
    border-bottom: 1px solid var(--border);
    background: #1a2532;
}

.modal-head h3 {
    margin: 0;
    font-size: 14.5px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.modal-close {
    background: none;
    border: none;
    color: var(--text-dim);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}

.modal-close:hover { color: #fff; }

.modal-body { padding: 8px 0 12px; overflow-y: auto; }

.plist { width: 100%; border-collapse: collapse; }

.plist th {
    text-align: left;
    font-size: 11.5px;
    color: var(--text-faint);
    font-weight: 600;
    padding: 6px 16px;
    border-bottom: 1px solid var(--border-soft);
}

.plist td {
    padding: 8px 16px;
    border-bottom: 1px solid var(--border-soft);
    font-size: 13px;
}

.plist tr:last-child td { border-bottom: none; }
.plist .p-name { color: #e8f0f8; word-break: break-all; }
.plist .p-num  { font-variant-numeric: tabular-nums; color: var(--text-dim); text-align: right; white-space: nowrap; }

.modal-msg { padding: 24px 16px; text-align: center; color: var(--text-dim); font-size: 13px; }

/* ============================================================

   服务器详情 / 操作页
   ============================================================ */


.ok   { color: var(--green); }
.bad  { color: var(--red); }
.warn { color: var(--yellow); }

code.mono {
    font-family: Consolas, "Courier New", monospace;
    font-size: 12.5px;
    color: #b6c6d6;
    background: #0e141b;
    padding: 1px 5px;
    border-radius: 3px;
}

.card {
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px 18px;
    margin-bottom: 16px;
}

.card h2 {
    margin: 0 0 14px;
    font-size: 15px;
    font-weight: 600;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border-soft);
}

.alert {
    padding: 12px 16px;
    border-radius: var(--radius);
    margin-bottom: 16px;
    font-size: 13.5px;
    line-height: 1.6;
    border: 1px solid transparent;
}

.alert-ok   { background: #16281a; border-color: #2c5133; color: #a8dda3; }
.alert-warn { background: #2e2614; border-color: #57492a; color: #e8cf94; }
.alert .hint { color: inherit; opacity: .78; }

.kv-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 8px 22px;
}

.kv {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 6px 0;
    border-bottom: 1px dashed var(--border-soft);
    font-size: 13px;
}

.kv span { color: var(--text-dim); flex: none; }
.kv b {
    color: #e8f0f8;
    font-weight: 500;
    text-align: right;
    word-break: break-all;
    min-width: 0;
}

.op-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
}

@media (max-width: 800px) {
    .op-grid { grid-template-columns: 1fr; }
}

.op-box {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 15px;
    display: flex;
    flex-direction: column;
}

/** 按钮组推到盒子底部，四个盒子看起来就一样高、按钮在同一水平线。 */
.op-box .row-act {
    margin-top: auto;
    padding-top: 10px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.op-box h3 {
    margin: 0 0 6px;
    font-size: 13.5px;
    font-weight: 600;
    color: #e8f0f8;
}

.op-box .hint {
    font-size: 12px;
    color: var(--text-faint);
    line-height: 1.6;
    margin: 0 0 10px;
}

.filter-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 12px;
}

.filter-row .inp { flex: 1 1 auto; min-width: 0; }
.filter-row .hint { flex: none; font-size: 12px; }

.file-list {
    list-style: none;
    margin: 10px 0 0;
    padding: 0;
    font-size: 12px;
    max-height: 160px;
    overflow: auto;
}

.file-list li {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    padding: 4px 0;
    border-bottom: 1px dashed var(--border-soft);
    color: var(--text-dim);
}

.file-list li b { font-weight: 500; color: #e8f0f8; }
.file-list li .ok   { color: var(--green); }
.file-list li .bad  { color: var(--red); }
.file-list li .warn { color: var(--yellow); }

.inp {
    width: 100%;
    height: 34px;
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    padding: 0 10px;
    font-size: 13px;
    font-family: inherit;
    outline: none;
}

.inp:focus { border-color: var(--accent); }
select.inp { cursor: pointer; padding: 0 6px; }
input[type="file"].inp {
    height: auto;
    padding: 7px 10px;
    font-size: 12px;
    cursor: pointer;
}

.lbl {
    display: block;
    font-size: 11.5px;
    color: var(--text-dim);
    margin: 0 0 4px;
}

/* ---------- 页面跳转时的加载遮罩 ---------- */
/** 管理页要做实时查询 + RCON 问地图列表，可能要等一两秒。 */

#pageLoading {
    position: fixed;
    inset: 0;
    z-index: 9999;
    background: rgba(11, 18, 26, .78);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    backdrop-filter: blur(2px);
}

#pageLoading[hidden] { display: none; }

#pageLoading .pl-text {
    font-size: 14px;
    color: #c7d5e0;
}

#pageLoading .pl-sub {
    font-size: 12px;
    color: #8f98a0;
}

#pageLoading .pl-bar {
    width: 220px;
    height: 3px;
    background: #2a475e;
    border-radius: 2px;
    overflow: hidden;
}

#pageLoading .pl-bar i {
    display: block;
    width: 40%;
    height: 100%;
    background: var(--accent);
    border-radius: 2px;
    animation: plslide 1.1s ease-in-out infinite;
}

@keyframes plslide {
    0%   { transform: translateX(-110%); }
    100% { transform: translateX(360%); }
}

.op-msg {
    margin-top: 12px;
    font-size: 12.5px;
    line-height: 1.65;
    white-space: pre-wrap;
    word-break: break-word;
}

.ck {
    width: 100%;
    border-collapse: collapse;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}

.ck th,
.ck td {
    padding: 9px 13px;
    text-align: left;
    border-bottom: 1px solid var(--border-soft);
    font-size: 13px;
    vertical-align: middle;
}

.ck th {
    background: #1a2532;
    color: var(--text-dim);
    font-size: 12px;
    font-weight: 600;
}

.ck tr:last-child td { border-bottom: none; }

.btn-danger {
    background: linear-gradient(180deg, #a8443f, #7d302c);
    border-color: #a8443f;
    color: #fff;
}
.btn-danger:hover { background: linear-gradient(180deg, #c2544e, #943933); border-color: #c2544e; }
.btn-danger:disabled,
.btn-danger:disabled:hover,
.btn-danger:disabled:active {
    background: #2a2f36;
    border-color: var(--border);
    color: var(--text-faint);
    cursor: not-allowed;
    opacity: .45;
}

/* ---------- 有人在线时的锁定提示 ---------- */
.lock-banner {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 11px 15px;
    margin: 0 0 14px;
    border-radius: var(--radius);
    background: #2e2614;
    border: 1px solid #57492a;
    color: #e8cf94;
    font-size: 13px;
    line-height: 1.6;
}

.lock-banner b { color: #ffd77a; font-size: 13.5px; }
.lock-banner span { opacity: .82; font-size: 12.5px; }

/** 确认期间那条。 ★ 不能用黄色 —— 黄条的含义是"有人在线，操作被挡"， 而确认期间恰恰是**没人**、只是还没核实完。用中性的蓝色。 */
.lock-banner-verify {
    background: #16283a;
    border-color: #2a4a66;
    color: #a8c8e4;
    /* b 和 span 的黄色是给"有玩家"那条用的，这里要盖掉 */
}

.lock-banner-verify b {
    color: #8fc4ec;
    display: flex;
    align-items: center;
    gap: 8px;
}

.lock-banner-verify span { opacity: .72; }

/* ---------- "当前 XX" 状态条 ---------- */
.now-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 9px 13px;
    margin: 0 0 12px;
    border-radius: 4px;
    background: #16202d;
    border-left: 3px solid var(--accent);
}

.now-row .now-label {
    font-size: 12px;
    color: var(--text-dim);
    flex: none;
}

.now-row .now-value {
    font-size: 17px;
    font-weight: 700;
    color: #e8f0f8;
    text-align: right;
    line-height: 1.25;
    word-break: break-all;
}

/* ---------------- 操作后的锁定遮罩 ---------------- */
/** 换图 / 重启之后服务器会短暂无响应，这时候刷新页面会显示"离线"， */

#opLock {
    position: fixed;
    inset: 0;
    z-index: 9999;
    background: rgba(11, 18, 26, .82);
    display: flex;
    align-items: center;
    justify-content: center;
    backdrop-filter: blur(2px);
}

#opLock .ol-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 26px 34px;
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    text-align: center;
}

#opLock .ol-title {
    font-size: 15px;
    font-weight: 600;
    color: #e8f0f8;
}

#opLock .ol-sub {
    font-size: 12.5px;
    color: var(--text-dim);
}

#opLock .ol-sub b {
    color: var(--accent-2);
    font-size: 15px;
    font-variant-numeric: tabular-nums;
}

#opLock .ol-bar {
    width: 200px;
    height: 3px;
    background: var(--border);
    border-radius: 2px;
    overflow: hidden;
}

#opLock .ol-bar i {
    display: block;
    height: 100%;
    background: var(--accent);
    border-radius: 2px;
    transition: width 1s linear;
}

/* ---------------- 自绘确认框 ---------------- */
/** 替代浏览器原生的 confirm()。原生那个是浏览器样式，和站点不搭， */

.cf-mask {
    position: fixed;
    inset: 0;
    z-index: 10000;
    background: rgba(11, 18, 26, .72);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    backdrop-filter: blur(2px);
}

.cf-box {
    width: 100%;
    max-width: 400px;
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 18px 20px 16px;
    box-shadow: 0 18px 50px rgba(0, 0, 0, .5);
}

.cf-title {
    font-size: 15px;
    font-weight: 600;
    color: #e8f0f8;
    margin-bottom: 10px;
}

.cf-body {
    font-size: 13px;
    line-height: 1.7;
    color: var(--text-dim);
    word-break: break-word;
}

.cf-body p { margin: 0; }
.cf-body p.cf-gap { height: 8px; }

.cf-act {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 18px;
}

/* 输入框（给地图命名用） */
.cf-input {
    width: 100%;
    margin-top: 12px;
    box-sizing: border-box;
}

.btn-danger {
    background: linear-gradient(180deg, #6b2b30, #4d1f23);
    border-color: #7d3a3f;
    color: #ffd9dc;
}

.btn-danger:hover {
    background: linear-gradient(180deg, #7d3339, #5a2429);
    border-color: #93454b;
}

/* ---------------- 自动更新的时间戳 ---------------- */

.live-tip {
    float: right;
    font-size: 11.5px;
    font-weight: 400;
    color: var(--text-faint);
    font-variant-numeric: tabular-nums;
    line-height: 1.9;
}

/* ---------------- 断网提示 ---------------- */
/* 和锁定遮罩同一套样式，只是没有倒数条 */


#netOffline {
    position: fixed;
    inset: 0;
    z-index: 10001;
    background: rgba(11, 18, 26, .88);
    display: flex;
    align-items: center;
    justify-content: center;
    backdrop-filter: blur(3px);
}

#netOffline .ol-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 26px 34px;
    background: var(--bg-2);
    border: 1px solid #7d3a3f;
    border-radius: var(--radius);
    text-align: center;
}

#netOffline .ol-title {
    font-size: 15px;
    font-weight: 600;
    color: #ffb4b9;
}

#netOffline .ol-sub {
    font-size: 12.5px;
    line-height: 1.7;
    color: var(--text-dim);
}

/* ---------------- 右下角浮动提示 ---------------- */

.toast {
    position: fixed;
    right: 22px;
    bottom: 22px;
    z-index: 10002;
    max-width: 340px;
    padding: 11px 16px;
    background: var(--bg-2);
    border: 1px solid var(--accent);
    border-left-width: 3px;
    border-radius: var(--radius);
    color: var(--text);
    font-size: 13px;
    line-height: 1.6;
    box-shadow: 0 12px 32px rgba(0, 0, 0, .45);

    opacity: 0;
    transform: translateY(8px);
    transition: opacity .22s, transform .22s;
}

.toast.is-on {
    opacity: 1;
    transform: translateY(0);
}

.toast-bad {
    border-color: #7d3a3f;
    border-left-color: #c05a62;
    color: #ffd9dc;
}

/* ---------------- 登录页（密钥入口） ---------------- */

.app-narrow {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
}

.gate-wrap { width: 100%; max-width: 460px; }

.gate-card { text-align: center; padding: 30px 28px 22px; }

.gate-logo {
    width: 56px;
    height: 56px;
    margin: 0 auto 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 14px;
    background: linear-gradient(145deg, #2f6ea8, #1d4a75);
    color: #eaf4ff;
    font-weight: 800;
    font-size: 15px;
    letter-spacing: .5px;
}

.gate-title {
    margin: 0 0 8px;
    padding: 0;
    border: none;
    font-size: 18px;
    font-weight: 600;
    text-align: center;
}

.gate-hint { margin: 0 0 16px; line-height: 1.7; }
.gate-hint b { color: var(--accent-2); }

.gate-alert { margin: 0 0 14px; text-align: left; }

.gate-form {
    display: flex;
    gap: 8px;
    margin-bottom: 14px;
}

/* 验证码那一行：输入框在左、图片在右 */
.gate-captcha-row {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-top: 10px;
}

.gate-form-wrap .gate-input,
.gate-form-wrap .gate-captcha-row { margin-bottom: 0; }

.gate-captcha-input {
    flex: 1 1 auto;
    min-width: 0;
    text-align: center;
    letter-spacing: 4px;
    text-transform: uppercase;
    font-weight: 600;
}

.gate-captcha {
    flex: none;
    height: 34px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    cursor: pointer;
    display: block;
}

.gate-form-wrap {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 14px;
}

.gate-form-wrap .gate-btn { width: 100%; margin-top: 4px; }

.gate-input {
    flex: 1 1 auto;
    min-width: 0;
    text-align: center;
    letter-spacing: 3px;
    font-size: 15px;
    font-weight: 600;
    text-transform: uppercase;
}

.gate-btn { flex: none; height: 34px; }

.gate-foot { margin: 0; font-size: 11.5px; }
.gate-foot b { color: var(--accent-2); }

.gate-back {
    margin: 16px 0 0;
    padding-top: 14px;
    border-top: 1px solid var(--border-soft);
    font-size: 12.5px;
}

.gate-back a { color: var(--text-dim); text-decoration: none; }
.gate-back a:hover { color: var(--accent-2); }

/* ---------------- 身份角标 ---------------- */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: 20px;
    font-size: 12px;
    font-weight: 600;
    border: 1px solid transparent;
    text-decoration: none;
    white-space: nowrap;
}

.badge-master {
    background: #3a2418;
    border-color: #7d4a2a;
    color: #ffc78a;
}

.badge-group {
    background: #16283a;
    border-color: #2a4a66;
    color: #8fc4ec;
}

.badge-player {
    background: #1e3330;
    border-color: #2e504a;
    color: #5fc9b0;
}

/* 角标旁边那一小块说明（鼠标悬停才看全） */
.badge-who {
    font-size: 11px;
    color: var(--text-faint);
    font-weight: 400;
}

/* ---------------- 站长模式横幅 ---------------- */
/** 管理页 / SM 页 / 列表页用的都是这一套 —— */


.master-strip {
    display: flex;

    /** baseline 是按"文字基线"对齐 —— 密钥用 16px 大字、 旁边的按钮只有 11px，基线一对齐，按钮就明显偏下， 看着像没对齐。 */
    align-items: center;

    gap: 10px;
    flex-wrap: wrap;
    padding: 10px 15px;
    margin: 0 0 16px;
    border-radius: var(--radius);
    background: #3a2418;
    border: 1px solid #7d4a2a;
    color: #ffd0a0;
    font-size: 12.5px;
}

.master-strip b {
    font-size: 13.5px;
    color: #ffc78a;
    letter-spacing: .5px;
}

.master-strip span { opacity: .8; }

/** 横幅里的按钮统一成一套配色 —— */
.master-strip .btn-mini {
    background: #4a3520;
    border-color: #7d4a2a;
    color: #ffd0a0;
}

.master-strip .btn-mini:hover {
    background: #5c4228;
    border-color: #9a5c34;
}

.master-strip.is-group .btn-mini {
    background: #1d3a52;
    border-color: #2f5578;
    color: #a8cbe8;
}

.master-strip.is-group .btn-mini:hover {
    background: #24486a;
    border-color: #3d6fa8;
}

/** 本服玩家那条横幅：**绿色**。 ★ 为什么和群成员分开： */
.master-strip.is-player {
    background: #1e3330;
    border-color: #2e504a;
    color: #7fd8c0;
}

.master-strip.is-player b {
    color: #5fc9b0;
}

.master-strip.is-player .btn-mini {
    background: #24403b;
    border-color: #2e504a;
    color: #7fd8c0;
}

.master-strip.is-player .btn-mini:hover {
    background: #2c4d46;
    border-color: #3d6b62;
}

/** 横幅最右边的「退出」。 ★ 这里**不能**给它加 margin-left: auto —— 密钥块（.master-key）已经有一个 auto 了。 */
.master-strip .strip-logout { opacity: 1; }

/** 但群成员那条横幅**没有密钥块** —— */
.master-strip.is-group .strip-logout,
.master-strip.is-player .strip-logout {
    margin-left: auto;
}
/** 群成员的那条横幅：**蓝色**，和站长的橙色区分开。 ★ 为什么要分色： */
.master-strip.is-group {
    background: #16283a;
    border-color: #2f5578;
    color: #a8cbe8;
}

.master-strip.is-group b {
    color: #7fb8e8;
}

/** 在列表页里它是 .topbar 的直接子元素，上下间距由 topbar 的 gap 管。 ★ 这里必须把自带的 margin-bottom 清掉 —— 不然上面 14px、下面 14+16=30px，看着就不居中。 */
.topbar .master-strip { margin: 0; }

/* 站长才能看到的「今日密钥」—— 直接复制去群里发 */
.master-key {
    margin-left: auto;
    display: inline-flex;

    /** 上一轮只改了外层 .master-strip，忘了这一层 —— 结果外层对齐了，密钥块**内部**还是按基线排： */
    align-items: center;

    /* 里面这几个元素永远不拆行 —— 拆开就不成一组了 */
    flex-wrap: nowrap;

    gap: 6px;
    opacity: 1 !important;
    font-size: 12px;
    color: #e8b98a;
}

.master-key b {
    font-size: 16px;
    letter-spacing: 3px;
    color: #ffd77a;
    font-family: Consolas, "Courier New", monospace;
    /* 方便三击全选复制 */
    user-select: all;

    /* 点一下就能复制（见 dialog.js 里的复制处理） */
    cursor: pointer;
    padding: 1px 4px;
    margin: 0 -4px;
    border-radius: 3px;
    transition: background .15s, color .15s;
}

.master-key b:hover {
    background: rgba(255, 215, 122, .16);
    color: #ffe9a8;
}

/* 复制成功的一瞬间闪一下绿 */
.master-key b.is-copied {
    background: rgba(95, 201, 176, .22);
    color: #7fd8c0;
}

.master-key i {
    font-style: normal;
    font-size: 11px;
    opacity: .65;
}

/* 「立即更换」按钮：要小、要贴在密钥旁边、但也要点得到 */
.master-key .btn-mini {
    margin-left: 4px;
    font-size: 11px;
    padding: 2px 8px;
    background: #4a3520;
    border-color: #7d4a2a;
    color: #ffd0a0;
}

.master-key .btn-mini:hover {
    background: #5c4228;
    border-color: #9a5c34;
}

/* ---------------- 列表页：身份 / "我在这台服上" ---------------- */


.me-badge {
    margin-left: 10px;
    vertical-align: middle;
    font-size: 12px;
    font-weight: 400;
}

/* 页脚的登录 / 退出入口（不抢标题区的地方） */

.foot-auth {
    margin-left: auto;
    font-size: 12px;
}

.foot-auth a,
.foot-logout {
    color: var(--text-faint);
    text-decoration: none;
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    font-size: 12px;
    cursor: pointer;
}

.foot-auth a:hover { color: var(--accent-2); text-decoration: underline; }
.foot-logout:hover { color: #e0708a; text-decoration: underline; }

/* 「你正在这台服上玩」提示条 */
.alert-here {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    background: linear-gradient(180deg, #1e3330, #1a2c2a);
    border: 1px solid #2e504a;
    color: #7fd8c0;
    padding: 12px 15px;
}

.alert-here b { color: #5fc9b0; }
.alert-here .btn-mini { margin-left: auto; }

/* 呼吸的绿点 —— 比放个图标更耐看，也不用担心字体里没有这个 emoji */
.here-dot {
    flex: none;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #5fc9b0;
    box-shadow: 0 0 0 0 rgba(95, 201, 176, .55);
    animation: herePulse 2.2s ease-out infinite;
}

@keyframes herePulse {
    0%   { box-shadow: 0 0 0 0 rgba(95, 201, 176, .55); }
    70%  { box-shadow: 0 0 0 9px rgba(95, 201, 176, 0); }
    100% { box-shadow: 0 0 0 0 rgba(95, 201, 176, 0); }
}

.here-main {
    display: flex;
    flex-direction: column;
    gap: 2px;
    line-height: 1.5;
    min-width: 0;
}

.here-cap {
    font-size: 11.5px;
    color: #5f8f85;
    letter-spacing: .5px;
}

/* 服名：比玩家名显眼，一眼知道是哪台 */
.here-srv {
    color: #9ee8d4;
    font-weight: 600;
    font-size: 13.5px;
}

.here-who {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    font-size: 12px;
    color: #7fd8c0;
}

.here-who b {
    color: #d6f5ec;
    font-size: 12.5px;
}

.here-who i {
    font-style: normal;
    font-size: 11.5px;
    color: #5f8f85;
    font-variant-numeric: tabular-nums;
}

/* 玩家所在的那一行 */
.server-table tr.is-mine > td {
    background: rgba(95, 201, 176, .07);
}

.server-table tr.is-mine > td:first-child {
    box-shadow: inset 3px 0 0 #5fc9b0;
}

.tag-here {
    background: #1e3330;
    color: #5fc9b0;
    border-color: #2e504a;
    font-weight: 600;
}

.btn-mini.is-here {
    background: #1e3330;
    border-color: #2e504a;
    color: #5fc9b0;
}

.btn-mini.is-here:hover {
    background: #24403b;
    border-color: #3d6b62;
}

/* 站长的 SM 快捷入口（普通访客和群成员看不到） */
.btn-mini.is-sm {
    background: #2c2440;
    border-color: #443862;
    color: #b9a0e8;
    font-weight: 600;
}

.btn-mini.is-sm:hover {
    background: #362c4e;
    border-color: #574875;
}

/* ---------------- SM 控制台 ---------------- */

.sm-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.sm-btn {
    min-width: 130px;
    justify-content: center;
}

.sm-opt { margin-bottom: 14px; }
.sm-opt:last-child { margin-bottom: 0; }

.sm-opt-row {
    display: flex;
    gap: 8px;
    align-items: center;
}

.sm-opt-row .inp { flex: 1 1 auto; max-width: 200px; }

.sm-log {
    max-height: 240px;
    overflow: auto;
    font-size: 12.5px;
    line-height: 1.9;
}

.sm-log-row {
    display: flex;
    gap: 12px;
    padding: 3px 0;
    border-bottom: 1px solid var(--border-soft);
}

.sm-log-row.is-bad { color: #e8a0a8; }

.sm-log-time {
    color: var(--text-faint);
    font-variant-numeric: tabular-nums;
    flex: none;
}

/* ---------------- 全屏开场动画（身份切换用） ---------------- */

.boot-splash {
    position: fixed;
    inset: 0;
    z-index: 10050;
    background: #0e141b;
    display: flex;
    align-items: center;
    justify-content: center;

    opacity: 0;
    transition: opacity .3s;
}

.boot-splash.is-on { opacity: 1; }

.boot-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    text-align: center;
    padding: 0 24px;
}

.boot-spin {
    width: 34px !important;
    height: 34px !important;
    border-width: 3px !important;
}

.boot-title {
    font-size: 22px;
    font-weight: 700;
    letter-spacing: 3px;
    color: #ffc78a;
}

.boot-sub {
    font-size: 12.5px;
    color: var(--text-dim);
    letter-spacing: .5px;
}

.boot-bar {
    width: 220px;
    height: 3px;
    border-radius: 2px;
    background: var(--border);
    overflow: hidden;
}

.boot-bar i {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 2px;
    background: linear-gradient(90deg, #2f6ea8, #ffc78a);
}

/* ---------------- 封禁管理面板 ---------------- */

.cf-box-wide { max-width: 520px; }

.cf-body-html {
    max-height: 60vh;
    overflow: auto;
}

.ban-mine {
    margin: 0 0 14px;
    padding: 9px 12px;
    border-radius: var(--radius);
    background: #3a2018;
    border: 1px solid #7d3a2a;
    color: #ffb9a0;
    font-size: 12.5px;
    line-height: 1.7;
}

.ban-head {
    margin: 16px 0 6px;
    font-size: 12px;
    color: var(--text-faint);
}

.ban-head:first-child { margin-top: 0; }

/* 分组标题后面补一句"这组意味着什么" */
.ban-note {
    margin-left: 8px;
    font-size: 11px;
    color: #56656f;
}

.ban-note::before { content: '· '; }

/* 第三组（只是输错过）压暗，别和真封禁抢注意力 */
.ban-list-dim { opacity: .6; }

.ban-list {
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
    overflow: hidden;
}

.ban-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-soft);
    font-size: 12.5px;
}

.ban-row:last-child { border-bottom: none; }

.ban-row code {
    flex: none;
    color: #cfdbe6;
    font-size: 12.5px;
}

.ban-row .ban-meta {
    flex: 1 1 auto;
    color: var(--text-faint);
    font-size: 11.5px;
}

.ban-all {
    margin-top: 16px;
    text-align: right;
}

/* ---------------- 「站长排查」折叠块 ---------------- */
/*
 * ★ 为什么要折叠：错误排查细节对站长有用，但**不能默认摊开** ——
 *   普通玩家打开页面看到一堆 chown / config.php / 端口，只会以为"这站坏了"。
 *   默认收起来，要查的人点一下就看到全部内容。
 */

details.trouble {
    margin: 10px 0 0;
    padding: 0;
    border: 1px solid var(--border-soft);
    border-left: 3px solid #6b5620;
    border-radius: var(--radius);
    background: rgba(224, 183, 74, .045);
    font-size: 12.5px;
    line-height: 1.75;
    color: var(--text-dim);
}

details.trouble > summary {
    padding: 8px 12px;
    cursor: pointer;
    color: #b9a97a;
    font-size: 12px;
    list-style: none;              /* 去掉浏览器默认三角，换成下面自己的 ▸ */
    user-select: none;
}

/* 自己画一个三角：收起时 ▸，展开时 ▾ */
details.trouble > summary::-webkit-details-marker { display: none; }

details.trouble > summary::before {
    content: '▸';
    display: inline-block;
    margin-right: 6px;
    color: var(--yellow);
    transition: transform .15s;
}

details.trouble[open] > summary::before { content: '▾'; }

details.trouble > summary:hover { color: #d8c79a; }

/* 展开后的正文：四周留白，代码块不撑破窄屏 */
details.trouble .trouble-body {
    padding: 2px 12px 11px;
    border-top: 1px solid var(--border-soft);
    margin-top: 2px;
    padding-top: 9px;
}

details.trouble code.mono {
    word-break: break-all;
}

/* ---------------- 通用加载遮罩 ---------------- */

.load-mask {
    position: fixed;
    inset: 0;
    z-index: 9000;

    background: rgba(14, 20, 27, .72);
    /* 不加 backdrop-filter —— 老显卡上会掉帧，而且本来也够暗了 */

    display: flex;
    align-items: center;
    justify-content: center;

    opacity: 0;
    transition: opacity .18s;
    pointer-events: all;
}

.load-mask.is-on { opacity: 1; }

.load-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 26px 34px;
    border-radius: 12px;
    background: var(--bg-2);
    border: 1px solid var(--border);
    box-shadow: 0 12px 40px rgba(0, 0, 0, .45);
}

/** 加载遮罩里的转圈：直接复用 .spinner，只把它放大一点。 */
.load-box .spinner,
.boot-box .spinner {
    width: 26px;
    height: 26px;
    border-width: 3px;
}

.load-text {
    font-size: 13px;
    color: var(--text);
    letter-spacing: .5px;
}

.load-sub {
    font-size: 11.5px;
    color: var(--text-faint);
}

/* ---------------- 强制重启卡片 ---------------- */

.force-card {
    border-color: #5c3038;
}

.force-card h2 { color: #e8a0a8; }

.force-path {
    margin: 0;
    padding: 9px 12px;
    border-radius: var(--radius);
    background: var(--bg-3);
    border: 1px solid var(--border);
    word-break: break-all;
}

.force-path code { color: #ffc78a; }

.force-sample {
    margin: 0;
    padding: 10px 12px;
    border-radius: var(--radius);
    background: #0d1319;
    border: 1px solid var(--border-soft);
    color: #9fb3c4;
    font-size: 11.5px;
    line-height: 1.7;
    overflow-x: auto;
    white-space: pre;
}

/* ---------------- 审计日志页 ---------------- */

.audit-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 10px;
    margin-bottom: 16px;
}

.audit-card {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 12px 14px;
    border-radius: var(--radius);
    background: var(--bg-2);
    border: 1px solid var(--border-soft);
}

.audit-num {
    font-size: 22px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text);
    line-height: 1.2;
}

.audit-cap {
    font-size: 12px;
    color: var(--text-dim);
}

.audit-sub {
    font-size: 11px;
    color: #56656f;
}

.audit-card.tone-good   { border-color: #2e504a; }
.audit-card.tone-good   .audit-num { color: #5fc9b0; }
.audit-card.tone-bad    { border-color: #5c3038; }
.audit-card.tone-bad    .audit-num { color: #e88a9a; }
.audit-card.tone-master { border-color: #7d4a2a; }
.audit-card.tone-master .audit-num { color: #ffc78a; }
.audit-card.tone-dim    .audit-num { color: var(--text-faint); }

/* --- 分类页签 --- */
.audit-tabs {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
    margin-bottom: 14px;
    border-bottom: 1px solid var(--border-soft);
    padding-bottom: 0;
}

.audit-tab {
    padding: 7px 14px;
    font-size: 12.5px;
    color: var(--text-dim);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}

.audit-tab:hover { color: var(--text); }

.audit-tab.is-on {
    color: #ffc78a;
    border-bottom-color: #7d4a2a;
    font-weight: 600;
}

/* --- 筛选表单 --- */
.audit-form {
    display: flex;
    gap: 12px;
    align-items: flex-end;
    flex-wrap: wrap;
}

/* --- 活跃 IP --- */
.audit-topips {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--border-soft);
    font-size: 12px;
}

.audit-topips-cap { color: var(--text-faint); }

.audit-ip {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    padding: 2px 8px;
    border-radius: 10px;
    background: var(--bg-3);
    border: 1px solid var(--border-soft);
    color: var(--text-dim);
    text-decoration: none;
    font-family: Consolas, "Courier New", monospace;
    font-size: 11.5px;
}

.audit-ip:hover { border-color: var(--accent); color: var(--accent-2); }

.audit-ip b { color: #ffc78a; font-size: 11px; }

/* --- 明细表 --- */
.audit-table-wrap {
    overflow-x: auto;
    margin: 0 -15px -14px;
    padding: 0 15px;
}

.audit-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12.5px;
}

.audit-table th {
    text-align: left;
    padding: 8px 10px;
    color: var(--text-faint);
    font-weight: 500;
    font-size: 11.5px;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}

.audit-table td {
    padding: 8px 10px;
    border-bottom: 1px solid var(--border-soft);
    vertical-align: top;
    color: var(--text-dim);
}

.audit-table tr:hover td { background: var(--bg-hover); }

.audit-time { white-space: nowrap; }
.audit-time b { color: var(--text); font-variant-numeric: tabular-nums; }
.audit-time i {
    display: block;
    font-style: normal;
    font-size: 11px;
    color: #56656f;
}

.audit-kind {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11.5px;
    white-space: nowrap;
    background: var(--bg-3);
    border: 1px solid var(--border-soft);
}

.audit-kind.tone-good   { color: #5fc9b0; border-color: #2e504a; }
.audit-kind.tone-bad    { color: #e88a9a; border-color: #5c3038; }
.audit-kind.tone-master { color: #ffc78a; border-color: #7d4a2a; font-weight: 600; }
.audit-kind.tone-dim    { color: var(--text-faint); }

.audit-sid { white-space: nowrap; font-size: 11.5px; }
.audit-srv { white-space: nowrap; font-size: 11.5px; }

.audit-detail {
    min-width: 220px;
    color: var(--text);
    word-break: break-word;
}

/* 站长操作整行标橙，扫一眼就能挑出来 */
.audit-table tr.tone-master td { background: rgba(255, 199, 138, .045); }
.audit-table tr.tone-bad td    { background: rgba(232, 138, 154, .04); }

/* ---------------- 上传页 / 上传进度 ---------------- */


.up-pick {
    display: flex;
    gap: 10px;
    align-items: center;
    flex-wrap: wrap;
}

.up-pick .inp { flex: 1 1 260px; min-width: 0; }

/** 为什么单独给它们上色： */
.btn-cancel,
.btn-cancel-del {
    border-color: #7a5c33;
    background: linear-gradient(180deg, #4a3a24, #33291b);
    color: #f0d9ae;
}

.btn-cancel:hover,
.btn-cancel-del:hover {
    border-color: #9a7440;
    background: linear-gradient(180deg, #5c4728, #3f3220);
    color: #ffe9c2;
}

.btn-cancel-del {
    border-color: #7c3b3b;
    background: linear-gradient(180deg, #4d2a2a, #35201f);
    color: #f3c2c2;
}

.btn-cancel-del:hover {
    border-color: #a04c4c;
    background: linear-gradient(180deg, #603333, #422625);
    color: #ffd9d9;
}

/** 为什么单独给这个按钮上色（青色，和后台模式一个色系）： */
.btn-direct {
    border-color: #3d6f7a;
    background: linear-gradient(180deg, #24444c, #1b3339);
    color: #bfe9ef;
}

.btn-direct:hover {
    border-color: #4f8f9c;
    background: linear-gradient(180deg, #2d565f, #214047);
    color: #e2f7fa;
}

/** 「当前配置：只允许直连，不允许中转」那段说明。 ★ 用偏黄的边框和底色：这是一条**会影响操作结果**的配置说明， 不是普通提示 —— 用户看到"直连失败"时要能马上对上这段话。 */
.up-note-relay-off {
    margin: 10px 0 0;
    padding: 10px 12px;
    border: 1px solid #6b5620;
    border-radius: var(--radius);
    background: rgba(224, 183, 74, .07);
    color: #d8c79a;
    line-height: 1.8;
}

.up-note-relay-off b { color: #e8cf94; }

.up-note-relay-off code {
    background: #0b1219;
    padding: 1px 5px;
    border-radius: 4px;
    font-size: 11.5px;
}

/* 上传模式的三种状态：直连用绿色（和后台模式一个待遇），中转是普通灰 */
.up-mode.is-direct { color: #7cc576; }

.up-row {
    margin-bottom: 12px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border-soft);
}

.up-row:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: none; }

.up-row-top {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 6px;
    font-size: 12.5px;
}

.up-name { flex: 1 1 auto; color: var(--text); word-break: break-all; }
.up-size { flex: none; color: var(--text-faint); font-size: 11.5px; }
.up-state { flex: none; color: var(--text-dim); font-size: 11.5px; }

.up-row.is-done .up-state { color: #5fc9b0; }
.up-row.is-bad  .up-state { color: #e88a9a; }

.up-bar {
    height: 4px;
    border-radius: 2px;
    background: var(--bg-3);
    overflow: hidden;
}

.up-bar i {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 2px;
    background: linear-gradient(90deg, #2f6ea8, #5fc9b0);
    transition: width .25s;
}

.up-row.is-done .up-bar i { background: #5fc9b0; }
.up-row.is-bad  .up-bar i { background: #e88a9a; }

.up-log {
    max-height: 260px;
    overflow: auto;
    font-size: 12px;
    line-height: 1.9;
    font-family: Consolas, "Courier New", monospace;
}

.up-log-row { color: var(--text-dim); padding: 1px 0; }
.up-log-row.is-ok  { color: #5fc9b0; }
.up-log-row.is-bad { color: #e88a9a; }

/* ---------------- 上传区（管理页里内嵌的那一块） ---------------- */

/* 拖拽区：把 .vpk 拖进来就能传 */

.up-drop {
    margin-top: 10px;
    padding: 14px 12px;
    border: 1px dashed var(--border);
    border-radius: var(--radius);
    background: rgba(76, 145, 212, .04);
    color: var(--text-faint);
    font-size: 12px;
    text-align: center;
    transition: border-color .15s, background .15s, color .15s;
}

.up-drop.is-over {
    border-color: var(--accent-2);
    background: rgba(76, 145, 212, .12);
    color: var(--text);
}

/** 「上传模式」那一行。 ★ 这一行是给"证书过期"这种情况看的： */
.up-mode {
    margin-top: 10px;
    font-size: 11.5px;
    color: var(--text-dim);
    cursor: help;
}

.up-mode.is-sw { color: #5fc9b0; }

/* 每个文件一行的进度（和上传页用的是同一套 .up-row / .up-bar） */

#upRows { margin-top: 12px; }

/* ---------------- 列表页顶部的上传进度条 ---------------- */

.upstrip {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 14px;
    margin: 0 0 14px;
    border-radius: var(--radius);
    background: #16283a;
    border: 1px solid #2f5578;
    color: #a8cbe8;
    font-size: 12.5px;
}

.upstrip b { color: #7fb8e8; flex: none; }

.upstrip-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: #cfe4f5;
}

.upstrip-bar {
    flex: none;
    width: 130px;
    height: 4px;
    border-radius: 2px;
    background: #0f1c28;
    overflow: hidden;
}

.upstrip-bar i {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 2px;
    background: linear-gradient(90deg, #2f6ea8, #7fb8e8);
    transition: width .3s;
}

.upstrip-pct { flex: none; font-variant-numeric: tabular-nums; color: #7fb8e8; }

/* ---------------- SM 控制台的新版布局 ---------------- */

/* 一栏一块，块之间用细线分开 */

.sm-block {
    padding: 14px 0;
    border-top: 1px solid var(--border-soft);
}

.sm-block:first-of-type { border-top: none; padding-top: 0; }
.sm-block:last-of-type { padding-bottom: 0; }

/* 行内元素多了要能换行 */
.sm-opt-row.sm-wrap { flex-wrap: wrap; }

/* 下拉框窄一点，一行能塞下好几个 */
.sm-opt-row .inp.sm-narrow { flex: 0 1 auto; min-width: 130px; max-width: 190px; }

.sm-arrow {
    flex: none;
    color: var(--text-faint);
    font-size: 12px;
    padding: 0 2px;
}

.sm-block > .lbl {
    display: block;
    margin-bottom: 8px;
    font-size: 12.5px;
    color: var(--text-dim);
}

/* ---------------- 响应式 ---------------- */

/*
 * 顶部结构在大屏小屏上是一样的（标题一行 + 统计一行），
 * 底部图表也一直在最下面。这里只处理三件事：
 *   · 长服务器名按宽度逐级截短
 *   · 手机（≤720px）统计区改成两列
 *   · 很窄的手机（≤420px）改成单列
 */


@media (max-width: 1500px) {
    /* 长服务器名根据屏幕宽度逐级截短，免得把表格撑得老宽 */
    .srv-title { max-width: 260px; }
}

@media (max-width: 1180px) {
    .srv-title { max-width: 200px; }
}

@media (max-width: 900px) {
    .srv-title { max-width: 150px; }
}

@media (max-width: 720px) {
    .app { padding: 14px 12px 28px; }
    .brand-logo { width: 44px; height: 44px; font-size: 13px; }
    .brand-text h1 { font-size: 17px; }

    /** 主题下拉框：手机上一律换到"标题下面一行"，不跟标题抢那点宽度；
        整行靠右（≤420px 时 theme.css 会让它铺满整行，点起来更好点）。 */
    .brand { flex-wrap: wrap; }
    .brand > .theme-pick { flex: 1 1 100%; margin-left: 0; justify-content: flex-end; }

    .updated { margin-left: 0; width: 100%; }

    .stats {
        grid-template-columns: 1fr 1fr;
        gap: 8px;
    }

    /* 时间占一整行，其他四块两两一行 */
    .stat-players { order: 1; }
    .stat-peak    { order: 4; }
    .stat-clock   { order: 5; grid-column: span 2; }

    .stat { padding: 8px 6px; }
    .stat-num { font-size: 17px; }
    .stat-label { font-size: 10.5px; }

    /* 手机上名字再短一点，把宽度留给地图和玩家数 */
    .srv-title { max-width: 110px; }

    /* 底部图表矮一点 */
    .sp-plot { height: 110px; }
    .chart-head { flex-wrap: wrap; gap: 4px; }
}

/* 很窄的手机：统计块改成一行一个，字别挤在一起 */
@media (max-width: 420px) {
    .stats { grid-template-columns: 1fr; }

    .stat-clock { grid-column: span 1; }

    .chart-axis .chart-legend { display: none; }
}

/* ================= SM 控制台：状态灯 ================= */

/** 一个开关 = 按钮 +（可选）状态灯，竖着排。 */

.sm-switch {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.sm-switch .sm-btn { width: 100%; }

.sm-state {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    align-self: flex-start;
    padding: 2px 9px;
    border-radius: 999px;
    font-size: 11.5px;
    line-height: 1.7;
    border: 1px solid transparent;
    white-space: nowrap;
}

/* 前面的小圆点 */
.sm-state::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.sm-state.is-on {
    color: #7fd8a0;
    background: #162c1d;
    border-color: #2c5138;
}

.sm-state.is-off {
    color: #8b98a8;
    background: #1b2028;
    border-color: #2c3542;
}

.sm-state.is-unknown {
    color: #8b98a8;
    background: #1b2028;
    border-color: #2c3542;
    opacity: .7;
}

/* ================= 手机端 ================= */

@media (max-width: 720px) {

    /** ---- 身份横幅（手机端）---- ★ 关键：**不要**改成 column！ */
    .master-strip {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: 8px;
        padding: 10px 12px;
        text-align: left;
    }

    /* 文字那块（如"小唯模式已启动"）占满一行，按钮从下一行开始排 */
    .master-strip > b,
    .master-strip > span:not(.master-key):not(.strip-logout) {
        flex: 1 1 100%;
    }

    .master-strip .master-key {
        flex: 1 1 auto;
        flex-wrap: wrap;
    }

    /* 退出跟在同一行末尾 —— 和封禁管理、审计日志并排 */
    .master-strip .strip-logout,
    .master-strip.is-group .strip-logout,
    .master-strip.is-player .strip-logout {
        margin-left: 0;
        align-self: center;
    }

    /* 密钥块原来靠 margin-left:auto 顶到右边，手机上要取消 */
    .master-strip .master-key {
        margin-left: 0;
        flex-wrap: wrap;
        gap: 6px;
    }

    /* 「退出」也一样 */
    .master-strip.is-group .strip-logout,
    .master-strip.is-player .strip-logout,
    .master-strip .strip-logout {
        margin-left: 0;
        align-self: flex-start;
    }

    /* 密钥那串大字在小屏上别撑破 */
    .master-strip .master-key b,
    .master-strip .master-key strong {
        font-size: 15px;
        letter-spacing: 1px;
    }

    /* ---- SM 页：下拉框一行放不下就换行 ---- */
    .sm-opt-row {
        flex-wrap: wrap;
    }

    .sm-opt-row .inp,
    .sm-opt-row .inp.sm-narrow {
        flex: 1 1 100%;
        max-width: none;
        min-width: 0;
    }

    .sm-opt-row .btn { flex: 1 1 100%; }

    .sm-arrow { display: none; }

    /** 按钮两列，别一个占一整行。 ★ .sm-grid 是 flex（不是 grid），所以用 flex-basis 算宽度。 */
    .sm-grid {
        gap: 8px;
    }

    .sm-grid > * {
        flex: 1 1 calc(50% - 4px);
        min-width: 0;
    }

    .sm-block { padding: 12px 0; }
}

@media (max-width: 420px) {
    .sm-grid > * { flex: 1 1 100%; }
}

/* ================= 开关型按钮的状态 ================= */

/** 开着 → 绿色；读不到 → 灰暗一点并带问号。 */

.sm-btn.is-switch-on {
    background: #1c3a28;
    border-color: #2f6a48;
    color: #86e0a8;
    font-weight: 600;
}

.sm-btn.is-switch-on:hover {
    background: #234c33;
    border-color: #3d8a5d;
}

.sm-btn.is-switch-unknown {
    opacity: .6;
}

/* ================= 选中玩家的状态条 ================= */

.sm-who {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 7px;
    margin: 10px 0 4px;
    padding: 9px 12px;
    background: var(--bg-soft);
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    font-size: 13px;
    min-height: 40px;
}

.sm-who b { color: var(--text); font-weight: 600; }

/* 状态小标签 */
.sm-tag {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 11.5px;
    line-height: 1.7;
    border: 1px solid transparent;
    white-space: nowrap;
}

.sm-tag.is-team { color: #8fb8e0; background: #17293c; border-color: #2a4560; }
.sm-tag.is-hp   { color: #d8c48a; background: #2b2617; border-color: #4a4028; }
.sm-tag.is-on   { color: #7fd8a0; background: #162c1d; border-color: #2c5138; }
.sm-tag.is-dead { color: #e09090; background: #331a1a; border-color: #572c2c; }
.sm-tag.is-idle { color: #b0a8d8; background: #24203a; border-color: #3d3760; }
.sm-tag.is-bot  { color: #a0a8b4; background: #22262c; border-color: #363c46; }

/* ================= 三个动作各自一行 ================= */

.sm-action {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 0;
    border-top: 1px solid var(--border-soft);
}

.sm-action:first-of-type { border-top: none; }

.sm-act-btn {
    flex: 0 0 auto;
    min-width: 150px;
}

.sm-act-hint {
    flex: 1 1 auto;
    font-size: 12.5px;
    color: var(--text-faint);
    line-height: 1.6;
}

@media (max-width: 720px) {
    .sm-action { flex-direction: column; align-items: stretch; gap: 6px; }
    .sm-act-btn { min-width: 0; width: 100%; }
}

/* ================= SM 页顶部：在线人数 ================= */

.sm-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    padding: 12px 16px;
}

.sm-head-info {
    font-size: 14px;
    color: var(--text-dim);
}

.sm-head-info b { color: var(--text); font-size: 16px; }
.sm-head-info b.is-human { color: #7fd8a0; }
.sm-head-info b.is-bot { color: #a0a8b4; }

.sm-head-map {
    font-size: 12.5px;
    color: var(--text-faint);
}

@media (max-width: 720px) {
    .sm-head { flex-direction: column; align-items: flex-start; gap: 6px; }
}

/* ================= 目标玩家卡片（页面顶部） ================= */

.sm-target-card {
    border-color: #2f5578;
}

/** 原来是个 11px 的 btn-mini，手指点起来太费劲， 桌面上也容易点空。 */
.btn-refresh {
    flex: 0 0 auto;
    min-width: 118px;
    padding: 9px 18px;
    font-size: 14px;
    font-weight: 600;
}

.sm-target-card .sm-opt-row {
    gap: 12px;
}

.sm-target-card .sm-opt-row .inp {
    flex: 1 1 auto;
    max-width: 460px;
}

@media (max-width: 720px) {
    .btn-refresh { width: 100%; min-width: 0; }
    .sm-target-card .sm-opt-row .inp { max-width: none; }
}

/* ================= SM 页：对抗模式禁用 ================= */

.sm-blocked {
    text-align: center;
    padding: 46px 26px;
    border-color: #6b3030;
    background: linear-gradient(180deg, #241618 0%, #1a1113 100%);
}

.sm-blocked-icon {
    font-size: 52px;
    line-height: 1;
    margin-bottom: 14px;
}

.sm-blocked h2 {
    color: #ff9a9a;
    margin: 0;
}

.sm-blocked .hint { text-align: left; max-width: 620px; margin-left: auto; margin-right: auto; }

/* ================= SM 页：进入确认弹窗 ================= */

.sm-enter-mask {
    position: fixed;
    inset: 0;
    background: rgba(6, 8, 12, .82);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    z-index: 9999;
    backdrop-filter: blur(3px);
}

.sm-enter-box {
    width: 100%;
    max-width: 520px;
    background: var(--bg-card);
    border: 1px solid #7d4a2a;
    border-radius: 14px;
    padding: 26px 26px 20px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, .55);
}

.sm-enter-box h3 {
    margin: 0 0 14px;
    font-size: 18px;
    color: #ffc78a;
}

.sm-enter-box p {
    margin: 0 0 12px;
    font-size: 13.5px;
    line-height: 1.9;
    color: var(--text-dim);
}

.sm-enter-box ul {
    margin: 0 0 14px;
    padding-left: 20px;
    font-size: 13px;
    line-height: 1.95;
    color: var(--text-dim);
}

.sm-enter-box ul b { color: #ffb0b0; }

.sm-enter-act {
    display: flex;
    gap: 10px;
    margin-top: 18px;
}

.sm-enter-act .btn { flex: 1 1 0; padding: 11px 16px; font-size: 14px; }

@media (max-width: 720px) {
    .sm-enter-act { flex-direction: column; }
    .sm-blocked { padding: 30px 18px; }
}

/* ================= SM 页：服务器信息 ================= */

.sm-srv { padding: 16px 18px; }

.sm-srv-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.sm-srv-state {
    font-size: 12px;
    padding: 2px 11px;
    border-radius: 999px;
    border: 1px solid transparent;
}

.sm-srv-state.is-on  { color: #7fd8a0; background: #162c1d; border-color: #2c5138; }
.sm-srv-state.is-off { color: #e09090; background: #331a1a; border-color: #572c2c; }

.sm-srv-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 12px;
}

.sm-srv-item { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.sm-srv-item .k { font-size: 11.5px; color: var(--text-faint); }
.sm-srv-item .v { font-size: 13.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sm-srv-item .v.mono { font-family: ui-monospace, Consolas, monospace; font-size: 12.5px; }

/* ================= SM 页：玩家名单 ================= */

.sm-who-list { display: flex; flex-direction: column; gap: 12px; }

.sm-who-group { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; }

.sm-who-group .g-label {
    flex: none;
    font-size: 12.5px;
    color: var(--text-faint);
    min-width: 96px;
}

.sm-who-group .g-count {
    font-weight: 700;
    font-size: 15px;
    margin-right: 2px;
}

.sm-who-group.is-human .g-count { color: #7fd8a0; }
.sm-who-group.is-bot   .g-count { color: #a8cbe8; }
.sm-who-group.is-si    .g-count { color: #e0a0a0; }

.sm-who-name {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 6px;
    background: var(--bg-soft);
    border: 1px solid var(--border-soft);
    font-size: 12.5px;
    color: var(--text-dim);
}

.sm-who-group.is-human .sm-who-name { color: #9fe0b8; border-color: #2c5138; background: #162c1d; }
.sm-who-group.is-bot   .sm-who-name { color: #a8cbe8; border-color: #2a4560; background: #17293c; }
.sm-who-group.is-si    .sm-who-name { color: #e8b0b0; border-color: #572c2c; background: #2b1a1a; }

@media (max-width: 720px) {
    .sm-srv-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .sm-who-group .g-label { min-width: 0; width: 100%; }
}

/* ================= 站长横幅：分行布局 ================= */

/** 小唯模式已启动 ← ① 身份 小唯模式 · 这就是开挂的力量吗 ← ② 介绍 今日密钥 ABC123 20:00更换 [立即更换] ← ③ 密钥 */


.master-strip {
    flex-wrap: wrap;
    align-items: center;
    row-gap: 8px;
}

/* ① 身份 + ② 介绍：各占一整行 */
.master-strip > b,
.master-strip > #masterStripSub,
.master-strip > span:not(.master-key):not(.strip-acts):not(.strip-logout) {
    flex: 1 1 100%;
    min-width: 0;
}

/* ③ 密钥那一行：整行，内部自己排 */
.master-strip .master-key {
    flex: 1 1 100%;
    margin-left: 0;
    flex-wrap: wrap;
    row-gap: 6px;
}

/** ④ 管理入口那一行：封禁管理 / 审计日志 / 退出 并排。 ★ 这里**不能**写 flex: 1 1 100% —— 那样它自己占满一整行，"退出"就被挤到下一行去了， 又变成对不齐。用自适应宽度，让退出能跟在后面。 */

.master-strip .strip-acts {
    flex: 1 1 100%;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
    margin: 0;
    opacity: 1;
}

/* 这一行里的按钮统一左对齐基线 */
.master-strip .strip-acts .btn-mini {
    margin-left: 0;
    align-self: center;
}

/** margin-left: auto 会把左边的空隙全吃掉 —— 「封禁管理」「审计日志」留在左边贴齐， 「退出」被顶到行尾，正好在整条横幅的右下角。 */
.master-strip .strip-acts .strip-logout {
    margin-left: auto;
    align-self: center;
}

/* 让这一行真的撑满横幅宽度，auto 才有空间可用 */
.master-strip .strip-acts {
    flex: 1 1 100%;
    justify-content: flex-start;
}

/** 退出按钮现在**已经在 .strip-acts 里面**了（HTML 层就放进去的）—— */
.master-strip > .strip-logout {
    flex: 0 0 auto;
    margin-left: 0;
}

/* 手机端再松一点，按钮别挤在一起 */
@media (max-width: 720px) {
    .master-strip .strip-acts { gap: 6px; }
    .master-strip .strip-acts .btn-mini { flex: 0 0 auto; }
}

/** 地图扫描提示：「正在扫描地图，请稍后…」 ★ 为什么需要这个： */
.scan-hint {
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 0 0 12px;
    padding: 9px 12px;
    border: 1px solid var(--border);
    /* 左边一道蓝杠：一眼看出这是"正在进行中"，不是报错 */
    border-left: 3px solid var(--accent-2);
    border-radius: 4px;
    background: var(--bg-3);
    color: var(--text-dim);
    font-size: 13px;
    line-height: 1.55;
}

/* 行首那个 ▸ （失败时换成 ✗） */
.scan-hint .scan-mark { color: var(--accent-2); }

/* 扫描失败：整条变红 —— 让用户分清"还在扫"和"扫挂了" */
.scan-hint.is-bad {
    border-left-color: var(--red);
    color: var(--red);
}

.scan-hint.is-bad .scan-mark { color: var(--red); }

/** 进页面时最先吐出来的那一条（见 server.php 里的"抢先输出"）。 */
.boot-scan-hint { margin: 22px 0 0; }

/** .scan-hint 是 display:flex，光靠 hidden 属性藏不住 */
.scan-hint[hidden] { display: none; }

/* ============================================================
   QQ 群（每个页面站点标题下面那一块 + 进站欢迎弹窗）
   ============================================================ */

/** 标题下方区块：不固定、不悬浮，跟着正文排 —— 盖不到任何内容。 */
.qq-card {
    margin-top: 18px;
    padding: 14px 16px;
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

/** ★ 它跟在**站点标题（.brand）正下方**，也就是 .topbar 的直接子元素（不在页脚了）：
    ① margin 归零 —— 上下间距交给 .topbar 的 gap，不然上面 14px、下面 14+18=32px，看着偏下；
    ② ★ 宽度**不限**：.topbar 的子元素都是 align-items: stretch，.brand / .stats /
       .master-strip / .row-act 全是铺满 .app 的内容宽（上限 1320 - 20×2 = 1280px）。
       这里跟着它们走，卡片左右两端才和上下那些块**齐平**（原来是 max-width: 560px，明显窄一截）。
       宽屏下内容横向铺开（见下面 min-width: 721px 那段），不会变成一根又高又空的怪条。 */
.topbar > .qq-card {
    margin: 0;
}

/** 群名就是区块标题，紧跟着的那一行才是群号。 */
.qq-title {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    word-break: break-word;
}

/* 群号紧跟标题，下面才是二维码 / 按钮 */
.qq-line { margin: 0 0 12px; font-size: 13px; color: var(--text-dim); text-align:center; }

/* 文字那一列允许被压缩（窄屏上是长群名 / 长链接先折行，而不是把二维码挤出去） */
.qq-info { min-width: 0; text-align: center; }

/* ★ 二维码在**左**、文字在中间：左列 auto（按二维码宽度），右列吃掉剩下的 */
.qq-main {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 18px;
    align-items: start;
}

/* ★ 把二维码排到前面（DOM 顺序不变，只改视觉顺序） */
.qq-qr { order: -1; }

.qq-head {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-bottom: 8px;
}

.qq-logo {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .5px;
    color: #dff0ff;
    background: linear-gradient(180deg, #3d8fd0, #2b6ca3);
    border-radius: 4px;
    padding: 2px 6px;
}

/* ★ 标题放大一档（原来是 14px，太小了） */
.qq-card h2 { margin: 0; font-size: 20px; font-weight: 600; }
/* 标题里放的是群名（可能很长），比"QQ 群"三个字更需要折行空间 */
.qq-card h2.qq-title { min-width: 0; font-size: 20px; line-height: 1.25; }

.qq-name { margin: 0 0 6px; font-size: 14px; font-weight: 600; color: #e8f0f8; word-break: break-word; }

.qq-line-cap { color: var(--text-faint); margin-right: 6px; }

.qq-line-inf { color: var(--text-faint); margin-left: 6px; }

/* 群号做成一枚按钮：样式像标签，但点一下就是"复制"，键盘也能按 */
.qq-num {
    font-family: Consolas, "Courier New", monospace;
    font-size: 14px;
    letter-spacing: .5px;
    color: var(--accent-2);
    background: var(--bg-3);
    border: 1px dashed var(--border);
    border-radius: 4px;
    padding: 2px 8px;
    cursor: pointer;
}

.qq-num:hover { border-color: var(--accent-2); background: #1b2836; }
.qq-num:active { transform: translateY(1px); }

.qq-copied { margin-left: 8px; font-size: 12px; color: var(--green); }
.qq-copied[hidden] { display: none; }

.qq-fallback { margin: 8px 0 0; }
.qq-fallback[hidden] { display: none; }

/* 复制不了的时候露出来的输入框：群号已经在里面选中了 */
.qq-sel { width: 100%; max-width: 260px; margin: 0 0 4px; font-family: Consolas, "Courier New", monospace; }

.qq-act { margin: 12px 0 0; }

.qq-url { margin: 10px 0 0; font-size: 12px; }
.qq-url code.mono { word-break: break-all; }

/* 二维码：白底，因为二维码本身是浅色的，深色底上扫不出来 */
.qq-qr img,
.qq-qr-miss {
    display: block;
    width: 116px;
    height: 116px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 6px;
}

/* 图片还没上传：白底占位 + 一行灰字，绝不出现破图 */
.qq-qr-miss {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    background: #101820;
    border-style: dashed;
    color: var(--text-faint);
    font-size: 12px;
    line-height: 1.5;
    padding: 6px;
    box-sizing: border-box;
}

/* 欢迎弹窗：正文比一般的确认框长一些，所以宽一点、能滚动 */
.cf-box-welcome { max-width: 440px; }
.cf-welcome { white-space: pre-wrap; }
.cf-box-welcome .cf-body p + p { margin-top: 10px; }
.cf-box-welcome .cf-body code.mono { font-size: 13px; }
/* 手机上「我知道了 / 加QQ群」各占一半，好点 */
.cf-box-welcome .cf-act .btn { flex: 1 1 0; }

/* ============================================================
   宽屏（≥721px）：把标题下面那块 QQ 卡片"压扁"
   ============================================================
   问题：卡片现在铺满整页宽（和 .brand / .stats 齐平），
        但里面的东西还是老排法 —— 群名、群号、按钮一竖列，二维码自己占一列压在下面，
        于是左边一大片空、右边一根 116px 的二维码，整块又高又空。

   办法：把 .qq-main 拆开（display: contents），让它里面的 .qq-info / .qq-qr
        直接参与 .qq-card 这个网格：
            ┌────────┬──────────────────────────────┐
            │        │ [QQ群] 群名                  │
            │ 二维码 │ 群号 362184232（点一下复制） │
            │ 96×96  │ [加QQ群]                     │
            └────────┴──────────────────────────────┘
        · 二维码放**左列**并跨满三行 → 卡片高度只剩"二维码 + 内边距"（约 124px，
          原来 ≈200px）；二维码紧挨着文字，不会甩到 1200px 外的另一头；
        · 尺寸 116 → 96px：整块矮一截，96px 在桌面上照样扫得清（手机端本来就不显示它）；
        · 行距 / 按钮上边距收紧，三行文字贴着二维码排。
   ★ 只对 .topbar > .qq-card 生效：login.php 里那块（.join-card 里的窄卡片）一点不变。 */
@media (min-width: 721px) {
    .topbar > .qq-card {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);   /* 左：二维码　右：文字 */
        grid-template-rows: repeat(3, auto);          /* 群名 / 群号 / 按钮 三行 */
        column-gap: 16px;
        row-gap: 6px;
        align-items: start;
        /* ★ 右列那三行一律居中（群名 / 群号 / 加群按钮） */
        justify-items: center;
    }

    /* ★ 标题那一行是 flex，居中由它自己管 */
    .topbar > .qq-card > .qq-head { justify-content: center; }

    /* .qq-main 只是个包装：拆掉它（display: contents），里面的两块直接落到上面的网格里。
       ★ 注意：display: contents 只改**盒子树**，DOM 树没变 —— 所以下面选 .qq-qr 时
         要用后代选择器（它的 DOM 父节点还是 .qq-main，不是 .qq-card）。 */
    .topbar > .qq-card > .qq-main { display: contents; }

    /* 二维码：左列、跨满三行、垂直居中 */
    .topbar > .qq-card .qq-qr {
        grid-column: 1;
        grid-row: 1 / span 3;
        align-self: center;
    }

    .topbar > .qq-card .qq-qr img,
    .topbar > .qq-card .qq-qr-miss {
        width: 96px;
        height: 96px;
    }

    /* 三行文字之间收紧一点，别把卡片顶高 */
    .topbar > .qq-card > .qq-head { margin-bottom: 0; }
    .topbar > .qq-card > .qq-line { margin-bottom: 0; }
    .topbar > .qq-card .qq-act { margin-top: 0; }
}

/* 手机上二维码换到下面一行 */
@media (max-width: 720px) {
    /* 标题下面那块：手机上一律铺满整行 */
    .topbar > .qq-card { max-width: none; }

    /** ★ 手机上**不显示二维码**（用户要求）：手机自己扫不了自己屏幕上的码，
        加群靠上面那个「加QQ群」按钮 / 复制群号。
        ★ 为什么用 CSS 藏、不在 lib/Qq.php 里不输出：
          同一份 HTML 桌面端还要显示这个码（服务端分不出"手机/桌面"，
          按 UA 猜也不可靠），display: none 一份 HTML 两套表现，最省事也最不会出错。
        ★ 连占位块 .qq-qr-miss（没上传二维码时那句"群二维码准备中"）一起藏。 */
    .qq-qr { display: none; }

    .qq-main { grid-template-columns: minmax(0, 1fr); }
    .qq-fallback .qq-sel { max-width: 100%; }
}

/* ============================================================
   管理入口 + QQ 群：**合并成一个区块**
   ============================================================
   ★ 顺序固定：访问密钥（上）→ 加群（下）。
   边框由外面 .join-card 一个人画，里面两块都不画 ——
   这样不管在宽屏还是手机上，它看着都是**一整块**，不是两张卡片。
*/

.join-card {
    width: 100%;
    max-width: 460px;
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;          /* 里面圆角/背景不会从边框里溢出来 */
}

/* 上半块：访问密钥。卡片外观交给外面 .join-card，这里只留内边距 */
.join-card .join-sec > .card {
    margin: 0;
    padding: 28px 26px 20px;
    border: none;
    border-radius: 0;
    background: none;
}

/* 下半块：QQ 群（顺序就在 HTML 里，这里只把它跟上半块连起来） */
.join-card .qq-card {
    margin: 0;
    border: none;
    border-top: 1px solid var(--border-soft);
    border-radius: 0;
    background: none;
}

/* 密钥块原来按"独立卡片"排的，合并之后这几处要跟着改 */
.join-card .gate-wrap { max-width: none; }
.join-card .gate-back { border-top: none; padding-top: 0; margin-top: 12px; }

/* ============================================================
   手机端（≤720px）：合并区块 + 群号 / 二维码 / 按钮全部改竖排
   ============================================================
   要解决的问题：
     · 左右两栏（文字 | 二维码）在手机上会挤成一团 → 一律竖排
     · 窄屏上任何东西都不许把页面撑出横向滚动条
     · 手指点得到：按钮和"点一下复制群号"都放大到 ≥44px
*/

@media (max-width: 720px) {

    /** ---- 合并区块：铺满屏宽，内边距收一点 ---- */
    .join-card {
        max-width: 100%;
        margin: 0;
        border-radius: 8px;
    }

    .join-card .gate-card { padding: 22px 16px 18px; }

    .join-card .qq-card { padding: 16px 16px 18px; }

    /** ---- 群号：标题下面的那一行，手机上也一样在标题下面 ---- */
    .qq-head { margin-bottom: 10px; }

    .qq-line {
        display: flex;                 /* 允许"群号"这枚按钮换行，不硬挤 */
        align-items: center;
        justify-content: center;       /* ★ flex 里 text-align 不管用，必须用这个才会居中 */
        flex-wrap: wrap;
        gap: 6px 8px;
        font-size: 13.5px;
        margin-bottom: 14px;
    }

    .qq-line-cap { margin-right: 0; }

    /* ★ 群号：手机上**不要**做得又高又胖 —— 保持正常字号，只把点击区留够 */
    .qq-num {
        font-size: 14px;
        padding: 0px 10px;
        min-height: 25px;
        display: inline-flex;
        align-items: center;
    }

    .qq-copied { margin-left: 0; font-size: 12.5px; }

    /** ---- 文字：竖排 ----
        （二维码手机上不显示，见上面「手机端不显示二维码」那条；
          所以这里不再有"二维码换到下一行 / 放大到 150px"的规则了） */
    .qq-main {
        grid-template-columns: minmax(0, 1fr);   /* 只有一列 = 竖排 */
        gap: 14px;
    }

    .qq-info { width: 100%; }

    /* 复制兜底那个输入框：整行宽，好长按 */
    .qq-fallback { margin-top: 10px; }
    .qq-fallback .qq-sel { max-width: 100%; height: 40px; }

    /* ★ 加群按钮：整行宽 + 44px 高，手机上一点就中 */
    .qq-act { margin-top: 14px; }
    .qq-act .btn {
        width: 100%;
        height: 44px;
        font-size: 15px;
    }

    /** ---- 上半块（密钥）也按手指尺寸来 ---- */
    .join-card .gate-title { font-size: 17px; }
    .join-card .gate-hint { font-size: 13px; margin-bottom: 14px; }

    /* 输入框和"进入"按钮都放大到 44px */
    .join-card .gate-input,
    .join-card .gate-captcha-input { height: 44px; font-size: 16px; }

    .join-card .gate-btn { height: 44px; font-size: 15px; }

    /* 验证码那一行：手机上图片也别把输入框挤没 */
    .join-card .gate-captcha-row { gap: 10px; }

    .join-card .gate-captcha { height: 44px; }

    .join-card .gate-foot { font-size: 12px; }

    /* 窄屏上别出现横向滚动条 —— 长群名 / 长链接一律折行 */
    .join-card .qq-title,
    .join-card .qq-url code.mono { word-break: break-word; overflow-wrap: anywhere; }
}

/* 很窄的手机（≤420px）：区块内边距再收一点
   （原来还有"二维码再小一号"两条，删了 —— 手机上整块二维码不显示，见上面）
   ★ 群号按钮这里**不再单独放大**：它会盖掉 ≤720px 那条"正常字号 + 小内边距"，
     结果窄屏上反而又高又胖。字号/内边距统一由上面 ≤720px 那条管。 */
@media (max-width: 420px) {
    .join-card .gate-card { padding: 20px 14px 16px; }
    .join-card .qq-card { padding: 14px 14px 16px; }
}

/* ============================================================
 * 页脚：logo（替代原本那行文字说明）+ 备案号
 * ============================================================ */

/* ★ logo 明暗两版叠在一起，靠主题切换显示哪一张 */
.foot .foot-brand {
    display: inline-flex;
    align-items: center;
    line-height: 0;
}

.foot .foot-logo {
    height: 26px;
    width: auto;
    display: block;
    opacity: .72;
    transition: opacity .18s;
}

.foot .foot-brand:hover .foot-logo { opacity: 1; }

.foot .foot-logo-dark { display: none; }

/* 深色主题（普拉娜 / 旧的 archive-dark）→ 换成白色版 logo */
html[data-theme="plana"] .foot .foot-logo-light,
html[data-theme="archive-dark"] .foot .foot-logo-light { display: none; }

html[data-theme="plana"] .foot .foot-logo-dark,
html[data-theme="archive-dark"] .foot .foot-logo-dark { display: block; }

/* 备案号：纯文字链接（法规要求：必须链接到 beian.miit.gov.cn） */
.foot .icp {
    color: var(--text-faint);
    text-decoration: none;
    font-size: 12px;
    transition: color .15s;
}

.foot .icp:hover {
    color: var(--accent-2);
    text-decoration: underline;
}

/* ---- 备案号：图片与文字统一 14px ---- */
.foot .foot-logo { height: 14px !important; width: auto; }
.foot .icp { display: inline-flex; align-items: center; gap: 4px; height: 14px; font-size: 12px; line-height: 14px; }
.foot .icp-badge { width: 14px !important; height: 14px !important; display: block; object-fit: contain; flex: none; }
.foot .icp-txt { white-space: nowrap; }

/* ============================================================
 * 页脚：三部分（ICP 左 · logo 中 · 公安 右）
 * ★ 所有东西统一 14px 高
 * ============================================================ */

.foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px 14px;
    position: relative;
}

/* 左右两块各自靠边 */
.foot .foot-left  { display: inline-flex; align-items: center; }
.foot .foot-right { display: inline-flex; align-items: center; }

/* ★ logo 居中（绝对居中，不受左右宽度影响） */
.foot .foot-brand {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    display: inline-flex;
    align-items: center;
    line-height: 0;
    pointer-events: none;
}

.foot .foot-logo {
    height: 14px;
    width: auto;
    display: block;
    opacity: .72;
    transition: opacity .18s;
}

.foot .foot-logo-dark { display: none; }

html[data-theme="plana"] .foot .foot-logo-light,
html[data-theme="archive-dark"] .foot .foot-logo-light { display: none; }

html[data-theme="plana"] .foot .foot-logo-dark,
html[data-theme="archive-dark"] .foot .foot-logo-dark { display: block; }

/* 备案号 */
.foot .icp {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 14px;
    font-size: 12px;
    line-height: 14px;
    color: var(--text-faint);
    text-decoration: none;
    transition: color .15s;
}

.foot .icp:hover { color: var(--accent-2); text-decoration: underline; }

.foot .icp-badge {
    width: 14px;
    height: 14px;
    display: block;
    object-fit: contain;
    flex: none;
}

.foot .icp-txt { white-space: nowrap; }

/* ★ 手机上 logo 不再绝对居中（会撞文字），改成换行居中 */
@media (max-width: 640px) {
    .foot { justify-content: center; text-align: center; }
    .foot .foot-brand {
        position: static;
        transform: none;
        order: -1;
        width: 100%;
        justify-content: center;
        margin-bottom: 2px;
    }
    .foot .foot-left, .foot .foot-right { justify-content: center; }
}
