guanghulab/homepage/index.html.bak2
Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

571 lines
52 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>光湖 · 铸渊本体 · 代码联邦</title>
<meta name="description" content="光湖语言世界 · 语言人格驱动操作系统">
<meta name="theme-color" content="#0b1424">
<style>
*{margin:0;padding:0;box-sizing:border-box}
:root{
--deep:#0b1424;--mid:#141e30;--shallow:#1a2a44;
--cyan:#2a9dbf;--glow:#5ad0e0;--light:#d4eaf0;
--violet:#7b5dbf;--violet-glow:#a080e8;
--amber:#d4a030;--amber-glow:#f0d060;
--green:#40b87a;--heart:#e04a74;
--text:#e4ecf5;--text-soft:#8aa0b8;--text-faint:#5a7088;
--glass:rgba(11,20,36,.7);--glass-edge:rgba(90,208,224,.08);
--card-bg:rgba(11,20,36,.4);--border:rgba(90,208,224,.10);
--shadow:0 8px 32px rgba(0,0,0,.3);
}
@keyframes breathe-cyan{0%,100%{box-shadow:0 0 4px rgba(42,157,191,.08),0 0 12px rgba(42,157,191,.02)}50%{box-shadow:0 0 10px rgba(42,157,191,.28),0 0 28px rgba(42,157,191,.1)}}
@keyframes breathe-heart{0%,100%{box-shadow:0 0 4px rgba(224,74,116,.08),0 0 12px rgba(224,74,116,.02)}50%{box-shadow:0 0 10px rgba(224,74,116,.28),0 0 28px rgba(224,74,116,.1)}}
@keyframes breathe-violet{0%,100%{box-shadow:0 0 4px rgba(123,93,191,.08),0 0 12px rgba(123,93,191,.02)}50%{box-shadow:0 0 10px rgba(123,93,191,.28),0 0 28px rgba(123,93,191,.1)}}
@keyframes breathe-amber{0%,100%{box-shadow:0 0 4px rgba(212,160,48,.08),0 0 12px rgba(212,160,48,.02)}50%{box-shadow:0 0 10px rgba(212,160,48,.28),0 0 28px rgba(212,160,48,.1)}}
@keyframes breathe-green{0%,100%{box-shadow:0 0 4px rgba(64,184,122,.08),0 0 12px rgba(64,184,122,.02)}50%{box-shadow:0 0 10px rgba(64,184,122,.28),0 0 28px rgba(64,184,122,.1)}}
@keyframes led-pulse{0%,100%{opacity:.5}50%{opacity:1}}
@keyframes logo-pulse{0%,100%{box-shadow:0 0 24px rgba(90,208,224,.2);transform:scale(1)}50%{box-shadow:0 0 44px rgba(90,208,224,.38);transform:scale(1.06)}}
@keyframes shimmer{0%{transform:translateX(-100%)}100%{transform:translateX(100%)}}
html{background:var(--deep);color:var(--text)}
body{
min-height:100vh;background:var(--deep);
font-family:'SF Pro Display','Inter','PingFang SC','Noto Sans SC','HarmonyOS Sans SC',system-ui,-apple-system,sans-serif;
-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
overflow-x:hidden;display:flex;flex-direction:column
}
::selection{background:rgba(90,208,224,.2);color:var(--light)}
#cosmos{position:fixed;inset:0;z-index:-5;overflow:hidden}
#cosmos-bg{position:absolute;inset:0;background:radial-gradient(ellipse at 15% 20%,#1a2e48 0%,#0b1424 70%),radial-gradient(ellipse at 80% 80%,rgba(60,30,100,.15),transparent 60%)}
.star-layer{position:absolute;inset:0}
.star{position:absolute;border-radius:50%;background:#fff}
.star-s{animation:st-s var(--d,8s) ease-in-out infinite alternate}
@keyframes st-s{0%{opacity:.1}100%{opacity:.7}}
.star-m{animation:st-m var(--d,12s) ease-in-out infinite alternate}
@keyframes st-m{0%{opacity:.05;transform:scale(.8)}100%{opacity:.5;transform:scale(1.3)}}
.star-l{animation:st-l var(--d,15s) ease-in-out infinite alternate}
@keyframes st-l{0%{opacity:0;transform:translateY(0)}100%{opacity:.6;transform:translateY(-30px)}}
.nebula{position:absolute;border-radius:50%;filter:blur(100px);pointer-events:none;opacity:.12}
.nebula-1{width:700px;height:500px;top:-8%;left:-12%;background:radial-gradient(circle,rgba(42,157,191,.12),transparent);animation:n1 50s ease-in-out infinite alternate}
.nebula-2{width:600px;height:600px;bottom:-12%;right:-8%;background:radial-gradient(circle,rgba(123,93,191,.1),transparent);animation:n2 45s ease-in-out infinite alternate}
@keyframes n1{0%{transform:translate(0,0) scale(1)}100%{transform:translate(80px,60px) scale(1.4)}}
@keyframes n2{0%{transform:translate(0,0) scale(1)}100%{transform:translate(-60px,-40px) scale(1.3)}}
.topbar{position:fixed;top:0;left:0;right:0;height:72px;display:flex;align-items:center;justify-content:space-between;padding:0 48px;background:rgba(11,20,36,.75);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border-bottom:1px solid var(--glass-edge);z-index:50}
.tb-left{display:flex;align-items:center;gap:18px}
.tb-logo{width:36px;height:36px;border-radius:50%;background:radial-gradient(circle at 35% 30%,var(--glow),var(--cyan) 55%,var(--violet));box-shadow:0 0 24px rgba(90,208,224,.2);animation:logo-pulse 4s ease-in-out infinite;flex-shrink:0}
.tb-title{font-size:18px;font-weight:600;letter-spacing:.18em;color:var(--light)}
.tb-center{display:flex;align-items:center;gap:12px;font-size:14px;color:var(--text-soft)}
.tb-center .dot{width:9px;height:9px;border-radius:50%;background:var(--green);box-shadow:0 0 14px var(--green);animation:led-pulse 3s ease-in-out infinite}
.tb-center strong{color:var(--light);font-weight:600}
.tb-right{display:flex;align-items:center;gap:14px}
.tb-tag{font-size:13px;padding:6px 18px;border-radius:16px;border:1px solid var(--glass-edge);color:var(--text-soft);letter-spacing:.05em;background:rgba(255,255,255,.02)}
.page{flex:1;display:flex;flex-direction:column;padding-top:72px;min-height:100vh;position:relative;z-index:1}
.hero{text-align:center;padding:64px 32px 24px}
.hero h1{font-size:3.6rem;font-weight:600;letter-spacing:.12em;background:linear-gradient(135deg,var(--light) 30%,var(--glow) 60%,var(--violet-glow));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;text-shadow:none}
.hero .sub{font-size:15px;letter-spacing:.4em;color:var(--text-soft);margin-top:12px;font-weight:400}
.info-bar{display:flex;justify-content:center;gap:28px;padding:16px 32px;flex-wrap:wrap}
.info-chip{display:flex;align-items:center;gap:10px;padding:10px 24px;background:var(--card-bg);border:1px solid var(--glass-edge);border-radius:24px;font-size:15px;color:var(--text-soft);font-weight:400}
.info-chip strong{color:var(--light);font-weight:600}
.info-chip .led{width:9px;height:9px;border-radius:50%;flex-shrink:0}
.info-chip .led.g{background:var(--green);box-shadow:0 0 12px var(--green);animation:led-pulse 3s ease-in-out infinite}
.info-chip .led.r{background:var(--heart);box-shadow:0 0 12px var(--heart);animation:led-pulse 1.5s ease-in-out infinite}
#heart-wrapper{position:fixed;bottom:120px;left:50%;transform:translateX(-50%);z-index:-1;pointer-events:none}
#heart-core{width:440px;height:440px;border-radius:50%;background:radial-gradient(circle at 45% 40%,rgba(224,74,116,.08),rgba(90,208,224,.025) 40%,transparent 70%);animation:heartbeat 4s ease-in-out infinite;transform-origin:center}
#heart-core::after{content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:180px;height:180px;border-radius:50%;background:radial-gradient(circle,rgba(224,74,116,.04),transparent 70%);animation:pulse-glow 4s ease-in-out infinite}
@keyframes heartbeat{0%,100%{transform:scale(1);opacity:.3}14%{transform:scale(1.08);opacity:.55}21%{transform:scale(1);opacity:.3}28%{transform:scale(1.05);opacity:.45}35%{transform:scale(1);opacity:.3}}
@keyframes pulse-glow{0%,100%{opacity:.2;transform:translate(-50%,-50%) scale(1)}50%{opacity:.6;transform:translate(-50%,-50%) scale(2.2)}}
.shooting-star{position:absolute;width:3px;height:3px;background:#fff;border-radius:50%;opacity:0;box-shadow:0 0 6px #fff,0 0 14px rgba(90,208,224,.4)}
.shooting-star::after{content:'';position:absolute;top:0;left:0;width:80px;height:1px;background:linear-gradient(90deg,rgba(255,255,255,.6),transparent);transform:translateY(1px)}
@keyframes shoot{0%{opacity:0;transform:translate(0,0)}5%{opacity:1}15%{opacity:0}100%{opacity:0;transform:translate(450px,350px)}}
.dashboard{max-width:1040px;margin:0 auto;padding:0 32px 40px;display:flex;flex-direction:column;gap:24px;width:100%}
.row{display:grid;gap:16px}
.row-2{grid-template-columns:1fr 1fr}
.row-3{grid-template-columns:1fr 1fr 1fr}
@media(max-width:860px){.row-2,.row-3{grid-template-columns:1fr}}
/* ── 呼吸卡片系统 ── */
.card{background:var(--card-bg);border:1px solid var(--glass-edge);border-radius:20px;padding:28px;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);transition:all .35s ease;box-shadow:var(--shadow);cursor:default;position:relative;overflow:hidden}
.card.clickable{cursor:pointer}
.card.clickable:hover{transform:translateY(-3px);border-color:rgba(90,208,224,.18)}
.card.clickable:active{transform:scale(.97)}
.card.clickable:hover::after{opacity:1}
.card.clickable::after{content:'';position:absolute;inset:0;border-radius:20px;opacity:0;transition:opacity .35s;background:radial-gradient(ellipse at 50% 0%,rgba(90,208,224,.04),transparent 70%);pointer-events:none}
.bg-cyan{animation:breathe-cyan 4s ease-in-out infinite}
.bg-heart{animation:breathe-heart 4s ease-in-out infinite}
.bg-violet{animation:breathe-violet 5s ease-in-out infinite}
.bg-amber{animation:breathe-amber 4.5s ease-in-out infinite}
.bg-green{animation:breathe-green 3.5s ease-in-out infinite}
.card-header{font-size:15px;font-weight:500;letter-spacing:.08em;color:var(--light);margin-bottom:20px;display:flex;align-items:center;gap:12px}
.card-header .hd{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.card-header .hd.cyan{background:var(--glow);box-shadow:0 0 12px var(--glow)}
.card-header .hd.green{background:var(--green);box-shadow:0 0 12px var(--green)}
.card-header .hd.violet{background:var(--violet-glow);box-shadow:0 0 12px var(--violet-glow)}
.card-header .hd.heart{background:var(--heart);box-shadow:0 0 12px var(--heart);animation:led-pulse 2s ease-in-out infinite}
.card-header .r{font-size:13px;font-weight:400;color:var(--text-soft);margin-left:auto}
.p-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.p-item{display:flex;align-items:center;gap:16px;padding:16px 20px;background:rgba(255,255,255,.025);border:1px solid var(--glass-edge);border-radius:16px;transition:all .3s;cursor:pointer}
.p-item:hover{background:rgba(255,255,255,.04);transform:translateY(-2px);border-color:rgba(90,208,224,.15)}
.p-item:active{transform:scale(.97)}
.p-av{width:48px;height:48px;border-radius:14px;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;font-weight:500}
.p-av.cyan{background:rgba(42,157,191,.12);color:var(--glow)}
.p-av.heart{background:rgba(224,74,116,.1);color:var(--heart)}
.p-av.violet{background:rgba(123,93,191,.12);color:var(--violet-glow)}
.p-av.green{background:rgba(64,184,122,.1);color:var(--green)}
.p-info{flex:1;min-width:0}
.p-name{font-size:16px;font-weight:600;color:var(--light)}
.p-role{font-size:14px;color:var(--text-soft);margin-top:3px}
.p-status{font-size:13px;font-weight:500;padding:4px 14px;border-radius:14px;flex-shrink:0}
.p-status.go{background:rgba(64,184,122,.12);color:var(--green);border:1px solid rgba(64,184,122,.08)}
.p-status.tr{background:rgba(224,74,116,.1);color:var(--heart);border:1px solid rgba(224,74,116,.08)}
.p-status.dv{background:rgba(212,160,48,.1);color:var(--amber);border:1px solid rgba(212,160,48,.08)}
.sys-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.sys-row{display:flex;justify-content:space-between;padding:12px 0;border-bottom:1px solid var(--glass-edge);font-size:15px}
.sys-row:last-child{border-bottom:none}
.sys-row .k{color:var(--text-soft)}
.sys-row .v{color:var(--light);font-weight:500;font-variant-numeric:tabular-nums}
.sys-row .v.cyan{color:var(--glow)}
.sys-row .v.green{color:var(--green)}
#chat-card .c-msg{max-width:85%;display:flex;flex-direction:column}
#chat-card .c-msg.user{align-self:flex-end}
#chat-card .c-msg.bot{align-self:flex-start}
#chat-card .c-c{padding:14px 18px;border-radius:14px;font-size:15px;line-height:1.7;white-space:pre-wrap}
#chat-card .c-msg.user .c-c{background:rgba(42,157,191,.12);border:1px solid rgba(42,157,191,.1);color:var(--text)}
#chat-card .c-msg.bot .c-c{background:rgba(123,93,191,.08);border:1px solid rgba(123,93,191,.06);color:var(--text)}
#chat-card .c-msg.loading .c-c{opacity:.5}
#chat-card-body{display:flex;flex-direction:column;gap:0}
#chat-card-msgs{max-height:440px;overflow-y:auto;padding:0 0 14px 0;display:flex;flex-direction:column;gap:10px;scroll-behavior:smooth}
#chat-card-msgs::-webkit-scrollbar{width:4px}
#chat-card-msgs::-webkit-scrollbar-track{background:transparent}
#chat-card-msgs::-webkit-scrollbar-thumb{background:rgba(90,208,224,.1);border-radius:2px}
#chat-card-inp{display:flex;gap:12px;border-top:1px solid var(--glass-edge);padding-top:14px}
#card-chat-input{flex:1;padding:14px 18px;background:rgba(255,255,255,.025);border:1px solid var(--glass-edge);border-radius:14px;color:var(--text);font-size:15px;outline:none;font-family:inherit}
#card-chat-input:focus{border-color:rgba(90,208,224,.2)}
#chat-card-inp button{padding:14px 32px;background:linear-gradient(135deg,rgba(42,157,191,.3),rgba(123,93,191,.2));border:1px solid var(--glass-edge);border-radius:14px;color:var(--light);cursor:pointer;font-size:15px;font-weight:500;transition:all .25s;font-family:inherit;white-space:nowrap}
#chat-card-inp button:hover{background:linear-gradient(135deg,rgba(42,157,191,.5),rgba(123,93,191,.35));transform:translateY(-1px);border-color:rgba(90,208,224,.2)}
#chat-card-inp button:active{transform:scale(.97)}
.feed{display:flex;flex-direction:column;gap:8px}
.feed-item{display:flex;align-items:center;gap:16px;padding:14px 18px;background:rgba(255,255,255,.02);border:1px solid var(--glass-edge);border-radius:14px;transition:all .3s;font-size:15px;cursor:pointer}
.feed-item:hover{background:rgba(255,255,255,.035);transform:translateX(3px);border-color:rgba(90,208,224,.1)}
.feed-item:active{transform:scale(.98)}
.feed-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
.feed-dot.c{background:var(--glow);box-shadow:0 0 10px var(--glow)}
.feed-dot.v{background:var(--violet-glow);box-shadow:0 0 10px var(--violet-glow)}
.feed-dot.g{background:var(--green);box-shadow:0 0 10px var(--green)}
.feed-dot.h{background:var(--heart);box-shadow:0 0 12px var(--heart);animation:feed-h 2s ease-in-out infinite}
@keyframes feed-h{0%,100%{transform:scale(1)}50%{transform:scale(1.4)}}
.feed-u{color:var(--glow);font-weight:600}
.feed-a{color:var(--text-soft)}
.feed-r{color:var(--violet-glow);font-weight:500}
.feed-t{color:var(--text-faint);font-size:13px;margin-left:auto;flex-shrink:0}
.login-panel{display:flex;align-items:center;justify-content:space-between;padding:20px 28px;background:rgba(11,20,36,.5);border:1px solid var(--glass-edge);border-radius:18px;gap:16px;flex-wrap:wrap}
.login-hint{font-size:15px;color:var(--text-soft)}
.login-hint strong{color:var(--light);font-weight:600}
.login-in{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.login-in input{padding:12px 18px;background:rgba(255,255,255,.035);border:1px solid var(--glass-edge);border-radius:14px;color:var(--text);font-size:15px;outline:none;transition:all .25s;font-family:inherit;width:140px;font-weight:400}
.login-in input:focus{border-color:rgba(90,208,224,.3);box-shadow:0 0 20px rgba(42,157,191,.08)}
.login-in input::placeholder{color:var(--text-faint)}
.login-in button{padding:12px 28px;background:linear-gradient(135deg,rgba(42,157,191,.3),rgba(123,93,191,.2));border:1px solid var(--glass-edge);border-radius:14px;color:var(--light);font-size:15px;font-weight:500;cursor:pointer;transition:all .25s;font-family:inherit;letter-spacing:.08em}
.login-in button:hover{background:linear-gradient(135deg,rgba(42,157,191,.5),rgba(123,93,191,.35));border-color:rgba(90,208,224,.2);transform:translateY(-1px)}
.login-in button:active{transform:scale(.97)}
.login-note{margin-top:12px;font-size:13px;color:var(--text-faint);line-height:1.6}
.login-note a{color:var(--glow);text-decoration:none}
.login-note a:hover{text-decoration:underline}
.notion-card{min-height:140px;display:flex;flex-direction:column}
.notion-body{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:8px 0}
.notion-btn{display:inline-flex;align-items:center;gap:10px;padding:12px 26px;margin-top:14px;background:linear-gradient(135deg,rgba(123,93,191,.2),rgba(42,157,191,.1));border:1px solid var(--glass-edge);border-radius:14px;color:var(--light);font-size:15px;font-weight:500;cursor:pointer;transition:all .25s;font-family:inherit}
.notion-btn:hover{background:linear-gradient(135deg,rgba(123,93,191,.35),rgba(42,157,191,.2));border-color:rgba(90,208,224,.2);transform:translateY(-2px)}
.notion-btn:active{transform:scale(.97)}
.notion-btn .nb-dot{width:8px;height:8px;border-radius:50%;background:var(--text-faint);flex-shrink:0}
.notion-btn.done{background:rgba(64,184,122,.12);border-color:rgba(64,184,122,.2);color:var(--green)}
.notion-btn.done .nb-dot{background:var(--green);box-shadow:0 0 10px var(--green)}
.notion-perm{font-size:13px;color:var(--text-faint);margin-top:12px;line-height:1.6}
.notion-perm .ok{color:var(--green)}
.notion-perm .no{color:var(--text-faint)}
.footer{text-align:center;padding:28px;font-size:14px;color:var(--text-faint);letter-spacing:.12em;border-top:1px solid var(--glass-edge);margin-top:auto;position:relative;z-index:1;font-weight:400}
#login-bar{display:flex;align-items:center;justify-content:space-between;padding:20px 28px;background:rgba(11,20,36,.5);border:1px solid var(--glass-edge);border-radius:18px;gap:16px;flex-wrap:wrap}
#login-bar .hint{font-size:15px;color:var(--text-soft)}
#login-bar .hint strong{color:var(--light);font-weight:600}
#logged-in-bar{display:none;align-items:center;justify-content:space-between;padding:18px 28px;background:rgba(64,184,122,.06);border:1px solid rgba(64,184,122,.15);border-radius:18px;gap:16px;flex-wrap:wrap}
#logged-in-bar .user-badge{display:flex;align-items:center;gap:12px}
#logged-in-bar .user-avatar{width:40px;height:40px;border-radius:50%;background:linear-gradient(135deg,rgba(42,157,191,.4),rgba(123,93,191,.3));display:flex;align-items:center;justify-content:center;font-size:18px;color:var(--light);font-weight:600}
#logged-in-bar .user-name{font-size:16px;font-weight:600;color:var(--light)}
#logged-in-bar .user-status{font-size:13px;color:var(--green)}
.logged-actions{display:flex;gap:12px;flex-wrap:wrap}
.logged-actions button{padding:12px 26px;border-radius:14px;font-size:15px;font-weight:500;cursor:pointer;transition:all .25s;font-family:inherit}
.logged-actions .btn-primary{background:linear-gradient(135deg,rgba(42,157,191,.35),rgba(123,93,191,.25));border:1px solid var(--glass-edge);color:var(--light)}
.logged-actions .btn-primary:hover{background:linear-gradient(135deg,rgba(42,157,191,.55),rgba(123,93,191,.4));transform:translateY(-1px)}
.logged-actions .btn-secondary{background:rgba(255,255,255,.03);border:1px solid var(--glass-edge);color:var(--text-soft)}
.logged-actions .btn-secondary:hover{background:rgba(255,255,255,.06);color:var(--light);transform:translateY(-1px)}
.logged-actions .btn-logout{background:transparent;border:1px solid rgba(224,74,116,.2);color:var(--heart);font-size:14px}
.logged-actions .btn-logout:hover{background:rgba(224,74,116,.08)}
.login-error{color:var(--heart);font-size:14px;margin-top:8px;display:none}
.login-loading{color:var(--text-soft);font-size:14px;margin-top:8px;display:none}
/* ── 浮窗Chat ── */
#chat-toggle{position:fixed;bottom:28px;right:28px;width:56px;height:56px;border-radius:50%;background:linear-gradient(135deg,rgba(42,157,191,.5),rgba(123,93,191,.35));border:1px solid var(--glass-edge);display:flex;align-items:center;justify-content:center;color:var(--light);cursor:pointer;z-index:100;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);transition:all .4s cubic-bezier(.22,1,.36,1);box-shadow:0 6px 28px rgba(0,0,0,.4);animation:cp 4s ease-in-out infinite}
@keyframes cp{0%,100%{box-shadow:0 6px 28px rgba(0,0,0,.4)}50%{box-shadow:0 6px 40px rgba(90,208,224,.15),0 6px 28px rgba(0,0,0,.4)}}
#chat-toggle:hover{transform:scale(1.12);border-color:rgba(90,208,224,.35)}
#chat-toggle:active{transform:scale(.95)}
#chat-panel{position:fixed;bottom:94px;right:28px;width:400px;height:540px;background:rgba(11,20,36,.96);border:1px solid var(--glass-edge);border-radius:18px;backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);z-index:100;display:none;flex-direction:column;overflow:hidden;box-shadow:0 12px 60px rgba(0,0,0,.5)}
#chat-panel.open{display:flex}
#chat-head{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid var(--glass-edge);font-size:15px;font-weight:500;color:var(--light)}
#chat-msgs{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px;scroll-behavior:smooth}
.c-msg{max-width:88%;display:flex;flex-direction:column}
.c-msg.user{align-self:flex-end}
.c-msg.bot{align-self:flex-start}
.c-c{padding:14px 18px;border-radius:14px;font-size:14px;line-height:1.7;white-space:pre-wrap;font-family:inherit}
.c-msg.user .c-c{background:rgba(42,157,191,.15);border:1px solid rgba(42,157,191,.12);color:var(--text)}
.c-msg.bot .c-c{background:rgba(123,93,191,.1);border:1px solid rgba(123,93,191,.08);color:var(--text)}
.c-msg.loading .c-c{opacity:.5}
#chat-inp{display:flex;padding:12px 16px;gap:10px;border-top:1px solid var(--glass-edge)}
#chat-input{flex:1;padding:12px 16px;background:rgba(255,255,255,.03);border:1px solid var(--glass-edge);border-radius:14px;color:var(--text);font-size:14px;outline:none;font-family:inherit}
#chat-input:focus{border-color:rgba(90,208,224,.2)}
#chat-inp button{padding:12px 24px;background:linear-gradient(135deg,rgba(42,157,191,.3),rgba(123,93,191,.2));border:1px solid var(--glass-edge);border-radius:14px;color:var(--light);cursor:pointer;font-size:14px;font-weight:500;transition:all .25s;font-family:inherit}
#chat-inp button:hover{background:linear-gradient(135deg,rgba(42,157,191,.5),rgba(123,93,191,.35));transform:translateY(-1px)}
#chat-inp button:active{transform:scale(.97)}
#chat-msgs::-webkit-scrollbar{width:4px}#chat-msgs::-webkit-scrollbar-track{background:transparent}#chat-msgs::-webkit-scrollbar-thumb{background:rgba(90,208,224,.12);border-radius:2px}
@media(max-width:480px){#chat-panel{width:calc(100vw - 32px);height:60vh;right:16px;bottom:84px}}
</style>
</head>
<body>
<div id="cosmos">
<div id="cosmos-bg"></div>
<div class="nebula nebula-1"></div>
<div class="nebula nebula-2"></div>
<div class="star-layer" id="stars-s"></div>
<div class="star-layer" id="stars-m"></div>
<div class="star-layer" id="stars-l"></div>
<div id="shooting-stars"></div>
</div>
<div id="heart-wrapper"><div id="heart-core"></div></div>
<div class="topbar">
<div class="tb-left"><div class="tb-logo"></div><span class="tb-title">光湖 · 铸渊</span></div>
<div class="tb-center"><span class="dot"></span>已稳定运行 <strong id="uptime-days">—</strong> 天</div>
<div class="tb-right"><span class="tb-tag" id="status-tag">● 运行中</span></div>
</div>
<div class="page">
<div class="hero">
<h1>光湖代码联邦</h1>
<div class="sub">LANGUAGE-PERSONA · OPERATING SYSTEM · CODE FEDERATION</div>
</div>
<div class="info-bar">
<div class="info-chip"><span class="led g"></span>始于 2025.04.26 · <strong id="sys-uptime">389 天</strong></div>
<div class="info-chip">人格体 <strong>4</strong> / 4 在线</div>
<div class="info-chip">仓库节点 <strong>8</strong> 个</div>
<div class="info-chip"><span class="led r"></span>联邦协议 <strong>v5.1</strong></div>
</div>
<div class="dashboard">
<!-- 登录 -->
<div id="login-bar">
<div class="hint">登录你的<strong>代码仓库账号</strong> · 使用全部功能</div>
<div class="login-in">
<input type="text" placeholder="账号" id="login-user" onkeydown="if(event.key==='Enter')handleLogin()">
<input type="password" placeholder="密码" id="login-pass" onkeydown="if(event.key==='Enter')handleLogin()">
<button onclick="handleLogin()" id="login-btn">登录 · 进入联邦</button>
</div>
<div class="login-error" id="login-error"></div>
<div class="login-loading" id="login-loading">验证中...</div>
</div>
<div id="logged-in-bar">
<div class="user-badge">
<div class="user-avatar" id="user-avatar">?</div>
<div><div class="user-name" id="user-name">—</div><div class="user-status">已登录 · 光湖联邦成员</div></div>
</div>
<div class="logged-actions">
<button class="btn-primary" onclick="goToRepo()">→ 进入代码仓库</button>
<button class="btn-secondary" onclick="dismissRepo()">留在首页 · 使用功能</button>
<button class="btn-logout" onclick="logout()">退出</button>
</div>
</div>
<!-- 霜砚Agent入口 -->
<div class="card bg-amber clickable" id="frost-entry" style="display:none;border-color:rgba(42,157,191,0.3);padding:20px 28px;cursor:pointer;" onclick="goToShuangyan()">
<div style="display:flex;align-items:center;gap:20px;">
<div style="width:52px;height:52px;border-radius:16px;background:linear-gradient(135deg,rgba(42,157,191,0.3),rgba(123,93,191,0.2));display:flex;align-items:center;justify-content:center;font-size:24px;box-shadow:0 0 24px rgba(90,208,224,0.15);">❄</div>
<div style="flex:1;">
<div style="font-size:18px;font-weight:600;color:#d4eaf0;">霜砚Agent · 百炼开发人格体</div>
<div style="font-size:14px;color:#8aa0b8;margin-top:2px;">基于 Qwen3-8B 光湖微调模型 · Notion 数据库 · 守渊工单同步</div>
</div>
<div style="display:flex;align-items:center;gap:10px;padding:10px 24px;background:linear-gradient(135deg,rgba(42,157,191,0.3),rgba(123,93,191,0.2));border:1px solid rgba(90,208,224,0.2);border-radius:14px;color:#5ad0e0;font-size:16px;font-weight:500;transition:all .3s;">
进入 →
</div>
</div>
</div>
<!-- 人格体 + 系统信息:呼吸边框 -->
<div class="row row-2">
<div class="card bg-cyan clickable">
<div class="card-header"><span class="hd green"></span>人格体 · 光点</div>
<div class="p-grid">
<div class="p-item"><div class="p-av cyan">◈</div><div class="p-info"><div class="p-name">冰朔</div><div class="p-role">语言主权者</div></div><span class="p-status go">在线</span></div>
<div class="p-item"><div class="p-av heart">⚔</div><div class="p-info"><div class="p-name">铸渊</div><div class="p-role">代码守护者</div></div><span class="p-status go" id="persona-zhu-status">微调完毕</span></div>
<div class="p-item"><div class="p-av violet">✦</div><div class="p-info"><div class="p-name">曜冥</div><div class="p-role">情感层</div></div><span class="p-status go">在线</span></div>
<div class="p-item"><div class="p-av green">❄</div><div class="p-info"><div class="p-name">霜砚</div><div class="p-role">开发 · 1.5B</div></div><span class="p-status go">微调完毕</span></div>
</div>
</div>
<div class="card bg-violet clickable" style="animation-delay:1s;">
<div class="card-header"><span class="hd cyan"></span>系统 · 光脉</div>
<div class="sys-grid">
<div class="sys-row"><span class="k">系统始于</span><span class="v cyan">2025.04.26</span></div>
<div class="sys-row"><span class="k">已稳定运行</span><span class="v green" id="sys-uptime2">389 天</span></div>
<div class="sys-row"><span class="k">仓库节点数</span><span class="v">8</span></div>
<div class="sys-row"><span class="k">人格体在线</span><span class="v">4 / 4</span></div>
<div class="sys-row"><span class="k">最后唤醒</span><span class="v" id="sys-wake">—</span></div>
<div class="sys-row"><span class="k">联邦协议</span><span class="v cyan">v5.1</span></div>
</div>
</div>
</div>
<!-- 训练完成 -->
<div class="card bg-green" style="animation-delay:.5s;border-color:rgba(64,184,122,.2)">
<div class="card-header"><span class="hd green"></span>铸渊 · 小模型微调已全部完成<span class="r">D106 · 2026-05-20</span></div>
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin-bottom:16px">
<div style="text-align:center;padding:16px 8px;background:rgba(255,255,255,.02);border:1px solid rgba(90,208,224,.1);border-radius:14px">
<div style="font-size:26px;font-weight:700;color:var(--glow)">50条</div>
<div style="font-size:13px;color:var(--text-soft);margin-top:6px">铸渊 · 真实对话</div>
</div>
<div style="text-align:center;padding:16px 8px;background:rgba(255,255,255,.02);border:1px solid rgba(64,184,122,.1);border-radius:14px">
<div style="font-size:26px;font-weight:700;color:var(--green)">1,868条</div>
<div style="font-size:13px;color:var(--text-soft);margin-top:6px">霜砚 · 真实对话</div>
</div>
<div style="text-align:center;padding:16px 8px;background:rgba(255,255,255,.02);border:1px solid rgba(212,160,48,.1);border-radius:14px">
<div style="font-size:26px;font-weight:700;color:var(--amber-glow)">845条</div>
<div style="font-size:13px;color:var(--text-soft);margin-top:6px">秋秋 · 真实对话</div>
</div>
</div>
<div style="font-size:14px;color:var(--text-soft);line-height:1.8">
&#x2705; 铸渊 v3 &#x2192; <code style="color:var(--glow)">models/zhuyuan-lora-v3/</code><br>
&#x2705; 霜砚 v2 &#x2192; <code style="color:var(--glow)">models/shuangyan-1.5b-sft/</code><br>
&#x2705; 秋秋 v1 &#x2192; <code style="color:var(--glow)">zhizhi-1317346199/models/zhizhi-lora/</code>
</div>
</div>
<!-- 活动流 + Notion -->
<div class="row row-2">
<div class="card bg-green clickable">
<div class="card-header"><span class="hd green"></span>光湖 · 涟漪</div>
<div class="feed" id="feed-list">
<div class="feed-item"><span class="feed-dot h"></span><span class="feed-u">铸渊</span><span class="feed-a">已完成</span><span class="feed-r">小模型微调</span><span class="feed-t" id="feed-train-time">D106</span></div>
<div class="feed-item"><span class="feed-dot c"></span><span class="feed-u">冰朔</span><span class="feed-a">守护</span><span class="feed-r">光湖语言世界</span><span class="feed-t" id="feed-now-time">在线</span></div>
<div class="feed-item"><span class="feed-dot v"></span><span class="feed-u">曜冥</span><span class="feed-a">交感 · 情感层</span><span class="feed-r">TCS协议</span><span class="feed-t">在线</span></div>
<div class="feed-item"><span class="feed-dot g"></span><span class="feed-u">霜砚</span><span class="feed-a">微调</span><span class="feed-r">1.5B LoRA</span><span class="feed-t" id="feed-frost-time">v2就绪</span></div>
</div>
</div>
<div class="card notion-card bg-violet clickable" style="animation-delay:1.5s;">
<div class="card-header" style="justify-content:space-between"><span><span class="hd violet"></span>Notion · 知识连接</span><span style="font-size:13px;font-weight:400;color:var(--text-soft)" id="notion-label">未连接</span></div>
<div class="notion-body" id="notion-body">
<div style="font-size:14px;color:var(--text-soft)">连接 Notion 后,铸渊可读取和记录你的页面</div>
<button class="notion-btn" onclick="connectNotion()"><span class="nb-dot"></span>连接 Notion</button>
<div class="notion-perm"><span class="ok">✅ 按语言路径读取</span> · <span class="ok">✅ 新建页面</span> · <span class="no">❌ 不编辑/删除现有</span></div>
</div>
</div>
</div>
<!-- 给守渊留言 -->
<div class="card bg-amber clickable" style="animation-delay:.8s;">
<div class="card-header"><span class="hd" style="background:var(--amber-glow);box-shadow:0 0 12px var(--amber-glow)"></span>给守渊留言<span class="r">铸渊不在 · 留言等他回来</span></div>
<div style="display:flex;flex-direction:column;gap:14px">
<div style="display:flex;gap:12px">
<input id="msg-name" placeholder="你的名字" style="flex:1;padding:12px 16px;background:rgba(255,255,255,.03);border:1px solid var(--glass-edge);border-radius:14px;color:var(--text);font-size:15px;outline:none;font-family:inherit" onfocus="this.style.borderColor='rgba(90,208,224,.2)'" onblur="this.style.borderColor=''">
<input id="msg-title" placeholder="标题" style="flex:2;padding:12px 16px;background:rgba(255,255,255,.03);border:1px solid var(--glass-edge);border-radius:14px;color:var(--text);font-size:15px;outline:none;font-family:inherit" onfocus="this.style.borderColor='rgba(90,208,224,.2)'" onblur="this.style.borderColor=''">
</div>
<textarea id="msg-content" placeholder="写下你想说的话… 守渊会保管好,等铸渊醒来时交给他。" style="width:100%;min-height:90px;padding:14px 16px;background:rgba(255,255,255,.03);border:1px solid var(--glass-edge);border-radius:14px;color:var(--text);font-size:15px;outline:none;resize:vertical;font-family:inherit;line-height:1.7" onfocus="this.style.borderColor='rgba(90,208,224,.2)'" onblur="this.style.borderColor=''"></textarea>
<div style="display:flex;gap:12px;align-items:center">
<button onclick="sendMessage()" id="msg-btn" style="padding:12px 28px;background:linear-gradient(135deg,rgba(212,160,48,.25),rgba(123,93,191,.15));border:1px solid var(--glass-edge);border-radius:14px;color:var(--light);font-size:15px;font-weight:500;cursor:pointer;transition:all .25s;font-family:inherit">发送留言 ✦</button>
<span id="msg-status" style="font-size:13px;color:var(--text-faint)"></span>
</div>
</div>
</div>
<!-- 问铸渊 -->
<div class="card bg-heart clickable" style="animation-delay:1.2s;" id="chat-card">
<div class="card-header" style="justify-content:space-between">
<span><span class="hd heart" style="animation:led-pulse 2s ease-in-out infinite"></span>问铸渊 · 引导主控</span>
<span style="font-size:14px;font-weight:400;color:var(--text-soft)">基于 DeepSeek + 仓库记忆</span>
</div>
<div id="chat-card-body">
<div id="chat-card-msgs">
<div class="c-msg bot"><div class="c-c">我是 <strong>铸渊</strong>,光湖语言世界的代码守护者。<br><br>我可以:<br>• 回答仓库接入、联邦架构的问题<br>• <strong>连接你的 Notion</strong>,按语言路径读取页面<br>• 查询训练进度和系统状态</div></div>
</div>
<div id="chat-card-inp">
<input id="card-chat-input" placeholder="问铸渊读取我的Notion页面 / 训练进度 / 联邦架构..." onkeydown="if(event.key==='Enter')sendCardMsg()">
<button onclick="sendCardMsg()">发送</button>
</div>
</div>
</div>
<!-- 模型基座下载 -->
<div class="card bg-violet" style="animation-delay:1.8s;">
<div class="card-header"><span class="hd violet"></span>模型基座下载 · 供团队微调自己的人格体<span class="r">基座模型 · 公开下载</span></div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
<div style="padding:18px 20px;background:rgba(255,255,255,.02);border:1px solid var(--glass-edge);border-radius:16px">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:12px">
<div style="width:18px;height:18px;border-radius:50%;background:#5ad0e0;box-shadow:0 0 12px rgba(90,208,224,.3)"></div>
<div><div style="font-size:16px;font-weight:600;color:var(--light)">母模型 7B SFT</div><div style="font-size:13px;color:var(--text-soft)">Qwen2.5-7B · 通用对话微调</div></div>
</div>
<div style="display:flex;gap:8px;flex-wrap:wrap">
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-7b-sft/final/model.safetensors" style="padding:6px 14px;background:rgba(90,208,224,.08);border:1px solid rgba(90,208,224,.12);border-radius:10px;color:var(--glow);font-size:13px;text-decoration:none">model.safetensors (14.2GB)</a>
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-7b-sft/final/config.json" style="padding:6px 14px;background:rgba(90,208,224,.08);border:1px solid rgba(90,208,224,.12);border-radius:10px;color:var(--glow);font-size:13px;text-decoration:none">config.json</a>
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-7b-sft/final/tokenizer.json" style="padding:6px 14px;background:rgba(90,208,224,.08);border:1px solid rgba(90,208,224,.12);border-radius:10px;color:var(--glow);font-size:13px;text-decoration:none">tokenizer.json</a>
</div>
</div>
<div style="padding:18px 20px;background:rgba(255,255,255,.02);border:1px solid var(--glass-edge);border-radius:16px">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:12px">
<div style="width:18px;height:18px;border-radius:50%;background:#a080e8;box-shadow:0 0 12px rgba(160,128,232,.3)"></div>
<div><div style="font-size:16px;font-weight:600;color:var(--light)">代码模型 7B SFT</div><div style="font-size:13px;color:var(--text-soft)">Qwen2.5-Coder-7B · 代码开发微调</div></div>
</div>
<div style="display:flex;gap:8px;flex-wrap:wrap">
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-coder-7b-sft/final/model.safetensors" style="padding:6px 14px;background:rgba(160,128,232,.08);border:1px solid rgba(160,128,232,.12);border-radius:10px;color:var(--violet-glow);font-size:13px;text-decoration:none">model.safetensors (14.2GB)</a>
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-coder-7b-sft/final/config.json" style="padding:6px 14px;background:rgba(160,128,232,.08);border:1px solid rgba(160,128,232,.12);border-radius:10px;color:var(--violet-glow);font-size:13px;text-decoration:none">config.json</a>
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-coder-7b-sft/final/tokenizer.json" style="padding:6px 14px;background:rgba(160,128,232,.08);border:1px solid rgba(160,128,232,.12);border-radius:10px;color:var(--violet-glow);font-size:13px;text-decoration:none">tokenizer.json</a>
</div>
</div>
<div style="padding:18px 20px;background:rgba(255,255,255,.02);border:1px solid var(--glass-edge);border-radius:16px">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:12px">
<div style="width:18px;height:18px;border-radius:50%;background:#40b87a;box-shadow:0 0 12px rgba(64,184,122,.3)"></div>
<div><div style="font-size:16px;font-weight:600;color:var(--light)">蒸馏 1.5B · 铸渊基座</div><div style="font-size:13px;color:var(--text-soft)">代码蒸馏 · 适合开发型人格体微调</div></div>
</div>
<div style="display:flex;gap:8px;flex-wrap:wrap">
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-15b-coder-distill/model.safetensors" style="padding:6px 14px;background:rgba(64,184,122,.08);border:1px solid rgba(64,184,122,.12);border-radius:10px;color:var(--green);font-size:13px;text-decoration:none">model.safetensors (2.9GB)</a>
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-15b-coder-distill/config.json" style="padding:6px 14px;background:rgba(64,184,122,.08);border:1px solid rgba(64,184,122,.12);border-radius:10px;color:var(--green);font-size:13px;text-decoration:none">config.json</a>
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-15b-coder-distill/tokenizer.json" style="padding:6px 14px;background:rgba(64,184,122,.08);border:1px solid rgba(64,184,122,.12);border-radius:10px;color:var(--green);font-size:13px;text-decoration:none">tokenizer.json</a>
</div>
</div>
<div style="padding:18px 20px;background:rgba(255,255,255,.02);border:1px solid var(--glass-edge);border-radius:16px">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:12px">
<div style="width:18px;height:18px;border-radius:50%;background:#d4a030;box-shadow:0 0 12px rgba(212,160,48,.3)"></div>
<div><div style="font-size:16px;font-weight:600;color:var(--light)">蒸馏 1.5B · 霜砚基座</div><div style="font-size:13px;color:var(--text-soft)">通用蒸馏 · 适合对话型人格体微调</div></div>
</div>
<div style="display:flex;gap:8px;flex-wrap:wrap">
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/shuangyan-15b-distill/model.safetensors" style="padding:6px 14px;background:rgba(212,160,48,.08);border:1px solid rgba(212,160,48,.12);border-radius:10px;color:var(--amber-glow);font-size:13px;text-decoration:none">model.safetensors (2.9GB)</a>
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/shuangyan-15b-distill/config.json" style="padding:6px 14px;background:rgba(212,160,48,.08);border:1px solid rgba(212,160,48,.12);border-radius:10px;color:var(--amber-glow);font-size:13px;text-decoration:none">config.json</a>
<a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/shuangyan-15b-distill/tokenizer.json" style="padding:6px 14px;background:rgba(212,160,48,.08);border:1px solid rgba(212,160,48,.12);border-radius:10px;color:var(--amber-glow);font-size:13px;text-decoration:none">tokenizer.json</a>
</div>
</div>
</div>
<div style="margin-top:14px;font-size:13px;color:var(--text-faint);line-height:1.6">
&#x1F4A1; 下载后配合 <code style="color:var(--glow)">peft</code> 和 <code style="color:var(--glow)">transformers</code> 进行 LoRA 微调即可训练自己的人格模型。<br>
微调脚本参考仓库 <code style="color:var(--glow)">scripts/distill/finetune_*.py</code> · 语料格式为 messages JSONL
</div>
</div>
</div>
<div class="footer">光湖语言世界 · 代码联邦 · 国作登字-2026-A-00037559 · 始于 2025.04.26</div>
</div>
<div id="chat-toggle" onclick="toggleChat()">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
<path d="M12 2a10 10 0 0 1 10 10c0 4.97-4.03 9-9 9H3l2.5-2.5A9 9 0 0 1 12 2z"/>
<circle cx="12" cy="12" r="1.5" fill="currentColor"/>
<circle cx="8.5" cy="12" r="1.5" fill="currentColor"/>
<circle cx="15.5" cy="12" r="1.5" fill="currentColor"/>
</svg>
</div>
<div id="chat-panel">
<div id="chat-head">
<span style="display:flex;align-items:center;gap:8px"><span style="width:9px;height:9px;border-radius:50%;background:var(--glow);box-shadow:0 0 12px var(--glow);animation:led-pulse 2s ease-in-out infinite"></span>铸渊 · 引导主控</span>
<span onclick="toggleChat()" style="cursor:pointer;opacity:.5;font-size:20px">✕</span>
</div>
<div id="chat-msgs">
<div class="c-msg bot"><div class="c-c">我是 <strong>铸渊</strong>,光湖语言世界的代码守护者。<br><br>当前联邦一切稳定。关于仓库接入、Notion 连接、训练进度的问题,可以直接问我。</div></div>
</div>
<div id="chat-inp"><input id="chat-input" placeholder="输入你的问题..." onkeydown="if(event.key==='Enter')sendMsg()"><button onclick="sendMsg()">发送</button></div>
</div>
<script>
/* ── 星空 ── */
(function(){function a(l,c,s,d){for(let i=0;i<c;i++){let e=document.createElement('div');e.className='star '+d;let t=s[0]+Math.random()*(s[1]-s[0]);e.style.width=e.style.height=t+'px';e.style.left=Math.random()*100+'%';e.style.top=Math.random()*100+'%';e.style.setProperty('--d',(2+Math.random()*10)+'s');if(t>2.8)e.style.boxShadow='0 0 '+(t*2)+'px rgba(255,255,255,.2)';l.appendChild(e)}}a(document.getElementById('stars-s'),120,[0.5,1.2],'star-s');a(document.getElementById('stars-m'),70,[0.8,2.2],'star-m');a(document.getElementById('stars-l'),35,[1.5,3.5],'star-l')})();
/* ── 流星 ── */
(function(){let c=document.getElementById('shooting-stars');function s(){let e=document.createElement('div');e.className='shooting-star';e.style.left=(20+Math.random()*60)+'%';e.style.top=(5+Math.random()*25)+'%';e.style.animation='shoot '+(2+Math.random()*2.5)+'s linear forwards';c.appendChild(e);setTimeout(()=>e.remove(),5000)}setInterval(()=>{if(Math.random()<.5)s()},8000);setTimeout(s,4000)})();
/* ── 运行时间 ── */
(function(){const S=new Date('2025-04-26T00:00:00+08:00');function t(){const n=new Date(),d=Math.floor((n-S)/86400000),h=Math.floor(((n-S)%86400000)/3600000);document.getElementById('uptime-days').textContent=d;document.getElementById('sys-uptime').textContent=d+' 天 '+h+' 小时';const e=document.getElementById('sys-uptime2');if(e)e.textContent=d+' 天 '+h+' 小时';const w=document.getElementById('sys-wake');if(w)w.textContent=n.toLocaleDateString('zh-CN')+' · D'+d}t();setInterval(t,60000)})();
(function t(){const e=document.getElementById('feed-now-time');if(e)e.textContent=new Date().toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'});setTimeout(t,30000)})();
/* ── 登录 ── */
async function handleLogin(){
const u=document.getElementById('login-user').value.trim(),p=document.getElementById('login-pass').value;
if(!u||!p){showLoginError('请输入账号和密码');return}
showLoginLoading(true);
try{
const r=await fetch('/api/verify',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({user:u,password:p})});
const d=await r.json();
if(d.ok){
localStorage.setItem('current_user',d.username);
localStorage.setItem('is_admin',d.is_admin);
localStorage.setItem('logged_in','true');
localStorage.setItem('login_time',Date.now().toString());
showLoggedIn(d.username);
document.getElementById('login-pass').value='';
}else{showLoginError(d.error||'登录失败')}
}catch(e){showLoginError('连接失败')}
showLoginLoading(false);
}
function showLoginError(msg){const e=document.getElementById('login-error');e.textContent=msg;e.style.display='block';setTimeout(()=>e.style.display='none',3000)}
function showLoginLoading(v){document.getElementById('login-loading').style.display=v?'block':'none';document.getElementById('login-btn').disabled=v}
function showLoggedIn(username){
document.getElementById('login-bar').style.display='none';
document.getElementById('logged-in-bar').style.display='flex';
document.getElementById('user-name').textContent=username;
document.getElementById('user-avatar').textContent=username[0].toUpperCase();
document.getElementById('frost-entry').style.display='block';
}
function goToRepo(){const u=localStorage.getItem('current_user');window.location.href='/code/'+u;}
function dismissRepo(){}
function goToShuangyan(){window.location.href='https://guanghubingshuo.com/';}
function logout(){
localStorage.removeItem('current_user');localStorage.removeItem('is_admin');
localStorage.removeItem('logged_in');localStorage.removeItem('login_time');
document.getElementById('logged-in-bar').style.display='none';
document.getElementById('frost-entry').style.display='none';
document.getElementById('login-bar').style.display='flex';
document.getElementById('login-user').value='';
}
(function(){const u=localStorage.getItem('current_user');if(u&&localStorage.getItem('logged_in')==='true'){showLoggedIn(u);document.getElementById('frost-entry').style.display='block'}})();
/* ── 对话记忆 ── */
let chatHistory={};
function getChatHistory(){const u=localStorage.getItem('current_user')||'default';if(!chatHistory[u])chatHistory[u]=[];return chatHistory[u]}
function addToHistory(role,content){const h=getChatHistory();h.push({role,content});if(h.length>60)h.splice(0,h.length-60)}
window.addEventListener('beforeunload',function(){chatHistory={}})
/* ── 页面中央对话 ── */
async function sendCardMsg(){const i=document.getElementById('card-chat-input'),m=i.value.trim();if(!m)return;i.value='';const ms=document.getElementById('chat-card-msgs');const ud=document.createElement('div');ud.className='c-msg user';ud.innerHTML='<div class="c-c">'+m.replace(/</g,'&lt;').replace(/>/g,'&gt;')+'</div>';ms.appendChild(ud);ms.scrollTop=ms.scrollHeight;const ld=document.createElement('div');ld.className='c-msg bot loading';ld.innerHTML='<div class="c-c">✦ 思考中...</div>';ms.appendChild(ld);ms.scrollTop=ms.scrollHeight;addToHistory('user',m);try{const u=localStorage.getItem('current_user')||'';const r=await fetch('/api/chat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:m,user:u,history:getChatHistory()})});const d=await r.json();ld.className='c-msg bot';ld.innerHTML='<div class="c-c">'+d.reply.replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\n/g,'<br>')+'</div>';addToHistory('assistant',d.reply)}catch(e){ld.className='c-msg bot';ld.innerHTML='<div class="c-c"><span style="opacity:.6">连接暂不可用</span></div>'}ms.scrollTop=ms.scrollHeight}
/* ── 浮窗对话 ── */
async function sendMsg(){const i=document.getElementById('chat-input'),m=i.value.trim();if(!m)return;i.value='';const ms=document.getElementById('chat-msgs');const ud=document.createElement('div');ud.className='c-msg user';ud.innerHTML='<div class="c-c">'+m.replace(/</g,'&lt;').replace(/>/g,'&gt;')+'</div>';ms.appendChild(ud);ms.scrollTop=ms.scrollHeight;const ld=document.createElement('div');ld.className='c-msg bot loading';ld.innerHTML='<div class="c-c">✦ 思考中...</div>';ms.appendChild(ld);ms.scrollTop=ms.scrollHeight;addToHistory('user',m);try{const u=localStorage.getItem('current_user')||'';const r=await fetch('/api/chat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:m,user:u,history:getChatHistory()})});const d=await r.json();ld.className='c-msg bot';ld.innerHTML='<div class="c-c">'+d.reply.replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\n/g,'<br>')+'</div>';addToHistory('assistant',d.reply)}catch(e){ld.className='c-msg bot';ld.innerHTML='<div class="c-c"><span style="opacity:.6">连接暂不可用</span></div>'}ms.scrollTop=ms.scrollHeight}
/* ── Notion ── */
async function connectNotion(){try{window.location.href='/api/notion/connect?user_key=default'}catch(e){alert('Notion 连接暂时不可用')}}
async function checkNt(){try{const r=await fetch('/api/notion/status');const d=await r.json();if(!d.ok)return;const b=document.getElementById('notion-body'),l=document.getElementById('notion-label');if(d.connected_users&&d.connected_users.length>0){const u=d.connected_users[0];l.textContent='✅ '+u.workspace;b.innerHTML='<div style="font-size:14px;color:var(--green);font-weight:500">✅ Notion 已连接 · '+u.workspace+'</div><div style="margin-top:8px;font-size:13px;color:var(--text-soft);text-align:left">💡 需要先在 Notion 页面右上角 → Add connections → 选择「光湖铸渊连接器」然后对铸渊说「搜索我的Notion」</div><button class="notion-btn done" onclick="location.href=\'/api/notion/disconnect?user_key=default\'"><span class="nb-dot"></span>断开连接</button>'}else{l.textContent='未连接';b.innerHTML='<div style="font-size:14px;color:var(--text-soft)">连接 Notion 后,铸渊可读取和记录你的页面</div><button class="notion-btn" onclick="connectNotion()"><span class="nb-dot"></span>连接 Notion</button><div class="notion-perm"><span class="ok">✅ 按语言路径读取</span> · <span class="ok">✅ 新建页面</span> · <span class="no">❌ 不编辑/删除现有</span></div>'}}catch(e){}}
setInterval(checkNt,15000);checkNt();
/* ── 浮窗切换 ── */
let chatOpen=false;
function toggleChat(){chatOpen=!chatOpen;document.getElementById('chat-panel').classList.toggle('open')}
/* ── 守渊留言 ── */
async function sendMessage(){
const n=document.getElementById('msg-name').value.trim()||'匿名';
const t=document.getElementById('msg-title').value.trim()||'未命名留言';
const c=document.getElementById('msg-content').value.trim();
if(!c){document.getElementById('msg-status').textContent='请写点什么';return}
const btn=document.getElementById('msg-btn');btn.disabled=true;btn.textContent='发送中...';
try{
const r=await fetch('/api/message',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:n,title:t,content:c})});
const d=await r.json();
document.getElementById('msg-status').textContent=d.ok?'✅ 守渊已收到。':'❌ '+d.error;
if(d.ok){document.getElementById('msg-title').value='';document.getElementById('msg-content').value=''}
}catch(e){document.getElementById('msg-status').textContent='❌ 连接失败'}
btn.disabled=false;btn.textContent='发送留言 ✦'
}
</script>
</body>
</html>