feat: 液态玻璃主题系统(深色/浅色切换) + 访问者计数 + 部署脚本

This commit is contained in:
freedakgmail
2026-07-06 21:32:09 +08:00
parent e76ed2d57e
commit 9c86f17643
3 changed files with 344 additions and 79 deletions
+309 -79
View File
@@ -10,22 +10,145 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" />
<style>
/* ===== Liquid Glass 主题变量 ===== */
:root {
--radius: 0.625rem;
color-scheme: dark;
--radius: 0.75rem;
--glass-blur: 24px;
--glass-saturate: 1.8;
--transition-theme: background 0.5s ease, color 0.5s ease, border-color 0.5s ease, box-shadow 0.5s ease;
}
/* ===== 深色模式 ===== */
:root[data-theme="dark"] {
color-scheme: dark;
--bg-base: oklch(0.08 0.01 260);
--bg-grad-1: oklch(0.28 0.08 275 / 0.55);
--bg-grad-2: oklch(0.25 0.07 210 / 0.5);
--bg-grad-3: oklch(0.22 0.06 170 / 0.4);
--bg-grad-linear: linear-gradient(160deg, oklch(0.14 0.02 265), oklch(0.1 0.015 260) 60%, oklch(0.08 0.01 255));
--grid-line: oklch(0.65 0.05 265 / 0.06);
--aurora-1: oklch(0.5 0.2 275 / 0.28);
--aurora-2: oklch(0.48 0.16 210 / 0.24);
--aurora-3: oklch(0.5 0.15 165 / 0.2);
--text-primary: oklch(0.92 0.01 260);
--text-secondary: oklch(0.72 0.02 260);
--text-muted: oklch(0.55 0.02 260);
--text-heading: oklch(0.95 0.01 260);
--glass-bg: oklch(0.14 0.015 260 / 0.55);
--glass-bg-hover: oklch(0.18 0.02 265 / 0.65);
--glass-border: oklch(0.4 0.03 265 / 0.35);
--glass-border-hover: oklch(0.5 0.04 265 / 0.5);
--glass-highlight: oklch(0.6 0.03 265 / 0.25);
--glass-shadow: oklch(0 0 0 / 0.3);
--glass-shadow-hover: oklch(0 0 0 / 0.4);
--glass-inset: oklch(0.5 0.03 265 / 0.3);
--header-bg: oklch(0.1 0.015 260 / 0.65);
--header-border: oklch(0.35 0.03 265 / 0.4);
--header-shadow: oklch(0 0 0 / 0.25);
--modal-bg: oklch(0.12 0.015 260 / 0.75);
--modal-border: oklch(0.4 0.03 265 / 0.4);
--modal-shadow: oklch(0 0 0 / 0.5);
--overlay-bg: oklch(0.04 0.005 255 / 0.6);
--section-bg: oklch(0.12 0.01 260 / 0.4);
--section-border: oklch(0.3 0.02 265 / 0.35);
--table-header-bg: oklch(0.16 0.015 260 / 0.5);
--table-border: oklch(0.25 0.02 265 / 0.35);
--table-hover: oklch(0.22 0.03 265 / 0.4);
--btn-bg: oklch(0.16 0.015 260 / 0.5);
--btn-border: oklch(0.35 0.03 265 / 0.4);
--btn-hover-bg: oklch(0.22 0.02 260 / 0.6);
--btn-hover-border: oklch(0.45 0.05 265 / 0.55);
--dot-bg: oklch(0.3 0.02 265 / 0.5);
--dot-active: oklch(0.68 0.16 235);
--link-color: oklch(0.68 0.16 235);
--link-hover: oklch(0.78 0.16 235);
--copy-feedback: oklch(0.72 0.18 150);
--status-glow: oklch(0.72 0.18 150);
--gradient-1: oklch(0.72 0.18 275);
--gradient-2: oklch(0.68 0.16 235);
--gradient-3: oklch(0.7 0.14 185);
--brand-1: oklch(0.62 0.24 275);
--brand-2: oklch(0.66 0.18 230);
--group-title-color: oklch(0.72 0.04 260);
--group-title-border: oklch(0.25 0.02 265 / 0.4);
--tag-bg-mix: oklch(0.15 0.015 260);
--launch-bg-mix: oklch(0.15 0.015 260);
--sheen-color: oklch(0.85 0.02 260 / 0.15);
--refraction-color: oklch(0.7 0.05 265 / 0.08);
}
/* ===== 浅色模式 ===== */
:root[data-theme="light"] {
color-scheme: light;
--bg-base: oklch(0.96 0.005 260);
--bg-grad-1: oklch(0.85 0.06 275 / 0.45);
--bg-grad-2: oklch(0.84 0.05 210 / 0.4);
--bg-grad-3: oklch(0.83 0.05 170 / 0.35);
--bg-grad-linear: linear-gradient(160deg, oklch(0.97 0.008 260), oklch(0.95 0.006 255) 60%, oklch(0.93 0.005 250));
--grid-line: oklch(0.4 0.03 265 / 0.05);
--aurora-1: oklch(0.75 0.15 275 / 0.2);
--aurora-2: oklch(0.73 0.12 210 / 0.18);
--aurora-3: oklch(0.72 0.1 165 / 0.15);
--text-primary: oklch(0.25 0.01 260);
--text-secondary: oklch(0.45 0.02 260);
--text-muted: oklch(0.55 0.02 260);
--text-heading: oklch(0.2 0.01 260);
--glass-bg: oklch(0.98 0.005 260 / 0.6);
--glass-bg-hover: oklch(1 0 0 / 0.75);
--glass-border: oklch(0.7 0.02 265 / 0.4);
--glass-border-hover: oklch(0.6 0.04 265 / 0.55);
--glass-highlight: oklch(1 0 0 / 0.6);
--glass-shadow: oklch(0.3 0.02 265 / 0.12);
--glass-shadow-hover: oklch(0.3 0.02 265 / 0.2);
--glass-inset: oklch(1 0 0 / 0.5);
--header-bg: oklch(0.95 0.006 260 / 0.65);
--header-border: oklch(0.7 0.02 265 / 0.35);
--header-shadow: oklch(0.3 0.02 265 / 0.08);
--modal-bg: oklch(0.97 0.006 260 / 0.8);
--modal-border: oklch(0.7 0.02 265 / 0.35);
--modal-shadow: oklch(0.3 0.02 265 / 0.2);
--overlay-bg: oklch(0.8 0.005 255 / 0.5);
--section-bg: oklch(0.95 0.005 260 / 0.5);
--section-border: oklch(0.75 0.015 265 / 0.3);
--table-header-bg: oklch(0.93 0.006 260 / 0.6);
--table-border: oklch(0.8 0.01 265 / 0.3);
--table-hover: oklch(0.88 0.02 265 / 0.35);
--btn-bg: oklch(0.95 0.006 260 / 0.5);
--btn-border: oklch(0.75 0.02 265 / 0.35);
--btn-hover-bg: oklch(0.9 0.008 260 / 0.65);
--btn-hover-border: oklch(0.65 0.04 265 / 0.5);
--dot-bg: oklch(0.7 0.02 265 / 0.4);
--dot-active: oklch(0.55 0.2 235);
--link-color: oklch(0.5 0.2 235);
--link-hover: oklch(0.42 0.2 235);
--copy-feedback: oklch(0.5 0.2 150);
--status-glow: oklch(0.55 0.2 150);
--gradient-1: oklch(0.5 0.22 275);
--gradient-2: oklch(0.48 0.2 235);
--gradient-3: oklch(0.5 0.18 185);
--brand-1: oklch(0.5 0.24 275);
--brand-2: oklch(0.54 0.2 230);
--group-title-color: oklch(0.4 0.03 260);
--group-title-border: oklch(0.8 0.01 265 / 0.35);
--tag-bg-mix: oklch(0.96 0.005 260);
--launch-bg-mix: oklch(0.96 0.005 260);
--sheen-color: oklch(1 0 0 / 0.4);
--refraction-color: oklch(0.5 0.05 265 / 0.06);
}
* { font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; }
html { font-size: 110%; }
body {
position: relative;
min-height: 100vh;
overflow-x: hidden;
color: oklch(0.92 0.01 260);
color: var(--text-primary);
background:
radial-gradient(circle at 15% 8%, oklch(0.28 0.08 275 / 0.55), transparent 32rem),
radial-gradient(circle at 85% 10%, oklch(0.25 0.07 210 / 0.5), transparent 34rem),
radial-gradient(circle at 50% 88%, oklch(0.22 0.06 170 / 0.4), transparent 34rem),
linear-gradient(160deg, oklch(0.14 0.02 265), oklch(0.1 0.015 260) 60%, oklch(0.08 0.01 255));
radial-gradient(circle at 15% 8%, var(--bg-grad-1), transparent 32rem),
radial-gradient(circle at 85% 10%, var(--bg-grad-2), transparent 34rem),
radial-gradient(circle at 50% 88%, var(--bg-grad-3), transparent 34rem),
var(--bg-grad-linear);
transition: var(--transition-theme);
}
body::before {
content: "";
@@ -33,8 +156,8 @@
inset: 0;
pointer-events: none;
background-image:
linear-gradient(oklch(0.65 0.05 265 / 0.06) 1px, transparent 1px),
linear-gradient(90deg, oklch(0.65 0.05 265 / 0.06) 1px, transparent 1px);
linear-gradient(var(--grid-line) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
background-size: 48px 48px;
mask-image: radial-gradient(circle at 50% 20%, black, transparent 78%);
z-index: 0;
@@ -44,9 +167,9 @@
inset: -30%;
pointer-events: none;
background:
radial-gradient(circle at 22% 20%, oklch(0.5 0.2 275 / 0.28), transparent 24rem),
radial-gradient(circle at 78% 18%, oklch(0.48 0.16 210 / 0.24), transparent 28rem),
radial-gradient(circle at 54% 72%, oklch(0.5 0.15 165 / 0.2), transparent 28rem);
radial-gradient(circle at 22% 20%, var(--aurora-1), transparent 24rem),
radial-gradient(circle at 78% 18%, var(--aurora-2), transparent 28rem),
radial-gradient(circle at 54% 72%, var(--aurora-3), transparent 28rem);
filter: blur(60px) saturate(1.3);
animation: auroraShift 18s ease-in-out infinite alternate;
z-index: 0;
@@ -55,15 +178,20 @@
position: relative;
z-index: 1;
}
/* ===== 液态玻璃核心样式 ===== */
.glass-header {
background: oklch(0.1 0.015 260 / 0.95);
border-bottom: 1px solid oklch(0.3 0.03 265 / 0.5);
box-shadow: 0 10px 34px oklch(0 0 0 / 0.4);
background: var(--header-bg);
border-bottom: 1px solid var(--header-border);
box-shadow: 0 10px 34px var(--header-shadow);
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
transition: var(--transition-theme);
}
.brand-mark {
position: relative;
background: linear-gradient(135deg, oklch(0.62 0.24 275), oklch(0.66 0.18 230));
box-shadow: 0 8px 24px oklch(0.55 0.2 265 / 0.3);
background: linear-gradient(135deg, var(--brand-1), var(--brand-2));
box-shadow: 0 8px 24px color-mix(in oklch, var(--brand-1) 30%, transparent);
}
.brand-mark::after {
content: "";
@@ -76,7 +204,7 @@
z-index: -1;
}
.gradient-text {
background: linear-gradient(135deg, oklch(0.72 0.18 275), oklch(0.68 0.16 235), oklch(0.7 0.14 185));
background: linear-gradient(135deg, var(--gradient-1), var(--gradient-2), var(--gradient-3));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
@@ -84,16 +212,18 @@
.hero-panel {
position: relative;
overflow: hidden;
border: 1px solid oklch(0.32 0.04 265 / 0.55);
background: linear-gradient(145deg, oklch(0.16 0.02 265 / 0.7), oklch(0.12 0.015 260 / 0.5));
box-shadow: 0 24px 70px oklch(0 0 0 / 0.35), inset 0 1px 0 oklch(0.4 0.03 265 / 0.4);
backdrop-filter: blur(20px) saturate(1.2);
border: 1px solid var(--glass-border);
background: var(--glass-bg);
box-shadow: 0 24px 70px var(--glass-shadow), inset 0 1px 0 var(--glass-inset);
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
transition: var(--transition-theme);
}
.hero-panel::before {
content: "";
position: absolute;
inset: -1px;
background: conic-gradient(from 160deg at 50% 50%, transparent, oklch(0.6 0.2 275 / 0.22), transparent, oklch(0.6 0.16 200 / 0.16), transparent);
background: conic-gradient(from 160deg at 50% 50%, transparent, color-mix(in oklch, var(--gradient-1) 22%, transparent), transparent, color-mix(in oklch, var(--gradient-3) 16%, transparent), transparent);
opacity: 0.7;
animation: spinGlow 12s linear infinite;
}
@@ -102,11 +232,15 @@
z-index: 1;
}
.stat-pill {
background: oklch(0.18 0.02 265 / 0.6);
border: 1px solid oklch(0.3 0.03 265 / 0.5);
box-shadow: inset 0 1px 0 oklch(0.35 0.03 265 / 0.3);
backdrop-filter: blur(14px);
background: var(--glass-bg);
border: 1px solid var(--glass-border);
box-shadow: inset 0 1px 0 var(--glass-inset);
backdrop-filter: blur(14px) saturate(1.5);
-webkit-backdrop-filter: blur(14px) saturate(1.5);
transition: var(--transition-theme);
}
/* ===== 液态玻璃卡片 ===== */
.portal-card {
--mx: 50%;
--my: 0%;
@@ -114,11 +248,13 @@
--ry: 0deg;
position: relative;
overflow: hidden;
border: 1px solid oklch(0.3 0.03 265 / 0.5);
background: linear-gradient(145deg, oklch(0.17 0.02 265 / 0.92), oklch(0.13 0.012 260 / 0.88));
box-shadow: 0 18px 48px oklch(0 0 0 / 0.3), inset 0 1px 0 oklch(0.35 0.03 265 / 0.35);
border: 1px solid var(--glass-border);
background: var(--glass-bg);
box-shadow: 0 18px 48px var(--glass-shadow), inset 0 1px 0 var(--glass-inset);
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
transform-style: preserve-3d;
transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.32s ease, border-color 0.32s ease;
transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.32s ease, border-color 0.32s ease, background 0.5s ease;
will-change: transform;
}
.portal-card::before {
@@ -135,14 +271,15 @@
position: absolute;
inset: 0;
pointer-events: none;
background: linear-gradient(115deg, transparent 20%, oklch(0.8 0.02 260 / 0.12) 45%, transparent 70%);
background: linear-gradient(115deg, transparent 20%, var(--sheen-color) 45%, transparent 70%);
transform: translateX(-125%);
transition: transform 0.65s ease;
}
.portal-card:hover {
transform: translateY(-9px) rotateX(var(--rx)) rotateY(var(--ry));
border-color: color-mix(in oklch, var(--accent) 48%, oklch(0.3 0.03 265));
box-shadow: 0 26px 70px color-mix(in oklch, var(--accent) 28%, transparent), inset 0 1px 0 oklch(0.4 0.03 265 / 0.4);
border-color: color-mix(in oklch, var(--accent) 48%, var(--glass-border));
box-shadow: 0 26px 70px color-mix(in oklch, var(--accent) 28%, transparent), inset 0 1px 0 var(--glass-inset);
background: var(--glass-bg-hover);
}
.portal-card:hover::before { opacity: 1; }
.portal-card:hover::after { transform: translateX(125%); }
@@ -173,18 +310,18 @@
}
.tag-pill {
color: var(--accent);
background: color-mix(in oklch, var(--accent) 14%, oklch(0.15 0.015 260));
background: color-mix(in oklch, var(--accent) 14%, var(--tag-bg-mix));
border: 1px solid color-mix(in oklch, var(--accent) 22%, transparent);
}
.launch-link {
color: var(--accent);
background: color-mix(in oklch, var(--accent) 12%, oklch(0.15 0.015 260));
background: color-mix(in oklch, var(--accent) 12%, var(--launch-bg-mix));
border: 1px solid color-mix(in oklch, var(--accent) 18%, transparent);
transition: transform 0.25s ease, background 0.25s ease;
}
.portal-card:hover .launch-link {
transform: translateX(2px);
background: color-mix(in oklch, var(--accent) 18%, oklch(0.15 0.015 260));
background: color-mix(in oklch, var(--accent) 18%, var(--launch-bg-mix));
}
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(22px) scale(0.98); }
@@ -222,10 +359,11 @@
.group-title {
font-size: 0.8rem;
font-weight: 800;
color: oklch(0.72 0.04 260);
color: var(--group-title-color);
padding: 0.5rem 0 0.25rem;
border-bottom: 1px solid oklch(0.25 0.02 265 / 0.4);
border-bottom: 1px solid var(--group-title-border);
margin-bottom: 0.75rem;
transition: var(--transition-theme);
}
.carousel-page {
flex: 0 0 100%;
@@ -241,7 +379,6 @@
@media (max-width: 520px) {
.carousel-page { grid-template-columns: 1fr; }
}
/* 手机端竖向列表 */
.mobile-app-list { display: none; }
@media (max-width: 768px) {
.mobile-app-list { display: block; }
@@ -249,10 +386,11 @@
.mobile-group-title {
font-size: 0.75rem;
font-weight: 800;
color: oklch(0.72 0.04 260);
color: var(--group-title-color);
padding: 0.75rem 0 0.25rem;
border-bottom: 1px solid oklch(0.25 0.02 265 / 0.4);
border-bottom: 1px solid var(--group-title-border);
margin-bottom: 0.5rem;
transition: var(--transition-theme);
}
.mobile-app-list .portal-card {
margin-bottom: 0.75rem;
@@ -270,16 +408,18 @@
display: flex;
align-items: center;
justify-content: center;
color: oklch(0.7 0.02 260);
background: oklch(0.15 0.015 260 / 0.8);
border: 1px solid oklch(0.3 0.03 265 / 0.5);
color: var(--text-secondary);
background: var(--btn-bg);
border: 1px solid var(--btn-border);
backdrop-filter: blur(12px) saturate(1.5);
-webkit-backdrop-filter: blur(12px) saturate(1.5);
cursor: pointer;
transition: all 0.25s ease;
}
.carousel-btn:hover {
color: oklch(0.9 0.05 260);
background: oklch(0.2 0.02 260 / 0.9);
border-color: oklch(0.4 0.05 265 / 0.6);
color: var(--text-primary);
background: var(--btn-hover-bg);
border-color: var(--btn-hover-border);
}
.carousel-btn:disabled {
opacity: 0.3;
@@ -297,26 +437,29 @@
width: 0.5rem;
height: 0.5rem;
border-radius: 50%;
background: oklch(0.3 0.02 265 / 0.5);
background: var(--dot-bg);
border: none;
cursor: pointer;
transition: all 0.25s ease;
padding: 0;
}
.carousel-dot.active {
background: oklch(0.68 0.16 235);
background: var(--dot-active);
width: 1.25rem;
border-radius: 0.25rem;
}
.contact-section {
border: 1px solid oklch(0.3 0.03 265 / 0.5);
background: linear-gradient(145deg, oklch(0.17 0.02 265 / 0.92), oklch(0.13 0.012 260 / 0.88));
border: 1px solid var(--glass-border);
background: var(--glass-bg);
border-radius: 1rem;
box-shadow: 0 18px 48px oklch(0 0 0 / 0.3), inset 0 1px 0 oklch(0.35 0.03 265 / 0.35);
box-shadow: 0 18px 48px var(--glass-shadow), inset 0 1px 0 var(--glass-inset);
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
transition: var(--transition-theme);
}
.contact-qr {
border-radius: 0.625rem;
border: 2px solid oklch(0.35 0.04 265 / 0.6);
border: 2px solid var(--glass-border);
}
@media (max-width: 520px) {
.contact-qr { width: 110px !important; height: 150px !important; }
@@ -334,21 +477,25 @@
}
}
.help-btn {
color: oklch(0.7 0.02 260);
background: oklch(0.15 0.015 260 / 0.6);
border: 1px solid oklch(0.3 0.03 265 / 0.5);
color: var(--text-secondary);
background: var(--btn-bg);
border: 1px solid var(--btn-border);
backdrop-filter: blur(10px) saturate(1.4);
-webkit-backdrop-filter: blur(10px) saturate(1.4);
transition: all 0.25s ease;
}
.help-btn:hover {
color: oklch(0.85 0.05 260);
background: oklch(0.2 0.02 260 / 0.7);
border-color: oklch(0.4 0.05 265 / 0.6);
color: var(--text-primary);
background: var(--btn-hover-bg);
border-color: var(--btn-hover-border);
}
.help-overlay {
position: fixed;
inset: 0;
z-index: 100;
background: oklch(0.05 0.01 255);
background: var(--overlay-bg);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
display: flex;
align-items: center;
justify-content: center;
@@ -366,16 +513,18 @@
pointer-events: auto;
}
.help-modal {
background: oklch(0.13 0.015 260 / 0.98);
border: 1px solid oklch(0.3 0.03 265 / 0.55);
box-shadow: 0 30px 80px oklch(0 0 0 / 0.5);
background: var(--modal-bg);
border: 1px solid var(--modal-border);
box-shadow: 0 30px 80px var(--modal-shadow);
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
max-width: 64rem;
width: 100%;
max-height: 85vh;
overflow-y: auto;
border-radius: 1rem;
transform: translateY(20px) scale(0.97);
transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), background 0.5s ease, border-color 0.5s ease;
will-change: transform;
}
.help-overlay.active .help-modal {
@@ -383,11 +532,14 @@
}
.help-modal::-webkit-scrollbar { width: 6px; }
.help-modal::-webkit-scrollbar-track { background: transparent; }
.help-modal::-webkit-scrollbar-thumb { background: oklch(0.3 0.03 265 / 0.5); border-radius: 3px; }
.help-modal::-webkit-scrollbar-thumb { background: var(--dot-bg); border-radius: 3px; }
.help-section {
border: 1px solid oklch(0.25 0.02 265 / 0.4);
background: oklch(0.1 0.01 260 / 0.5);
border: 1px solid var(--section-border);
background: var(--section-bg);
border-radius: 0.625rem;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
transition: var(--transition-theme);
}
.help-table {
width: 100%;
@@ -399,18 +551,18 @@
-webkit-overflow-scrolling: touch;
}
.help-table th {
background: oklch(0.15 0.015 260 / 0.6);
color: oklch(0.7 0.02 260);
background: var(--table-header-bg);
color: var(--text-secondary);
font-weight: 600;
text-align: left;
padding: 6px 10px;
border-bottom: 1px solid oklch(0.25 0.02 265 / 0.4);
border-bottom: 1px solid var(--table-border);
white-space: nowrap;
}
.help-table td {
padding: 5px 10px;
border-bottom: 1px solid oklch(0.2 0.015 265 / 0.3);
color: oklch(0.8 0.01 260);
border-bottom: 1px solid var(--table-border);
color: var(--text-primary);
}
.help-table td.copy-cell {
cursor: pointer;
@@ -418,14 +570,14 @@
border-radius: 0.25rem;
}
.help-table td.copy-cell:hover {
color: oklch(0.9 0.05 260);
background: oklch(0.2 0.03 265 / 0.4);
color: var(--text-heading);
background: var(--table-hover);
}
.help-table td.copy-cell:active {
background: oklch(0.25 0.04 265 / 0.5);
background: var(--table-hover);
}
.copy-feedback {
color: oklch(0.72 0.18 150) !important;
color: var(--copy-feedback) !important;
}
.help-table tr:last-child td { border-bottom: none; }
.aurora-paused {
@@ -440,11 +592,44 @@
backdrop-filter: none !important;
}
.help-link {
color: oklch(0.68 0.16 235);
color: var(--link-color);
text-decoration: none;
transition: color 0.2s ease;
}
.help-link:hover { color: oklch(0.78 0.16 235); text-decoration: underline; }
.help-link:hover { color: var(--link-hover); text-decoration: underline; }
/* ===== 主题切换按钮 ===== */
.theme-toggle {
color: var(--text-secondary);
background: var(--btn-bg);
border: 1px solid var(--btn-border);
backdrop-filter: blur(10px) saturate(1.4);
-webkit-backdrop-filter: blur(10px) saturate(1.4);
transition: all 0.25s ease;
}
.theme-toggle:hover {
color: var(--text-primary);
background: var(--btn-hover-bg);
border-color: var(--btn-hover-border);
}
.theme-toggle .sun-icon { display: none; }
.theme-toggle .moon-icon { display: block; }
:root[data-theme="light"] .theme-toggle .sun-icon { display: block; }
:root[data-theme="light"] .theme-toggle .moon-icon { display: none; }
/* ===== 浅色模式文字适配 ===== */
:root[data-theme="light"] .text-slate-100 { color: oklch(0.2 0.01 260) !important; }
:root[data-theme="light"] .text-slate-400 { color: oklch(0.45 0.02 260) !important; }
:root[data-theme="light"] .text-slate-500 { color: oklch(0.5 0.02 260) !important; }
:root[data-theme="light"] .text-slate-300 { color: oklch(0.35 0.02 260) !important; }
:root[data-theme="light"] .bg-white\/5 { background: oklch(0 0 0 / 0.04) !important; }
:root[data-theme="light"] .ring-white\/10 { --tw-ring-color: oklch(0 0 0 / 0.08) !important; }
:root[data-theme="light"] .border-white\/10 { border-color: oklch(0 0 0 / 0.08) !important; }
:root[data-theme="light"] .border-white\/5 { border-color: oklch(0 0 0 / 0.05) !important; }
:root[data-theme="light"] .group-hover\:text-white:hover { color: oklch(0.15 0.01 260) !important; }
:root[data-theme="light"] .bg-emerald-400 { background: oklch(0.6 0.2 150) !important; }
:root[data-theme="light"] .from-indigo-500 { --tw-gradient-from: oklch(0.5 0.24 275) !important; }
:root[data-theme="light"] .to-violet-500 { --tw-gradient-to: oklch(0.54 0.2 230) !important; }
</style>
</head>
<body class="antialiased relative">
@@ -467,6 +652,10 @@
<span class="h-1.5 w-1.5 rounded-full bg-emerald-400 shadow-[0_0_12px_oklch(0.72_0.18_150)]"></span>
20 个智能应用在线 / 20 Apps Online
</span>
<button class="theme-toggle w-7 h-7 rounded-full flex items-center justify-center" onclick="toggleTheme()" aria-label="切换主题 / Toggle Theme">
<svg class="moon-icon w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
<svg class="sun-icon w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg>
</button>
<button class="help-btn w-7 h-7 rounded-full flex items-center justify-center" onclick="toggleHelpModal(true)" aria-label="帮助 / Help">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 18v-3"/><circle cx="12" cy="12" r="9"/><path d="M8.5 8.5a3.5 3.5 0 1 1 5 3c-1 .5-1.5 1-1.5 2"/></svg>
</button>
@@ -510,6 +699,10 @@
<!-- Footer -->
<footer class="mt-10 pt-5 border-t border-white/10 text-center text-[11px] text-slate-500">
<p>&copy; 2026 AI 应用门户 · AI Application Portal</p>
<p id="visitorCount" class="mt-1.5 inline-flex items-center gap-1.5 opacity-0 transition-opacity duration-500">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.5 12C4 7.5 7.7 5 12 5s8 2.5 9.5 7c-1.5 4.5-5.2 7-9.5 7s-8-2.5-9.5-7z"/></svg>
<span>本站已被访问 <strong id="visitorCountNum" class="font-bold text-slate-400">--</strong></span>
</p>
</footer>
</main>
@@ -549,6 +742,12 @@
</div>
<script>
(function() {
const saved = localStorage.getItem('portal-theme');
const theme = saved || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark');
document.documentElement.setAttribute('data-theme', theme);
})();
const iconPaths = {
chart: '<path d="M4 19V5"/><path d="M4 19h16"/><path d="M8 16v-5"/><path d="M12 16V8"/><path d="M16 16v-8"/>',
network: '<path d="M12 5a3 3 0 1 0 0 6 3 3 0 0 0 0-6z"/><path d="M5.5 17a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5z"/><path d="M18.5 17a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5z"/><path d="M10.2 10.4 6.8 17"/><path d="m13.8 10.4 3.4 6.6"/>',
@@ -972,6 +1171,30 @@
renderCarousel();
renderMobileList();
/**
* 调用第三方计数 API 获取并递增全局访问量,更新页脚显示。
*/
function updateVisitorCount() {
const countKey = 'all8ai-portal-visits-2026';
const url = `https://countapi.mileshilliard.com/api/v1/hit/${countKey}`;
fetch(url)
.then(res => res.json())
.then(data => {
if (data && data.value !== undefined) {
const count = Number(data.value);
const numEl = document.getElementById('visitorCountNum');
const numEnEl = document.getElementById('visitorCountNumEn');
const wrapEl = document.getElementById('visitorCount');
if (numEl) numEl.textContent = count.toLocaleString();
if (numEnEl) numEnEl.textContent = count.toLocaleString();
if (wrapEl) wrapEl.style.opacity = '1';
}
})
.catch(() => {});
}
updateVisitorCount();
/**
* 帮助弹窗的测试账号数据,中英双语展示。
*/
@@ -1202,6 +1425,13 @@
document.body.classList.remove('gpu-off');
}
}
function toggleTheme() {
const current = document.documentElement.getAttribute('data-theme');
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('portal-theme', next);
}
</script>
</body>
</html>