mirror of
https://github.com/Silentely/eSIM-Tools.git
synced 2026-09-03 06:24:20 +08:00
✨ style: 优化前端 UI 流畅度、视觉层次与暗色模式
统一 motion token,拆分步骤 completed/active 与进度轨,弱化表单卡上浮 与无限呼吸动画;首页改中性 mesh 背景,补齐三页暗色与通知 safe-area。
This commit is contained in:
197
index.html
197
index.html
@@ -2,7 +2,8 @@
|
||||
<html lang="zh-CN" data-page="home">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<meta name="description" content="eSIM 设备管理工具集,支持已有 Giffgaff 与 Simyo 号码的 eSIM 转换、设备更换、二维码生成及验证码处理。">
|
||||
|
||||
<!-- Sentry 错误监控配置(必须在其他脚本之前) -->
|
||||
@@ -95,36 +96,38 @@
|
||||
--accent-warn:#f59e0b; /* amber-500 */
|
||||
--accent-danger:#ef4444; /* red-500 */
|
||||
|
||||
/* Surface & Text */
|
||||
/* 背景改为淡色 #f2f5c4 */
|
||||
--bg-grad-start:#f2f5c4;
|
||||
--bg-grad-end:#f1f5bb;
|
||||
/* Surface & Text:中性 indigo/slate,替代旧黄绿背景 */
|
||||
--bg-grad-start:#eef2ff;
|
||||
--bg-grad-end:#f8fafc;
|
||||
--surface:#ffffff;
|
||||
--surface-alpha:92%;
|
||||
--surface-alpha:94%;
|
||||
--text-primary:#1f2937; /* slate-800 */
|
||||
--text-secondary:#374151; /* gray-700 */
|
||||
--text-muted:#6b7280; /* gray-500 */
|
||||
|
||||
/* Radius & Elevation & Spacing */
|
||||
--radius-lg:18px;
|
||||
--shadow-sm:0 4px 10px rgba(0,0,0,.08);
|
||||
--shadow-md:0 10px 30px rgba(0,0,0,.10);
|
||||
--shadow-lg:0 18px 40px rgba(0,0,0,.15);
|
||||
--shadow-sm:0 4px 12px rgba(15,23,42,.06);
|
||||
--shadow-md:0 10px 28px rgba(15,23,42,.08);
|
||||
--shadow-lg:0 22px 50px rgba(15,23,42,.10);
|
||||
--ring:0 0 0 3px rgba(99,102,241,.35);
|
||||
|
||||
--s1:8px; --s2:12px; --s3:16px; --s4:20px; --s5:24px; --s6:32px;
|
||||
|
||||
/* Motion */
|
||||
/* Motion:与 design-system 对齐 */
|
||||
--ease-standard:cubic-bezier(.2,.8,.2,1);
|
||||
--duration-fast:.18s;
|
||||
--duration-normal:.28s;
|
||||
--duration-fast:160ms;
|
||||
--duration-normal:240ms;
|
||||
}
|
||||
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
|
||||
body{
|
||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, 'Helvetica Neue', Arial, 'Noto Sans', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
||||
background: linear-gradient(135deg, var(--bg-grad-start) 0%, var(--bg-grad-end) 100%);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
||||
background:
|
||||
radial-gradient(1100px 560px at 8% -8%, rgba(99,102,241,.14), transparent 58%),
|
||||
radial-gradient(900px 480px at 100% 0%, rgba(139,92,246,.10), transparent 52%),
|
||||
linear-gradient(160deg, var(--bg-grad-start) 0%, var(--bg-grad-end) 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -135,15 +138,15 @@
|
||||
|
||||
.main-container{
|
||||
background: color-mix(in oklab, white var(--surface-alpha), transparent);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(14px);
|
||||
backdrop-filter: blur(14px);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: clamp(20px, 4vw, 40px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
max-width: 960px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
border: 1px solid color-mix(in oklab, white 70%, transparent);
|
||||
border: 1px solid color-mix(in oklab, white 78%, rgba(99,102,241,.18));
|
||||
}
|
||||
|
||||
.language-switcher{
|
||||
@@ -159,15 +162,18 @@
|
||||
padding:6px 16px;
|
||||
border-radius:999px;
|
||||
border:1px solid rgba(99,102,241,.25);
|
||||
background: rgba(255,255,255,.7);
|
||||
background: rgba(255,255,255,.75);
|
||||
color: var(--text-primary);
|
||||
font-weight:600;
|
||||
cursor:pointer;
|
||||
transition: transform var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
|
||||
transition: transform var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard);
|
||||
}
|
||||
.lang-switch:hover{
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-sm);
|
||||
@media (hover: hover){
|
||||
.lang-switch:hover{
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-sm);
|
||||
background: rgba(255,255,255,.92);
|
||||
}
|
||||
}
|
||||
.lang-switch:focus-visible{
|
||||
outline:none;
|
||||
@@ -205,19 +211,19 @@
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
border-radius: 999px;
|
||||
transition: transform var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);
|
||||
transition: transform var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard);
|
||||
gap: 8px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
text-decoration: none !important;
|
||||
outline: none;
|
||||
will-change: transform;
|
||||
border: 1px solid rgba(255,255,255,.18);
|
||||
}
|
||||
.github-btn{ background: #24292e; color:#fff !important; }
|
||||
.github-btn:hover{ transform: translateY(-1px); box-shadow: var(--shadow-md); background:#111; }
|
||||
|
||||
.kofi-btn{ background: #FF5E5B; color:#fff !important; }
|
||||
.kofi-btn:hover{ transform: translateY(-1px); box-shadow: var(--shadow-md); background:#e64a47; }
|
||||
@media (hover: hover){
|
||||
.github-btn:hover{ transform: translateY(-1px); box-shadow: var(--shadow-md); background:#111; }
|
||||
.kofi-btn:hover{ transform: translateY(-1px); box-shadow: var(--shadow-md); background:#e64a47; }
|
||||
}
|
||||
|
||||
.github-btn:focus-visible, .kofi-btn:focus-visible{ outline: none; box-shadow: var(--ring); }
|
||||
|
||||
@@ -230,15 +236,14 @@
|
||||
@media (max-width: 720px){ .tools-grid{ grid-template-columns: 1fr; } }
|
||||
|
||||
.tool-card{
|
||||
background: var(--surface);
|
||||
background: color-mix(in oklab, var(--surface) 96%, transparent);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: clamp(20px, 3.2vw, 28px);
|
||||
box-shadow: var(--shadow-md);
|
||||
transition: transform var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
|
||||
border: 2px solid transparent;
|
||||
transition: transform var(--duration-normal) var(--ease-standard), box-shadow var(--duration-normal) var(--ease-standard), border-color var(--duration-normal) var(--ease-standard);
|
||||
border: 1px solid color-mix(in oklab, var(--primary) 12%, transparent);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
will-change: transform, box-shadow;
|
||||
}
|
||||
.tool-card::before{
|
||||
content: '';
|
||||
@@ -247,12 +252,14 @@
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, var(--primary), var(--secondary));
|
||||
}
|
||||
.tool-card:hover{
|
||||
transform: translateY(-6px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
border-color: color-mix(in oklab, var(--primary) 40%, transparent);
|
||||
@media (hover: hover){
|
||||
.tool-card:hover{
|
||||
transform: translateY(-4px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
border-color: color-mix(in oklab, var(--primary) 36%, transparent);
|
||||
}
|
||||
}
|
||||
.tool-card:focus-within{ box-shadow: var(--ring); }
|
||||
.tool-card:focus-within{ box-shadow: var(--ring), var(--shadow-md); }
|
||||
|
||||
/* 品牌色注入 */
|
||||
.giffgaff-card{ --primary:#ff6b00; --secondary:#ff8c42; }
|
||||
@@ -304,12 +311,14 @@
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
transition: transform var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard), filter var(--duration-fast) var(--ease-standard);
|
||||
box-shadow: 0 6px 16px color-mix(in oklab, var(--primary) 35%, transparent);
|
||||
box-shadow: 0 6px 16px color-mix(in oklab, var(--primary) 32%, transparent);
|
||||
outline: none;
|
||||
will-change: transform, filter;
|
||||
}
|
||||
.tool-btn:hover{ transform: translateY(-2px); text-decoration: none; color: #fff; filter: brightness(1.03); }
|
||||
@media (hover: hover){
|
||||
.tool-btn:hover{ transform: translateY(-2px); text-decoration: none; color: #fff; filter: brightness(1.04); box-shadow: 0 10px 22px color-mix(in oklab, var(--primary) 38%, transparent); }
|
||||
}
|
||||
.tool-btn:focus-visible{ box-shadow: var(--ring); }
|
||||
.tool-btn:active{ transform: scale(0.98); }
|
||||
|
||||
.footer{
|
||||
margin-top: var(--s6);
|
||||
@@ -322,13 +331,13 @@
|
||||
}
|
||||
|
||||
/* 入场动画:IntersectionObserver 触发,避免 setTimeout 抖动 */
|
||||
.reveal{ opacity: 0; transform: translateY(12px); transition: opacity .5s var(--ease-standard), transform .5s var(--ease-standard); will-change: opacity, transform; }
|
||||
.reveal{ opacity: 0; transform: translateY(12px); transition: opacity var(--duration-normal) var(--ease-standard), transform var(--duration-normal) var(--ease-standard); }
|
||||
.reveal.show{ opacity: 1; transform: translateY(0); }
|
||||
|
||||
/* 降低动效:尊重用户的减少动态偏好 */
|
||||
@media (prefers-reduced-motion: reduce){
|
||||
.reveal{ transition: none; transform: none; opacity: 1; }
|
||||
.tool-card, .github-btn, .tool-btn{ transition: none!important; }
|
||||
.tool-card, .github-btn, .kofi-btn, .tool-btn, .lang-switch{ transition: none!important; }
|
||||
}
|
||||
|
||||
/* 小屏进一步优化 */
|
||||
@@ -524,6 +533,12 @@
|
||||
background: var(--surface);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
border: 1px solid color-mix(in oklab, var(--brand-start) 10%, transparent);
|
||||
transition: box-shadow var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
|
||||
}
|
||||
.faq-item[open]{
|
||||
border-color: color-mix(in oklab, var(--brand-start) 22%, transparent);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
.faq-item summary{
|
||||
padding: var(--s3) var(--s4);
|
||||
@@ -531,16 +546,25 @@
|
||||
font-size: .95rem;
|
||||
color: var(--text-primary);
|
||||
cursor: pointer;
|
||||
transition: background var(--duration-fast) var(--ease-standard);
|
||||
list-style: none;
|
||||
transition: background-color var(--duration-fast) var(--ease-standard);
|
||||
}
|
||||
.faq-item summary:hover{
|
||||
background: color-mix(in oklab, var(--brand-start) 5%, transparent);
|
||||
.faq-item summary::-webkit-details-marker{ display: none; }
|
||||
@media (hover: hover){
|
||||
.faq-item summary:hover{
|
||||
background: color-mix(in oklab, var(--brand-start) 6%, transparent);
|
||||
}
|
||||
}
|
||||
.faq-item p{
|
||||
padding: 0 var(--s4) var(--s3);
|
||||
font-size: .9rem;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
animation: section-enter var(--duration-normal) var(--ease-standard) both;
|
||||
}
|
||||
@keyframes section-enter{
|
||||
from{ opacity: 0; transform: translateY(8px); }
|
||||
to{ opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
/* 安全声明 */
|
||||
@@ -580,11 +604,94 @@
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* ===== 暗色模式 ===== */
|
||||
@media (prefers-color-scheme: dark){
|
||||
:root{
|
||||
--bg-grad-start:#0f1220;
|
||||
--bg-grad-end:#0b0d14;
|
||||
--surface:#1a1d2a;
|
||||
--surface-alpha:88%;
|
||||
--text-primary:#e8eaf0;
|
||||
--text-secondary:#c4c9d4;
|
||||
--text-muted:#9aa3b2;
|
||||
--shadow-sm:0 4px 12px rgba(0,0,0,.35);
|
||||
--shadow-md:0 10px 28px rgba(0,0,0,.4);
|
||||
--shadow-lg:0 22px 50px rgba(0,0,0,.5);
|
||||
--ring:0 0 0 3px rgba(129,140,248,.4);
|
||||
}
|
||||
|
||||
body{
|
||||
background:
|
||||
radial-gradient(1100px 560px at 8% -8%, rgba(99,102,241,.18), transparent 58%),
|
||||
radial-gradient(900px 480px at 100% 0%, rgba(139,92,246,.12), transparent 52%),
|
||||
linear-gradient(160deg, var(--bg-grad-start) 0%, var(--bg-grad-end) 100%);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.main-container{
|
||||
background: color-mix(in oklab, #161926 var(--surface-alpha), transparent);
|
||||
border-color: color-mix(in oklab, white 12%, rgba(99,102,241,.2));
|
||||
}
|
||||
|
||||
.lang-switch{
|
||||
background: rgba(255,255,255,.08);
|
||||
border-color: rgba(165,180,252,.3);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
@media (hover: hover){
|
||||
.lang-switch:hover{ background: rgba(255,255,255,.12); }
|
||||
}
|
||||
|
||||
.tool-card{
|
||||
background: color-mix(in oklab, var(--surface) 96%, transparent);
|
||||
border-color: color-mix(in oklab, var(--primary) 22%, transparent);
|
||||
}
|
||||
|
||||
.compat-card,
|
||||
.tutorial-card,
|
||||
.region-card,
|
||||
.glossary-item,
|
||||
.faq-item,
|
||||
.disclaimer-item{
|
||||
background: var(--surface);
|
||||
border-color: color-mix(in oklab, var(--brand-start) 18%, transparent);
|
||||
}
|
||||
|
||||
.compat-check{
|
||||
background: color-mix(in oklab, var(--accent-ok) 14%, transparent);
|
||||
}
|
||||
.compat-check code{
|
||||
background: rgba(255,255,255,.08);
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.compare-table{
|
||||
background: var(--surface);
|
||||
}
|
||||
.compare-table th{
|
||||
background: color-mix(in oklab, var(--brand-start) 18%, transparent);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.compare-table td{
|
||||
border-bottom-color: rgba(255,255,255,.06);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.footer{
|
||||
border-top-color: rgba(255,255,255,.08);
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.tutorial-note{
|
||||
background: color-mix(in oklab, var(--accent-warn) 14%, transparent);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Google tag (gtag.js) 延迟加载 -->
|
||||
<script type="module" src="/src/js/captcha-client.js"></script>
|
||||
<script defer src="https://www.googletagmanager.com/gtag/js?id=G-HGX38HMNL1" crossorigin="anonymous"></script></script>
|
||||
<script defer src="https://www.googletagmanager.com/gtag/js?id=G-HGX38HMNL1" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body aria-label="eSIM 工具选择">
|
||||
<div class="main-container" role="region" aria-label="eSIM 工具选择">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="zh-CN" data-page="giffgaff">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<meta name="description" content="Giffgaff eSIM 工具,支持 OAuth 登录、MFA 验证、二维码生成与设备更换。">
|
||||
|
||||
|
||||
@@ -97,18 +97,40 @@ export class UIController {
|
||||
* 更新步骤指示器
|
||||
*/
|
||||
updateSteps(currentStep) {
|
||||
this.elements.steps.forEach((step, index) => {
|
||||
const steps = this.elements.steps;
|
||||
const total = steps.length;
|
||||
|
||||
steps.forEach((step, index) => {
|
||||
const stepNo = index + 1;
|
||||
if (stepNo <= currentStep) {
|
||||
step.classList.remove('active', 'completed');
|
||||
|
||||
if (stepNo < currentStep) {
|
||||
step.classList.add('completed');
|
||||
step.style.cursor = 'pointer';
|
||||
step.title = tl('点击返回此步骤');
|
||||
step.setAttribute('aria-current', 'false');
|
||||
} else if (stepNo === currentStep) {
|
||||
step.classList.add('active');
|
||||
step.style.cursor = 'pointer';
|
||||
step.title = stepNo < currentStep ? tl('点击返回此步骤') : '';
|
||||
step.title = '';
|
||||
step.setAttribute('aria-current', 'step');
|
||||
} else {
|
||||
step.classList.remove('active');
|
||||
step.style.cursor = 'not-allowed';
|
||||
step.title = tl('请按顺序完成前序步骤');
|
||||
step.setAttribute('aria-current', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
// 进度轨:已完成区间占比(1 步时为 0,末步为 1)
|
||||
const indicator = steps[0] && steps[0].closest
|
||||
? steps[0].closest('.step-indicator')
|
||||
: null;
|
||||
if (indicator && total > 1) {
|
||||
const progress = Math.max(0, Math.min(1, (currentStep - 1) / (total - 1)));
|
||||
indicator.style.setProperty('--step-progress', String(progress));
|
||||
} else if (indicator) {
|
||||
indicator.style.setProperty('--step-progress', currentStep > 0 ? '1' : '0');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,96 +45,68 @@
|
||||
60% { transform: translateY(-3px); }
|
||||
}
|
||||
|
||||
/* ===== 服务时间动画 ===== */
|
||||
/* ===== 服务时间动画(仅 opacity / 阴影,禁止 scale 以降低干扰与耗电) ===== */
|
||||
@keyframes breathing-light {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 5px rgba(220, 38, 38, 0.3);
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.25);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 20px rgba(220, 38, 38, 0.6);
|
||||
transform: scale(1.05);
|
||||
opacity: 0.92;
|
||||
box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.12);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes breathing-light-orange {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 5px rgba(245, 158, 11, 0.3);
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.25);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 20px rgba(245, 158, 11, 0.6);
|
||||
transform: scale(1.05);
|
||||
opacity: 0.92;
|
||||
box-shadow: 0 0 0 4px rgba(245, 158, 11, 0.12);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes breathing-light-green {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 5px rgba(22, 163, 74, 0.3);
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 20px rgba(22, 163, 74, 0.6);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.88; }
|
||||
}
|
||||
|
||||
@keyframes breathing-light-purple {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 5px rgba(99, 102, 241, 0.3);
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 20px rgba(99, 102, 241, 0.6);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.88; }
|
||||
}
|
||||
|
||||
/* 警告:轻微 opacity,不再缩放 */
|
||||
@keyframes warning-pulse {
|
||||
0%, 100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.85; }
|
||||
}
|
||||
|
||||
@keyframes success-bounce {
|
||||
0%, 100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
25% {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
75% {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.9; }
|
||||
}
|
||||
|
||||
@keyframes pulse-glow {
|
||||
0%, 100% {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 4px 16px rgba(99, 102, 241, 0.3);
|
||||
box-shadow: 0 4px 14px rgba(99, 102, 241, 0.18);
|
||||
}
|
||||
}
|
||||
|
||||
/* 时间数字更新:一次轻触反馈,由 JS 触发类名时使用 */
|
||||
@keyframes time-update {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
0% { opacity: 0.7; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes time-breathe {
|
||||
0%, 100% { transform: translateZ(0) scale(1); }
|
||||
50% { transform: translateZ(0) scale(1.02); }
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.92; }
|
||||
}
|
||||
|
||||
@keyframes modalSlideIn {
|
||||
@@ -144,5 +116,20 @@
|
||||
|
||||
/* ===== 服务时间图标过渡 ===== */
|
||||
#serviceTimeIcon {
|
||||
transition: all 0.3s ease;
|
||||
transition:
|
||||
color var(--transition-base, 240ms ease),
|
||||
transform var(--transition-base, 240ms ease),
|
||||
opacity var(--transition-base, 240ms ease);
|
||||
}
|
||||
|
||||
/* 步骤内容进入(与 design-system / animations 对齐的本地兜底) */
|
||||
@keyframes section-enter {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ body {
|
||||
color: #212529;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
font-family: var(--font-sans, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,10 @@ textarea, input {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: #212529;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s ease;
|
||||
transition:
|
||||
border-color var(--transition-base, 240ms ease),
|
||||
box-shadow var(--transition-base, 240ms ease),
|
||||
background-color var(--transition-base, 240ms ease);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -77,21 +80,24 @@ textarea:focus, input:focus {
|
||||
background: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
/* 卡片样式 */
|
||||
/* 卡片样式:内容卡仅微调阴影,避免填表时大幅上浮 */
|
||||
.card {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(255, 204, 0, 0.3);
|
||||
box-shadow: 0 4px 25px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||
margin-bottom: 30px;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
transition:
|
||||
box-shadow var(--transition-base, 240ms ease),
|
||||
border-color var(--transition-base, 240ms ease);
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
|
||||
border: 1px solid rgba(255, 204, 0, 0.5);
|
||||
@media (hover: hover) {
|
||||
.card:hover {
|
||||
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.1);
|
||||
border-color: rgba(255, 204, 0, 0.45);
|
||||
}
|
||||
}
|
||||
|
||||
.card-header {
|
||||
@@ -132,4 +138,107 @@ textarea:focus, input:focus {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* ===== 暗色模式 ===== */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--secondary: #1e1e1e;
|
||||
--light: #1a1a1a;
|
||||
--dark: #e9ecef;
|
||||
--gray: #adb5bd;
|
||||
--st-muted: #94a3b8;
|
||||
--st-strong: #f1f5f9;
|
||||
--st-card-shadow: 0 8px 28px rgba(0, 0, 0, 0.4);
|
||||
--st-soft-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
--st-border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
body {
|
||||
background: linear-gradient(135deg, #1a1610 0%, #12100c 45%, #0c0b09 100%);
|
||||
color: #e9ecef;
|
||||
}
|
||||
|
||||
textarea,
|
||||
input {
|
||||
background: rgba(30, 30, 30, 0.92);
|
||||
color: #e9ecef;
|
||||
border-color: rgba(255, 204, 0, 0.28);
|
||||
}
|
||||
|
||||
textarea:focus,
|
||||
input:focus {
|
||||
background: rgba(36, 36, 36, 1);
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 4px rgba(255, 204, 0, 0.15);
|
||||
}
|
||||
|
||||
.card {
|
||||
background: rgba(30, 30, 30, 0.92);
|
||||
border-color: rgba(255, 204, 0, 0.22);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
.card:hover {
|
||||
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
|
||||
border-color: rgba(255, 204, 0, 0.38);
|
||||
}
|
||||
}
|
||||
|
||||
.card-header {
|
||||
background: rgba(255, 204, 0, 0.1);
|
||||
color: #f8f9fa;
|
||||
border-bottom-color: rgba(255, 204, 0, 0.18);
|
||||
}
|
||||
|
||||
.status-panel {
|
||||
background: linear-gradient(135deg, rgba(36, 32, 20, 0.95) 0%, rgba(28, 26, 18, 0.95) 100%);
|
||||
border-color: rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.status-panel h3 {
|
||||
color: #e9ecef;
|
||||
}
|
||||
|
||||
/* Bootstrap 工具类在暗色下的可读性 */
|
||||
.text-dark {
|
||||
color: #e9ecef !important;
|
||||
}
|
||||
|
||||
.bg-light {
|
||||
background-color: #2a2a2a !important;
|
||||
color: #e9ecef;
|
||||
}
|
||||
|
||||
.bg-warning.text-dark,
|
||||
.card-header.bg-warning {
|
||||
color: #111 !important;
|
||||
}
|
||||
|
||||
.alert-danger {
|
||||
background-color: rgba(127, 29, 29, 0.35) !important;
|
||||
border-color: rgba(248, 113, 113, 0.35) !important;
|
||||
color: #fecaca !important;
|
||||
}
|
||||
|
||||
.alert-warning {
|
||||
background-color: rgba(120, 53, 15, 0.35) !important;
|
||||
border-color: rgba(251, 191, 36, 0.35) !important;
|
||||
color: #fde68a !important;
|
||||
}
|
||||
|
||||
.alert-info {
|
||||
background-color: rgba(30, 58, 138, 0.35) !important;
|
||||
border-color: rgba(96, 165, 250, 0.35) !important;
|
||||
color: #bfdbfe !important;
|
||||
}
|
||||
|
||||
pre.bg-light,
|
||||
.border.bg-light {
|
||||
background-color: #242424 !important;
|
||||
border-color: rgba(255, 255, 255, 0.1) !important;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,11 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 30px;
|
||||
transition: all 0.3s;
|
||||
transition:
|
||||
transform var(--transition-fast, 160ms ease),
|
||||
box-shadow var(--transition-fast, 160ms ease),
|
||||
border-color var(--transition-base, 240ms ease),
|
||||
background var(--transition-base, 240ms ease);
|
||||
gap: 8px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||
text-decoration: none;
|
||||
@@ -59,11 +63,13 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.login-btn:hover {
|
||||
background: linear-gradient(to right, #ffffff, #ffcc00);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
|
||||
border-color: rgba(255, 204, 0, 0.5);
|
||||
@media (hover: hover) {
|
||||
.login-btn:hover {
|
||||
background: linear-gradient(to right, #ffffff, #ffcc00);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
|
||||
border-color: rgba(255, 204, 0, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.github-btn {
|
||||
@@ -77,7 +83,12 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 30px;
|
||||
transition: all 0.3s;
|
||||
transition:
|
||||
transform var(--transition-fast, 160ms ease),
|
||||
box-shadow var(--transition-fast, 160ms ease),
|
||||
border-color var(--transition-base, 240ms ease),
|
||||
background var(--transition-base, 240ms ease),
|
||||
color var(--transition-fast, 160ms ease);
|
||||
gap: 8px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||
text-decoration: none;
|
||||
@@ -87,12 +98,14 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.github-btn:hover {
|
||||
background: linear-gradient(to right, #666666, #333333);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
|
||||
border-color: rgba(51, 51, 51, 0.5);
|
||||
color: #ffffff;
|
||||
@media (hover: hover) {
|
||||
.github-btn:hover {
|
||||
background: linear-gradient(to right, #666666, #333333);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
|
||||
border-color: rgba(51, 51, 51, 0.5);
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
@@ -108,7 +121,11 @@
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
transition:
|
||||
transform var(--transition-fast, 160ms ease),
|
||||
box-shadow var(--transition-fast, 160ms ease),
|
||||
background var(--transition-base, 240ms ease),
|
||||
opacity var(--transition-fast, 160ms ease);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -121,10 +138,12 @@
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(to right, #ffffff, #ffcc00);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.15);
|
||||
@media (hover: hover) {
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(to right, #ffffff, #ffcc00);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
@@ -142,15 +161,20 @@
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
transition:
|
||||
transform var(--transition-fast, 160ms ease),
|
||||
box-shadow var(--transition-fast, 160ms ease),
|
||||
background var(--transition-base, 240ms ease);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.clear-session-btn:hover {
|
||||
background: linear-gradient(135deg, #c82333 0%, #a71e2a 100%);
|
||||
transform: translateY(-1px);
|
||||
@media (hover: hover) {
|
||||
.clear-session-btn:hover {
|
||||
background: linear-gradient(135deg, #c82333 0%, #a71e2a 100%);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 页面标题 ===== */
|
||||
@@ -189,7 +213,7 @@
|
||||
content: counter(list-item) ".\00A0\00A0";
|
||||
}
|
||||
|
||||
/* ===== 步骤指示器 ===== */
|
||||
/* ===== 步骤指示器(进度轨见 design-system) ===== */
|
||||
.step-indicator {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -211,6 +235,7 @@
|
||||
z-index: 2;
|
||||
width: 120px;
|
||||
position: relative;
|
||||
transition: opacity var(--transition-fast, 160ms ease);
|
||||
}
|
||||
|
||||
.step-number {
|
||||
@@ -227,20 +252,45 @@
|
||||
color: #212529;
|
||||
border: 2px solid rgba(255, 193, 7, 0.55);
|
||||
box-shadow: inset 0 0 0 2px rgba(255, 193, 7, 0.18);
|
||||
transition:
|
||||
background var(--transition-base, 240ms ease),
|
||||
border-color var(--transition-base, 240ms ease),
|
||||
box-shadow var(--transition-base, 240ms ease),
|
||||
color var(--transition-base, 240ms ease),
|
||||
transform var(--transition-fast, 160ms ease);
|
||||
}
|
||||
|
||||
.step.completed .step-number {
|
||||
background: linear-gradient(135deg, #f0c000, #e6b800);
|
||||
color: #212529;
|
||||
border-color: rgba(230, 184, 0, 0.9);
|
||||
box-shadow: 0 4px 12px rgba(255, 193, 7, 0.35);
|
||||
}
|
||||
|
||||
.step.completed .step-text {
|
||||
color: #854d0e;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.step.active .step-number {
|
||||
background: linear-gradient(135deg, #ffcc00, #ffd84d);
|
||||
color: white;
|
||||
color: #212529;
|
||||
box-shadow: 0 6px 16px rgba(255, 193, 7, 0.45);
|
||||
border-color: rgba(255, 193, 7, 0.8);
|
||||
border-color: rgba(255, 193, 7, 0.85);
|
||||
transform: scale(1.06);
|
||||
}
|
||||
|
||||
.step.active .step-text {
|
||||
color: #713f12;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.step-text {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
color: #212529;
|
||||
color: #64748b;
|
||||
font-weight: 500;
|
||||
transition: color var(--transition-fast, 160ms ease);
|
||||
}
|
||||
|
||||
/* ===== 状态显示 ===== */
|
||||
@@ -378,7 +428,8 @@
|
||||
margin: 20px 0;
|
||||
padding: 16px 20px;
|
||||
box-shadow: 0 4px 15px rgba(255, 204, 0, 0.3);
|
||||
animation: subtle-pulse 3s ease-in-out infinite;
|
||||
/* 静态展示,避免持续脉冲 */
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.promo-content {
|
||||
@@ -392,7 +443,7 @@
|
||||
.promo-icon {
|
||||
color: #212529;
|
||||
font-size: 20px;
|
||||
animation: bounce 2s ease-in-out infinite;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.promo-text {
|
||||
@@ -406,7 +457,7 @@
|
||||
color: #212529;
|
||||
text-decoration: underline;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
transition: color var(--transition-fast, 160ms ease), text-shadow var(--transition-fast, 160ms ease);
|
||||
}
|
||||
|
||||
.promo-link:hover {
|
||||
@@ -415,14 +466,14 @@
|
||||
text-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* ===== 章节控制 ===== */
|
||||
/* ===== 章节控制:进入时淡入上移 ===== */
|
||||
.section {
|
||||
display: none;
|
||||
animation: slideIn 0.5s ease;
|
||||
}
|
||||
|
||||
.section.active {
|
||||
display: block;
|
||||
animation: section-enter 0.35s var(--ease-out, cubic-bezier(.2, .8, .2, 1)) both;
|
||||
}
|
||||
|
||||
.verification-section {
|
||||
@@ -432,7 +483,14 @@
|
||||
|
||||
.verification-section.active {
|
||||
display: block;
|
||||
animation: fadeIn 0.5s ease;
|
||||
animation: section-enter 0.35s var(--ease-out, cubic-bezier(.2, .8, .2, 1)) both;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.section.active,
|
||||
.verification-section.active {
|
||||
animation: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 表单标签 ===== */
|
||||
@@ -612,3 +670,77 @@
|
||||
display: block;
|
||||
animation: fadeIn 0.4s ease;
|
||||
}
|
||||
|
||||
/* ===== 暗色模式:组件层 ===== */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.page-title h1 {
|
||||
color: #f8fafc;
|
||||
}
|
||||
|
||||
.page-title p {
|
||||
color: rgba(233, 236, 239, 0.72);
|
||||
}
|
||||
|
||||
.step-indicator {
|
||||
background: linear-gradient(135deg, #1e1e1e, #252525);
|
||||
border-color: rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.step-number {
|
||||
background: #2a2618;
|
||||
color: #f8fafc;
|
||||
border-color: rgba(255, 193, 7, 0.45);
|
||||
box-shadow: inset 0 0 0 2px rgba(255, 193, 7, 0.12);
|
||||
}
|
||||
|
||||
.step-text {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.step.completed .step-text {
|
||||
color: #fde68a;
|
||||
}
|
||||
|
||||
.step.active .step-text {
|
||||
color: #fef3c7;
|
||||
}
|
||||
|
||||
.status {
|
||||
background: rgba(30, 30, 30, 0.92);
|
||||
color: #e9ecef;
|
||||
}
|
||||
|
||||
.status-item {
|
||||
background: rgba(42, 42, 42, 0.9);
|
||||
border-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.status-label {
|
||||
color: #adb5bd;
|
||||
}
|
||||
|
||||
.status-value {
|
||||
color: #d0d0d0;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
color: #e9ecef;
|
||||
}
|
||||
|
||||
.new-user-notice {
|
||||
background: linear-gradient(135deg, rgba(127, 29, 29, 0.35), rgba(69, 10, 10, 0.45));
|
||||
border-color: rgba(248, 113, 113, 0.35);
|
||||
color: #fecaca;
|
||||
}
|
||||
|
||||
.promo-banner {
|
||||
box-shadow: 0 4px 18px rgba(255, 204, 0, 0.18);
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
color: #111;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,32 +117,35 @@
|
||||
}
|
||||
|
||||
#serviceTimeIcon.warning {
|
||||
background: #e6f6ee;
|
||||
color: #10b981;
|
||||
box-shadow: inset 0 0 0 2px rgba(16,185,129,0.15);
|
||||
animation: breathing-light-green 2s ease-in-out infinite;
|
||||
background: #fef3c7;
|
||||
color: #d97706;
|
||||
box-shadow: inset 0 0 0 2px rgba(245,158,11,0.2);
|
||||
/* 警告态保留极轻 opacity 脉动,成功态静态 */
|
||||
animation: warning-pulse 2.8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
#serviceTimeIcon.success {
|
||||
background: #e6f6ee;
|
||||
color: #10b981;
|
||||
box-shadow: inset 0 0 0 2px rgba(16,185,129,0.15);
|
||||
animation: breathing-light-green 2s ease-in-out infinite;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
#serviceTimeIcon:hover {
|
||||
transform: scale(1.1);
|
||||
@media (hover: hover) {
|
||||
#serviceTimeIcon:hover {
|
||||
transform: scale(1.04);
|
||||
}
|
||||
}
|
||||
|
||||
.alert-warning #serviceTimeIcon {
|
||||
animation: warning-pulse 2s ease-in-out infinite;
|
||||
animation: warning-pulse 2.8s ease-in-out infinite;
|
||||
background: #f8ecbb;
|
||||
color: #f59d06;
|
||||
box-shadow: inset 0 0 0 2px rgba(245,158,11,0.15);
|
||||
}
|
||||
|
||||
.alert-success #serviceTimeIcon {
|
||||
animation: breathing-light-green 2s ease-in-out infinite;
|
||||
animation: none;
|
||||
background: #e0f6eb;
|
||||
color: #10b981;
|
||||
box-shadow: inset 0 0 0 2px rgba(16,185,129,0.15);
|
||||
@@ -157,7 +160,11 @@
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
transition:
|
||||
transform var(--transition-fast, 160ms ease),
|
||||
box-shadow var(--transition-base, 240ms ease),
|
||||
background-color var(--transition-base, 240ms ease),
|
||||
border-color var(--transition-base, 240ms ease);
|
||||
z-index: 10;
|
||||
flex-shrink: 0;
|
||||
text-align: center;
|
||||
@@ -167,7 +174,7 @@
|
||||
background: #f0fdf4;
|
||||
color: #16a34a;
|
||||
border: 2px solid #16a34a;
|
||||
animation: breathing-light-green 2s ease-in-out infinite;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.service-time-action-badge.warning {
|
||||
@@ -176,7 +183,8 @@
|
||||
border: 2px solid #dc2626;
|
||||
font-weight: 800;
|
||||
text-shadow: none;
|
||||
animation: breathing-light 2s ease-in-out infinite;
|
||||
/* 仅警告徽章保留轻量脉动 */
|
||||
animation: breathing-light 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.service-time-action-badge:hover {
|
||||
@@ -199,7 +207,8 @@
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
isolation: isolate;
|
||||
animation: pulse-glow 2s ease-in-out infinite;
|
||||
/* 时间卡静态展示,避免持续 glow 动画 */
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.current-time-card::after {
|
||||
@@ -219,7 +228,7 @@
|
||||
display: grid;
|
||||
place-items: center;
|
||||
box-shadow: inset 0 0 0 1px rgba(99,102,241,0.22);
|
||||
animation: breathing-light-purple 2s ease-in-out infinite;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.time-card-icon i {
|
||||
@@ -247,11 +256,92 @@
|
||||
letter-spacing: 1.2px;
|
||||
color: #0b1324;
|
||||
text-shadow: 0 1px 0 rgba(255,255,255,0.6);
|
||||
animation: time-breathe 3s ease-in-out infinite;
|
||||
/* 静态可读,避免持续呼吸动画 */
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.time-card-hint {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
/* 服务时间:暗色模式 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.service-time-grid {
|
||||
background: linear-gradient(135deg, #2a2418 0%, #1f1b14 100%);
|
||||
border-color: rgba(255, 193, 7, 0.22);
|
||||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.service-time-left {
|
||||
background: linear-gradient(135deg, #322b1c 60%, #241f16 60%);
|
||||
border-color: rgba(255, 193, 7, 0.2);
|
||||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.service-time-title {
|
||||
color: #f8fafc;
|
||||
}
|
||||
|
||||
.service-time-message {
|
||||
color: #cbd5e1;
|
||||
}
|
||||
|
||||
.current-time-card {
|
||||
background: linear-gradient(135deg, #2a2418 60%, #322b1c 60%);
|
||||
box-shadow: 0 8px 28px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.current-time-card::after {
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.06), rgba(255,255,255,0));
|
||||
}
|
||||
|
||||
.time-card-value {
|
||||
color: #f8fafc;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.time-card-hint {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
#serviceTimeIcon {
|
||||
background: rgba(16, 185, 129, 0.15);
|
||||
color: #34d399;
|
||||
box-shadow: inset 0 0 0 2px rgba(16, 185, 129, 0.25);
|
||||
}
|
||||
|
||||
.alert-warning #serviceTimeIcon,
|
||||
#serviceTimeIcon.warning {
|
||||
background: rgba(245, 158, 11, 0.18);
|
||||
color: #fbbf24;
|
||||
box-shadow: inset 0 0 0 2px rgba(245, 158, 11, 0.28);
|
||||
}
|
||||
|
||||
.service-time-action-badge.success {
|
||||
background: rgba(22, 163, 74, 0.15);
|
||||
color: #4ade80;
|
||||
border-color: #16a34a;
|
||||
}
|
||||
|
||||
.service-time-action-badge.warning {
|
||||
background: rgba(220, 38, 38, 0.15);
|
||||
color: #f87171;
|
||||
border-color: #dc2626;
|
||||
}
|
||||
|
||||
.time-card-icon {
|
||||
background: linear-gradient(135deg, #1e1b2e, #252038);
|
||||
box-shadow: inset 0 0 0 1px rgba(129, 140, 248, 0.28);
|
||||
}
|
||||
}
|
||||
|
||||
/* 尊重减少动态偏好:去掉剩余状态脉动 */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
#serviceTimeIcon.warning,
|
||||
.alert-warning #serviceTimeIcon,
|
||||
.service-time-action-badge.warning {
|
||||
animation: none !important;
|
||||
}
|
||||
}
|
||||
@@ -85,18 +85,40 @@ export class UIController {
|
||||
* 更新步骤指示器
|
||||
*/
|
||||
updateSteps(currentStep) {
|
||||
this.elements.steps.forEach((step, index) => {
|
||||
const steps = this.elements.steps;
|
||||
const total = steps.length;
|
||||
|
||||
steps.forEach((step, index) => {
|
||||
const stepNo = index + 1;
|
||||
if (stepNo <= currentStep) {
|
||||
step.classList.remove('active', 'completed');
|
||||
|
||||
if (stepNo < currentStep) {
|
||||
step.classList.add('completed');
|
||||
step.style.cursor = 'pointer';
|
||||
step.title = tl('点击返回此步骤');
|
||||
step.setAttribute('aria-current', 'false');
|
||||
} else if (stepNo === currentStep) {
|
||||
step.classList.add('active');
|
||||
step.style.cursor = 'pointer';
|
||||
step.title = stepNo < currentStep ? tl('点击返回此步骤') : '';
|
||||
step.title = '';
|
||||
step.setAttribute('aria-current', 'step');
|
||||
} else {
|
||||
step.classList.remove('active');
|
||||
step.style.cursor = 'not-allowed';
|
||||
step.title = tl('请按顺序完成前序步骤');
|
||||
step.setAttribute('aria-current', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
// 进度轨:已完成区间占比(1 步时为 0,末步为 1)
|
||||
const indicator = steps[0] && steps[0].closest
|
||||
? steps[0].closest('.step-indicator')
|
||||
: null;
|
||||
if (indicator && total > 1) {
|
||||
const progress = Math.max(0, Math.min(1, (currentStep - 1) / (total - 1)));
|
||||
indicator.style.setProperty('--step-progress', String(progress));
|
||||
} else if (indicator) {
|
||||
indicator.style.setProperty('--step-progress', currentStep > 0 ? '1' : '0');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="zh-CN" data-page="simyo">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<meta name="description" content="Simyo eSIM 工具,支持设备更换、短信验证码、二维码生成与安装确认,帮助您快速管理荷兰 Simyo eSIM。">
|
||||
|
||||
|
||||
@@ -54,8 +54,9 @@
|
||||
.reveal {
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
transition: opacity 0.5s ease, transform 0.5s ease;
|
||||
will-change: opacity, transform;
|
||||
transition:
|
||||
opacity var(--transition-base, 240ms ease),
|
||||
transform var(--transition-base, 240ms ease);
|
||||
}
|
||||
|
||||
.reveal.show {
|
||||
@@ -63,6 +64,18 @@
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* 步骤内容进入 */
|
||||
@keyframes section-enter {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 降低动效:尊重用户的减少动态偏好 */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.reveal {
|
||||
|
||||
@@ -19,7 +19,7 @@ body {
|
||||
color: #212529;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
font-family: var(--font-sans, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ body {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* 步骤指示器 */
|
||||
/* 步骤指示器(进度轨见 design-system .step-indicator::before/::after) */
|
||||
.step-indicator {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -105,6 +105,7 @@ body {
|
||||
z-index: 2;
|
||||
width: 120px;
|
||||
position: relative;
|
||||
transition: opacity var(--transition-fast, 160ms ease);
|
||||
}
|
||||
|
||||
.step-number {
|
||||
@@ -121,20 +122,45 @@ body {
|
||||
color: #212529;
|
||||
border: 2px solid rgba(255, 107, 0, 0.55);
|
||||
box-shadow: inset 0 0 0 2px rgba(255, 107, 0, 0.18);
|
||||
transition:
|
||||
background var(--transition-base, 240ms ease),
|
||||
border-color var(--transition-base, 240ms ease),
|
||||
box-shadow var(--transition-base, 240ms ease),
|
||||
color var(--transition-base, 240ms ease),
|
||||
transform var(--transition-fast, 160ms ease);
|
||||
}
|
||||
|
||||
.step.completed .step-number {
|
||||
background: linear-gradient(135deg, #ff8a2b, #ff6b00);
|
||||
color: #fff;
|
||||
border-color: rgba(255, 107, 0, 0.9);
|
||||
box-shadow: 0 4px 12px rgba(255, 107, 0, 0.3);
|
||||
}
|
||||
|
||||
.step.completed .step-text {
|
||||
color: #c2410c;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.step.active .step-number {
|
||||
background: linear-gradient(135deg, #ff7a1a, #ffb066);
|
||||
color: white;
|
||||
color: #fff;
|
||||
border-color: rgba(255, 107, 0, 0.85);
|
||||
box-shadow: 0 6px 16px rgba(255, 107, 0, 0.45);
|
||||
border-color: rgba(255, 107, 0, 0.8);
|
||||
transform: scale(1.06);
|
||||
}
|
||||
|
||||
.step.active .step-text {
|
||||
color: #9a3412;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.step-text {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
color: #212529;
|
||||
color: #64748b;
|
||||
font-weight: 500;
|
||||
transition: color var(--transition-fast, 160ms ease);
|
||||
}
|
||||
|
||||
/* 表单元素 */
|
||||
@@ -154,7 +180,10 @@ textarea, input {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: #212529;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s ease;
|
||||
transition:
|
||||
border-color var(--transition-base, 240ms ease),
|
||||
box-shadow var(--transition-base, 240ms ease),
|
||||
background-color var(--transition-base, 240ms ease);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -184,13 +213,14 @@ textarea:focus-visible {
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* 区块显示控制 */
|
||||
/* 区块显示控制:进入时淡入上移 */
|
||||
.section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.section.active {
|
||||
display: block;
|
||||
animation: section-enter 0.35s var(--ease-out, cubic-bezier(.2, .8, .2, 1)) both;
|
||||
}
|
||||
|
||||
#resultContainer {
|
||||
@@ -199,6 +229,14 @@ textarea:focus-visible {
|
||||
|
||||
#resultContainer.active {
|
||||
display: block;
|
||||
animation: section-enter 0.35s var(--ease-out, cubic-bezier(.2, .8, .2, 1)) both;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.section.active,
|
||||
#resultContainer.active {
|
||||
animation: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 加载动画 */
|
||||
@@ -239,6 +277,100 @@ textarea:focus-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* ===== 暗色模式 ===== */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--secondary: #2a1f16;
|
||||
--light: #1a1a1a;
|
||||
--dark: #e9ecef;
|
||||
--gray: #adb5bd;
|
||||
}
|
||||
|
||||
body {
|
||||
background: linear-gradient(135deg, #1a1410 0%, #12100e 50%, #0c0b0a 100%);
|
||||
color: #e9ecef;
|
||||
}
|
||||
|
||||
.app-title {
|
||||
background: linear-gradient(to right, #ff8a3d, #6eb0ff);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
}
|
||||
|
||||
.page-title h1 {
|
||||
color: #f1f5f9;
|
||||
}
|
||||
|
||||
.page-title p {
|
||||
color: rgba(233, 236, 239, 0.72);
|
||||
}
|
||||
|
||||
.step-indicator {
|
||||
background: linear-gradient(135deg, #1e1e1e, #252525);
|
||||
border-color: rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.step-number {
|
||||
background: #2a2118;
|
||||
color: #f8fafc;
|
||||
border-color: rgba(255, 107, 0, 0.45);
|
||||
box-shadow: inset 0 0 0 2px rgba(255, 107, 0, 0.12);
|
||||
}
|
||||
|
||||
.step-text {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.step.completed .step-text {
|
||||
color: #fdba74;
|
||||
}
|
||||
|
||||
.step.active .step-text {
|
||||
color: #ffedd5;
|
||||
}
|
||||
|
||||
textarea,
|
||||
input {
|
||||
background: rgba(30, 30, 30, 0.92);
|
||||
color: #e9ecef;
|
||||
border-color: rgba(255, 107, 0, 0.28);
|
||||
}
|
||||
|
||||
textarea:focus,
|
||||
input:focus {
|
||||
background: rgba(36, 36, 36, 1);
|
||||
box-shadow: 0 0 0 4px rgba(255, 107, 0, 0.18);
|
||||
}
|
||||
|
||||
.text-dark {
|
||||
color: #e9ecef !important;
|
||||
}
|
||||
|
||||
.bg-light {
|
||||
background-color: #2a2a2a !important;
|
||||
color: #e9ecef;
|
||||
}
|
||||
|
||||
.alert-danger {
|
||||
background-color: rgba(127, 29, 29, 0.35) !important;
|
||||
border-color: rgba(248, 113, 113, 0.35) !important;
|
||||
color: #fecaca !important;
|
||||
}
|
||||
|
||||
.alert-warning {
|
||||
background-color: rgba(120, 53, 15, 0.35) !important;
|
||||
border-color: rgba(251, 191, 36, 0.35) !important;
|
||||
color: #fde68a !important;
|
||||
}
|
||||
|
||||
.alert-info {
|
||||
background-color: rgba(30, 58, 138, 0.35) !important;
|
||||
border-color: rgba(96, 165, 250, 0.35) !important;
|
||||
color: #bfdbfe !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Toast通知样式 */
|
||||
.toast-notification {
|
||||
position: fixed;
|
||||
|
||||
@@ -3,21 +3,24 @@
|
||||
* 定义卡片、按钮、状态面板等组件样式
|
||||
*/
|
||||
|
||||
/* 卡片样式 */
|
||||
/* 卡片样式:内容卡仅微调阴影,避免填表时大幅上浮 */
|
||||
.card {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(255, 107, 0, 0.3);
|
||||
box-shadow: 0 4px 25px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||
margin-bottom: 30px;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
transition:
|
||||
box-shadow var(--transition-base, 240ms ease),
|
||||
border-color var(--transition-base, 240ms ease);
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
|
||||
border: 1px solid rgba(255, 107, 0, 0.5);
|
||||
@media (hover: hover) {
|
||||
.card:hover {
|
||||
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.1);
|
||||
border-color: rgba(255, 107, 0, 0.45);
|
||||
}
|
||||
}
|
||||
|
||||
.card-header {
|
||||
@@ -55,7 +58,11 @@
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
transition:
|
||||
transform var(--transition-fast, 160ms ease),
|
||||
box-shadow var(--transition-fast, 160ms ease),
|
||||
background var(--transition-base, 240ms ease),
|
||||
opacity var(--transition-fast, 160ms ease);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -68,10 +75,12 @@
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(to right, #ffffff, #ff6b00);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.15);
|
||||
@media (hover: hover) {
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(to right, #ffffff, #ff6b00);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
@@ -92,7 +101,11 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 30px;
|
||||
transition: all 0.3s;
|
||||
transition:
|
||||
transform var(--transition-fast, 160ms ease),
|
||||
box-shadow var(--transition-fast, 160ms ease),
|
||||
border-color var(--transition-base, 240ms ease),
|
||||
background var(--transition-base, 240ms ease);
|
||||
gap: 8px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||
text-decoration: none;
|
||||
@@ -101,11 +114,13 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.help-btn:hover {
|
||||
background: linear-gradient(to right, #ffffff, #ff6b00);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
|
||||
border-color: rgba(255, 107, 0, 0.5);
|
||||
@media (hover: hover) {
|
||||
.help-btn:hover {
|
||||
background: linear-gradient(to right, #ffffff, #ff6b00);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
|
||||
border-color: rgba(255, 107, 0, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.github-btn {
|
||||
@@ -119,7 +134,12 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 30px;
|
||||
transition: all 0.3s;
|
||||
transition:
|
||||
transform var(--transition-fast, 160ms ease),
|
||||
box-shadow var(--transition-fast, 160ms ease),
|
||||
border-color var(--transition-base, 240ms ease),
|
||||
background var(--transition-base, 240ms ease),
|
||||
color var(--transition-fast, 160ms ease);
|
||||
gap: 8px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||
text-decoration: none;
|
||||
@@ -129,12 +149,14 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.github-btn:hover {
|
||||
background: linear-gradient(to right, #666666, #333333);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
|
||||
border-color: rgba(51, 51, 51, 0.5);
|
||||
color: #ffffff;
|
||||
@media (hover: hover) {
|
||||
.github-btn:hover {
|
||||
background: linear-gradient(to right, #666666, #333333);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
|
||||
border-color: rgba(51, 51, 51, 0.5);
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* 状态显示 */
|
||||
@@ -259,15 +281,19 @@
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
transition:
|
||||
transform var(--transition-fast, 160ms ease),
|
||||
background var(--transition-base, 240ms ease);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.clear-session-btn:hover {
|
||||
background: linear-gradient(135deg, #c82333 0%, #a71e2a 100%);
|
||||
transform: translateY(-1px);
|
||||
@media (hover: hover) {
|
||||
.clear-session-btn:hover {
|
||||
background: linear-gradient(135deg, #c82333 0%, #a71e2a 100%);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
}
|
||||
|
||||
/* 信息卡片 */
|
||||
@@ -298,7 +324,7 @@
|
||||
margin: 20px 0;
|
||||
padding: 16px 20px;
|
||||
box-shadow: 0 4px 15px rgba(255, 107, 0, 0.3);
|
||||
animation: subtle-pulse 3s ease-in-out infinite;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.promo-content {
|
||||
@@ -312,7 +338,7 @@
|
||||
.promo-icon {
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
animation: bounce 2s ease-in-out infinite;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.promo-text {
|
||||
@@ -326,7 +352,7 @@
|
||||
color: white;
|
||||
text-decoration: underline;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
transition: color var(--transition-fast, 160ms ease), text-shadow var(--transition-fast, 160ms ease);
|
||||
}
|
||||
|
||||
.promo-link:hover {
|
||||
@@ -344,4 +370,63 @@
|
||||
|
||||
.qrcode-container:hover .tooltip {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* ===== 暗色模式:组件层 ===== */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.card {
|
||||
background: rgba(30, 30, 30, 0.92);
|
||||
border-color: rgba(255, 107, 0, 0.28);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
.card:hover {
|
||||
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
|
||||
border-color: rgba(255, 107, 0, 0.42);
|
||||
}
|
||||
}
|
||||
|
||||
.card-header {
|
||||
background: rgba(255, 107, 0, 0.12);
|
||||
color: #f8f9fa;
|
||||
border-bottom-color: rgba(255, 107, 0, 0.2);
|
||||
}
|
||||
|
||||
.status {
|
||||
background: rgba(30, 30, 30, 0.92);
|
||||
color: #e9ecef;
|
||||
}
|
||||
|
||||
.status-item {
|
||||
background: rgba(42, 42, 42, 0.9);
|
||||
border-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.status-label {
|
||||
color: #adb5bd;
|
||||
}
|
||||
|
||||
.status-value {
|
||||
color: #d0d0d0;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
color: #e9ecef;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
background: linear-gradient(135deg, #2a1f16 0%, #3d2818 100%);
|
||||
color: #f8fafc;
|
||||
border-color: rgba(255, 107, 0, 0.3);
|
||||
}
|
||||
|
||||
.promo-banner {
|
||||
animation: none;
|
||||
box-shadow: 0 4px 18px rgba(255, 107, 0, 0.22);
|
||||
}
|
||||
|
||||
.promo-icon {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,48 @@
|
||||
/* 微交互动画和触摸反馈 */
|
||||
/* 微交互动画与触摸反馈
|
||||
依赖 design-system.css 的 motion tokens,禁止在此重新定义 --transition-* 时长格式
|
||||
*/
|
||||
|
||||
/* 基础动画变量 */
|
||||
/* 本地缓动别名(与 design-system 对齐,作兜底) */
|
||||
:root {
|
||||
--transition-fast: 0.15s ease-out;
|
||||
--transition-normal: 0.3s ease-out;
|
||||
--transition-slow: 0.5s ease-out;
|
||||
--bounce-ease: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
--smooth-ease: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--smooth-ease: var(--ease-out, cubic-bezier(0.22, 0.61, 0.36, 1));
|
||||
}
|
||||
|
||||
/* 按钮点击反馈动画 */
|
||||
/* 按钮点击反馈 */
|
||||
.btn {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all var(--transition-normal) var(--smooth-ease);
|
||||
transform: translateZ(0);
|
||||
will-change: transform;
|
||||
transition:
|
||||
transform var(--transition-fast, 120ms var(--smooth-ease)),
|
||||
box-shadow var(--transition-fast, 120ms var(--smooth-ease)),
|
||||
background-color var(--transition-base, 200ms var(--smooth-ease)),
|
||||
border-color var(--transition-base, 200ms var(--smooth-ease)),
|
||||
color var(--transition-fast, 120ms var(--smooth-ease)),
|
||||
opacity var(--transition-fast, 120ms var(--smooth-ease));
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: scale(0.95) translateZ(0);
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.btn::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transition: width 0.6s, height 0.6s;
|
||||
}
|
||||
|
||||
.btn:active::before {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
/* 卡片悬停效果 */
|
||||
/* 卡片:仅声明过渡,上浮由可导航卡片自行定义 */
|
||||
.card {
|
||||
transition: all var(--transition-normal) var(--smooth-ease);
|
||||
transform: translateZ(0);
|
||||
will-change: transform, box-shadow;
|
||||
transition:
|
||||
transform var(--transition-base, 200ms var(--smooth-ease)),
|
||||
box-shadow var(--transition-base, 200ms var(--smooth-ease)),
|
||||
border-color var(--transition-base, 200ms var(--smooth-ease));
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-2px) translateZ(0);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.card:active {
|
||||
transform: translateY(0) translateZ(0);
|
||||
}
|
||||
|
||||
/* 输入框焦点动画 */
|
||||
/* 输入框焦点:ring 即可,避免 scale 造成布局抖动 */
|
||||
.form-control {
|
||||
transition: all var(--transition-normal) var(--smooth-ease);
|
||||
transform: translateZ(0);
|
||||
transition:
|
||||
border-color var(--transition-base, 200ms var(--smooth-ease)),
|
||||
box-shadow var(--transition-base, 200ms var(--smooth-ease)),
|
||||
background-color var(--transition-base, 200ms var(--smooth-ease));
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
transform: scale(1.02) translateZ(0);
|
||||
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
|
||||
box-shadow: 0 0 0 3px var(--ring-color, rgba(0, 123, 255, 0.15));
|
||||
}
|
||||
|
||||
/* 加载状态指示器 */
|
||||
@@ -95,7 +73,7 @@
|
||||
|
||||
/* 淡入动画 */
|
||||
.fade-in {
|
||||
animation: fadeIn 0.5s ease-out;
|
||||
animation: fadeIn 0.35s var(--smooth-ease);
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
@@ -103,14 +81,26 @@
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
/* 步骤内容区进入动画 */
|
||||
@keyframes section-enter {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 滑入动画 */
|
||||
.slide-in {
|
||||
animation: slideIn 0.3s ease-out;
|
||||
animation: slideIn 0.3s var(--smooth-ease);
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
from { transform: translateX(-100%); }
|
||||
to { transform: translateX(0); }
|
||||
from { transform: translateX(-100%); opacity: 0; }
|
||||
to { transform: translateX(0); opacity: 1; }
|
||||
}
|
||||
|
||||
/* 弹跳动画 */
|
||||
@@ -131,18 +121,9 @@
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
|
||||
.btn:active {
|
||||
transform: scale(0.98);
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.card:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +158,9 @@
|
||||
z-index: 9999;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all var(--transition-normal);
|
||||
transition:
|
||||
opacity var(--transition-base, 200ms var(--smooth-ease)),
|
||||
visibility var(--transition-base, 200ms var(--smooth-ease));
|
||||
}
|
||||
|
||||
.loading-overlay.show {
|
||||
@@ -188,7 +171,7 @@
|
||||
/* 进度条动画 */
|
||||
.progress-bar {
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, #007bff, #28a745);
|
||||
background: linear-gradient(90deg, var(--primary, #007bff), #28a745);
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
@@ -210,10 +193,12 @@
|
||||
100% { left: 100%; }
|
||||
}
|
||||
|
||||
/* 工具提示动画优化 */
|
||||
/* 工具提示动画 */
|
||||
.tooltip {
|
||||
transition: opacity var(--transition-fast), transform var(--transition-fast);
|
||||
transform: scale(0.9);
|
||||
transition:
|
||||
opacity var(--transition-fast, 120ms var(--smooth-ease)),
|
||||
transform var(--transition-fast, 120ms var(--smooth-ease));
|
||||
transform: scale(0.96);
|
||||
transform-origin: center bottom;
|
||||
}
|
||||
|
||||
@@ -223,30 +208,34 @@
|
||||
|
||||
/* 状态切换动画 */
|
||||
.status-transition {
|
||||
transition: all var(--transition-normal) var(--smooth-ease);
|
||||
transition:
|
||||
color var(--transition-base, 200ms var(--smooth-ease)),
|
||||
transform var(--transition-base, 200ms var(--smooth-ease));
|
||||
}
|
||||
|
||||
.status-transition.connected {
|
||||
color: #28a745;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.status-transition.disconnected {
|
||||
color: #dc3545;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% { background-position: 200% 0; }
|
||||
100% { background-position: -200% 0; }
|
||||
}
|
||||
|
||||
/* 步骤脉冲环动画 */
|
||||
/* 步骤脉冲环(颜色跟随品牌 --primary) */
|
||||
@keyframes pulse-ring {
|
||||
0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(13, 110, 253, 0.7); }
|
||||
70% { transform: scale(1); box-shadow: 0 0 0 10px rgba(13, 110, 253, 0); }
|
||||
100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(13, 110, 253, 0); }
|
||||
0% {
|
||||
box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary, #0d6efd) 55%, transparent);
|
||||
}
|
||||
70% {
|
||||
box-shadow: 0 0 0 10px color-mix(in srgb, var(--primary, #0d6efd) 0%, transparent);
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary, #0d6efd) 0%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/* Design System: tokens, utilities, base components
|
||||
Scope: shared across brand pages. Brands override --primary/--secondary in page-level :root.
|
||||
字体使用系统栈,避免阻塞式 Google Fonts @import。
|
||||
*/
|
||||
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
||||
|
||||
/* 按钮组与打赏按钮样式 */
|
||||
.header-actions {
|
||||
display: flex;
|
||||
@@ -22,10 +21,9 @@
|
||||
justify-content: center;
|
||||
border-radius: 999px;
|
||||
gap: 8px;
|
||||
transition: transform var(--transition-fast), box-shadow var(--transition-fast), background var(--transition-fast);
|
||||
transition: transform var(--transition-fast), box-shadow var(--transition-fast), background-color var(--transition-fast);
|
||||
text-decoration: none !important;
|
||||
box-shadow: var(--shadow-sm);
|
||||
will-change: transform;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
@@ -90,12 +88,13 @@
|
||||
--shadow-md: 0 4px 18px rgba(0,0,0,0.12);
|
||||
--shadow-lg: 0 8px 28px rgba(0,0,0,0.18);
|
||||
|
||||
/* Motion */
|
||||
--ease-out: cubic-bezier(.22,.61,.36,1);
|
||||
--ease-in: cubic-bezier(.55,.085,.68,.53);
|
||||
--transition-fast: 120ms var(--ease-out);
|
||||
--transition-base: 200ms var(--ease-out);
|
||||
--transition-slow: 320ms var(--ease-out);
|
||||
/* Motion:全站唯一时长/缓动源,品牌页与 animations.css 禁止覆盖为其它格式 */
|
||||
--ease-out: cubic-bezier(.2, .8, .2, 1);
|
||||
--ease-in: cubic-bezier(.55, .085, .68, .53);
|
||||
--ease-standard: var(--ease-out);
|
||||
--transition-fast: 160ms var(--ease-out);
|
||||
--transition-base: 240ms var(--ease-out);
|
||||
--transition-slow: 360ms var(--ease-out);
|
||||
|
||||
/* Focus ring */
|
||||
--ring-color: rgba(76,154,255,.35);
|
||||
@@ -110,8 +109,8 @@
|
||||
--space-6: 24px;
|
||||
--space-8: 32px;
|
||||
|
||||
/* Typography */
|
||||
--font-sans: 'Inter', system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
/* Typography:系统字体栈,含中文回退 */
|
||||
--font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
||||
}
|
||||
|
||||
/* Dark Mode Support */
|
||||
@@ -161,10 +160,22 @@
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
/* body 背景由各品牌页 / 首页自行定义,避免全局硬覆盖品牌色渐变 */
|
||||
body {
|
||||
background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.card-header-soft {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.status-label {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.loading-overlay {
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
/* 2) Accessibility and base resets */
|
||||
@@ -265,9 +276,8 @@ html[data-locale="en"] .lang-en { display: inline !important; }
|
||||
/* Reveal-on-scroll animation */
|
||||
.reveal {
|
||||
opacity: 0;
|
||||
transform: translateY(16px);
|
||||
transform: translateY(12px);
|
||||
transition: opacity var(--transition-base), transform var(--transition-base);
|
||||
will-change: opacity, transform;
|
||||
}
|
||||
.reveal.show {
|
||||
opacity: 1;
|
||||
@@ -290,10 +300,6 @@ html[data-locale="en"] .lang-en { display: inline !important; }
|
||||
* { scroll-behavior: auto !important; }
|
||||
}
|
||||
|
||||
/* Fine-tune reveal transition to be lightweight and smooth */
|
||||
.reveal { will-change: opacity, transform; }
|
||||
.reveal.show { transition: transform var(--transition-base), opacity var(--transition-base); }
|
||||
|
||||
/* 4) Components */
|
||||
.card-elevated {
|
||||
background: var(--surface-glass);
|
||||
@@ -461,17 +467,17 @@ html[data-locale="en"] .lang-en { display: inline !important; }
|
||||
}
|
||||
.tooltip.show { opacity: 1; }
|
||||
|
||||
/* Promo banner */
|
||||
/* Promo banner:静态展示,避免持续 scale 动画 */
|
||||
.promo-banner {
|
||||
border-radius: var(--radius-md);
|
||||
margin: 20px 0;
|
||||
padding: 16px 20px;
|
||||
box-shadow: 0 4px 15px color-mix(in srgb, var(--primary) 30%, transparent);
|
||||
animation: subtle-pulse 3s ease-in-out infinite;
|
||||
animation: none;
|
||||
}
|
||||
@keyframes subtle-pulse {
|
||||
0%,100% { transform: scale(1); }
|
||||
50% { transform: scale(1.02); }
|
||||
0%,100% { opacity: 1; }
|
||||
50% { opacity: 0.92; }
|
||||
}
|
||||
|
||||
/* Reveal helpers for QR preview hovers may reuse .tooltip from above */
|
||||
@@ -528,10 +534,65 @@ html[data-locale="en"] .lang-en { display: inline !important; }
|
||||
}
|
||||
}
|
||||
|
||||
/* Step Indicator Pulse */
|
||||
/* Step Indicator:当前步脉冲(颜色跟随 --primary) */
|
||||
.step.active .step-number {
|
||||
box-shadow: 0 0 0 0 rgba(13, 110, 253, 0.7);
|
||||
animation: pulse-ring 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
animation: pulse-ring 2s var(--ease-out) infinite;
|
||||
}
|
||||
|
||||
/* 步骤指示器进度轨(--step-progress: 0~1,由 JS 写入) */
|
||||
.step-indicator {
|
||||
--step-progress: 0;
|
||||
}
|
||||
|
||||
.step-indicator::before,
|
||||
.step-indicator::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: calc(16px + 28px);
|
||||
left: 10%;
|
||||
right: 10%;
|
||||
height: 3px;
|
||||
border-radius: 999px;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.step-indicator::before {
|
||||
background: color-mix(in srgb, var(--muted, #6c757d) 22%, transparent);
|
||||
}
|
||||
|
||||
.step-indicator::after {
|
||||
right: auto;
|
||||
width: calc((100% - 20%) * var(--step-progress, 0));
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
color-mix(in srgb, var(--primary) 75%, transparent),
|
||||
var(--primary)
|
||||
);
|
||||
transition: width var(--transition-slow);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.step-indicator::before,
|
||||
.step-indicator::after {
|
||||
top: calc(16px + 20px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.step-indicator::before,
|
||||
.step-indicator::after {
|
||||
top: calc(16px + 17px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.step.active .step-number {
|
||||
animation: none !important;
|
||||
}
|
||||
.step-indicator::after {
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyboard focus visibility for custom buttons built on <a> */
|
||||
|
||||
@@ -363,10 +363,9 @@ a:not(.btn) {
|
||||
性能优化
|
||||
======================================== */
|
||||
|
||||
/* GPU加速 */
|
||||
/* GPU 加速:仅在动画中临时使用,避免常驻 will-change */
|
||||
.gpu-accelerated {
|
||||
transform: translateZ(0);
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
/* 减少重绘 */
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
.notification-container {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
top: max(16px, calc(env(safe-area-inset-top, 0px) + 12px));
|
||||
right: max(16px, calc(env(safe-area-inset-right, 0px) + 12px));
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -25,9 +25,8 @@
|
||||
pointer-events: auto;
|
||||
transform: translateX(calc(100% + 20px));
|
||||
opacity: 0;
|
||||
transition: transform var(--transition-base, 200ms) var(--ease-out, cubic-bezier(.22,.61,.36,1)),
|
||||
opacity var(--transition-base, 200ms) var(--ease-out, cubic-bezier(.22,.61,.36,1));
|
||||
will-change: transform, opacity;
|
||||
transition: transform var(--transition-base, 240ms var(--ease-out, cubic-bezier(.2,.8,.2,1))),
|
||||
opacity var(--transition-base, 240ms var(--ease-out, cubic-bezier(.2,.8,.2,1)));
|
||||
}
|
||||
|
||||
.notification.show {
|
||||
@@ -64,10 +63,12 @@
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 4px;
|
||||
min-width: 32px;
|
||||
min-height: 32px;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
opacity: 0.7;
|
||||
transition: opacity var(--transition-fast, 120ms);
|
||||
transition: opacity var(--transition-fast, 160ms);
|
||||
flex-shrink: 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
@@ -102,17 +103,26 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
/* 响应式 + 安全区 */
|
||||
@media (max-width: 768px) {
|
||||
.notification-container {
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
left: 10px;
|
||||
top: max(10px, calc(env(safe-area-inset-top, 0px) + 8px));
|
||||
right: max(10px, calc(env(safe-area-inset-right, 0px) + 8px));
|
||||
left: max(10px, calc(env(safe-area-inset-left, 0px) + 8px));
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.notification {
|
||||
padding: 14px 16px;
|
||||
transform: translateY(calc(-100% - 16px));
|
||||
}
|
||||
|
||||
.notification.show {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.notification.hide {
|
||||
transform: translateY(calc(-100% - 16px));
|
||||
}
|
||||
|
||||
.notification-message {
|
||||
@@ -136,11 +146,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 网络状态指示器样式 (Ported from index.html) */
|
||||
/* 网络状态指示器 */
|
||||
.network-status {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
top: max(16px, calc(env(safe-area-inset-top, 0px) + 12px));
|
||||
right: max(16px, calc(env(safe-area-inset-right, 0px) + 12px));
|
||||
padding: 12px 20px;
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
@@ -148,7 +158,7 @@
|
||||
z-index: 10000;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
transform: translateX(100%);
|
||||
transition: transform 0.3s ease;
|
||||
transition: transform var(--transition-base, 240ms ease);
|
||||
}
|
||||
|
||||
.network-status.success {
|
||||
@@ -169,21 +179,15 @@
|
||||
|
||||
.update-notification {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
bottom: max(16px, calc(env(safe-area-inset-bottom, 0px) + 12px));
|
||||
right: max(16px, calc(env(safe-area-inset-right, 0px) + 12px));
|
||||
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
||||
color: white;
|
||||
padding: 16px 20px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 25px rgba(99, 102, 241, 0.3);
|
||||
z-index: 10000;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.notification-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
max-width: min(300px, calc(100vw - 32px - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px)));
|
||||
}
|
||||
|
||||
/* 加载状态样式 */
|
||||
@@ -201,7 +205,7 @@
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.3s ease;
|
||||
transition: opacity var(--transition-base, 240ms ease);
|
||||
}
|
||||
|
||||
.loading-overlay.show {
|
||||
@@ -237,3 +241,25 @@
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* 暗色模式 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.loading-overlay {
|
||||
background: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
|
||||
.loading-content {
|
||||
background: #1e1e1e;
|
||||
color: #e9ecef;
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.loading-content p {
|
||||
color: #adb5bd;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
border-color: #333;
|
||||
border-top-color: var(--primary, #8b5cf6);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user