大地图跟随机器人 + 可调图幅 - 爬取与显示区域改为以机器人当前位置为中心(bigMap.followBot 默认开启), 不再傻傻地爬世界原点周边 - 界面新增「图幅」下拉(±512/1024/2048/4096/8192/全世界)与「爬取周边」按钮, 只爬当前图幅内的瓦片:层级 0 每张覆盖 4096 格,±4096 只需 9 张,全世界要 100 张 - POST /api/bigmap/crawl 支持 centerX/centerZ/rangeBlocks;GET /api/bigmap 支持 rangeBlocks/bot 查询参数;启动预爬取会先等机器人进入世界再以其位置为中心 领土地图以机器人所在邦国为中心 - 之前初始视图用的是控制器的 playerChunk,而任务启动前它是 (0,0), 导致地图永远停在世界原点附近。现在按「机器人所在区块 → 包含它的邦国 → 该邦国王城/外接矩形」定位 定时重复发送消息(src/bot/scheduledMessenger.js) - 每个机器人可配多条定时任务,按固定间隔重复发送同一内容,如每 300 秒 /u restore confirm - 以 / 开头按游戏指令发送,否则按公屏消息发送 - 只在已连接且通过登录验证时发送;未就绪的周期顺延且不补发,避免重连后一次性连发 - 与指令节流队列共用,间隔下限 5 秒、单机器人最多 20 条 - 控制台新增「定时消息」卡片(新增/删除/启停 + 剩余秒数倒计时) 控制台界面重做 + 移动端适配 - 重新设计的深色主题:统一圆角、阴影、焦点态与悬停态,卡片式分层 - 响应式三档:≥1200px 三栏;≤1200px 两栏;≤820px 单栏 + 底部导航 - 移动端:触控目标 ≥36px、地图/日志高度按视口自适应、避让底部安全区、 横屏压矮地图、尊重「减少动效」偏好、Toast 全宽 - 「添加玩家」折叠进 details;顶栏窄屏自动换行且按钮等分 修复 - POST /api/bigmap/crawl 响应把中心与图幅字段传错(实际爬取正确,返回值显示成原点) - 定时任务保存后接口返回原始列表而非归一化结果,前端拿不到剩余秒数 测试 308 -> 325,全部通过。
510 行
18 KiB
CSS
510 行
18 KiB
CSS
/* ==========================================================================
|
|
AutoStore Bot 控制台样式
|
|
设计要点:
|
|
- 深色主题,卡片式布局,三层栅格(左状态 / 中地图日志 / 右配置)
|
|
- 响应式:≤1200px 收成两栏,≤820px 收成单栏并启用底部导航
|
|
- 移动端:触控目标 ≥ 36px、地图自适应高度、底部安全区避让
|
|
========================================================================== */
|
|
|
|
:root {
|
|
--bg: #0b0f16;
|
|
--bg-soft: #10151d;
|
|
--panel: #151b25;
|
|
--panel-2: #1b2230;
|
|
--panel-3: #212a3a;
|
|
--border: #2b3444;
|
|
--border-soft: #222a37;
|
|
--text: #d7dee8;
|
|
--text-dim: #9aa7b8;
|
|
--muted: #6b7787;
|
|
|
|
--accent: #e94560;
|
|
--accent-hover: #f2586f;
|
|
--accent-2: #3b8ef7;
|
|
--accent-2-hover: #5aa0f9;
|
|
--green: #3fb950;
|
|
--yellow: #d6a01f;
|
|
--red: #f85149;
|
|
--purple: #bc8cff;
|
|
|
|
--radius-sm: 6px;
|
|
--radius: 10px;
|
|
--radius-lg: 14px;
|
|
--shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 8px 24px -12px rgba(0, 0, 0, .5);
|
|
--gap: 12px;
|
|
--topbar-h: 58px;
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
|
|
html, body {
|
|
margin: 0;
|
|
padding: 0;
|
|
min-height: 100%;
|
|
background: radial-gradient(1200px 600px at 20% -10%, #16202e 0%, var(--bg) 55%);
|
|
color: var(--text);
|
|
font-family: "Segoe UI", "Microsoft YaHei", system-ui, -apple-system, "Helvetica Neue", sans-serif;
|
|
font-size: 14px;
|
|
line-height: 1.5;
|
|
-webkit-text-size-adjust: 100%;
|
|
}
|
|
|
|
.mono { font-family: Consolas, "Cascadia Mono", ui-monospace, monospace; }
|
|
.small { font-size: 12px; }
|
|
.hidden { display: none !important; }
|
|
.error-text { color: var(--red); }
|
|
|
|
/* ==================== 顶栏 ==================== */
|
|
.topbar {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 30;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
flex-wrap: wrap;
|
|
padding: 10px 16px;
|
|
background: rgba(16, 21, 29, .92);
|
|
backdrop-filter: blur(10px);
|
|
border-bottom: 1px solid var(--border-soft);
|
|
}
|
|
|
|
.brand { display: flex; align-items: center; gap: 11px; min-width: 0; }
|
|
.logo {
|
|
width: 36px; height: 36px;
|
|
display: grid; place-items: center;
|
|
border-radius: var(--radius);
|
|
background: linear-gradient(135deg, var(--accent), #b5324a);
|
|
color: #fff; font-weight: 700; letter-spacing: .5px;
|
|
box-shadow: 0 4px 14px -6px rgba(233, 69, 96, .9);
|
|
flex: 0 0 auto;
|
|
}
|
|
.brand-text { min-width: 0; }
|
|
.brand h1 { font-size: 15px; margin: 0; white-space: nowrap; }
|
|
.brand p { font-size: 11.5px; margin: 1px 0 0; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
|
|
.topbar-right { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
|
.badges { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
.topbar-actions { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
|
|
.badge {
|
|
padding: 3px 10px;
|
|
border-radius: 999px;
|
|
font-size: 11.5px;
|
|
border: 1px solid var(--border);
|
|
background: var(--panel-2);
|
|
white-space: nowrap;
|
|
}
|
|
.badge-online { color: var(--green); border-color: #1f6f34; background: rgba(63, 185, 80, .1); }
|
|
.badge-offline { color: var(--muted); }
|
|
.badge-running { color: var(--accent-2); border-color: #1f4f8f; background: rgba(59, 142, 247, .12); }
|
|
.badge-idle { color: var(--muted); }
|
|
.badge-error { color: var(--red); border-color: #8f2b26; }
|
|
|
|
/* ==================== 按钮 ==================== */
|
|
.btn {
|
|
padding: 6px 12px;
|
|
border-radius: var(--radius-sm);
|
|
border: 1px solid var(--border);
|
|
background: var(--panel-2);
|
|
color: var(--text);
|
|
cursor: pointer;
|
|
font-size: 13px;
|
|
font-family: inherit;
|
|
white-space: nowrap;
|
|
transition: background .15s, border-color .15s, transform .06s, opacity .15s;
|
|
}
|
|
.btn:hover:not(:disabled) { background: var(--panel-3); border-color: #3c4759; }
|
|
.btn:active:not(:disabled) { transform: translateY(1px); }
|
|
.btn:disabled { opacity: .55; cursor: not-allowed; }
|
|
.btn-primary { background: var(--accent-2); border-color: var(--accent-2); color: #fff; }
|
|
.btn-primary:hover:not(:disabled) { background: var(--accent-2-hover); border-color: var(--accent-2-hover); }
|
|
.btn-danger { background: rgba(248, 81, 73, .12); border-color: #7a2b34; color: #ff9aa2; }
|
|
.btn-danger:hover:not(:disabled) { background: rgba(248, 81, 73, .2); }
|
|
.btn-sm { padding: 4px 9px; font-size: 12px; }
|
|
.btn-block { width: 100%; }
|
|
.btn-grow { flex: 1 1 auto; }
|
|
|
|
/* ==================== 布局 ==================== */
|
|
.layout {
|
|
display: grid;
|
|
grid-template-columns: 320px minmax(420px, 1fr) 380px;
|
|
gap: var(--gap);
|
|
padding: var(--gap);
|
|
align-items: start;
|
|
}
|
|
.column { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; }
|
|
|
|
/* ==================== 卡片 ==================== */
|
|
.card {
|
|
background: linear-gradient(180deg, var(--panel) 0%, var(--bg-soft) 100%);
|
|
border: 1px solid var(--border-soft);
|
|
border-radius: var(--radius-lg);
|
|
padding: 13px;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
.card h2 {
|
|
font-size: 12px;
|
|
margin: 0 0 9px;
|
|
color: var(--text-dim);
|
|
text-transform: uppercase;
|
|
letter-spacing: .7px;
|
|
font-weight: 600;
|
|
}
|
|
.card-head {
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
gap: 8px; margin-bottom: 9px;
|
|
}
|
|
.card-head h2 { margin: 0; }
|
|
.card-head-wrap { flex-wrap: wrap; }
|
|
.row { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-top: 8px; }
|
|
.row-compact { margin-top: 6px; }
|
|
|
|
/* ==================== 键值表 ==================== */
|
|
.kv {
|
|
display: grid;
|
|
grid-template-columns: 92px 1fr;
|
|
gap: 4px 8px;
|
|
margin: 0;
|
|
font-size: 13px;
|
|
}
|
|
.kv dt { color: var(--muted); }
|
|
.kv dd { margin: 0; word-break: break-word; }
|
|
|
|
.progress {
|
|
margin-top: 10px; height: 6px; border-radius: 3px;
|
|
background: #080b11; overflow: hidden;
|
|
}
|
|
.progress-fill {
|
|
height: 100%; width: 0%;
|
|
background: linear-gradient(90deg, var(--accent-2), var(--green));
|
|
transition: width .25s;
|
|
}
|
|
|
|
.issues { margin: 8px 0 0; padding-left: 18px; color: var(--yellow); font-size: 12px; }
|
|
.issues li { margin-bottom: 3px; }
|
|
|
|
/* ==================== 机器人列表 ==================== */
|
|
.bot-list { display: flex; flex-direction: column; gap: 6px; }
|
|
.bot-item {
|
|
display: grid;
|
|
grid-template-columns: 10px minmax(0, 1fr) auto;
|
|
gap: 9px; align-items: center;
|
|
padding: 8px 10px;
|
|
border: 1px solid var(--border-soft);
|
|
border-radius: var(--radius);
|
|
background: var(--panel-2);
|
|
cursor: pointer;
|
|
transition: border-color .15s, background .15s;
|
|
}
|
|
.bot-item:hover { border-color: #3c4759; }
|
|
.bot-item.active { border-color: var(--accent-2); background: rgba(59, 142, 247, .08); }
|
|
.bot-item .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--muted); }
|
|
.bot-item .dot.online { background: var(--green); box-shadow: 0 0 8px rgba(63, 185, 80, .7); }
|
|
.bot-item .dot.connecting { background: var(--yellow); }
|
|
.bot-item .dot.offline { background: var(--red); }
|
|
.bot-item .dot.disabled { background: #454e5e; }
|
|
.bot-item .name { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.bot-item .sub { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.bot-item .meta { font-size: 11px; color: var(--muted); text-align: right; white-space: nowrap; }
|
|
.bot-item .remove {
|
|
margin-left: 6px; padding: 0 6px;
|
|
border: 1px solid var(--border); border-radius: 4px;
|
|
background: transparent; color: var(--muted); cursor: pointer;
|
|
font-size: 13px; line-height: 18px;
|
|
}
|
|
.bot-item .remove:hover { color: var(--red); border-color: #7a2b34; }
|
|
|
|
.add-bot { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--border); }
|
|
.add-bot summary {
|
|
cursor: pointer; font-size: 12.5px; color: var(--accent-2);
|
|
list-style: none; user-select: none;
|
|
}
|
|
.add-bot summary::-webkit-details-marker { display: none; }
|
|
.add-bot summary::before { content: '▸ '; }
|
|
.add-bot[open] summary::before { content: '▾ '; }
|
|
.add-bot .field { margin-top: 8px; }
|
|
.add-bot .hint { font-size: 11px; color: var(--muted); margin: 8px 0 0; }
|
|
|
|
/* ==================== 定时消息 ==================== */
|
|
.schedule-list { display: flex; flex-direction: column; gap: 6px; }
|
|
.schedule-item {
|
|
display: grid;
|
|
grid-template-columns: auto minmax(0, 1fr) auto auto;
|
|
gap: 8px; align-items: center;
|
|
padding: 7px 9px;
|
|
border: 1px solid var(--border-soft);
|
|
border-radius: var(--radius);
|
|
background: var(--panel-2);
|
|
font-size: 12.5px;
|
|
}
|
|
.schedule-item.off { opacity: .55; }
|
|
.schedule-item .content { min-width: 0; }
|
|
.schedule-item .content code {
|
|
display: block;
|
|
font-family: Consolas, ui-monospace, monospace;
|
|
color: var(--text);
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
}
|
|
.schedule-item .sub { font-size: 11px; color: var(--muted); }
|
|
.schedule-item .remove {
|
|
padding: 0 6px; border: 1px solid var(--border); border-radius: 4px;
|
|
background: transparent; color: var(--muted); cursor: pointer; line-height: 18px;
|
|
}
|
|
.schedule-item .remove:hover { color: var(--red); border-color: #7a2b34; }
|
|
.schedule-empty { font-size: 12px; color: var(--muted); padding: 4px 0; }
|
|
.schedule-editor {
|
|
margin-top: 10px; padding-top: 10px;
|
|
border-top: 1px dashed var(--border);
|
|
}
|
|
.schedule-editor .hint { font-size: 11px; color: var(--muted); margin: 6px 0 0; }
|
|
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
|
|
|
|
/* ==================== 地图 ==================== */
|
|
.card-map { display: flex; flex-direction: column; }
|
|
#mapCanvas {
|
|
width: 100%;
|
|
height: clamp(300px, 46vh, 520px);
|
|
background: #05070a;
|
|
border: 1px solid var(--border-soft);
|
|
border-radius: var(--radius);
|
|
display: block;
|
|
cursor: grab;
|
|
touch-action: none;
|
|
}
|
|
#mapCanvas:active { cursor: grabbing; }
|
|
.map-legend {
|
|
display: flex; gap: 12px; flex-wrap: wrap;
|
|
margin-top: 8px; font-size: 11.5px; color: var(--muted);
|
|
align-items: center;
|
|
}
|
|
.sw {
|
|
display: inline-block; width: 10px; height: 10px;
|
|
border-radius: 2px; margin-right: 4px; vertical-align: -1px;
|
|
}
|
|
.sw-self { background: #3b8ef7; }
|
|
.sw-session { background: #3fb950; }
|
|
.sw-flying { background: #f85149; }
|
|
.sw-target { background: #d6a01f; }
|
|
.sw-player { background: #ffffff; }
|
|
.sw-capital { background: #bc8cff; }
|
|
.sw-bot { background: #ffd33d; }
|
|
|
|
/* ==================== 日志 / 聊天 / 表格 ==================== */
|
|
.card-log { display: flex; flex-direction: column; }
|
|
.log-view {
|
|
height: clamp(220px, 34vh, 380px);
|
|
overflow-y: auto;
|
|
background: #05070a;
|
|
border: 1px solid var(--border-soft);
|
|
border-radius: var(--radius);
|
|
padding: 8px 10px;
|
|
font-family: Consolas, "Cascadia Mono", ui-monospace, monospace;
|
|
font-size: 12px;
|
|
line-height: 1.6;
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
overscroll-behavior: contain;
|
|
}
|
|
.log-line { display: block; }
|
|
.log-time { color: #55606f; margin-right: 6px; }
|
|
.log-info { color: var(--text); }
|
|
.log-warn { color: var(--yellow); }
|
|
.log-error { color: var(--red); }
|
|
.log-success { color: var(--green); }
|
|
|
|
.chat-line { display: block; }
|
|
.chat-time { color: #55606f; margin-right: 6px; }
|
|
.chat-bot { color: var(--accent-2); margin-right: 4px; }
|
|
.chat-user { color: var(--purple); margin-right: 4px; }
|
|
.chat-out { color: var(--green); }
|
|
.chat-command { color: var(--yellow); }
|
|
.chat-system { color: var(--text-dim); }
|
|
.chat-action { color: var(--muted); }
|
|
|
|
.log-table { white-space: normal; padding: 0; }
|
|
.exp-table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
|
.exp-table th {
|
|
position: sticky; top: 0; z-index: 1;
|
|
text-align: left; color: var(--text-dim); font-weight: 600;
|
|
background: #05070a; padding: 5px 7px;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
.exp-table td { padding: 3px 7px; border-bottom: 1px solid #10151d; white-space: nowrap; }
|
|
.exp-table tbody tr:hover { background: #0d1219; }
|
|
.exp-empty { color: var(--muted); padding: 8px; }
|
|
|
|
/* ==================== 表单 ==================== */
|
|
.card-config { display: flex; flex-direction: column; }
|
|
.config-scope { margin-bottom: 8px; }
|
|
.tabs { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: 9px; }
|
|
.tabs-inline { margin-bottom: 0; }
|
|
.tab {
|
|
padding: 4px 10px; font-size: 12px; cursor: pointer;
|
|
background: var(--panel-2); border: 1px solid var(--border-soft);
|
|
border-radius: 999px; color: var(--muted);
|
|
font-family: inherit;
|
|
transition: background .15s, color .15s, border-color .15s;
|
|
}
|
|
.tab:hover { color: var(--text); }
|
|
.tab.active { color: #fff; background: var(--accent-2); border-color: var(--accent-2); }
|
|
.config-body { max-height: min(58vh, 560px); overflow-y: auto; padding-right: 2px; }
|
|
|
|
.field { margin-bottom: 9px; }
|
|
.field label { display: block; font-size: 12px; color: var(--muted); margin-bottom: 3px; }
|
|
.field .hint { font-size: 11px; color: var(--muted); margin-top: 3px; line-height: 1.45; }
|
|
.input, select.input {
|
|
width: 100%; padding: 6px 9px;
|
|
background: #080b11; border: 1px solid var(--border);
|
|
border-radius: var(--radius-sm); color: var(--text); font-size: 13px;
|
|
font-family: inherit;
|
|
outline: none;
|
|
transition: border-color .15s, box-shadow .15s;
|
|
}
|
|
.input:focus { border-color: var(--accent-2); box-shadow: 0 0 0 3px rgba(59, 142, 247, .15); }
|
|
.field-inline { display: flex; align-items: center; gap: 6px; }
|
|
.field-inline input[type=checkbox] { width: 15px; height: 15px; accent-color: var(--accent-2); }
|
|
.field-label { font-size: 12px; color: var(--muted); white-space: nowrap; }
|
|
.input-sm { width: auto; min-width: 104px; padding: 4px 8px; font-size: 12px; }
|
|
.input-grow { flex: 1 1 120px; min-width: 0; width: auto; }
|
|
.group-title {
|
|
font-size: 12px; color: var(--accent-2);
|
|
margin: 13px 0 7px; padding-bottom: 4px;
|
|
border-bottom: 1px dashed var(--border);
|
|
font-weight: 600;
|
|
}
|
|
.group-title:first-child { margin-top: 0; }
|
|
|
|
.chk { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text-dim); cursor: pointer; }
|
|
.chk input[type=checkbox] { accent-color: var(--accent-2); }
|
|
|
|
/* ==================== 提示 ==================== */
|
|
.toast {
|
|
position: fixed; right: 16px; bottom: 16px;
|
|
background: var(--panel-3); border: 1px solid var(--border);
|
|
border-left: 3px solid var(--accent-2);
|
|
padding: 10px 14px; border-radius: var(--radius);
|
|
font-size: 13px; max-width: min(380px, calc(100vw - 32px));
|
|
opacity: 0; transform: translateY(8px);
|
|
transition: opacity .2s, transform .2s;
|
|
pointer-events: none;
|
|
z-index: 100;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
.toast.show { opacity: 1; transform: translateY(0); }
|
|
.toast.error { border-left-color: var(--red); }
|
|
|
|
/* ==================== 登录遮罩 ==================== */
|
|
.overlay {
|
|
position: fixed; inset: 0; z-index: 200;
|
|
display: grid; place-items: center;
|
|
padding: 16px;
|
|
background: rgba(5, 7, 10, .8);
|
|
backdrop-filter: blur(3px);
|
|
}
|
|
.overlay-box {
|
|
width: min(380px, 100%);
|
|
background: linear-gradient(180deg, var(--panel) 0%, var(--bg-soft) 100%);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-lg);
|
|
padding: 20px;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
.overlay-box h2 { font-size: 16px; margin: 0 0 6px; color: var(--text); text-transform: none; letter-spacing: 0; }
|
|
.overlay-box .input { margin: 12px 0; }
|
|
|
|
/* ==================== 移动端底部导航 ==================== */
|
|
.mobile-nav { display: none; }
|
|
|
|
/* ==================== 响应式 ==================== */
|
|
|
|
/* 中等屏幕:配置栏移到下方,两栏布局 */
|
|
@media (max-width: 1200px) {
|
|
.layout { grid-template-columns: minmax(280px, 320px) minmax(0, 1fr); }
|
|
.col-right { grid-column: 1 / -1; }
|
|
.col-right { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); align-items: start; }
|
|
.config-body { max-height: min(46vh, 460px); }
|
|
}
|
|
|
|
/* 平板 / 手机:单栏 + 底部导航 */
|
|
@media (max-width: 820px) {
|
|
:root { --gap: 10px; }
|
|
|
|
.topbar {
|
|
padding: 8px 12px;
|
|
gap: 8px;
|
|
align-items: center;
|
|
}
|
|
.brand p { display: none; }
|
|
.topbar-right { width: 100%; justify-content: space-between; }
|
|
.topbar-right .field-inline { flex: 1 1 100%; }
|
|
.topbar-right .field-inline select { flex: 1 1 auto; width: auto; }
|
|
.topbar-actions { width: 100%; }
|
|
.topbar-actions .btn { flex: 1 1 0; text-align: center; }
|
|
.badges { width: 100%; }
|
|
|
|
.layout {
|
|
grid-template-columns: 1fr;
|
|
padding: 10px 10px calc(64px + env(safe-area-inset-bottom, 0px));
|
|
}
|
|
.col-right { grid-column: auto; display: flex; }
|
|
|
|
/* 底部导航:把「状态 / 地图 / 日志 / 配置」四块一键定位 */
|
|
.mobile-nav {
|
|
display: flex;
|
|
position: fixed;
|
|
left: 0; right: 0; bottom: 0;
|
|
z-index: 40;
|
|
background: rgba(16, 21, 29, .96);
|
|
backdrop-filter: blur(10px);
|
|
border-top: 1px solid var(--border-soft);
|
|
padding-bottom: env(safe-area-inset-bottom, 0px);
|
|
}
|
|
.mobile-nav-item {
|
|
flex: 1 1 0;
|
|
padding: 11px 4px;
|
|
background: transparent;
|
|
border: none;
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
font-family: inherit;
|
|
cursor: pointer;
|
|
border-top: 2px solid transparent;
|
|
}
|
|
.mobile-nav-item.active { color: var(--accent-2); border-top-color: var(--accent-2); }
|
|
|
|
/* 触控目标放大 */
|
|
.btn { padding: 8px 13px; font-size: 13px; }
|
|
.btn-sm { padding: 6px 11px; font-size: 12.5px; }
|
|
.input, select.input { padding: 8px 10px; font-size: 14px; }
|
|
.input-sm { padding: 6px 9px; font-size: 12.5px; }
|
|
.tab { padding: 6px 12px; font-size: 12.5px; }
|
|
|
|
#mapCanvas { height: clamp(260px, 52vh, 420px); }
|
|
.log-view { height: clamp(240px, 46vh, 400px); font-size: 12.5px; }
|
|
.config-body { max-height: none; }
|
|
|
|
.card { padding: 12px; }
|
|
.kv { grid-template-columns: 84px 1fr; }
|
|
.toast { left: 12px; right: 12px; bottom: calc(64px + env(safe-area-inset-bottom, 0px)); max-width: none; }
|
|
}
|
|
|
|
@media (max-width: 420px) {
|
|
.brand h1 { font-size: 14px; }
|
|
.schedule-item { grid-template-columns: auto minmax(0, 1fr) auto; }
|
|
.schedule-item .next { display: none; }
|
|
.field-row { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
/* 横屏手机:地图压矮一点,避免看不到下面的日志 */
|
|
@media (max-height: 520px) and (orientation: landscape) {
|
|
#mapCanvas { height: 46vh; }
|
|
.log-view { height: 40vh; }
|
|
}
|
|
|
|
/* 尊重「减少动效」偏好 */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
* { transition: none !important; animation: none !important; }
|
|
}
|