Files
tamakyi a7408e2bb5 feat(theme): 全局装饰遮罩 + 尺寸统一;全局审阅修复对比度/暗色/平板布局
用户反馈的两点:
1. 遮罩看不出效果 → 人物与单车统一全局半透明 settings.decoOpacity(默认 .78)
   (此前 0.92/0.80 不一致且几乎无感),各自保留边缘渐隐
2. 切视图时人物比例变化 → 删掉卡片视图专用的 300px 高度,两种视图尺寸一致
3. 保留原始素材 → 原图归档 assets-src/,处理流程固化为 scripts/prepare-artwork.py

全局审阅发现并修复:
- 无障碍对比度:两套主题的状态色当文字用时远低于 AA(最低 2.56:1)→ 双色体系
  (填充色 ≥3:1 保持鲜亮 / 文字色 ≥4.5:1 同色系加深),暗色模式同步
- 暗色模式主题失效:顶栏/卡片/表头/分组行是硬编码白色 → 改为随模式切换的变量
- 平板竖屏 768px 表格需内部横滚 242px → 自动切卡片阈值 700 → 1024
- Cloudflare Worker 快照补齐 dataUpdatedAt/updateIntervalSec/dataFilter
- 清理失效 CSS(.logo .halo)

测试脚本修掉两个自身 bug(均为误报):color(srgb/…) 与半透明底的解析、
渐变背景被误判为透明。verify-views 新增对比度断言 8 条,四套合计 89 项全通过。
2026-10-13 21:55:44 +08:00

