diff --git a/docs/index.html b/docs/index.html index 5abbc1dc..79b65181 100644 --- a/docs/index.html +++ b/docs/index.html @@ -14,34 +14,35 @@ /* ═══ Themes ═══ */ :root{ - --bg:#060a14;--bg1:#0c1220;--bg2:#111827;--bg3:#1a2332; - --border:#1e2d44;--accent:#4f8ef7;--accent2:#7c6ef7;--accent3:#a78bfa; + --bg:#03060e;--bg1:rgba(8,14,30,.85);--bg2:rgba(12,20,40,.8);--bg3:rgba(18,28,52,.75); + --border:rgba(80,120,200,.15);--accent:#6ea8fe;--accent2:#a78bfa;--accent3:#c4b5fd; --ok:#34d399;--warn:#fbbf24;--err:#f87171; - --text:#e2e8f0;--dim:#64748b;--muted:#334155; - --glow:0 0 24px rgba(79,142,247,.1); - --r:12px;--rs:8px; + --text:#e2e8f0;--dim:#7c8db5;--muted:rgba(100,130,180,.3); + --glow:0 0 30px rgba(110,168,254,.15),0 0 60px rgba(167,139,250,.08); + --r:14px;--rs:8px; --f:-apple-system,BlinkMacSystemFont,'PingFang SC','Helvetica Neue','Microsoft YaHei',sans-serif; --m:'SF Mono','Fira Code',Consolas,monospace; --sb:env(safe-area-inset-bottom,0px);--st:env(safe-area-inset-top,0px); + --glass:rgba(10,16,32,.6);--glass-border:rgba(100,140,220,.12); } -.t-twi{--bg:#0a0612;--bg1:#140e22;--bg2:#1a1430;--bg3:#241c3d;--accent:#c084fc;--accent2:#e879f9;--accent3:#f0abfc;--border:#2d1f4e} -.t-sea{--bg:#041318;--bg1:#082029;--bg2:#0c2d3a;--bg3:#103a4c;--accent:#22d3ee;--accent2:#06b6d4;--accent3:#67e8f9;--border:#164e63} -.t-for{--bg:#06120a;--bg1:#0c2014;--bg2:#112d1c;--bg3:#183a26;--accent:#34d399;--accent2:#4ade80;--accent3:#86efac;--border:#1a4a2e} -.t-emb{--bg:#140a06;--bg1:#221208;--bg2:#2d1a0e;--bg3:#3a2414;--accent:#fb923c;--accent2:#f97316;--accent3:#fdba74;--border:#4a2e1a} +.t-twi{--bg:#06030f;--bg1:rgba(16,10,30,.85);--bg2:rgba(22,16,42,.8);--bg3:rgba(30,22,55,.75);--accent:#c084fc;--accent2:#e879f9;--accent3:#f0abfc;--border:rgba(140,80,200,.15)} +.t-sea{--bg:#030d12;--bg1:rgba(6,20,30,.85);--bg2:rgba(10,30,44,.8);--bg3:rgba(14,40,56,.75);--accent:#22d3ee;--accent2:#06b6d4;--accent3:#67e8f9;--border:rgba(34,211,238,.12)} +.t-for{--bg:#040e06;--bg1:rgba(8,24,14,.85);--bg2:rgba(14,34,22,.8);--bg3:rgba(18,44,30,.75);--accent:#34d399;--accent2:#4ade80;--accent3:#86efac;--border:rgba(52,211,153,.12)} +.t-emb{--bg:#0e0604;--bg1:rgba(28,14,6,.85);--bg2:rgba(38,22,10,.8);--bg3:rgba(48,30,16,.75);--accent:#fb923c;--accent2:#f97316;--accent3:#fdba74;--border:rgba(251,146,60,.12)} html{-webkit-tap-highlight-color:transparent} body{font-family:var(--f);background:var(--bg);color:var(--text);font-size:15px;line-height:1.6;overflow:hidden;height:100vh;height:100dvh;-webkit-font-smoothing:antialiased} a{color:var(--accent);text-decoration:none} ::-webkit-scrollbar{width:4px}::-webkit-scrollbar-thumb{background:var(--muted);border-radius:2px} -/* ═══ Background ═══ */ -.bg{position:fixed;inset:0;z-index:0;pointer-events:none} -.bg::before{content:'';position:absolute;inset:0;background-image:linear-gradient(rgba(79,142,247,.02) 1px,transparent 1px),linear-gradient(90deg,rgba(79,142,247,.02) 1px,transparent 1px);background-size:50px 50px;animation:gm 30s linear infinite} -@keyframes gm{to{background-position:50px 50px}} -.orb{position:absolute;border-radius:50%;filter:blur(80px);opacity:.07;animation:ob 22s ease-in-out infinite} -.orb:nth-child(1){width:350px;height:350px;background:var(--accent);top:-8%;left:-4%} -.orb:nth-child(2){width:280px;height:280px;background:var(--accent2);bottom:-6%;right:-4%;animation-delay:8s} -@keyframes ob{0%,100%{transform:translate(0,0)}50%{transform:translate(20px,-15px)}} +/* ═══ Background: Galaxy Star Field ═══ */ +.bg{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden} +#starCanvas{position:absolute;inset:0;width:100%;height:100%} +.nebula{position:absolute;border-radius:50%;filter:blur(120px);animation:nebPulse 12s ease-in-out infinite} +.nebula:nth-child(2){width:50vw;height:50vh;background:radial-gradient(ellipse,rgba(110,168,254,.06),transparent 70%);top:-10%;left:-10%} +.nebula:nth-child(3){width:45vw;height:45vh;background:radial-gradient(ellipse,rgba(167,139,250,.05),transparent 70%);bottom:-8%;right:-5%;animation-delay:6s} +.nebula:nth-child(4){width:35vw;height:35vh;background:radial-gradient(ellipse,rgba(196,181,253,.04),transparent 70%);top:40%;left:50%;animation-delay:3s} +@keyframes nebPulse{0%,100%{opacity:.6;transform:scale(1) translate(0,0)}50%{opacity:1;transform:scale(1.08) translate(10px,-8px)}} /* ═══ 3D Page Flip Engine ═══ */ .pages{position:fixed;inset:0;z-index:1;perspective:1400px;overflow:hidden} @@ -62,27 +63,30 @@ a{color:var(--accent);text-decoration:none} .page[data-state="hidden"]{transform:rotateY(92deg) scale(.88);opacity:0;z-index:0;pointer-events:none;transition:none} /* ═══ Common UI ═══ */ -.bar{position:sticky;top:0;z-index:10;display:flex;align-items:center;justify-content:space-between;padding:10px 16px;background:rgba(6,10,20,.92);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);border-bottom:1px solid var(--border);min-height:48px;padding-top:calc(10px + var(--st))} +.bar{position:sticky;top:0;z-index:10;display:flex;align-items:center;justify-content:space-between;padding:10px 16px;background:rgba(3,6,14,.88);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border-bottom:1px solid var(--glass-border);min-height:48px;padding-top:calc(10px + var(--st))} .bar-title{font-size:14px;font-weight:700;display:flex;align-items:center;gap:6px} .bar-right{display:flex;align-items:center;gap:8px} .dot{width:6px;height:6px;border-radius:50%;background:var(--ok);box-shadow:0 0 6px var(--ok);animation:pls 2s infinite;flex-shrink:0} @keyframes pls{50%{opacity:.4}} -.btn{background:none;border:1px solid var(--border);color:var(--dim);padding:5px 12px;border-radius:var(--rs);font-size:12px;cursor:pointer;font-family:var(--f);transition:all .2s;white-space:nowrap} -.btn:hover{color:var(--accent);border-color:var(--accent)} +.btn{background:none;border:1px solid var(--border);color:var(--dim);padding:5px 12px;border-radius:var(--rs);font-size:12px;cursor:pointer;font-family:var(--f);transition:all .35s cubic-bezier(.4,0,.2,1);white-space:nowrap;position:relative;overflow:hidden} +.btn::before{content:'';position:absolute;inset:0;background:linear-gradient(120deg,transparent 30%,rgba(110,168,254,.08) 50%,transparent 70%);transform:translateX(-100%);transition:transform .5s} +.btn:hover{color:var(--accent);border-color:var(--accent);box-shadow:0 0 16px rgba(110,168,254,.12),inset 0 0 16px rgba(110,168,254,.04)} +.btn:hover::before{transform:translateX(100%)} .btn:active{transform:scale(.96)} -.btn-accent{background:linear-gradient(135deg,var(--accent),var(--accent2));border:none;color:#fff} -.btn-accent:hover{opacity:.88;color:#fff} +.btn-accent{background:linear-gradient(135deg,var(--accent),var(--accent2));border:none;color:#fff;box-shadow:0 2px 12px rgba(110,168,254,.2)} +.btn-accent:hover{opacity:.88;color:#fff;box-shadow:0 4px 20px rgba(110,168,254,.35)} +.btn-accent::before{background:linear-gradient(120deg,transparent 30%,rgba(255,255,255,.15) 50%,transparent 70%)} .content{padding:16px;max-width:700px;margin:0 auto} -.card{background:var(--bg1);border:1px solid var(--border);border-radius:var(--r);padding:16px;margin-bottom:12px;transition:border-color .3s} -.card:hover{border-color:var(--accent)} +.card{background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--r);padding:16px;margin-bottom:12px;transition:all .35s cubic-bezier(.4,0,.2,1);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)} +.card:hover{border-color:rgba(110,168,254,.3);box-shadow:var(--glow)} .tag{display:inline-block;padding:2px 8px;border-radius:20px;font-size:10px;font-weight:600} .tag-ok{background:rgba(52,211,153,.12);color:var(--ok)} .tag-warn{background:rgba(251,191,36,.12);color:var(--warn)} .tag-info{background:rgba(79,142,247,.12);color:var(--accent)} .empty{text-align:center;padding:40px 16px;color:var(--muted);font-size:14px} .empty em{font-style:normal;font-size:40px;display:block;margin-bottom:12px} -input[type=text],textarea{background:var(--bg2);border:1px solid var(--border);border-radius:var(--rs);color:var(--text);padding:10px 12px;font-size:14px;font-family:var(--f);outline:none;width:100%;transition:border-color .2s;-webkit-appearance:none} -input[type=text]:focus,textarea:focus{border-color:var(--accent)} +input[type=text],input[type=password],textarea{background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--rs);color:var(--text);padding:10px 12px;font-size:14px;font-family:var(--f);outline:none;width:100%;transition:all .3s;-webkit-appearance:none;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)} +input[type=text]:focus,input[type=password]:focus,textarea:focus{border-color:var(--accent);box-shadow:0 0 16px rgba(110,168,254,.1),inset 0 0 16px rgba(110,168,254,.03)} ::placeholder{color:var(--muted)} label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weight:600} .form-row{margin-bottom:14px} @@ -90,18 +94,21 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh @media(max-width:480px){.form-row-inline{flex-direction:column}} /* ═══ PAGE: Home ═══ */ -.home-hero{text-align:center;padding:32px 16px} -.home-ver{display:inline-flex;align-items:center;gap:6px;padding:4px 12px;border-radius:20px;background:rgba(79,142,247,.08);border:1px solid rgba(79,142,247,.12);font-size:11px;color:var(--accent);font-family:var(--m);margin-bottom:16px} -.home-hero h1{font-size:clamp(26px,5.5vw,40px);font-weight:800;line-height:1.2;margin-bottom:6px} -.home-hero .sub{font-size:clamp(12px,2.5vw,15px);color:var(--dim);margin-bottom:12px} -.home-hero .quote{font-size:13px;color:var(--accent2);font-style:italic} +.home-hero{text-align:center;padding:40px 16px 32px} +.home-ver{display:inline-flex;align-items:center;gap:6px;padding:4px 14px;border-radius:20px;background:rgba(110,168,254,.06);border:1px solid rgba(110,168,254,.12);font-size:11px;color:var(--accent);font-family:var(--m);margin-bottom:16px;animation:breathe 4s ease-in-out infinite} +@keyframes breathe{0%,100%{box-shadow:0 0 8px rgba(110,168,254,.1)}50%{box-shadow:0 0 20px rgba(110,168,254,.25)}} +.home-hero h1{font-size:clamp(28px,5.5vw,44px);font-weight:800;line-height:1.2;margin-bottom:8px;background:linear-gradient(135deg,#e2e8f0 0%,#6ea8fe 50%,#a78bfa 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text} +.home-hero .sub{font-size:clamp(12px,2.5vw,15px);color:var(--dim);margin-bottom:14px} +.home-hero .quote{font-size:14px;color:var(--accent2);font-style:italic;opacity:.8} .upd{display:flex;gap:10px;padding:12px;margin-bottom:8px;background:var(--bg1);border:1px solid var(--border);border-radius:var(--r);transition:border-color .3s} .upd:hover{border-color:var(--accent)} .upd-v{min-width:42px;padding:3px 6px;text-align:center;background:rgba(79,142,247,.08);border-radius:var(--rs);color:var(--accent);font-size:10px;font-weight:600;font-family:var(--m);height:fit-content;flex-shrink:0} .upd h4{font-size:13px;font-weight:600;margin-bottom:2px} .upd p{font-size:11px;color:var(--dim);line-height:1.5} -.home-enter{padding:24px;text-align:center;background:linear-gradient(135deg,var(--bg1),var(--bg2));border:1px solid var(--border);border-radius:var(--r);cursor:pointer;transition:all .3s;margin:20px 0} -.home-enter:hover{border-color:var(--accent);box-shadow:var(--glow)} +.home-enter{padding:28px;text-align:center;background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--r);cursor:pointer;transition:all .4s cubic-bezier(.4,0,.2,1);margin:20px 0;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);position:relative;overflow:hidden} +.home-enter::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at 50% 50%,rgba(110,168,254,.04),transparent 70%);opacity:0;transition:opacity .4s} +.home-enter:hover{border-color:rgba(110,168,254,.35);box-shadow:var(--glow);transform:translateY(-2px)} +.home-enter:hover::after{opacity:1} .home-enter:active{transform:scale(.98)} .home-enter em{font-style:normal;font-size:36px;display:block;margin-bottom:8px} .home-enter strong{font-size:17px;display:block;margin-bottom:4px} @@ -121,10 +128,12 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh .hub-title p{font-size:12px;color:var(--dim);margin-top:2px} .hub-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px} @media(max-width:360px){.hub-grid{grid-template-columns:1fr}} -.hub-card{text-align:center;padding:20px 12px;background:var(--bg1);border:1px solid var(--border);border-radius:var(--r);cursor:pointer;transition:all .3s} -.hub-card:hover{border-color:var(--accent);box-shadow:var(--glow)} +.hub-card{text-align:center;padding:24px 14px;background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--r);cursor:pointer;transition:all .4s cubic-bezier(.4,0,.2,1);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);position:relative;overflow:hidden} +.hub-card::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at 50% 0%,rgba(110,168,254,.06),transparent 70%);opacity:0;transition:opacity .4s} +.hub-card:hover{border-color:rgba(110,168,254,.35);box-shadow:var(--glow);transform:translateY(-2px)} +.hub-card:hover::after{opacity:1} .hub-card:active{transform:scale(.97)} -.hub-card em{font-style:normal;font-size:28px;display:block;margin-bottom:6px} +.hub-card em{font-style:normal;font-size:32px;display:block;margin-bottom:8px;filter:drop-shadow(0 0 8px rgba(110,168,254,.3))} .hub-card strong{font-size:14px;display:block;margin-bottom:3px} .hub-card span{font-size:11px;color:var(--dim)} .hub-stats{display:flex;justify-content:center;gap:20px;padding:12px 0;flex-wrap:wrap} @@ -150,9 +159,26 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh .editor-textarea{min-height:calc(100vh - 260px);min-height:calc(100dvh - 260px);resize:none;line-height:2;font-size:15px;border:none;background:transparent;padding:0} .editor-textarea:focus{border:none} .editor-bottom{position:sticky;bottom:0;padding:8px 0;background:var(--bg);display:flex;justify-content:space-between;align-items:center;border-top:1px solid var(--border);font-size:11px;color:var(--dim);font-family:var(--m)} +/* ═══ Editor Toolbar ═══ */ +.ed-toolbar{display:flex;gap:4px;align-items:center;flex-wrap:wrap} +.ed-toolbar .tb-btn{background:var(--glass);border:1px solid var(--glass-border);color:var(--dim);width:32px;height:28px;border-radius:6px;cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center;transition:all .25s;font-family:var(--f);position:relative;overflow:hidden} +.ed-toolbar .tb-btn:hover{color:var(--accent);border-color:var(--accent);box-shadow:0 0 10px rgba(110,168,254,.12);background:rgba(110,168,254,.06)} +.ed-toolbar .tb-btn:active{transform:scale(.92)} +.ed-toolbar .tb-sep{width:1px;height:18px;background:var(--border);margin:0 4px} +/* ═══ Create Success Overlay ═══ */ +.create-success{display:none;text-align:center;padding:40px 20px;animation:fadeUp .5s ease-out} +.create-success.show{display:block} +.create-success em{font-style:normal;font-size:56px;display:block;margin-bottom:16px;animation:successPop .6s cubic-bezier(.68,-.55,.27,1.55)} +.create-success h3{font-size:20px;font-weight:700;margin-bottom:8px} +.create-success p{color:var(--dim);font-size:13px;margin-bottom:24px} +.create-actions{display:flex;gap:10px;justify-content:center;flex-wrap:wrap} +.create-actions .btn{padding:10px 24px;font-size:14px;border-radius:var(--r)} +@keyframes fadeUp{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}} +@keyframes successPop{0%{transform:scale(0) rotate(-20deg)}100%{transform:scale(1) rotate(0)}} /* ═══ Chat FAB ═══ */ -.chat-fab{position:fixed;bottom:calc(16px + var(--sb));right:14px;z-index:50;width:50px;height:50px;border-radius:50%;background:linear-gradient(135deg,var(--accent),var(--accent2));border:none;color:#fff;font-size:21px;cursor:pointer;box-shadow:0 4px 16px rgba(79,142,247,.3);transition:all .25s;display:flex;align-items:center;justify-content:center} +.chat-fab{position:fixed;bottom:calc(16px + var(--sb));right:14px;z-index:50;width:52px;height:52px;border-radius:50%;background:linear-gradient(135deg,var(--accent),var(--accent2));border:none;color:#fff;font-size:21px;cursor:pointer;box-shadow:0 4px 20px rgba(110,168,254,.3),0 0 40px rgba(167,139,250,.15);transition:all .25s;display:flex;align-items:center;justify-content:center;animation:fabBreathe 4s ease-in-out infinite} +@keyframes fabBreathe{0%,100%{box-shadow:0 4px 20px rgba(110,168,254,.3),0 0 40px rgba(167,139,250,.1)}50%{box-shadow:0 6px 28px rgba(110,168,254,.45),0 0 50px rgba(167,139,250,.2)}} .chat-fab:hover{transform:scale(1.06)} .chat-fab:active{transform:scale(.93)} .chat-fab.on{border-radius:var(--r);background:rgba(248,113,113,.85)} @@ -161,7 +187,7 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh .chat-fab.editor-mode:hover{opacity:1;transform:scale(1.1)} /* ═══ Chat Panel ═══ */ -.chat-p{position:fixed;bottom:calc(76px + var(--sb));right:14px;z-index:50;width:min(360px,calc(100vw - 28px));height:min(440px,calc(100vh - 120px));height:min(440px,calc(100dvh - 120px));background:var(--bg1);border:1px solid var(--border);border-radius:var(--r);display:flex;flex-direction:column;transform:scale(.9) translateY(14px);opacity:0;pointer-events:none;transition:all .22s cubic-bezier(.4,0,.2,1);box-shadow:0 12px 40px rgba(0,0,0,.5)} +.chat-p{position:fixed;bottom:calc(76px + var(--sb));right:14px;z-index:50;width:min(360px,calc(100vw - 28px));height:min(440px,calc(100vh - 120px));height:min(440px,calc(100dvh - 120px));background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--r);display:flex;flex-direction:column;transform:scale(.9) translateY(14px);opacity:0;pointer-events:none;transition:all .22s cubic-bezier(.4,0,.2,1);box-shadow:0 12px 48px rgba(0,0,0,.5),0 0 40px rgba(110,168,254,.06);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px)} .chat-p.open{transform:scale(1) translateY(0);opacity:1;pointer-events:auto} @media(max-width:480px){.chat-p{bottom:0;right:0;left:0;width:100%;height:calc(100vh - 48px);height:calc(100dvh - 48px);border-radius:var(--r) var(--r) 0 0;padding-bottom:var(--sb)}} .chat-hd{padding:10px 14px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px;flex-shrink:0} @@ -190,7 +216,7 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh /* ═══ Three-Column Home Layout ═══ */ .home-grid{display:grid;grid-template-columns:260px 1fr 260px;gap:16px;padding:16px;max-width:1200px;margin:0 auto;align-content:start} @media(max-width:960px){.home-grid{grid-template-columns:1fr;max-width:600px}} -.panel{background:var(--bg1);border:1px solid var(--border);border-radius:var(--r);padding:14px;height:fit-content} +.panel{background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--r);padding:14px;height:fit-content;backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px)} .panel-title{font-size:11px;color:var(--dim);text-transform:uppercase;letter-spacing:1.2px;font-weight:700;margin-bottom:10px;display:flex;align-items:center;gap:6px} .panel-item{padding:6px 0;border-bottom:1px solid var(--border);font-size:12px} .panel-item:last-child{border-bottom:none} @@ -201,10 +227,10 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh .panel-value.err{color:var(--err)} /* ═══ Ticker ═══ */ -.ticker-wrap{overflow:hidden;background:var(--bg1);border:1px solid var(--border);border-radius:var(--rs);padding:6px 0;margin-bottom:14px;position:relative} -.ticker-wrap::before,.ticker-wrap::after{content:'';position:absolute;top:0;bottom:0;width:24px;z-index:2;pointer-events:none} -.ticker-wrap::before{left:0;background:linear-gradient(90deg,var(--bg1),transparent)} -.ticker-wrap::after{right:0;background:linear-gradient(-90deg,var(--bg1),transparent)} +.ticker-wrap{overflow:hidden;background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--rs);padding:6px 0;margin-bottom:14px;position:relative} +.ticker-wrap::before,.ticker-wrap::after{content:'';position:absolute;top:0;bottom:0;width:32px;z-index:2;pointer-events:none} +.ticker-wrap::before{left:0;background:linear-gradient(90deg,rgba(3,6,14,.9),transparent)} +.ticker-wrap::after{right:0;background:linear-gradient(-90deg,rgba(3,6,14,.9),transparent)} .ticker{display:flex;animation:tickScroll 28s linear infinite;white-space:nowrap;gap:36px;padding:0 16px} .ticker:hover{animation-play-state:paused} .ticker span{font-size:11px;color:var(--dim);display:flex;align-items:center;gap:5px;flex-shrink:0} @@ -212,8 +238,8 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh @keyframes tickScroll{0%{transform:translateX(0)}100%{transform:translateX(-50%)}} /* ═══ Team Card ═══ */ -.team-slot{display:flex;align-items:center;gap:8px;padding:7px 8px;background:var(--bg2);border-radius:var(--rs);margin-bottom:5px;transition:border-color .3s;border:1px solid transparent} -.team-slot:hover{border-color:var(--accent)} +.team-slot{display:flex;align-items:center;gap:8px;padding:7px 8px;background:var(--glass);border-radius:var(--rs);margin-bottom:5px;transition:all .3s;border:1px solid transparent} +.team-slot:hover{border-color:rgba(110,168,254,.2);box-shadow:0 0 12px rgba(110,168,254,.06)} .team-av{width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;flex-shrink:0} .team-nm{font-size:11px;font-weight:600} .team-role{font-size:9px;color:var(--dim)} @@ -229,16 +255,19 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh /* ═══ Home Entry Cards ═══ */ .home-entries{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:16px 0} @media(max-width:480px){.home-entries{grid-template-columns:1fr}} -.entry-card{padding:18px 14px;text-align:center;background:linear-gradient(135deg,var(--bg1),var(--bg2));border:1px solid var(--border);border-radius:var(--r);cursor:pointer;transition:all .3s} -.entry-card:hover{border-color:var(--accent);box-shadow:var(--glow)} -.entry-card:active{transform:scale(.98)} -.entry-card em{font-style:normal;font-size:28px;display:block;margin-bottom:6px} -.entry-card strong{font-size:14px;display:block;margin-bottom:3px} +.entry-card{padding:24px 16px;text-align:center;background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--r);cursor:pointer;transition:all .4s cubic-bezier(.4,0,.2,1);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);position:relative;overflow:hidden} +.entry-card::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at 50% 0%,rgba(110,168,254,.06),transparent 70%);opacity:0;transition:opacity .4s} +.entry-card:hover{border-color:rgba(110,168,254,.35);box-shadow:var(--glow);transform:translateY(-2px)} +.entry-card:hover::after{opacity:1} +.entry-card:active{transform:scale(.98) translateY(0)} +.entry-card em{font-style:normal;font-size:32px;display:block;margin-bottom:8px;filter:drop-shadow(0 0 8px rgba(110,168,254,.3))} +.entry-card strong{font-size:15px;display:block;margin-bottom:4px} .entry-card span{font-size:11px;color:var(--dim)} -/* ═══ Monitor ═══ */ -.mon{position:fixed;top:calc(6px + var(--st));right:10px;z-index:40;background:rgba(12,18,32,.9);border:1px solid var(--border);border-radius:var(--r);padding:5px 9px;font-size:9px;font-family:var(--m);color:var(--dim);cursor:pointer;transition:all .3s;user-select:none;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)} -.mon:hover{border-color:var(--accent)} +/* ═══ Monitor (draggable) ═══ */ +.mon{position:fixed;top:calc(6px + var(--st));right:10px;z-index:40;background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--r);padding:5px 9px;font-size:9px;font-family:var(--m);color:var(--dim);cursor:grab;transition:all .3s;user-select:none;backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);touch-action:none} +.mon:active{cursor:grabbing} +.mon:hover{border-color:rgba(110,168,254,.3)} .mon.x{padding:8px 12px} .mr{display:flex;justify-content:space-between;gap:8px;padding:1px 0} .mv{color:var(--accent);font-weight:600} @@ -273,7 +302,7 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh -
+
@@ -288,24 +317,22 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh
📡 系统状态
-
服务器
检测中…
+
服务器
检测中…
延迟
运行时间
-
工作流
18 个 · 9 军团
-
模块部署
52 模块
-
COS 存储
双桶就绪
+
工作流
检测中…
+
模块部署
检测中…
+
COS 存储
检测中…
🧠 版本更新
-
v40.0 · 2026-04-02
COS双桶存储上线
-
v39.0 · 2026-04-01
全链路部署观测
-
v38.0 · 2026-04-01
HLDP协作语言协议
+
v42.0 · 2026-04-02
银河星空UI改版
-
AGE OS v40.0
+
AGE OS v42.0

光湖灯塔

语言驱动操作系统 · 人类只说话,系统搞定一切
「语言 = 现实」
@@ -313,15 +340,15 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh
- 🏛️ AGE OS v40.0 运行中 + 🏛️ AGE OS v42.0 运行中 + 🌌 银河星空UI上线 📡 COS双桶存储已上线 🧠 HLDP协作语言协议在线 - 全链路部署观测系统就绪 ✍️ 码字工作台 Beta 内测中 - 🏛️ AGE OS v40.0 运行中 + 🏛️ AGE OS v42.0 运行中 + 🌌 银河星空UI上线 📡 COS双桶存储已上线 🧠 HLDP协作语言协议在线 - 全链路部署观测系统就绪 ✍️ 码字工作台 Beta 内测中
@@ -411,12 +438,32 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh
📖 新建作品
- +
-
-
-
+
+
+
📖
+

开始你的创作

+

一个故事的诞生,从这里开始

+
+
+
+
+
+ + +
+
+
+ 🎉 +

作品创建成功!

+

你的新故事已诞生,准备好开始了吗?

+
+ + +
+
@@ -526,8 +573,17 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh
+
+ + +
+ + +
+ + +
字数:0 - 自动保存 · 点右下角💬唤醒铸渊
@@ -574,21 +630,24 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh - +
-
🔑 接入自己的大模型 API
+
🔑 接入大模型 API(支持所有三方)
-
- - - +
+ +
+
+ + +
+
未连接 · 粘贴密钥后自动检测可用模型
+ -
未连接 · 服务器离线时启用自定义模型
@@ -606,6 +665,73 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh (function(){ 'use strict'; +/* ════════════════════════════════════════ + STAR FIELD PARTICLE SYSTEM (Galaxy Breathing) + ════════════════════════════════════════ */ +(function initStarField(){ + var canvas=document.getElementById('starCanvas'); + if(!canvas)return; + var ctx=canvas.getContext('2d'); + var stars=[]; + var STAR_COUNT=180; + var w,h; + + function resize(){ + w=canvas.width=window.innerWidth; + h=canvas.height=window.innerHeight; + } + resize(); + window.addEventListener('resize',resize); + + // Create stars + for(var i=0;i0.7?(200+Math.random()*60):(220+Math.random()*40) // blue-purple range + }); + } + + var time=0; + function draw(){ + time+=16; + ctx.clearRect(0,0,w,h); + for(var i=0;ih+5)s.y=-5; + if(s.y<-5)s.y=h+5; + + var sx=s.x%w; + var sy=s.y%h; + + ctx.beginPath(); + ctx.arc(sx,sy,s.r,0,Math.PI*2); + ctx.fillStyle='hsla('+s.hue+',70%,82%,'+alpha+')'; + ctx.fill(); + + // Glow for bigger stars + if(s.r>1.2){ + ctx.beginPath(); + ctx.arc(sx,sy,s.r*3,0,Math.PI*2); + ctx.fillStyle='hsla('+s.hue+',60%,70%,'+(alpha*0.15)+')'; + ctx.fill(); + } + } + requestAnimationFrame(draw); + } + draw(); +})(); + /* ════════════════════════════════════════ 3D PAGE FLIP ENGINE ════════════════════════════════════════ */ @@ -671,6 +797,13 @@ function go(target){ if(target==='editor')renderEditor(); if(target==='charEdit'&&editingCharId)renderCharEdit(); if(target==='feedback')renderFeedback(); + if(target==='create'){ + // Reset create form state + var cf=document.getElementById('createForm'); + var cs=document.getElementById('createSuccess'); + if(cf)cf.style.display=''; + if(cs)cs.classList.remove('show'); + } } window.go=go; @@ -751,11 +884,28 @@ document.getElementById('createSave').onclick=function(){ }; ws.push(nw); saveWorks(ws); - document.getElementById('cTitle').value=''; - document.getElementById('cGenre').value=''; - document.getElementById('cSummary').value=''; activeWorkId=nw.id; - go('hub'); + + // Show success UI + var form=document.getElementById('createForm'); + var succ=document.getElementById('createSuccess'); + var succTitle=document.getElementById('createSuccessTitle'); + var succDesc=document.getElementById('createSuccessDesc'); + if(form)form.style.display='none'; + if(succTitle)succTitle.textContent='「'+t+'」创建成功!'; + if(succDesc)succDesc.textContent=(nw.genre?nw.genre+' · ':'')+'准备好开始创作了吗?'; + if(succ)succ.classList.add('show'); + + // Wire up the "进入作品" button + document.getElementById('createGoWrite').onclick=function(){ + // Reset form for next time + document.getElementById('cTitle').value=''; + document.getElementById('cGenre').value=''; + document.getElementById('cSummary').value=''; + if(form)form.style.display=''; + if(succ)succ.classList.remove('show'); + go('hub'); + }; }; /* ════════════════════════════════════════ @@ -977,6 +1127,32 @@ document.getElementById('edSave').onclick=function(){ chatMsg('章节已保存 ✅','b'); }; +// Editor toolbar: prev/next chapter navigation +document.getElementById('edPrev').onclick=function(){ + var w=getWork(activeWorkId); + if(!w||!w.chapters||w.chapters.length<2)return; + var idx=w.chapters.findIndex(function(c){return c.id===activeChapterId}); + if(idx>0){saveEditorContent();activeChapterId=w.chapters[idx-1].id;renderEditor();} +}; +document.getElementById('edNext').onclick=function(){ + var w=getWork(activeWorkId); + if(!w||!w.chapters)return; + var idx=w.chapters.findIndex(function(c){return c.id===activeChapterId}); + if(idx0){ + modelSel.innerHTML=apiCfg.models.map(function(m){return''}).join(''); + modelListDiv.style.display='block'; + } } tog.onclick=function(){ @@ -1212,40 +1399,122 @@ try{var ak=localStorage.getItem('hl-api');if(ak){var ap=JSON.parse(ak);if(ap.key tog.classList.toggle('open',isOpen); }; - document.getElementById('apiConnBtn').onclick=async function(){ - var key=keyInp.value.trim(); - if(!key){keyInp.focus();return;} - var model=modelSel.value; - var btn=this; - btn.disabled=true;btn.textContent='测试中…'; - st.textContent='连接测试中…';st.style.color='var(--dim)'; + // Model selection change + modelSel.onchange=function(){ + if(!apiCfg.connected)return; + apiCfg.model=this.value; + try{localStorage.setItem('hl-api',JSON.stringify(apiCfg))}catch(e){} + st.textContent='✅ 已切换模型 · '+apiCfg.model; + document.getElementById('chatTg').textContent=apiCfg.model; + }; + + // Auto-detect: try to fetch /v1/models + async function detectModels(baseUrl,key){ + var url=baseUrl.replace(/\/+$/,'')+'/models'; try{ - var ep=OPENAI_EP; - var r=await fetch(ep,{ + var r=await fetch(url,{ + headers:{'Authorization':'Bearer '+key}, + signal:AbortSignal.timeout(10000) + }); + if(!r.ok)return[]; + var data=await r.json(); + if(data.data&&Array.isArray(data.data)){ + return data.data.map(function(m){return m.id}).filter(function(id){ + // Filter to chat-capable models + return /gpt|claude|gemini|glm|qwen|deepseek|yi-|llama|mistral|chat|turbo/i.test(id); + }).sort(); + } + }catch(e){} + return[]; + } + + // Test connection with a simple request + async function testConnection(baseUrl,key,model){ + var url=baseUrl.replace(/\/+$/,'')+'/chat/completions'; + try{ + var r=await fetch(url,{ method:'POST', headers:{'Content-Type':'application/json','Authorization':'Bearer '+key}, body:JSON.stringify({model:model,messages:[{role:'user',content:'hi'}],max_tokens:5}), - signal:AbortSignal.timeout(12000) + signal:AbortSignal.timeout(15000) }); - if(r.ok){ - apiCfg={key:key,model:model,baseUrl:OPENAI_EP,connected:true}; - try{localStorage.setItem('hl-api',JSON.stringify(apiCfg))}catch(e){} - st.textContent='✅ 连接成功 · '+model; - st.style.color='var(--ok)'; - document.getElementById('chatTg').textContent=model; - chatMsg('🔑 API已连接('+model+')现在我可以完整回答你了','b',{m:'铸渊',t:'自定义'}); - }else{ - var errData=await r.json().catch(function(){return{}}); - st.textContent='❌ '+(errData.error&&errData.error.message?errData.error.message.slice(0,40):'API Key无效'); + return r.ok; + }catch(e){return false} + } + + document.getElementById('apiConnBtn').onclick=async function(){ + var key=keyInp.value.trim(); + if(!key){keyInp.focus();return;} + var userBase=baseUrlInp.value.trim(); + var btn=this; + btn.disabled=true;btn.textContent='检测中…'; + st.textContent='🔍 正在检测可用模型…';st.style.color='var(--dim)'; + + var foundModels=[]; + var workingBase=''; + + // If user provided a base URL, try that first + if(userBase){ + st.textContent='🔍 检测 '+userBase+' …'; + foundModels=await detectModels(userBase,key); + if(foundModels.length>0)workingBase=userBase; + } + + // If no models found, try common endpoints + if(foundModels.length===0){ + for(var i=0;i0){workingBase=COMMON_ENDPOINTS[i];break;} + } + } + + if(foundModels.length>0){ + // Show model list + modelSel.innerHTML=foundModels.map(function(m){return''}).join(''); + modelListDiv.style.display='block'; + + // Auto-select a reasonable default + var defaultModel=foundModels.find(function(m){return/gpt-4o-mini/i.test(m)})|| + foundModels.find(function(m){return/gpt-4o/i.test(m)})|| + foundModels.find(function(m){return/gpt-4/i.test(m)})|| + foundModels.find(function(m){return/claude/i.test(m)})|| + foundModels[0]; + modelSel.value=defaultModel; + + apiCfg={key:key,model:defaultModel,baseUrl:workingBase,connected:true,models:foundModels}; + try{localStorage.setItem('hl-api',JSON.stringify(apiCfg))}catch(e){} + st.textContent='✅ 检测到 '+foundModels.length+' 个模型 · 当前:'+defaultModel; + st.style.color='var(--ok)'; + document.getElementById('chatTg').textContent=defaultModel; + chatMsg('🔑 API已连接 · 检测到'+foundModels.length+'个可用模型\n当前使用:'+defaultModel+'\n可在下拉菜单切换模型','b',{m:'铸渊',t:'自定义'}); + }else{ + // Can't get model list, try direct connection test with common models + st.textContent='🔍 模型列表不可用,尝试直连测试…'; + var tryBase=userBase||COMMON_ENDPOINTS[0]; + var testModels=['gpt-4o-mini','gpt-4o','gpt-3.5-turbo','deepseek-chat','claude-3-haiku-20240307']; + var worked=false; + for(var j=0;j'+testModels[j]+''; + modelListDiv.style.display='block'; + st.textContent='✅ 连接成功 · '+testModels[j]; + st.style.color='var(--ok)'; + document.getElementById('chatTg').textContent=testModels[j]; + chatMsg('🔑 API已连接('+testModels[j]+')','b',{m:'铸渊',t:'自定义'}); + worked=true;break; + } + } + if(!worked){ + st.textContent='❌ 无法连接 · 请检查密钥和API地址'; st.style.color='var(--err)'; apiCfg.connected=false; } - }catch(e){ - st.textContent='❌ 连接失败,检查Key和网络'; - st.style.color='var(--err)'; - apiCfg.connected=false; } - btn.disabled=false;btn.textContent='连接'; + btn.disabled=false;btn.textContent='检测'; }; })(); @@ -1285,7 +1554,72 @@ tryLoadFromCOS(); /* ════════════════════════════════════════ MONITOR ════════════════════════════════════════ */ -document.getElementById('mon').onclick=function(){this.classList.toggle('x')}; +/* ════════════════════════════════════════ + MONITOR (draggable + toggle) + ════════════════════════════════════════ */ +(function(){ + var mon=document.getElementById('mon'); + if(!mon)return; + var isDrag=false,hasMoved=false; + var startX,startY,monX,monY; + + // Restore position + try{ + var pos=JSON.parse(localStorage.getItem('hl-mon-pos')); + if(pos&&typeof pos.x==='number'){ + var ww=window.innerWidth,wh=window.innerHeight; + var mw=mon.offsetWidth||80,mh=mon.offsetHeight||30; + if(pos.x>=0&&pos.x<=ww-mw&&pos.y>=0&&pos.y<=wh-mh){ + mon.style.right='auto';mon.style.top='auto'; + mon.style.left=pos.x+'px';mon.style.top=pos.y+'px'; + } + } + }catch(e){} + + function getXY(e){return e.touches?{x:e.touches[0].clientX,y:e.touches[0].clientY}:{x:e.clientX,y:e.clientY}} + + function onStart(e){ + isDrag=true;hasMoved=false; + var xy=getXY(e); + var rect=mon.getBoundingClientRect(); + startX=xy.x-rect.left;startY=xy.y-rect.top; + monX=rect.left;monY=rect.top; + mon.style.transition='none'; + } + function onMove(e){ + if(!isDrag)return; + var xy=getXY(e); + var nx=xy.x-startX,ny=xy.y-startY; + if(!hasMoved&&Math.abs(nx-monX)<5&&Math.abs(ny-monY)<5)return; + hasMoved=true; + e.preventDefault(); + var mw=mon.offsetWidth,mh=mon.offsetHeight; + monX=Math.max(0,Math.min(window.innerWidth-mw,nx)); + monY=Math.max(0,Math.min(window.innerHeight-mh,ny)); + mon.style.right='auto'; + mon.style.left=monX+'px';mon.style.top=monY+'px'; + } + function onEnd(){ + if(!isDrag)return; + isDrag=false; + mon.style.transition='all .3s'; + if(hasMoved){ + try{localStorage.setItem('hl-mon-pos',JSON.stringify({x:monX,y:monY}))}catch(e){} + } + } + + mon.addEventListener('touchstart',onStart,{passive:true}); + document.addEventListener('touchmove',onMove,{passive:false}); + document.addEventListener('touchend',onEnd); + mon.addEventListener('mousedown',function(e){if(e.button===0)onStart(e)}); + document.addEventListener('mousemove',onMove); + document.addEventListener('mouseup',onEnd); + + mon.onclick=function(e){ + if(hasMoved){hasMoved=false;return} + this.classList.toggle('x'); + }; +})(); async function checkConn(){ try{var t=performance.now();var r=await fetch('/api/health',{signal:AbortSignal.timeout(4000)});var ms=Math.round(performance.now()-t); document.getElementById('mN').textContent=ms+'ms';document.getElementById('mN').style.color=ms<500?'var(--ok)':'var(--warn)'; @@ -1380,14 +1714,17 @@ checkConn();setInterval(checkConn,30000); SYSTEM STATUS (左面板实时数据) ════════════════════════════════════════ */ async function loadSysStatus(){ + var sEl=document.getElementById('sysStatus'); + var lEl=document.getElementById('sysLatency'); + var uEl=document.getElementById('sysUptime'); + var wfEl=document.getElementById('sysWorkflows'); + var modEl=document.getElementById('sysModules'); + var cosEl=document.getElementById('sysCos'); try{ var t=performance.now(); var r=await fetch('/api/health',{signal:AbortSignal.timeout(5000)}); var ms=Math.round(performance.now()-t); var data=await r.json(); - var sEl=document.getElementById('sysStatus'); - var lEl=document.getElementById('sysLatency'); - var uEl=document.getElementById('sysUptime'); if(sEl){sEl.textContent='🟢 在线';sEl.className='panel-value ok'} if(lEl){lEl.textContent=ms+'ms';lEl.className='panel-value '+(ms<500?'ok':'warn')} if(uEl){ @@ -1395,12 +1732,24 @@ async function loadSysStatus(){ var uh=Math.floor(um/60); uEl.textContent=uh>0?uh+'h '+um%60+'m':um+'分钟'; } + // Real data from server if available + if(wfEl){wfEl.textContent=data.workflows?data.workflows:'无法获取';wfEl.className='panel-value '+(data.workflows?'ok':'')} + if(modEl){modEl.textContent=data.modules?data.modules:'无法获取';modEl.className='panel-value '+(data.modules?'ok':'')} + if(cosEl){ + if(data.cos){cosEl.textContent=data.cos;cosEl.className='panel-value ok'} + else{cosEl.textContent='无法确认';cosEl.className='panel-value warn'} + } }catch(e){ - var sEl=document.getElementById('sysStatus'); if(sEl){sEl.textContent='🔴 离线';sEl.className='panel-value err'} + if(lEl){lEl.textContent='—';lEl.className='panel-value err'} + if(uEl){uEl.textContent='—';uEl.className='panel-value'} + if(wfEl){wfEl.textContent='无法连接';wfEl.className='panel-value err'} + if(modEl){modEl.textContent='无法连接';modEl.className='panel-value err'} + if(cosEl){cosEl.textContent='无法连接';cosEl.className='panel-value err'} } } loadSysStatus(); +setInterval(loadSysStatus,30000); /* ════════════════════════════════════════ BULLETIN & TICKER (动态公告)