class-studys 7.0.1 → 7.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.html +299 -114
- package/package.json +1 -1
package/index.html
CHANGED
|
@@ -21,8 +21,8 @@ button{font-family:inherit;cursor:pointer;border:none;background:none;color:inhe
|
|
|
21
21
|
/* ---------- particles ---------- */
|
|
22
22
|
#particles{position:fixed;inset:0;z-index:0;pointer-events:none}
|
|
23
23
|
|
|
24
|
-
/* ---------- ambient glow
|
|
25
|
-
.glow{position:fixed;z-index:0;pointer-events:none;filter:blur(120px);opacity:.
|
|
24
|
+
/* ---------- ambient glow ---------- */
|
|
25
|
+
.glow{position:fixed;z-index:0;pointer-events:none;filter:blur(120px);opacity:.13;border-radius:50%;
|
|
26
26
|
background:var(--accent);animation:glowFloat 14s ease-in-out infinite alternate}
|
|
27
27
|
.glow.g1{width:55vw;height:55vw;top:-20vw;right:-15vw}
|
|
28
28
|
.glow.g2{width:40vw;height:40vw;bottom:-15vw;left:-10vw;animation-delay:-7s}
|
|
@@ -41,91 +41,123 @@ button{font-family:inherit;cursor:pointer;border:none;background:none;color:inhe
|
|
|
41
41
|
.glass::before{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
|
|
42
42
|
background:linear-gradient(135deg,rgba(255,255,255,.14),transparent 40%,transparent 70%,rgba(255,255,255,.05))}
|
|
43
43
|
|
|
44
|
-
/*
|
|
45
|
-
|
|
44
|
+
/* ============================================================
|
|
45
|
+
HOME — left-aligned hero, long scrollable page
|
|
46
|
+
============================================================ */
|
|
47
|
+
#home{overflow-y:auto;scrollbar-width:none;display:block;padding:0}
|
|
48
|
+
#proxy{padding:0}
|
|
49
|
+
#proxyFrame{flex:1;width:100%;height:100%;border:none;background:#000}
|
|
46
50
|
#home::-webkit-scrollbar{display:none}
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
|
|
52
|
+
.hero{min-height:100vh;display:flex;flex-direction:column;justify-content:center;align-items:flex-start;
|
|
53
|
+
padding:12vh 7vw 10vh;position:relative;text-align:left;overflow:hidden}
|
|
54
|
+
/* left edge accent beam */
|
|
55
|
+
.hero::before{content:"";position:absolute;left:0;top:15%;bottom:15%;width:3px;border-radius:3px;
|
|
56
|
+
background:linear-gradient(180deg,transparent,var(--accent),transparent);
|
|
57
|
+
animation:beamPulse 4s ease-in-out infinite;opacity:.7}
|
|
58
|
+
@keyframes beamPulse{0%,100%{opacity:.35;filter:blur(1px)}50%{opacity:.9;filter:blur(0)}}
|
|
59
|
+
|
|
49
60
|
.os-badge{display:inline-flex;align-items:center;gap:8px;padding:6px 16px;border-radius:99px;
|
|
50
61
|
font-size:12px;letter-spacing:.25em;text-transform:uppercase;color:var(--accent);
|
|
51
|
-
border:1px solid color-mix(in srgb,var(--accent) 40%,transparent);margin-bottom:
|
|
52
|
-
animation:pulseBadge 3s ease-in-out infinite}
|
|
62
|
+
border:1px solid color-mix(in srgb,var(--accent) 40%,transparent);margin-bottom:26px;
|
|
63
|
+
animation:slideLeft .8s cubic-bezier(.22,1,.36,1) both, pulseBadge 3s ease-in-out infinite 1s}
|
|
64
|
+
@keyframes slideLeft{from{opacity:0;transform:translateX(-46px)}to{opacity:1;transform:none}}
|
|
53
65
|
@keyframes pulseBadge{0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--accent) 35%,transparent)}
|
|
54
66
|
50%{box-shadow:0 0 24px 4px color-mix(in srgb,var(--accent) 25%,transparent)}}
|
|
55
67
|
.os-badge .dot{width:7px;height:7px;border-radius:50%;background:var(--accent);animation:blink 1.6s infinite}
|
|
56
68
|
@keyframes blink{50%{opacity:.25}}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
#bigTitle
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
|
|
70
|
+
#bigTitle{font-size:clamp(60px,10vw,138px);font-weight:800;line-height:.93;letter-spacing:-.035em;
|
|
71
|
+
display:flex;flex-direction:column;align-items:flex-start}
|
|
72
|
+
#bigTitle {
|
|
73
|
+
font-size: clamp(60px, 10vw, 138px);
|
|
74
|
+
font-weight: 800;
|
|
75
|
+
line-height: 1;
|
|
76
|
+
letter-spacing: -0.035em;
|
|
77
|
+
display: flex;
|
|
78
|
+
flex-direction: row;
|
|
79
|
+
align-items: center;
|
|
80
|
+
gap: 0.2em;
|
|
81
|
+
white-space: nowrap;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
#rotator{height:30px;margin-top:26px;font-size:clamp(15px,1.6vw,20px);color:#9a9a9a;overflow:hidden;position:relative;width:min(560px,80vw)}
|
|
85
|
+
#rotator .line{position:absolute;inset:0;display:flex;align-items:center;gap:10px;
|
|
86
|
+
opacity:0;transform:translateY(26px);transition:opacity .6s,transform .6s cubic-bezier(.22,1,.36,1)}
|
|
66
87
|
#rotator .line.on{opacity:1;transform:none}
|
|
67
|
-
#rotator .line.off{opacity:0;transform:translateY(-
|
|
68
|
-
#rotator .tick{width:22px;height:2px;background:var(--accent);border-radius:2px;flex:none
|
|
88
|
+
#rotator .line.off{opacity:0;transform:translateY(-26px)}
|
|
89
|
+
#rotator .tick{width:22px;height:2px;background:var(--accent);border-radius:2px;flex:none;
|
|
90
|
+
box-shadow:0 0 10px var(--accent)}
|
|
69
91
|
|
|
70
|
-
/*
|
|
71
|
-
.widget-row{display:flex;gap:16px;margin-top:
|
|
92
|
+
/* widget row */
|
|
93
|
+
.widget-row{display:flex;gap:16px;margin-top:48px;flex-wrap:wrap;animation:slideLeft 1s .55s cubic-bezier(.22,1,.36,1) both}
|
|
72
94
|
.widget{padding:18px 22px;display:flex;align-items:center;gap:16px;min-width:200px;
|
|
95
|
+
animation:floaty 5.5s ease-in-out infinite;animation-delay:var(--fd,0s);
|
|
73
96
|
transition:transform .35s cubic-bezier(.22,1,.36,1),box-shadow .35s}
|
|
74
|
-
.widget:hover{transform:translateY(-
|
|
97
|
+
.widget:hover{transform:translateY(-6px) scale(1.03);box-shadow:0 16px 44px rgba(0,0,0,.6),0 0 30px color-mix(in srgb,var(--accent) 14%,transparent)}
|
|
98
|
+
@keyframes floaty{0%,100%{translate:0 0}50%{translate:0 -7px}}
|
|
75
99
|
.widget .wicon{font-size:30px;filter:drop-shadow(0 0 12px color-mix(in srgb,var(--accent) 45%,transparent))}
|
|
76
100
|
.widget .wlabel{font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:#888}
|
|
77
101
|
.widget .wvalue{font-size:20px;font-weight:700;margin-top:2px}
|
|
78
|
-
/* battery ring */
|
|
79
102
|
.ring{transform:rotate(-90deg)}
|
|
80
103
|
.ring .bg{stroke:rgba(255,255,255,.1)}
|
|
81
|
-
.ring .fg{stroke:var(--accent);stroke-linecap:round;transition:stroke-dashoffset 1s cubic-bezier(.22,1,.36,1)
|
|
104
|
+
.ring .fg{stroke:var(--accent);stroke-linecap:round;transition:stroke-dashoffset 1s cubic-bezier(.22,1,.36,1);
|
|
105
|
+
filter:drop-shadow(0 0 6px var(--accent))}
|
|
82
106
|
|
|
83
|
-
/*
|
|
84
|
-
.home-nav{display:flex;gap:14px;margin-top:
|
|
85
|
-
.nav-btn{padding:
|
|
107
|
+
/* nav */
|
|
108
|
+
.home-nav{display:flex;gap:14px;margin-top:50px;flex-wrap:wrap;animation:slideLeft 1.1s .7s cubic-bezier(.22,1,.36,1) both}
|
|
109
|
+
.nav-btn{padding:15px 30px;border-radius:18px;font-size:15px;font-weight:600;letter-spacing:.04em;
|
|
86
110
|
display:flex;align-items:center;gap:10px;transition:all .3s cubic-bezier(.22,1,.36,1)}
|
|
87
111
|
.nav-btn:hover{transform:translateY(-4px) scale(1.03);border-color:color-mix(in srgb,var(--accent) 55%,transparent);
|
|
88
112
|
box-shadow:0 12px 34px rgba(0,0,0,.55),0 0 26px color-mix(in srgb,var(--accent) 18%,transparent)}
|
|
89
113
|
.nav-btn .arr{transition:transform .3s}
|
|
90
|
-
.nav-btn:hover .arr{transform:translateX(
|
|
114
|
+
.nav-btn:hover .arr{transform:translateX(6px)}
|
|
91
115
|
.nav-btn.primary{background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 70%,#000));
|
|
92
116
|
color:#0a0a0a;box-shadow:0 8px 26px color-mix(in srgb,var(--accent) 35%,transparent)}
|
|
93
117
|
|
|
94
|
-
/*
|
|
95
|
-
.
|
|
96
|
-
|
|
97
|
-
.
|
|
98
|
-
|
|
99
|
-
.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
118
|
+
/* scroll cue */
|
|
119
|
+
.scroll-cue{position:absolute;left:50%;bottom:26px;transform:translateX(-50%);display:flex;flex-direction:column;
|
|
120
|
+
align-items:center;gap:6px;color:#666;font-size:10px;letter-spacing:.35em;text-transform:uppercase;
|
|
121
|
+
animation:fadeIn 1.4s 1.6s both}
|
|
122
|
+
.scroll-cue .chev{width:12px;height:12px;border-right:2px solid var(--accent);border-bottom:2px solid var(--accent);
|
|
123
|
+
transform:rotate(45deg);animation:chevBounce 1.6s ease-in-out infinite}
|
|
124
|
+
@keyframes chevBounce{0%,100%{transform:rotate(45deg) translate(0,0);opacity:.5}50%{transform:rotate(45deg) translate(5px,5px);opacity:1}}
|
|
125
|
+
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
|
|
126
|
+
|
|
127
|
+
/* ---------- library marquee ---------- */
|
|
128
|
+
.library{width:100%;padding:9vh 0 16vh;display:flex;flex-direction:column;gap:24px;
|
|
129
|
+
animation:fadeIn 1s both}
|
|
130
|
+
.library .lib-title{padding:0 7vw;font-size:clamp(28px,4vw,48px);font-weight:800;letter-spacing:-.02em;display:flex;align-items:baseline;gap:16px}
|
|
131
|
+
.library .lib-title em{font-style:normal;color:var(--accent)}
|
|
132
|
+
.library .lib-title .n{font-size:13px;color:#666;font-weight:600;letter-spacing:.2em}
|
|
133
|
+
.library .lib-sub{padding:0 7vw;color:#777;font-size:14px;margin-top:-12px}
|
|
134
|
+
.rail-window{overflow:hidden;width:100%;position:relative;padding:8px 0;
|
|
103
135
|
-webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
|
|
104
136
|
mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
|
|
105
|
-
.rail-track{display:flex;gap:
|
|
106
|
-
|
|
107
|
-
.rail-track.rev{animation-direction:reverse;animation-duration:50s}
|
|
137
|
+
.rail-track{display:flex;gap:20px;width:max-content;padding-right:20px;animation:railScroll 42s linear infinite}
|
|
138
|
+
.rail-track.rev{animation-direction:reverse;animation-duration:52s}
|
|
108
139
|
.rail-window:hover .rail-track{animation-play-state:paused}
|
|
109
140
|
@keyframes railScroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
|
|
110
|
-
.rail-game{width:
|
|
141
|
+
.rail-game{width:96px;height:96px;flex:none;border-radius:26px;overflow:hidden;
|
|
111
142
|
position:relative;border:1px solid var(--glass-border);cursor:pointer;
|
|
112
|
-
transition:transform .35s cubic-bezier(.34,1.56,.64,1),box-shadow .35s}
|
|
113
|
-
.rail-game:hover{transform:scale(1.
|
|
143
|
+
transition:transform .35s cubic-bezier(.34,1.56,.64,1),box-shadow .35s;animation:floaty 6s ease-in-out infinite;animation-delay:var(--fd,0s)}
|
|
144
|
+
.rail-game:hover{transform:scale(1.16) rotate(-4deg);animation-play-state:paused;
|
|
145
|
+
box-shadow:0 12px 34px rgba(0,0,0,.65),0 0 26px var(--gc,#ff6b1a)}
|
|
114
146
|
.rail-game img{width:100%;height:100%;object-fit:cover;display:block}
|
|
115
147
|
|
|
116
|
-
/*
|
|
148
|
+
/* section headers */
|
|
117
149
|
.hub{padding:34px 5vw 130px;overflow-y:auto;scrollbar-width:none}
|
|
118
150
|
.hub::-webkit-scrollbar{display:none}
|
|
119
151
|
.hub-head{display:flex;align-items:flex-end;justify-content:space-between;margin-bottom:34px;
|
|
120
|
-
animation:
|
|
152
|
+
animation:slideLeft .7s cubic-bezier(.22,1,.36,1) both}
|
|
121
153
|
.hub-head h2{font-size:clamp(34px,4.5vw,58px);font-weight:800;letter-spacing:-.02em}
|
|
122
154
|
.hub-head h2 em{font-style:normal;color:var(--accent)}
|
|
123
155
|
.hub-head .count{font-size:13px;color:#777;letter-spacing:.15em;text-transform:uppercase}
|
|
124
156
|
|
|
125
|
-
/* games grid: rows of 5
|
|
157
|
+
/* games grid: rows of 5 */
|
|
126
158
|
.games-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:22px}
|
|
127
159
|
@media(max-width:1100px){.games-grid{grid-template-columns:repeat(4,1fr)}}
|
|
128
|
-
@media(max-width:800px){.games-grid{grid-template-columns:repeat(3,1fr)}}
|
|
160
|
+
@media(max-width:800px){.games-grid{grid-template-columns:repeat(3,1fr)}.hero{padding:10vh 6vw}}
|
|
129
161
|
@media(max-width:520px){.games-grid{grid-template-columns:repeat(2,1fr)}}
|
|
130
162
|
.game-tile{aspect-ratio:1;border-radius:26px;overflow:hidden;position:relative;cursor:pointer;
|
|
131
163
|
border:1px solid var(--glass-border);
|
|
@@ -153,7 +185,7 @@ button{font-family:inherit;cursor:pointer;border:none;background:none;color:inhe
|
|
|
153
185
|
.game-tile .feat-tag{position:absolute;top:10px;left:10px;background:var(--accent);color:#000;
|
|
154
186
|
font-size:9px;font-weight:800;letter-spacing:.12em;padding:4px 9px;border-radius:8px}
|
|
155
187
|
|
|
156
|
-
/* movies
|
|
188
|
+
/* movies */
|
|
157
189
|
.movies-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:26px}
|
|
158
190
|
.movie-tile{border-radius:20px;overflow:hidden;cursor:pointer;position:relative;aspect-ratio:2/3;
|
|
159
191
|
border:1px solid var(--glass-border);
|
|
@@ -169,24 +201,25 @@ button{font-family:inherit;cursor:pointer;border:none;background:none;color:inhe
|
|
|
169
201
|
filter:drop-shadow(0 0 14px var(--accent));transition:transform .3s}
|
|
170
202
|
.movie-tile:hover .tri{transform:scale(1.2)}
|
|
171
203
|
|
|
172
|
-
/*
|
|
204
|
+
/* play modal */
|
|
173
205
|
#playModal{position:fixed;inset:0;z-index:50;display:none;align-items:center;justify-content:center;
|
|
174
206
|
background:rgba(0,0,0,.82);backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px)}
|
|
175
207
|
#playModal.open{display:flex;animation:fadeIn .3s ease}
|
|
176
|
-
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
|
|
177
208
|
.play-shell{width:min(1100px,94vw);height:min(86vh,90vh);border-radius:26px;overflow:hidden;
|
|
178
|
-
display:flex;flex-direction:column;border:1px solid var(--glass-border);
|
|
179
|
-
|
|
209
|
+
display:flex;flex-direction:column;border:1px solid var(--glass-border);background:#0a0a0a;
|
|
210
|
+
box-shadow:0 40px 120px rgba(0,0,0,.8),0 0 60px color-mix(in srgb,var(--accent) 10%,transparent);
|
|
180
211
|
animation:popIn .45s cubic-bezier(.34,1.56,.64,1)}
|
|
181
212
|
@keyframes popIn{from{opacity:0;transform:scale(.9)}to{opacity:1;transform:none}}
|
|
182
213
|
.play-bar{display:flex;align-items:center;gap:14px;padding:12px 18px;
|
|
183
214
|
background:rgba(255,255,255,.04);border-bottom:1px solid var(--glass-border)}
|
|
184
|
-
.play-bar .ttl{font-weight:700;font-size:15px;
|
|
215
|
+
.play-bar .ttl{font-weight:700;font-size:15px;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
185
216
|
.play-bar .live{width:8px;height:8px;border-radius:50%;background:var(--accent);animation:blink 1.4s infinite;flex:none}
|
|
186
217
|
.play-bar button{padding:8px 18px;border-radius:12px;font-size:13px;font-weight:700;
|
|
187
218
|
background:rgba(255,255,255,.08);border:1px solid var(--glass-border);transition:all .25s}
|
|
188
219
|
.play-bar button:hover{background:var(--accent);color:#000}
|
|
189
220
|
#playFrame{flex:1;width:100%;border:none;background:#000}
|
|
221
|
+
.play-shell:fullscreen{width:100vw;height:100vh;border-radius:0}
|
|
222
|
+
.play-shell:fullscreen .play-bar{padding:14px 22px}
|
|
190
223
|
.play-loading{position:absolute;inset:44px 0 0;display:flex;flex-direction:column;gap:18px;
|
|
191
224
|
align-items:center;justify-content:center;background:#0a0a0a;transition:opacity .4s;z-index:2}
|
|
192
225
|
.play-loading.gone{opacity:0;pointer-events:none}
|
|
@@ -194,9 +227,10 @@ button{font-family:inherit;cursor:pointer;border:none;background:none;color:inhe
|
|
|
194
227
|
border-top-color:var(--accent);animation:spin 1s linear infinite}
|
|
195
228
|
@keyframes spin{to{transform:rotate(360deg)}}
|
|
196
229
|
|
|
197
|
-
/*
|
|
230
|
+
/* dock */
|
|
198
231
|
#dock{position:fixed;left:50%;bottom:22px;transform:translateX(-50%);z-index:20;display:flex;gap:6px;
|
|
199
232
|
padding:8px;border-radius:24px;animation:riseIn 1s .5s cubic-bezier(.22,1,.36,1) both}
|
|
233
|
+
@keyframes riseIn{from{opacity:0;transform:translate(-50%,40px)}to{opacity:1;transform:translate(-50%,0)}}
|
|
200
234
|
.dock-btn{padding:12px 22px;border-radius:17px;font-size:14px;font-weight:600;color:#aaa;
|
|
201
235
|
display:flex;align-items:center;gap:8px;transition:all .3s cubic-bezier(.22,1,.36,1);position:relative}
|
|
202
236
|
.dock-btn:hover{color:#fff;transform:translateY(-3px)}
|
|
@@ -204,7 +238,7 @@ button{font-family:inherit;cursor:pointer;border:none;background:none;color:inhe
|
|
|
204
238
|
box-shadow:0 6px 22px color-mix(in srgb,var(--accent) 40%,transparent)}
|
|
205
239
|
.dock-btn .dicon{font-size:16px}
|
|
206
240
|
|
|
207
|
-
/*
|
|
241
|
+
/* settings */
|
|
208
242
|
#settingsModal{position:fixed;inset:0;z-index:60;display:none;align-items:center;justify-content:center;
|
|
209
243
|
background:rgba(0,0,0,.7);backdrop-filter:blur(14px)}
|
|
210
244
|
#settingsModal.open{display:flex;animation:fadeIn .25s ease}
|
|
@@ -226,10 +260,31 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
226
260
|
padding:10px 14px;border-radius:12px;font-size:14px;width:170px;outline:none;transition:border .25s}
|
|
227
261
|
.set-input:focus{border-color:var(--accent)}
|
|
228
262
|
|
|
263
|
+
/* ---------- TOUR ---------- */
|
|
264
|
+
#tour{position:fixed;inset:0;z-index:80;display:none}
|
|
265
|
+
#tour.open{display:block}
|
|
266
|
+
#tour .dim{position:absolute;inset:0;background:rgba(0,0,0,.72);backdrop-filter:blur(6px);animation:fadeIn .3s}
|
|
267
|
+
.tour-card{position:absolute;left:50%;bottom:110px;transform:translateX(-50%);width:min(440px,90vw);
|
|
268
|
+
padding:26px 28px;animation:popIn .45s cubic-bezier(.34,1.56,.64,1)}
|
|
269
|
+
.tour-card .step-n{font-size:10px;letter-spacing:.3em;color:var(--accent);font-weight:800;text-transform:uppercase}
|
|
270
|
+
.tour-card h4{font-size:20px;font-weight:800;margin:8px 0 8px}
|
|
271
|
+
.tour-card p{font-size:14px;color:#b5b5b5;line-height:1.6}
|
|
272
|
+
.tour-card .tour-nav{display:flex;gap:10px;margin-top:20px;align-items:center}
|
|
273
|
+
.tour-card .tour-nav .prog{flex:1;display:flex;gap:6px}
|
|
274
|
+
.tour-card .tour-nav .prog i{flex:1;height:3px;border-radius:3px;background:rgba(255,255,255,.14);transition:background .3s}
|
|
275
|
+
.tour-card .tour-nav .prog i.on{background:var(--accent);box-shadow:0 0 8px var(--accent)}
|
|
276
|
+
.tour-btn{padding:10px 20px;border-radius:13px;font-size:13px;font-weight:700;
|
|
277
|
+
background:rgba(255,255,255,.08);border:1px solid var(--glass-border);transition:all .25s}
|
|
278
|
+
.tour-btn.next{background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 75%,#000));color:#0a0a0a;border:none}
|
|
279
|
+
.tour-btn:hover{transform:translateY(-2px)}
|
|
280
|
+
.tour-spot{position:absolute;z-index:81;border-radius:28px;pointer-events:none;
|
|
281
|
+
box-shadow:0 0 0 3px var(--accent),0 0 44px 6px color-mix(in srgb,var(--accent) 45%,transparent);
|
|
282
|
+
animation:spotPulse 1.6s ease-in-out infinite;transition:all .5s cubic-bezier(.22,1,.36,1)}
|
|
283
|
+
@keyframes spotPulse{0%,100%{opacity:.85}50%{opacity:1}}
|
|
284
|
+
|
|
229
285
|
/* ---------- AI ---------- */
|
|
230
|
-
#ai{padding:0}
|
|
231
286
|
.ai-wrap{flex:1;display:flex;flex-direction:column;max-width:900px;width:100%;margin:0 auto;padding:30px 4vw 120px}
|
|
232
|
-
.ai-head{display:flex;align-items:center;gap:16px;margin-bottom:20px;animation:
|
|
287
|
+
.ai-head{display:flex;align-items:center;gap:16px;margin-bottom:20px;animation:slideLeft .6s both}
|
|
233
288
|
.ai-orb{width:52px;height:52px;border-radius:50%;flex:none;position:relative;
|
|
234
289
|
background:radial-gradient(circle at 32% 30%,color-mix(in srgb,var(--accent) 80%,#fff),var(--accent) 45%,#3a1500);
|
|
235
290
|
animation:orbFloat 4s ease-in-out infinite;box-shadow:0 0 34px color-mix(in srgb,var(--accent) 45%,transparent)}
|
|
@@ -249,7 +304,6 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
249
304
|
.msg.bot{align-self:flex-start;background:var(--glass);backdrop-filter:blur(20px);
|
|
250
305
|
border:1px solid var(--glass-border);border-bottom-left-radius:6px}
|
|
251
306
|
.msg.bot .who{font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--accent);font-weight:800;margin-bottom:6px}
|
|
252
|
-
/* code widget */
|
|
253
307
|
.code-widget{margin:12px 0;border-radius:16px;overflow:hidden;border:1px solid var(--glass-border);
|
|
254
308
|
background:#0b0b0f;box-shadow:0 8px 24px rgba(0,0,0,.4)}
|
|
255
309
|
.code-head{display:flex;align-items:center;gap:10px;padding:9px 14px;background:rgba(255,255,255,.05);
|
|
@@ -271,7 +325,8 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
271
325
|
.typing i:nth-child(2){animation-delay:.18s}.typing i:nth-child(3){animation-delay:.36s}
|
|
272
326
|
@keyframes tp{0%,60%,100%{transform:translateY(0);opacity:.4}30%{transform:translateY(-7px);opacity:1}}
|
|
273
327
|
#aiInputBar{display:flex;gap:12px;margin-top:18px;padding:10px 10px 10px 22px;align-items:center;
|
|
274
|
-
animation:
|
|
328
|
+
animation:riseInDock .8s .2s both}
|
|
329
|
+
@keyframes riseInDock{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:none}}
|
|
275
330
|
#aiInput{flex:1;background:none;border:none;outline:none;color:#fff;font-size:15px;font-family:inherit}
|
|
276
331
|
#aiInput::placeholder{color:#666}
|
|
277
332
|
#sendBtn{width:48px;height:48px;border-radius:16px;flex:none;display:flex;align-items:center;justify-content:center;
|
|
@@ -283,14 +338,14 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
283
338
|
color:#aaa;background:rgba(255,255,255,.04);transition:all .25s}
|
|
284
339
|
.chip:hover{color:#fff;border-color:var(--accent);transform:translateY(-2px)}
|
|
285
340
|
|
|
286
|
-
/* toast */
|
|
287
341
|
#toast{position:fixed;left:50%;bottom:96px;transform:translate(-50%,20px);z-index:99;opacity:0;
|
|
288
|
-
background:rgba(15,15,
|
|
342
|
+
background:rgba(15,15,10,.92);backdrop-filter:blur(14px);border:1px solid var(--glass-border);
|
|
289
343
|
padding:11px 22px;border-radius:14px;font-size:13px;font-weight:600;pointer-events:none;
|
|
290
344
|
transition:all .35s cubic-bezier(.22,1,.36,1)}
|
|
291
345
|
#toast.on{opacity:1;transform:translate(-50%,0)}
|
|
292
346
|
</style>
|
|
293
347
|
<base target="_blank">
|
|
348
|
+
<base target="_blank">
|
|
294
349
|
</head>
|
|
295
350
|
<body>
|
|
296
351
|
|
|
@@ -300,17 +355,20 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
300
355
|
|
|
301
356
|
<!-- ============ HOME ============ -->
|
|
302
357
|
<div class="screen active" id="home">
|
|
303
|
-
<div class="
|
|
304
|
-
<div class="os-badge"><span class="dot"></span>IGNITE OS · v2.
|
|
305
|
-
<h1 id="bigTitle">
|
|
358
|
+
<div class="hero" id="hero">
|
|
359
|
+
<div class="os-badge"><span class="dot"></span>IGNITE OS · v2.1</div>
|
|
360
|
+
<h1 id="bigTitle">
|
|
361
|
+
<span class="row" data-txt="IGNITE"></span>
|
|
362
|
+
<span class="row os" data-txt="OS"></span>
|
|
363
|
+
</h1>
|
|
306
364
|
<div id="rotator"></div>
|
|
307
365
|
|
|
308
|
-
<div class="widget-row">
|
|
309
|
-
<div class="widget glass">
|
|
366
|
+
<div class="widget-row" id="widgetRow">
|
|
367
|
+
<div class="widget glass" style="--fd:0s">
|
|
310
368
|
<div class="wicon" id="wIcon">⛅</div>
|
|
311
369
|
<div><div class="wlabel">Weather</div><div class="wvalue" id="wVal">--°</div></div>
|
|
312
370
|
</div>
|
|
313
|
-
<div class="widget glass">
|
|
371
|
+
<div class="widget glass" style="--fd:1.4s">
|
|
314
372
|
<svg class="ring" width="52" height="52" viewBox="0 0 52 52">
|
|
315
373
|
<circle class="bg" cx="26" cy="26" r="21" fill="none" stroke-width="5"/>
|
|
316
374
|
<circle class="fg" id="battRing" cx="26" cy="26" r="21" fill="none" stroke-width="5"
|
|
@@ -318,7 +376,7 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
318
376
|
</svg>
|
|
319
377
|
<div><div class="wlabel">Battery</div><div class="wvalue" id="battVal">--%</div></div>
|
|
320
378
|
</div>
|
|
321
|
-
<div class="widget glass">
|
|
379
|
+
<div class="widget glass" style="--fd:2.8s">
|
|
322
380
|
<div class="wicon">🕒</div>
|
|
323
381
|
<div><div class="wlabel">Time</div><div class="wvalue" id="clockVal">--:--</div></div>
|
|
324
382
|
</div>
|
|
@@ -329,17 +387,19 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
329
387
|
<button class="nav-btn glass" onclick="go('movies')">Movies <span class="arr">→</span></button>
|
|
330
388
|
<button class="nav-btn glass" onclick="go('ai')">Ask IGNITE AI <span class="arr">→</span></button>
|
|
331
389
|
</div>
|
|
390
|
+
|
|
391
|
+
<div class="scroll-cue"><span>Scroll</span><div class="chev"></div></div>
|
|
332
392
|
</div>
|
|
333
393
|
|
|
334
394
|
<!-- library marquee -->
|
|
335
|
-
<div class="library">
|
|
336
|
-
<div class="lib-
|
|
395
|
+
<div class="library" id="librarySec">
|
|
396
|
+
<div class="lib-title">Game <em>Library</em> <span class="n">20 TITLES</span></div>
|
|
397
|
+
<div class="lib-sub">Auto-scrolling · hover to pause · click any icon to play instantly</div>
|
|
337
398
|
<div class="rail-window"><div class="rail-track" id="railTrack"></div></div>
|
|
338
399
|
<div class="rail-window"><div class="rail-track rev" id="railTrack2"></div></div>
|
|
339
400
|
</div>
|
|
340
401
|
</div>
|
|
341
402
|
|
|
342
|
-
|
|
343
403
|
<!-- ============ GAMES HUB ============ -->
|
|
344
404
|
<div class="screen" id="games">
|
|
345
405
|
<div class="hub">
|
|
@@ -373,7 +433,7 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
373
433
|
</div>
|
|
374
434
|
</div>
|
|
375
435
|
<div id="chatLog"></div>
|
|
376
|
-
<div class="chips"
|
|
436
|
+
<div class="chips">
|
|
377
437
|
<button class="chip" onclick="quickAsk('Write a Python script that sorts a list and explain it')">💻 Give me code</button>
|
|
378
438
|
<button class="chip" onclick="quickAsk('Explain quantum computing simply')">🧠 Teach me something</button>
|
|
379
439
|
<button class="chip" onclick="quickAsk('Help me build a game in JavaScript')">🎮 Build a game</button>
|
|
@@ -385,13 +445,20 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
385
445
|
</div>
|
|
386
446
|
</div>
|
|
387
447
|
|
|
448
|
+
<!-- ============ PROXY ============ -->
|
|
449
|
+
<div class="screen" id="proxy">
|
|
450
|
+
<iframe id="proxyFrame" src="about:blank"
|
|
451
|
+
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"></iframe>
|
|
452
|
+
</div>
|
|
453
|
+
|
|
388
454
|
<!-- ============ DOCK ============ -->
|
|
389
455
|
<nav id="dock" class="glass">
|
|
390
456
|
<button class="dock-btn on" data-s="home" onclick="go('home')"><span class="dicon">⌂</span>Home</button>
|
|
391
457
|
<button class="dock-btn" data-s="games" onclick="go('games')"><span class="dicon">🎮</span>Games</button>
|
|
392
458
|
<button class="dock-btn" data-s="movies" onclick="go('movies')"><span class="dicon">🎬</span>Movies</button>
|
|
393
459
|
<button class="dock-btn" data-s="ai" onclick="go('ai')"><span class="dicon">✦</span>AI</button>
|
|
394
|
-
<button class="dock-btn" onclick="
|
|
460
|
+
<button class="dock-btn" data-s="proxy" onclick="go('proxy')"><span class="dicon">🧭</span>Proxy</button>
|
|
461
|
+
<button class="dock-btn" id="settingsBtn" onclick="openSettings()"><span class="dicon">⚙</span></button>
|
|
395
462
|
</nav>
|
|
396
463
|
|
|
397
464
|
<!-- ============ PLAY MODAL ============ -->
|
|
@@ -400,11 +467,12 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
400
467
|
<div class="play-bar">
|
|
401
468
|
<span class="live"></span>
|
|
402
469
|
<span class="ttl" id="playTitle">Now Playing</span>
|
|
470
|
+
<button onclick="toggleFullScreen()" title="Fullscreen">⛶ Fullscreen</button>
|
|
403
471
|
<button onclick="closePlay()">✕ Close</button>
|
|
404
472
|
</div>
|
|
405
473
|
<div style="position:relative;flex:1;display:flex">
|
|
406
474
|
<div class="play-loading" id="playLoading"><div class="spinner"></div><div style="color:#888;font-size:13px">Loading…</div></div>
|
|
407
|
-
<iframe id="playFrame" allowfullscreen sandbox="allow-scripts allow-same-origin allow-forms allow-popups-to-escape-sandbox"></iframe>
|
|
475
|
+
<iframe id="playFrame" allowfullscreen sandbox="allow-scripts allow-same-origin allow-forms allow-fullscreen allow-popups-to-escape-sandbox"></iframe>
|
|
408
476
|
</div>
|
|
409
477
|
</div>
|
|
410
478
|
</div>
|
|
@@ -413,7 +481,7 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
413
481
|
<div id="settingsModal" onclick="if(event.target===this)closeSettings()">
|
|
414
482
|
<div class="settings-card glass">
|
|
415
483
|
<h3>Settings</h3>
|
|
416
|
-
<div class="sub">Customize IGNITE OS — accent color, weather &
|
|
484
|
+
<div class="sub">Customize IGNITE OS — accent color, weather, particles & AI.</div>
|
|
417
485
|
|
|
418
486
|
<div class="set-row">
|
|
419
487
|
<div><div class="lbl">Accent Color</div><div class="hint">The tiny bit of orange — make it yours.</div></div>
|
|
@@ -431,10 +499,15 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
431
499
|
</div>
|
|
432
500
|
|
|
433
501
|
<div class="set-row">
|
|
434
|
-
<div><div class="lbl">AI Model</div><div class="hint">
|
|
502
|
+
<div><div class="lbl">AI Model</div><div class="hint">Which OpenAI model IGNITE AI uses.</div></div>
|
|
435
503
|
<input class="set-input" id="modelInput" type="text" placeholder="model name">
|
|
436
504
|
</div>
|
|
437
505
|
|
|
506
|
+
<div class="set-row">
|
|
507
|
+
<div><div class="lbl">Beginner Tour</div><div class="hint">Replay the welcome walkthrough.</div></div>
|
|
508
|
+
<button class="tour-btn" onclick="closeSettings();startTour()">▶ Replay</button>
|
|
509
|
+
</div>
|
|
510
|
+
|
|
438
511
|
<div style="display:flex;gap:12px;margin-top:26px">
|
|
439
512
|
<button class="nav-btn primary glass" style="flex:1;justify-content:center" onclick="saveSettings()">Save</button>
|
|
440
513
|
<button class="nav-btn glass" style="flex:1;justify-content:center" onclick="closeSettings()">Cancel</button>
|
|
@@ -442,12 +515,27 @@ input[type=text],input[type=range]{accent-color:var(--accent)}
|
|
|
442
515
|
</div>
|
|
443
516
|
</div>
|
|
444
517
|
|
|
518
|
+
<!-- ============ TOUR ============ -->
|
|
519
|
+
<div id="tour">
|
|
520
|
+
<div class="dim"></div>
|
|
521
|
+
<div class="tour-spot" id="tourSpot"></div>
|
|
522
|
+
<div class="tour-card glass">
|
|
523
|
+
<div class="step-n" id="tourStepN">Step 1 of 5</div>
|
|
524
|
+
<h4 id="tourTitle"></h4>
|
|
525
|
+
<p id="tourText"></p>
|
|
526
|
+
<div class="tour-nav">
|
|
527
|
+
<div class="prog" id="tourProg"></div>
|
|
528
|
+
<button class="tour-btn" onclick="endTour()">Skip</button>
|
|
529
|
+
<button class="tour-btn next" id="tourNext" onclick="tourNext()">Next →</button>
|
|
530
|
+
</div>
|
|
531
|
+
</div>
|
|
532
|
+
</div>
|
|
533
|
+
|
|
445
534
|
<div id="toast"></div>
|
|
446
535
|
|
|
447
536
|
<script>
|
|
448
537
|
/* ================= DATA (links encoded — not exposed) ================= */
|
|
449
|
-
const GAMES = [{id:'
|
|
450
|
-
{id:'cookie-clicker',name:'Cookie Clicker',color:'#22d3ee',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLWNvb2tpZS1jbGlja2VyQDUuMC4wL2luZGV4Lmh0bWw=',cover:'https://i.imgur.com/3ZQ3Z3Z.png'},
|
|
538
|
+
const GAMES = [{id:'cookie-clicker',name:'Cookie Clicker',color:'#22d3ee',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLWNvb2tpZS1jbGlja2VyQDUuMC4wL2luZGV4Lmh0bWw=',cover:'https://i.imgur.com/3ZQ3Z3Z.png'},
|
|
451
539
|
{id:'recoil',name:'Recoil',color:'#ff6b1a',featured:false,u:'aHR0cHM6Ly9nZW5lcmljLWFscGFjYS0zMjUzMjEuZnJhbWVyLmFwcC8=',cover:'https://fancade.com/images/5E9F40DA7F9C9FA8.jpg'},
|
|
452
540
|
{id:'retro-ball',name:'Retro Ball',color:'#a855f7',featured:false,u:'aHR0cHM6Ly9vYmplY3RzdG9yYWdlLnVzLWFzaGJ1cm4tMS5vcmFjbGVjbG91ZC5jb20vbi9pZHpneWZpN2F3d3IvYi9idWNrZXQtMjAyMzEwMDEtMTUxOC1yYjEuMC9vL2luZGV4Lmh0bWw=',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTfQEUbXopS95V30bru2UdgdystMD8ElzCDFzH6k6_pUQ&s'},
|
|
453
541
|
{id:'drift-boss',name:'Drift Boss',color:'#3b82f6',featured:false,u:'aHR0cHM6Ly93d3cubWF0aHBsYXlncm91bmQuY29tL2RyaWZ0LWJvc3MtdjMvaW5kZXguaHRtbA==',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMW_L-ZhbnvWj1lwNrWeAGDaK0rG0lCw52zSIsTfTmWNZ9oOVhXvQ_oJRA&s=10'},
|
|
@@ -466,16 +554,18 @@ const GAMES = [{id:'duck-math',name:'DUCK MATH',color:'#ffb26b',featured:true,u:
|
|
|
466
554
|
{id:'bitlife',name:'Bitlife',color:'#34d399',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLWJpdGxpZmVANS4wLjAvaW5kZXguaHRtbA==',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZdo5cBqkv1uAcfCofpC-WAViocRNLlysohwHMV2Lqzw&s=10'},
|
|
467
555
|
{id:'tag',name:'Tag',color:'#facc15',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLXRhZ0AxLjAuMC9pbmRleC5odG1s',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFwGQ9vG6ZifxDpWHtuu8oSzYqll79xZ9rW_KwPwzCdA&s'},
|
|
468
556
|
{id:'block-blast',name:'Block Blast',color:'#a855f7',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLWJsb2NrLWJsYXN0QDUuMC4wL2luZGV4Lmh0bWw=',cover:'https://imgs.crazygames.com/block-puzzle-master_1x1/20250924025352/block-puzzle-master_1x1-cover?format=auto&quality=70&metadata=none'},
|
|
469
|
-
{id:'cut-the-rope',name:'Cut the Rope',color:'#34d399',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLWN1dC10aGUtcm9wZUA1LjAuMC9pbmRleC5odG1s',cover:'https://play-lh.googleusercontent.com/2bTmHHM7DBMVe7fLh16Em-J-tVBMFGL2HJCxPAMNF7gAYIfU6EZoYG1__lQ0cvFMEyp3GU9CGijZzEB1qJHF'}
|
|
557
|
+
{id:'cut-the-rope',name:'Cut the Rope',color:'#34d399',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLWN1dC10aGUtcm9wZUA1LjAuMC9pbmRleC5odG1s',cover:'https://play-lh.googleusercontent.com/2bTmHHM7DBMVe7fLh16Em-J-tVBMFGL2HJCxPAMNF7gAYIfU6EZoYG1__lQ0cvFMEyp3GU9CGijZzEB1qJHF'},
|
|
558
|
+
{id:'duck-math',name:'Duck Math',color:'#34d399',featured:true,u:'aHR0cHM6Ly91bnBrZy5jb20vaWduaXRlLWdvb2JlckAxLjEuNC9pbmRleC5odG1sIy9jbGFzcy9kcmlmdC1raW5n',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRJFXWvY3bIWxbR2SZEnbZaVFRYqFzZJZlOo4SYkWOexg&s'}];
|
|
470
559
|
const MOVIES = [{name:'Spiderman: Far From Home',u:'aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xdDYyWVk1VjJXRnFQQTgwMWNERUN3dzFFUVlrNGZNbmsvcHJldmlldw==',poster:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSjdXbHSbJUSaJdgj45vDisJUiPj1qljxkOPbfojU3M1w&s=10'},
|
|
471
560
|
{name:'Spiderman: Homecoming',u:'aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xaFVJeDA1RzNOX3VjZzhTd2RaSFJ0XzVNZHFMUVp0YWkvcHJldmlldw==',poster:'https://resizing.flixster.com/-XZAfHZM39UwaGJIFWKAE8fS0ak=/v3/t/assets/p12798844_p_v8_ao.jpg'},
|
|
472
561
|
{name:'F1',u:'aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xa196UkR0NFJuXzlGb3RZSlVmcmhKWjBaREtmd3FRazEvcHJldmlldw==',poster:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSr2SgmDLkFhLGuF1CnP_xJv1stiKvK027DkN6m6wdqdg&s=10'},
|
|
473
562
|
{name:'Obsession',u:'aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xRkVOMTZMd001WnpUQlNiQnRrWTk1THJJemxzSFhGeDcvcHJldmlldw==',poster:'https://images.contentstack.io/v3/assets/blt13adb7e2033fcee5/blt5c8bcbfee5dade5c/6a2b47a8c284bac540ef3353/Obsession_keyart_poster_2000x3000.jpg?width=2560'}];
|
|
474
563
|
const dec = s => atob(s);
|
|
564
|
+
const PROXY_URL = dec('aHR0cHM6Ly9tb2JpbGUtc2VydmljZS0zODYzMTEuZnJhbWVyLmFwcC8=');
|
|
475
565
|
const AI_KEY = "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";
|
|
476
566
|
|
|
477
567
|
/* ================= SETTINGS ================= */
|
|
478
|
-
const DEFAULTS = {accent:"#ff6b1a", city:"", particles:140, model:"gpt-4o
|
|
568
|
+
const DEFAULTS = {accent:"#ff6b1a", city:"", particles:140, model:"gpt-4o"};
|
|
479
569
|
let S = {...DEFAULTS, ...JSON.parse(localStorage.getItem("igniteos")||"{}")};
|
|
480
570
|
const saveS = () => localStorage.setItem("igniteos", JSON.stringify(S));
|
|
481
571
|
const applyAccent = () => document.documentElement.style.setProperty("--accent", S.accent);
|
|
@@ -485,10 +575,15 @@ function go(id){
|
|
|
485
575
|
document.querySelectorAll(".screen").forEach(s=>s.classList.remove("active"));
|
|
486
576
|
document.getElementById(id).classList.add("active");
|
|
487
577
|
document.querySelectorAll(".dock-btn[data-s]").forEach(b=>b.classList.toggle("on", b.dataset.s===id));
|
|
578
|
+
if(id==="proxy"){
|
|
579
|
+
const pf = document.getElementById("proxyFrame");
|
|
580
|
+
if(!pf.src || pf.src==="about:blank") pf.src = PROXY_URL;
|
|
581
|
+
}
|
|
488
582
|
if(id==="home") startParticles(); else stopParticles();
|
|
583
|
+
window.scrollTo(0,0); document.getElementById(id==='home'?'home':id).scrollTop = 0;
|
|
489
584
|
}
|
|
490
585
|
|
|
491
|
-
/* ================= PARTICLES
|
|
586
|
+
/* ================= PARTICLES ================= */
|
|
492
587
|
const cv = document.getElementById("particles"), ctx = cv.getContext("2d");
|
|
493
588
|
let flakes = [], raf = null;
|
|
494
589
|
function sizeCanvas(){ cv.width = innerWidth; cv.height = innerHeight; }
|
|
@@ -520,9 +615,19 @@ function hexA(h, a){
|
|
|
520
615
|
function startParticles(){ if(!raf){ makeFlakes(); drawFlakes(); } }
|
|
521
616
|
function stopParticles(){ cancelAnimationFrame(raf); raf = null; ctx.clearRect(0,0,cv.width,cv.height); }
|
|
522
617
|
|
|
523
|
-
/* =================
|
|
618
|
+
/* ================= TITLE letters ================= */
|
|
619
|
+
document.querySelectorAll("#bigTitle .row").forEach((row, ri)=>{
|
|
620
|
+
[...row.dataset.txt].forEach((ch, i)=>{
|
|
621
|
+
const s = document.createElement("span");
|
|
622
|
+
s.className = "ch"; s.textContent = ch;
|
|
623
|
+
s.style.setProperty("--cd", (0.15 + ri*0.28 + i*0.055) + "s");
|
|
624
|
+
row.appendChild(s);
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
/* ================= ROTATOR ================= */
|
|
524
629
|
const LINES = [
|
|
525
|
-
"
|
|
630
|
+
"20 hand-picked games. Zero loading pain.",
|
|
526
631
|
"A private movie theater, right in your browser.",
|
|
527
632
|
"An AI that codes, explains and builds with you.",
|
|
528
633
|
"Liquid glass. Falling light. Pure black.",
|
|
@@ -544,11 +649,23 @@ setInterval(()=>{
|
|
|
544
649
|
lines[li].classList.add("on");
|
|
545
650
|
}, 3800);
|
|
546
651
|
|
|
652
|
+
/* ================= HERO mouse parallax ================= */
|
|
653
|
+
const hero = document.getElementById("hero");
|
|
654
|
+
hero.addEventListener("mousemove", e=>{
|
|
655
|
+
const rx = (e.clientX/innerWidth - .5), ry = (e.clientY/innerHeight - .5);
|
|
656
|
+
hero.querySelectorAll(".os-badge,#bigTitle,.widget-row,.home-nav").forEach((el,i)=>{
|
|
657
|
+
const d = (i+1)*4;
|
|
658
|
+
el.style.transform = `translate(${-rx*d}px, ${-ry*d}px)`;
|
|
659
|
+
});
|
|
660
|
+
});
|
|
661
|
+
hero.addEventListener("mouseleave", ()=>{
|
|
662
|
+
hero.querySelectorAll(".os-badge,#bigTitle,.widget-row,.home-nav").forEach(el=>el.style.transform="");
|
|
663
|
+
});
|
|
664
|
+
|
|
547
665
|
/* ================= CLOCK ================= */
|
|
548
666
|
setInterval(()=>{
|
|
549
|
-
const d = new Date();
|
|
550
667
|
document.getElementById("clockVal").textContent =
|
|
551
|
-
|
|
668
|
+
new Date().toLocaleTimeString([], {hour:"2-digit", minute:"2-digit"});
|
|
552
669
|
}, 1000);
|
|
553
670
|
|
|
554
671
|
/* ================= BATTERY ================= */
|
|
@@ -564,7 +681,7 @@ setInterval(()=>{
|
|
|
564
681
|
}catch(e){ document.getElementById("battVal").textContent = "N/A"; }
|
|
565
682
|
})();
|
|
566
683
|
|
|
567
|
-
/* ================= WEATHER
|
|
684
|
+
/* ================= WEATHER ================= */
|
|
568
685
|
const WMO = {0:"☀️",1:"🌤️",2:"⛅",3:"☁️",45:"🌫️",48:"🌫️",51:"🌦️",53:"🌦️",55:"🌧️",56:"🌧️",57:"🌧️",
|
|
569
686
|
61:"🌧️",63:"🌧️",65:"🌧️",66:"🌧️",67:"🌧️",71:"🌨️",73:"🌨️",75:"🌨️",77:"🌨️",80:"🌦️",81:"🌧️",82:"⛈️",
|
|
570
687
|
85:"🌨️",86:"🌨️",95:"⛈️",96:"⛈️",99:"⛈️"};
|
|
@@ -587,7 +704,7 @@ async function loadWeather(){
|
|
|
587
704
|
}catch(e){ val.textContent = "Set city ⚙"; ic.textContent = "🌍"; }
|
|
588
705
|
}
|
|
589
706
|
|
|
590
|
-
/* ================= BUILD GAMES ================= */
|
|
707
|
+
/* ================= BUILD GAMES GRID ================= */
|
|
591
708
|
const gamesGrid = document.getElementById("gamesGrid");
|
|
592
709
|
GAMES.forEach((g,i)=>{
|
|
593
710
|
const t = document.createElement("div");
|
|
@@ -602,11 +719,12 @@ GAMES.forEach((g,i)=>{
|
|
|
602
719
|
});
|
|
603
720
|
document.getElementById("gameCount").textContent = GAMES.length + " titles · click to play";
|
|
604
721
|
|
|
605
|
-
/* library marquee
|
|
722
|
+
/* library marquee rows */
|
|
606
723
|
function buildRail(el, list){
|
|
607
|
-
[...list, ...list].forEach(g=>{
|
|
724
|
+
[...list, ...list].forEach((g,i)=>{
|
|
608
725
|
const d = document.createElement("div");
|
|
609
726
|
d.className = "rail-game"; d.style.setProperty("--gc", g.color);
|
|
727
|
+
d.style.setProperty("--fd", ((i%10)*0.35)+"s");
|
|
610
728
|
d.innerHTML = `<img src="${g.cover}" alt="" loading="lazy" onerror="this.style.display='none'">`;
|
|
611
729
|
d.title = g.name;
|
|
612
730
|
d.onclick = ()=>openPlay(g.name, dec(g.u));
|
|
@@ -627,7 +745,7 @@ MOVIES.forEach((m,i)=>{
|
|
|
627
745
|
});
|
|
628
746
|
document.getElementById("movieCount").textContent = MOVIES.length + " now streaming";
|
|
629
747
|
|
|
630
|
-
/* ================= PLAY MODAL
|
|
748
|
+
/* ================= PLAY MODAL ================= */
|
|
631
749
|
const pm = document.getElementById("playModal"), pf = document.getElementById("playFrame"),
|
|
632
750
|
pl = document.getElementById("playLoading");
|
|
633
751
|
function openPlay(title, url){
|
|
@@ -636,16 +754,25 @@ function openPlay(title, url){
|
|
|
636
754
|
pm.classList.add("open");
|
|
637
755
|
pf.src = url;
|
|
638
756
|
pf.onload = ()=>setTimeout(()=>pl.classList.add("gone"), 400);
|
|
639
|
-
document.body.style.overflow = "hidden";
|
|
640
757
|
}
|
|
641
758
|
function closePlay(){
|
|
759
|
+
if(document.fullscreenElement) document.exitFullscreen().catch(()=>{});
|
|
642
760
|
pm.classList.remove("open");
|
|
643
761
|
pf.src = "about:blank";
|
|
644
|
-
document.body.style.overflow = "";
|
|
645
762
|
}
|
|
646
|
-
|
|
763
|
+
function toggleFullScreen(){
|
|
764
|
+
const shell = pm.querySelector(".play-shell");
|
|
765
|
+
if(document.fullscreenElement){ document.exitFullscreen().catch(()=>{}); return; }
|
|
766
|
+
if(shell.requestFullscreen) shell.requestFullscreen().catch(()=>toast("Fullscreen blocked by browser"));
|
|
767
|
+
else toast("Fullscreen not supported");
|
|
768
|
+
}
|
|
769
|
+
document.addEventListener("fullscreenchange", ()=>{
|
|
770
|
+
const btn = document.querySelector("#playModal .play-bar button[onclick='toggleFullScreen()']");
|
|
771
|
+
if(btn) btn.innerHTML = document.fullscreenElement ? "🗗 Exit Full" : "⛶ Fullscreen";
|
|
772
|
+
});
|
|
773
|
+
addEventListener("keydown", e=>{ if(e.key==="Escape"){ closePlay(); closeSettings(); endTour(); } });
|
|
647
774
|
|
|
648
|
-
/* ================= SETTINGS
|
|
775
|
+
/* ================= SETTINGS ================= */
|
|
649
776
|
const COLORS = ["#ff6b1a","#ff3b30","#ff9500","#ffd60a","#34c759","#00c7be","#32ade6","#7d7aff","#bf5af2","#ff375f"];
|
|
650
777
|
const sw = document.getElementById("swatches");
|
|
651
778
|
COLORS.forEach(c=>{
|
|
@@ -674,17 +801,55 @@ function toast(t){
|
|
|
674
801
|
clearTimeout(el._t); el._t = setTimeout(()=>el.classList.remove("on"), 2200);
|
|
675
802
|
}
|
|
676
803
|
|
|
804
|
+
/* ================= TOUR ================= */
|
|
805
|
+
const TOUR_STEPS = [
|
|
806
|
+
{t:"#bigTitle", title:"Welcome to IGNITE OS ✦", text:"This is your command center. Everything runs right here in the browser — snow falls, glass glows, and your whole library lives one click away."},
|
|
807
|
+
{t:"#widgetRow", title:"Live widgets", text:"Real-time weather, your battery ring, and the clock — all in liquid glass. Set your city later in Settings (the ⚙ button)."},
|
|
808
|
+
{t:"#librarySec", title:"The Game Library", text:"All 20 games scroll past automatically — two rows, opposite directions. Hover to pause, click any icon and it starts instantly. No links, no new tabs."},
|
|
809
|
+
{t:"#dock", title:"The Dock", text:"Jump between Home, Games Hub, Movie Theater and IGNITE AI anytime. The ✦ button opens your AI assistant."},
|
|
810
|
+
{t:"#settingsBtn", title:"Make it yours", text:"Tap the gear to change the accent color, weather city, snow density, and the AI model. That's it — you're ready. Have fun!"}
|
|
811
|
+
];
|
|
812
|
+
let tIdx = 0;
|
|
813
|
+
const tourEl = document.getElementById("tour"), spot = document.getElementById("tourSpot");
|
|
814
|
+
function startTour(){
|
|
815
|
+
if(!document.getElementById("home").classList.contains("active")) go("home");
|
|
816
|
+
document.getElementById("home").scrollTop = 0;
|
|
817
|
+
tourEl.classList.add("open"); tIdx = 0; showStep();
|
|
818
|
+
}
|
|
819
|
+
function showStep(){
|
|
820
|
+
const s = TOUR_STEPS[tIdx];
|
|
821
|
+
document.getElementById("tourStepN").textContent = `Step ${tIdx+1} of ${TOUR_STEPS.length}`;
|
|
822
|
+
document.getElementById("tourTitle").textContent = s.title;
|
|
823
|
+
document.getElementById("tourText").textContent = s.text;
|
|
824
|
+
document.getElementById("tourNext").textContent = tIdx===TOUR_STEPS.length-1 ? "Finish ✦" : "Next →";
|
|
825
|
+
const prog = document.getElementById("tourProg");
|
|
826
|
+
prog.innerHTML = TOUR_STEPS.map((_,i)=>`<i class="${i<=tIdx?'on':''}"></i>`).join("");
|
|
827
|
+
const el = document.querySelector(s.t);
|
|
828
|
+
el.scrollIntoView({block:"center", behavior:"smooth"});
|
|
829
|
+
setTimeout(()=>{
|
|
830
|
+
const r = el.getBoundingClientRect();
|
|
831
|
+
spot.style.cssText = `left:${r.left-14}px;top:${r.top-14}px;width:${r.width+28}px;height:${r.height+28}px;display:block`;
|
|
832
|
+
}, 350);
|
|
833
|
+
}
|
|
834
|
+
function tourNext(){
|
|
835
|
+
if(tIdx === TOUR_STEPS.length-1){ endTour(); return; }
|
|
836
|
+
tIdx++; showStep();
|
|
837
|
+
}
|
|
838
|
+
function endTour(){
|
|
839
|
+
tourEl.classList.remove("open");
|
|
840
|
+
spot.style.display = "none";
|
|
841
|
+
localStorage.setItem("igniteos_toured", "1");
|
|
842
|
+
}
|
|
843
|
+
|
|
677
844
|
/* ================= AI ================= */
|
|
678
845
|
const chatLog = document.getElementById("chatLog");
|
|
679
846
|
const history = [];
|
|
680
847
|
function addMsg(text, who){
|
|
681
848
|
const d = document.createElement("div");
|
|
682
849
|
d.className = "msg " + who;
|
|
683
|
-
if(who==="bot")
|
|
684
|
-
|
|
685
|
-
} else d.textContent = text;
|
|
850
|
+
if(who==="bot") d.innerHTML = '<div class="who">IGNITE AI</div>' + renderBot(text);
|
|
851
|
+
else d.textContent = text;
|
|
686
852
|
chatLog.appendChild(d); chatLog.scrollTop = chatLog.scrollHeight;
|
|
687
|
-
return d;
|
|
688
853
|
}
|
|
689
854
|
function renderBot(text){
|
|
690
855
|
const parts = text.split(/```(\w*)\n?([\s\S]*?)(?:```|$)/g);
|
|
@@ -716,6 +881,26 @@ chatLog.addEventListener("click", e=>{
|
|
|
716
881
|
}
|
|
717
882
|
});
|
|
718
883
|
function quickAsk(q){ document.getElementById("aiInput").value = q; sendMsg(); }
|
|
884
|
+
|
|
885
|
+
async function askOpenAI(model, q){
|
|
886
|
+
const res = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
887
|
+
method:"POST",
|
|
888
|
+
headers:{ "Content-Type":"application/json", "Authorization":"Bearer " + AI_KEY },
|
|
889
|
+
body: JSON.stringify({
|
|
890
|
+
model,
|
|
891
|
+
messages: [
|
|
892
|
+
{role:"system", content:"You are IGNITE AI, a super-smart, friendly assistant inside IGNITE OS. You are excellent at coding, explanations, math, creative writing, game ideas and problem solving. Always format code in triple backticks with the language name. Be concise but complete."},
|
|
893
|
+
...history.slice(-10),
|
|
894
|
+
{role:"user", content:q}
|
|
895
|
+
]
|
|
896
|
+
})
|
|
897
|
+
});
|
|
898
|
+
const data = await res.json().catch(()=>({}));
|
|
899
|
+
if(!res.ok) throw {status:res.status, msg:data.error?.message || ("HTTP " + res.status)};
|
|
900
|
+
if(!data.choices?.[0]?.message?.content) throw {status:res.status, msg:"Unexpected response shape"};
|
|
901
|
+
return data.choices[0].message.content;
|
|
902
|
+
}
|
|
903
|
+
|
|
719
904
|
async function sendMsg(){
|
|
720
905
|
const inp = document.getElementById("aiInput"), q = inp.value.trim();
|
|
721
906
|
if(!q) return;
|
|
@@ -724,27 +909,26 @@ async function sendMsg(){
|
|
|
724
909
|
tp.className = "msg bot typing"; tp.innerHTML = "<i></i><i></i><i></i>";
|
|
725
910
|
chatLog.appendChild(tp); chatLog.scrollTop = chatLog.scrollHeight;
|
|
726
911
|
try{
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
})
|
|
738
|
-
});
|
|
739
|
-
const data = await res.json();
|
|
912
|
+
let reply, lastErr;
|
|
913
|
+
const tries = [S.model, "gpt-4o", "gpt-4o-mini", "gpt-3.5-turbo"].filter((v,i,a)=>a.indexOf(v)===i);
|
|
914
|
+
for(const m of tries){
|
|
915
|
+
try{ reply = await askOpenAI(m, q); if(m!==S.model) toast(`Auto-switched to ${m}`); break; }
|
|
916
|
+
catch(e){
|
|
917
|
+
lastErr = e;
|
|
918
|
+
const notModelIssue = e.status===401 || e.status===403 || e.status===429;
|
|
919
|
+
if(notModelIssue || tries.indexOf(m)===tries.length-1) throw e;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
740
922
|
tp.remove();
|
|
741
|
-
if(!res.ok || !data.choices) throw new Error(data.error?.message || "API error");
|
|
742
|
-
const reply = data.choices[0].message.content;
|
|
743
923
|
history.push({role:"user",content:q},{role:"assistant",content:reply});
|
|
744
924
|
addMsg(reply, "bot");
|
|
745
925
|
}catch(err){
|
|
746
926
|
tp.remove();
|
|
747
|
-
|
|
927
|
+
let hint = "";
|
|
928
|
+
if(err.status===401) hint = "The API key was rejected (401). Double-check it in the code.";
|
|
929
|
+
else if(err.status===429) hint = "Rate limit hit (429) — wait a moment and retry.";
|
|
930
|
+
else if(err.status===404) hint = "Model not found (404) — set a valid model in Settings.";
|
|
931
|
+
addMsg(`⚠️ AI error: ${esc(err.msg||err.message||"unknown")}\n${hint}`, "bot");
|
|
748
932
|
}
|
|
749
933
|
}
|
|
750
934
|
document.getElementById("aiInput").addEventListener("keydown", e=>{ if(e.key==="Enter") sendMsg(); });
|
|
@@ -752,6 +936,7 @@ document.getElementById("aiInput").addEventListener("keydown", e=>{ if(e.key==="
|
|
|
752
936
|
/* ================= BOOT ================= */
|
|
753
937
|
applyAccent(); startParticles(); loadWeather();
|
|
754
938
|
addMsg("Hey! I'm IGNITE AI ✦ I'm great at a lot of things — coding, explaining, brainstorming, math, you name it. Ask me anything, and if you want code just say so — I'll wrap it in a neat copyable block.", "bot");
|
|
939
|
+
if(!localStorage.getItem("igniteos_toured")) setTimeout(startTour, 900);
|
|
755
940
|
</script>
|
|
756
941
|
</body>
|
|
757
942
|
</html>
|