264 lines
10 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ============================================================
砂狼白子主题(shiroko)
真实素材(头像 / 立绘)来自社区数据库 SchaleDB,版权归 NEXON Games · Yostar;
其余装饰为自绘几何图形,均按其公开设定还原:
· 光环:倾斜的椭圆环 + 四方位带圆头的短杆(全息瞄准镜准星意象)
· 发饰:青色倒十字(旋转 45°)
· 围巾:天蓝色飘带(星野的信物)
· 座驾:公路车
仅在 body[data-theme="shiroko"] 下生效,不影响默认主题。
============================================================ */
body[data-theme="shiroko"] {
--bg: #eef7fd;
--surface: #ffffff;
--border: #d3e6f5;
--text: #17253d;
--text-2: #55708c;
--up: #0da093;
--up-text: #0e7c72;
--up-bg: #e4faf6;
--down: #e0524e;
--down-text: #c0362f;
--down-bg: #fdecec;
--pending: #c07d0d;
--pending-text: #8a5a00;
--pending-bg: #fff7e6;
--accent: #0e7490;
--uptime-ok: #0da093;
--uptime-warn: #c07d0d;
--uptime-bad: #e0524e;
--uptime-none: #dbe8f3;
--shadow: 0 1px 2px rgb(23 60 100 / 0.05), 0 10px 26px -20px rgb(23 60 100 / 0.35);
--sh-sky: #8fe0ff;
--sh-sky-deep: #2ea8dc;
--sh-navy: #1c2f4d;
/* 面板/表头/分组的底色与标题色随明暗模式切换(此前是硬编码浅色,暗色模式会「白顶栏 + 深页面」) */
--sh-panel-1: #ffffff;
--sh-panel-2: #f6fcff;
--sh-card-2: #fbfdff;
--sh-th-1: #f7fcff;
--sh-th-2: #eef7fd;
--sh-group: #eaf6fd;
--sh-title: #1c2f4d;
}
@media (prefers-color-scheme: dark) {
body[data-theme="shiroko"] {
--bg: #0a1622;
--surface: #101d2c;
--border: #1d3247;
--text: #e4eef7;
--text-2: #8ba6bf;
--up: #2fd4c2;
--up-text: #4fe0cf;
--up-bg: #0d2a2a;
--down: #f4736c;
--down-text: #f9a29c;
--down-bg: #2c1518;
--pending: #e8b344;
--pending-text: #f0c76a;
--pending-bg: #2a2113;
--accent: #55c2ef;
--uptime-ok: #2fd4c2;
--uptime-none: #1a2b3d;
--shadow: none;
--sh-panel-1: #14243a;
--sh-panel-2: #101d2c;
--sh-card-2: #0e1a27;
--sh-th-1: #16273c;
--sh-th-2: #101d2c;
--sh-group: #132437;
--sh-title: #e4eef7;
}
}
/* ---------- 背景:天蓝渐变 + 淡斜纹 ---------- */
body[data-theme="shiroko"] {
background-color: var(--bg);
background-image:
repeating-linear-gradient(135deg, rgb(46 168 220 / 4%) 0 1px, transparent 1px 9px),
radial-gradient(120% 60% at 50% -20%, rgb(143 224 255 / 26%), transparent 70%),
linear-gradient(180deg, rgb(255 255 255 / 70%), transparent 320px);
background-attachment: fixed;
}
/* 页脚下方空带:按官方造型还原的光环水印(倾斜椭圆环 + 四方位圆头短杆),
与左下角公路车、右下角立绘形成一条装饰带,互不遮挡 */
body[data-theme="shiroko"]::after {
content: "";
position: fixed;
left: 44%;
bottom: 0;
width: 330px;
height: 180px;
pointer-events: none;
z-index: 0;
opacity: 0.5;
background-repeat: no-repeat;
background-size: contain;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 130'><g stroke='%232ea8dc' stroke-opacity='0.11' fill='none' stroke-linecap='round'><ellipse cx='120' cy='64' rx='86' ry='38' stroke-width='11'/><ellipse cx='120' cy='70' rx='48' ry='21' stroke-width='6'/><g stroke-width='7'><line x1='22' y1='64' x2='6' y2='64'/><line x1='218' y1='64' x2='234' y2='64'/><line x1='120' y1='18' x2='120' y2='2'/><line x1='120' y1='110' x2='120' y2='126'/></g></g><g fill='%232ea8dc' fill-opacity='0.11'><circle cx='6' cy='64' r='4.6'/><circle cx='234' cy='64' r='4.6'/><circle cx='120' cy='2' r='4.6'/><circle cx='120' cy='126' r='4.6'/></g></svg>");
}
/* 左下角:简约风公路车插画(与人物同一套扁平风格) */
body[data-theme="shiroko"]::before {
content: "";
position: fixed;
left: 8px;
bottom: 2px;
width: 158px;
height: 93px;
pointer-events: none;
z-index: 0;
/* 全局半透明 + 两端渐隐,弱化「一块贴图」的突兀感 */
opacity: var(--sh-deco-opacity, 0.78);
filter: saturate(0.92);
mask-image: linear-gradient(180deg, transparent 0, #000 16%, #000 84%, transparent 100%);
-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 16%, #000 84%, transparent 100%);
background: url("shiroko-bike.webp") no-repeat center / contain;
}
/* ---------- 顶栏:天蓝到白 + 底部围巾飘带 ---------- */
body[data-theme="shiroko"] .topbar {
background: linear-gradient(180deg, var(--sh-panel-1) 0%, var(--sh-panel-2) 100%);
border-bottom: 0;
box-shadow: var(--shadow);
overflow: hidden;
}
body[data-theme="shiroko"] .topbar::after {
content: "";
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 12px;
background: url("deco-scarf.svg") repeat-x bottom left / 300px 12px;
pointer-events: none;
}
/* ---------- 品牌:真实头像 + 光环环 ---------- */
body[data-theme="shiroko"] .logo {
width: 34px;
height: 34px;
border-radius: 50%;
background: #eaf7ff url("shiroko-icon.webp") center / cover no-repeat;
box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--sh-sky-deep), 0 0 12px rgb(46 168 220 / 55%);
animation: avatar-halo 3.4s ease-out infinite;
}
@keyframes avatar-halo {
0% { box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--sh-sky-deep), 0 0 12px rgb(46 168 220 / 55%); }
65% { box-shadow: 0 0 0 2px #fff, 0 0 0 8px rgb(46 168 220 / 0%), 0 0 16px rgb(46 168 220 / 30%); }
100% { box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--sh-sky-deep), 0 0 12px rgb(46 168 220 / 55%); }
}
body[data-theme="shiroko"] .brand-text h1 {
color: var(--sh-title);
letter-spacing: 0.04em;
}
/* 分组标题前的青色倒十字发饰(旋转 45°) */
body[data-theme="shiroko"] .group-title::before,
body[data-theme="shiroko"] .group-row td::before {
content: "";
display: inline-block;
width: 11px;
height: 11px;
margin-right: 7px;
vertical-align: middle;
background-repeat: no-repeat;
background-size: contain;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><g transform='rotate(45 10 10)' fill='%232ea8dc'><rect x='8.5' y='0.5' width='3' height='19' rx='1.4'/><rect x='0.5' y='8.5' width='19' height='3' rx='1.4'/></g><circle cx='10' cy='10' r='2.6' fill='%23bfeaff'/></svg>");
}
/* ---------- 状态点 → 迷你光环 ---------- */
body[data-theme="shiroko"] [data-status="up"] { --sh-state: var(--up); }
body[data-theme="shiroko"] [data-status="down"] { --sh-state: var(--down); }
body[data-theme="shiroko"] [data-status="pending"] { --sh-state: var(--pending); }
body[data-theme="shiroko"] .dot {
width: 12px;
height: 12px;
background: transparent;
border: 2px solid var(--sh-state, var(--pending));
border-radius: 50%;
position: relative;
box-shadow: 0 0 7px -1px var(--sh-state, var(--pending));
}
body[data-theme="shiroko"] .dot::after {
content: "";
position: absolute;
inset: 2.5px;
border-radius: 50%;
background: var(--sh-state, var(--pending));
}
body[data-theme="shiroko"] .card[data-status="up"] .dot { animation: halo-pulse 2.6s ease-out infinite; }
@keyframes halo-pulse {
0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--up) 45%, transparent); }
70% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--up) 0%, transparent); }
100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--up) 0%, transparent); }
}
/* ---------- 卡片 / 表格 / 交互 ---------- */
body[data-theme="shiroko"] .card {
border-left-width: 3px;
background: linear-gradient(180deg, var(--sh-panel-1), var(--sh-card-2));
}
body[data-theme="shiroko"] .tab.active,
body[data-theme="shiroko"] .view-btn.active {
background: linear-gradient(135deg, var(--sh-sky-deep), #1b7fb4);
box-shadow: 0 3px 10px -4px rgb(46 168 220 / 70%);
}
body[data-theme="shiroko"] #refresh-btn:hover { border-color: var(--accent); color: var(--accent); }
body[data-theme="shiroko"] .monitor-table th {
background: linear-gradient(180deg, var(--sh-th-1), var(--sh-th-2));
color: var(--sh-title);
border-bottom: 1px solid var(--border);
}
body[data-theme="shiroko"] .monitor-table tbody tr:hover { background: rgb(46 168 220 / 6%); }
body[data-theme="shiroko"] .group-row td {
background: linear-gradient(90deg, var(--sh-group), var(--sh-th-1));
border-left: 3px solid var(--sh-sky-deep);
color: var(--sh-title);
}
body[data-theme="shiroko"] .table-wrap { box-shadow: var(--shadow); }
body[data-theme="shiroko"] .uptime-cell.lv-none {
background-image: repeating-linear-gradient(135deg, rgb(46 168 220 / 16%) 0 1px, transparent 1px 3px);
background-color: var(--uptime-none);
}
/* ---------- 刷新按钮的公路车轮加载态 ---------- */
body[data-theme="shiroko"] #refresh-btn .wheel { animation: wheel-spin 0.9s linear infinite; }
@keyframes wheel-spin { to { transform: rotate(360deg); } }
/* ---------- 简约风立绘(settings.artwork,默认指向内置形象) ---------- */
/* --sh-deco-opacity 由面板按 settings.decoOpacity 注入,人物与单车共用同一个值 */
body[data-theme="shiroko"] .artwork {
position: fixed;
right: 10px;
bottom: 0;
width: auto;
height: min(40vh, 340px);
z-index: 0;
pointer-events: none;
user-select: none;
/* 全局半透明(整张图统一淡化)+ 上下渐隐,读起来是背景插画而不是贴上去的贴纸 */
opacity: var(--sh-deco-opacity, 0.78);
filter: drop-shadow(0 6px 18px rgb(23 60 100 / 10%));
mask-image: linear-gradient(180deg, transparent 0, #000 4%, #000 92%, rgb(0 0 0 / 45%) 100%);
-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 4%, #000 92%, rgb(0 0 0 / 45%) 100%);
}
/* 窄屏:立绘与固定装饰全部撤掉,避免压住内容或溢出(手机只保留配色与围巾飘带) */
@media (max-width: 820px) {
body[data-theme="shiroko"] .artwork,
body[data-theme="shiroko"]::before,
body[data-theme="shiroko"]::after { display: none; }
}
/* 横屏手机:可用高度很小,立绘同样撤掉 */
@media (max-height: 520px) {
body[data-theme="shiroko"] .artwork { display: none; }
}
/* 注:立绘尺寸在卡片/表格两种视图下必须保持一致,不再按视图改高度 */
/* 内容层置于装饰之上 */
body[data-theme="shiroko"] .grid,
body[data-theme="shiroko"] .footer,
body[data-theme="shiroko"] .group-tabs { position: relative; z-index: 1; }