class-studys 7.0.1 → 8.0.0

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.
Files changed (103) hide show
  1. package/.well-known/discord +1 -0
  2. package/21fn9e.js +54 -0
  3. package/README.md +25 -0
  4. package/assets/AccountPage-DmlYaBSE-8068ec8f.js +1 -0
  5. package/assets/AccountPage-fg4fizGa-8068ec8f.css +1 -0
  6. package/assets/AiPage-CTjB7gWo-8068ec8f.css +1 -0
  7. package/assets/AiPage-CbTtOj3W-8068ec8f.js +18 -0
  8. package/assets/DarkVeil-CC-BBhGo-8068ec8f.js +69 -0
  9. package/assets/GamesPage--YRYDVtw-8068ec8f.css +1 -0
  10. package/assets/GamesPage-D-HV0rpM-8068ec8f.js +1 -0
  11. package/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  12. package/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  13. package/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  14. package/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  15. package/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  16. package/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  17. package/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  18. package/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  19. package/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  20. package/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  21. package/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  22. package/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  23. package/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  24. package/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  25. package/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  26. package/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  27. package/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  28. package/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  29. package/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  30. package/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  31. package/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  32. package/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  33. package/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  34. package/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  35. package/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  36. package/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  37. package/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  38. package/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  39. package/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  40. package/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  41. package/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  42. package/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  43. package/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  44. package/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  45. package/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  46. package/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  47. package/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  48. package/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  49. package/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  50. package/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  51. package/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  52. package/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  53. package/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  54. package/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  55. package/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  56. package/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  57. package/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  58. package/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  59. package/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  60. package/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  61. package/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  62. package/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  63. package/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  64. package/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  65. package/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  66. package/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  67. package/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  68. package/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  69. package/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  70. package/assets/PlusPage-DBE836ej-8068ec8f.js +1 -0
  71. package/assets/PlusPage-vOvT9Zss-8068ec8f.css +1 -0
  72. package/assets/SettingsPage-CsV-N8Y0-8068ec8f.js +1 -0
  73. package/assets/boot-D3vqjHTs-8068ec8f.js +1 -0
  74. package/assets/fingerprint-Y5nV5FVa-8068ec8f.js +4 -0
  75. package/assets/index-COUSXtyQ-8068ec8f.js +3 -0
  76. package/assets/index-D4-Q3uqd-8068ec8f.css +1 -0
  77. package/assets/markdown-BtlGIx_H-8068ec8f.js +291 -0
  78. package/assets/markdown-dIRGbAJA-8068ec8f.css +1 -0
  79. package/assets/motion-B1hdS1Lc-8068ec8f.js +9 -0
  80. package/assets/ogl-BWe_HKY6-8068ec8f.js +1 -0
  81. package/assets/proxy-runtime-hRo6K69j-8068ec8f.js +13 -0
  82. package/assets/react-BNEptbwn-8068ec8f.js +49 -0
  83. package/assets/settings-page-B-LiQw8a-8068ec8f.css +1 -0
  84. package/assets/verity-mini-DjLHPujK.png +0 -0
  85. package/branding/ignite-os-browser-834cc7f9f1eda4fb.png +0 -0
  86. package/branding/ignite-os-browser-spooky-805a89482927bc04.png +0 -0
  87. package/branding/ignite-os-browser-spooky-no-drips-52ef55ca90dacae1.png +0 -0
  88. package/equ4q/67140b.js +2 -0
  89. package/equ4q/8tzsxm.js +41 -0
  90. package/equ4q/datyqq.js +2 -0
  91. package/favicon.svg +8 -0
  92. package/ignite-ember.css +191 -0
  93. package/index.html +29 -757
  94. package/index.svg +36 -0
  95. package/jr1n9/4m74rv.js +31 -0
  96. package/jr1n9/cw3zk6.wasm +0 -0
  97. package/logo.svg +36 -0
  98. package/package.json +25 -63
  99. package/privacy.html +113 -0
  100. package/release-manifest.json +1 -0
  101. package/release.json +1 -0
  102. package/study.html +29 -0
  103. package/terms.html +96 -0
package/index.html CHANGED
@@ -1,757 +1,29 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>IGNITE OS</title>
7
- <style>
8
- :root{
9
- --accent:#ff6b1a;
10
- --bg:#050505;
11
- --glass:rgba(255,255,255,.06);
12
- --glass-border:rgba(255,255,255,.12);
13
- --text:#f5f5f5;
14
- }
15
- *{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
16
- html,body{height:100%;overflow:hidden;background:var(--bg);color:var(--text);
17
- font-family:-apple-system,BlinkMacSystemFont,"SF Pro Display","Segoe UI",Inter,Roboto,sans-serif;}
18
- ::selection{background:var(--accent);color:#000}
19
- button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}
20
-
21
- /* ---------- particles ---------- */
22
- #particles{position:fixed;inset:0;z-index:0;pointer-events:none}
23
-
24
- /* ---------- ambient glow (tiny bit of orange) ---------- */
25
- .glow{position:fixed;z-index:0;pointer-events:none;filter:blur(120px);opacity:.14;border-radius:50%;
26
- background:var(--accent);animation:glowFloat 14s ease-in-out infinite alternate}
27
- .glow.g1{width:55vw;height:55vw;top:-20vw;right:-15vw}
28
- .glow.g2{width:40vw;height:40vw;bottom:-15vw;left:-10vw;animation-delay:-7s}
29
- @keyframes glowFloat{from{transform:translate(0,0) scale(1)}to{transform:translate(4vw,-3vw) scale(1.15)}}
30
-
31
- /* ---------- screens ---------- */
32
- .screen{position:fixed;inset:0;z-index:2;display:none;flex-direction:column;
33
- opacity:0;transform:scale(.985);transition:opacity .45s cubic-bezier(.22,1,.36,1),transform .45s cubic-bezier(.22,1,.36,1)}
34
- .screen.active{display:flex;opacity:1;transform:scale(1)}
35
-
36
- /* ---------- liquid glass ---------- */
37
- .glass{background:var(--glass);backdrop-filter:blur(28px) saturate(180%);
38
- -webkit-backdrop-filter:blur(28px) saturate(180%);
39
- border:1px solid var(--glass-border);border-radius:24px;position:relative;overflow:hidden;
40
- box-shadow:0 8px 32px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.15)}
41
- .glass::before{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
42
- background:linear-gradient(135deg,rgba(255,255,255,.14),transparent 40%,transparent 70%,rgba(255,255,255,.05))}
43
-
44
- /* ---------- HOME ---------- */
45
- #home{padding:6vh 6vw 150px;overflow-y:auto;scrollbar-width:none;align-items:center;text-align:center;display:flex;flex-direction:column}
46
- #home::-webkit-scrollbar{display:none}
47
- .home-left{max-width:900px;width:100%;display:flex;flex-direction:column;align-items:center;animation:riseIn 1s cubic-bezier(.22,1,.36,1) both}
48
- @keyframes riseIn{from{opacity:0;transform:translateY(40px)}to{opacity:1;transform:none}}
49
- .os-badge{display:inline-flex;align-items:center;gap:8px;padding:6px 16px;border-radius:99px;
50
- 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:24px;
52
- animation:pulseBadge 3s ease-in-out infinite}
53
- @keyframes pulseBadge{0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--accent) 35%,transparent)}
54
- 50%{box-shadow:0 0 24px 4px color-mix(in srgb,var(--accent) 25%,transparent)}}
55
- .os-badge .dot{width:7px;height:7px;border-radius:50%;background:var(--accent);animation:blink 1.6s infinite}
56
- @keyframes blink{50%{opacity:.25}}
57
- #bigTitle{font-size:clamp(56px,9vw,124px);font-weight:800;line-height:.95;letter-spacing:-.03em;
58
- background:linear-gradient(180deg,#fff 30%,#8a8a8a);-webkit-background-clip:text;background-clip:text;
59
- -webkit-text-fill-color:transparent;animation:titleShimmer 6s ease-in-out infinite}
60
- #bigTitle span{background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 55%,#fff));
61
- -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
62
- @keyframes titleShimmer{0%,100%{filter:drop-shadow(0 0 0 transparent)}50%{filter:drop-shadow(0 0 34px color-mix(in srgb,var(--accent) 30%,transparent))}}
63
- #rotator{height:28px;margin-top:22px;font-size:clamp(15px,1.6vw,20px);color:#9a9a9a;overflow:hidden;position:relative;width:100%}
64
- #rotator .line{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:10px;
65
- opacity:0;transform:translateY(24px);transition:opacity .6s,transform .6s cubic-bezier(.22,1,.36,1)}
66
- #rotator .line.on{opacity:1;transform:none}
67
- #rotator .line.off{opacity:0;transform:translateY(-24px)}
68
- #rotator .tick{width:22px;height:2px;background:var(--accent);border-radius:2px;flex:none}
69
-
70
- /* home widget row */
71
- .widget-row{display:flex;gap:16px;margin-top:44px;flex-wrap:wrap;justify-content:center;animation:riseIn 1.1s .15s cubic-bezier(.22,1,.36,1) both}
72
- .widget{padding:18px 22px;display:flex;align-items:center;gap:16px;min-width:200px;
73
- transition:transform .35s cubic-bezier(.22,1,.36,1),box-shadow .35s}
74
- .widget:hover{transform:translateY(-5px);box-shadow:0 16px 44px rgba(0,0,0,.6),0 0 30px color-mix(in srgb,var(--accent) 12%,transparent)}
75
- .widget .wicon{font-size:30px;filter:drop-shadow(0 0 12px color-mix(in srgb,var(--accent) 45%,transparent))}
76
- .widget .wlabel{font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:#888}
77
- .widget .wvalue{font-size:20px;font-weight:700;margin-top:2px}
78
- /* battery ring */
79
- .ring{transform:rotate(-90deg)}
80
- .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)}
82
-
83
- /* home nav */
84
- .home-nav{display:flex;gap:14px;margin-top:46px;flex-wrap:wrap;justify-content:center;animation:riseIn 1.2s .3s cubic-bezier(.22,1,.36,1) both}
85
- .nav-btn{padding:14px 30px;border-radius:18px;font-size:15px;font-weight:600;letter-spacing:.04em;
86
- display:flex;align-items:center;gap:10px;transition:all .3s cubic-bezier(.22,1,.36,1)}
87
- .nav-btn:hover{transform:translateY(-4px) scale(1.03);border-color:color-mix(in srgb,var(--accent) 55%,transparent);
88
- box-shadow:0 12px 34px rgba(0,0,0,.55),0 0 26px color-mix(in srgb,var(--accent) 18%,transparent)}
89
- .nav-btn .arr{transition:transform .3s}
90
- .nav-btn:hover .arr{transform:translateX(5px)}
91
- .nav-btn.primary{background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 70%,#000));
92
- color:#0a0a0a;box-shadow:0 8px 26px color-mix(in srgb,var(--accent) 35%,transparent)}
93
-
94
- /* ---------- home library marquee ---------- */
95
- .library{width:100%;max-width:1200px;margin-top:80px;display:flex;flex-direction:column;gap:20px;
96
- animation:riseIn 1.3s .4s cubic-bezier(.22,1,.36,1) both}
97
- .library .lib-head{font-size:11px;letter-spacing:.4em;text-transform:uppercase;color:#666;
98
- display:flex;align-items:center;justify-content:center;gap:16px}
99
- .library .lib-head::before,.library .lib-head::after{content:"";width:70px;height:1px;
100
- background:linear-gradient(90deg,transparent,rgba(255,255,255,.25))}
101
- .library .lib-head::after{background:linear-gradient(90deg,rgba(255,255,255,.25),transparent)}
102
- .rail-window{overflow:hidden;width:100%;position:relative;padding:6px 0;
103
- -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
104
- mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
105
- .rail-track{display:flex;gap:18px;width:max-content;padding-right:18px;
106
- animation:railScroll 42s linear infinite}
107
- .rail-track.rev{animation-direction:reverse;animation-duration:50s}
108
- .rail-window:hover .rail-track{animation-play-state:paused}
109
- @keyframes railScroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
110
- .rail-game{width:92px;height:92px;flex:none;border-radius:24px;overflow:hidden;
111
- 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.15) rotate(-3deg);box-shadow:0 10px 30px rgba(0,0,0,.6),0 0 24px var(--gc,#ff6b1a)}
114
- .rail-game img{width:100%;height:100%;object-fit:cover;display:block}
115
-
116
- /* ---------- section headers (games / movies) ---------- */
117
- .hub{padding:34px 5vw 130px;overflow-y:auto;scrollbar-width:none}
118
- .hub::-webkit-scrollbar{display:none}
119
- .hub-head{display:flex;align-items:flex-end;justify-content:space-between;margin-bottom:34px;
120
- animation:riseIn .7s cubic-bezier(.22,1,.36,1) both}
121
- .hub-head h2{font-size:clamp(34px,4.5vw,58px);font-weight:800;letter-spacing:-.02em}
122
- .hub-head h2 em{font-style:normal;color:var(--accent)}
123
- .hub-head .count{font-size:13px;color:#777;letter-spacing:.15em;text-transform:uppercase}
124
-
125
- /* games grid: rows of 5, icons only */
126
- .games-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:22px}
127
- @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)}}
129
- @media(max-width:520px){.games-grid{grid-template-columns:repeat(2,1fr)}}
130
- .game-tile{aspect-ratio:1;border-radius:26px;overflow:hidden;position:relative;cursor:pointer;
131
- border:1px solid var(--glass-border);
132
- animation:tileIn .7s cubic-bezier(.22,1,.36,1) both;animation-delay:var(--d,0s);
133
- transition:transform .4s cubic-bezier(.34,1.56,.64,1),box-shadow .4s}
134
- @keyframes tileIn{from{opacity:0;transform:translateY(34px) scale(.92)}to{opacity:1;transform:none}}
135
- .game-tile:hover{transform:translateY(-8px) scale(1.04);z-index:2;
136
- box-shadow:0 20px 50px rgba(0,0,0,.65),0 0 34px var(--gc,#ff6b1a)}
137
- .game-tile img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .6s cubic-bezier(.22,1,.36,1)}
138
- .game-tile:hover img{transform:scale(1.12)}
139
- .game-tile .shine{position:absolute;inset:0;pointer-events:none;
140
- background:linear-gradient(115deg,transparent 30%,rgba(255,255,255,.22) 48%,transparent 62%);
141
- transform:translateX(-120%);transition:transform .7s ease}
142
- .game-tile:hover .shine{transform:translateX(120%)}
143
- .game-tile .tip{position:absolute;left:50%;bottom:-8px;transform:translate(-50%,10px);opacity:0;
144
- background:rgba(10,10,10,.88);backdrop-filter:blur(10px);border:1px solid var(--glass-border);
145
- padding:7px 15px;border-radius:12px;font-size:13px;font-weight:600;white-space:nowrap;pointer-events:none;
146
- transition:all .3s cubic-bezier(.22,1,.36,1);z-index:3}
147
- .game-tile:hover .tip{opacity:1;transform:translate(-50%,0)}
148
- .game-tile .play-hint{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
149
- background:rgba(0,0,0,.45);opacity:0;transition:opacity .3s}
150
- .game-tile:hover .play-hint{opacity:1}
151
- .play-hint .tri{width:0;height:0;border-left:22px solid #fff;border-top:13px solid transparent;border-bottom:13px solid transparent;
152
- filter:drop-shadow(0 0 14px var(--accent));margin-left:6px}
153
- .game-tile .feat-tag{position:absolute;top:10px;left:10px;background:var(--accent);color:#000;
154
- font-size:9px;font-weight:800;letter-spacing:.12em;padding:4px 9px;border-radius:8px}
155
-
156
- /* movies grid: no names */
157
- .movies-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:26px}
158
- .movie-tile{border-radius:20px;overflow:hidden;cursor:pointer;position:relative;aspect-ratio:2/3;
159
- border:1px solid var(--glass-border);
160
- animation:tileIn .7s cubic-bezier(.22,1,.36,1) both;animation-delay:var(--d,0s);
161
- transition:transform .45s cubic-bezier(.22,1,.36,1),box-shadow .45s}
162
- .movie-tile:hover{transform:translateY(-10px) scale(1.05);box-shadow:0 24px 60px rgba(0,0,0,.7),0 0 40px color-mix(in srgb,var(--accent) 20%,transparent)}
163
- .movie-tile img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .6s cubic-bezier(.22,1,.36,1)}
164
- .movie-tile:hover img{transform:scale(1.1)}
165
- .movie-tile .veil{position:absolute;inset:0;background:linear-gradient(180deg,transparent 55%,rgba(0,0,0,.75));
166
- opacity:0;transition:opacity .35s;display:flex;align-items:flex-end;justify-content:center;padding-bottom:20px}
167
- .movie-tile:hover .veil{opacity:1}
168
- .movie-tile .tri{width:0;height:0;border-left:20px solid #fff;border-top:12px solid transparent;border-bottom:12px solid transparent;
169
- filter:drop-shadow(0 0 14px var(--accent));transition:transform .3s}
170
- .movie-tile:hover .tri{transform:scale(1.2)}
171
-
172
- /* ---------- play modal ---------- */
173
- #playModal{position:fixed;inset:0;z-index:50;display:none;align-items:center;justify-content:center;
174
- background:rgba(0,0,0,.82);backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px)}
175
- #playModal.open{display:flex;animation:fadeIn .3s ease}
176
- @keyframes fadeIn{from{opacity:0}to{opacity:1}}
177
- .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
- background:#0a0a0a;box-shadow:0 40px 120px rgba(0,0,0,.8),0 0 60px color-mix(in srgb,var(--accent) 10%,transparent);
180
- animation:popIn .45s cubic-bezier(.34,1.56,.64,1)}
181
- @keyframes popIn{from{opacity:0;transform:scale(.9)}to{opacity:1;transform:none}}
182
- .play-bar{display:flex;align-items:center;gap:14px;padding:12px 18px;
183
- background:rgba(255,255,255,.04);border-bottom:1px solid var(--glass-border)}
184
- .play-bar .ttl{font-weight:700;font-size:15px;letter-spacing:.02em;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
185
- .play-bar .live{width:8px;height:8px;border-radius:50%;background:var(--accent);animation:blink 1.4s infinite;flex:none}
186
- .play-bar button{padding:8px 18px;border-radius:12px;font-size:13px;font-weight:700;
187
- background:rgba(255,255,255,.08);border:1px solid var(--glass-border);transition:all .25s}
188
- .play-bar button:hover{background:var(--accent);color:#000}
189
- #playFrame{flex:1;width:100%;border:none;background:#000}
190
- .play-loading{position:absolute;inset:44px 0 0;display:flex;flex-direction:column;gap:18px;
191
- align-items:center;justify-content:center;background:#0a0a0a;transition:opacity .4s;z-index:2}
192
- .play-loading.gone{opacity:0;pointer-events:none}
193
- .spinner{width:52px;height:52px;border-radius:50%;border:3px solid rgba(255,255,255,.1);
194
- border-top-color:var(--accent);animation:spin 1s linear infinite}
195
- @keyframes spin{to{transform:rotate(360deg)}}
196
-
197
- /* ---------- bottom nav ---------- */
198
- #dock{position:fixed;left:50%;bottom:22px;transform:translateX(-50%);z-index:20;display:flex;gap:6px;
199
- padding:8px;border-radius:24px;animation:riseIn 1s .5s cubic-bezier(.22,1,.36,1) both}
200
- .dock-btn{padding:12px 22px;border-radius:17px;font-size:14px;font-weight:600;color:#aaa;
201
- display:flex;align-items:center;gap:8px;transition:all .3s cubic-bezier(.22,1,.36,1);position:relative}
202
- .dock-btn:hover{color:#fff;transform:translateY(-3px)}
203
- .dock-btn.on{color:#0a0a0a;background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 75%,#000));
204
- box-shadow:0 6px 22px color-mix(in srgb,var(--accent) 40%,transparent)}
205
- .dock-btn .dicon{font-size:16px}
206
-
207
- /* ---------- settings ---------- */
208
- #settingsModal{position:fixed;inset:0;z-index:60;display:none;align-items:center;justify-content:center;
209
- background:rgba(0,0,0,.7);backdrop-filter:blur(14px)}
210
- #settingsModal.open{display:flex;animation:fadeIn .25s ease}
211
- .settings-card{width:min(560px,92vw);max-height:86vh;overflow-y:auto;padding:32px;scrollbar-width:none;
212
- animation:popIn .4s cubic-bezier(.34,1.56,.64,1)}
213
- .settings-card::-webkit-scrollbar{display:none}
214
- .settings-card h3{font-size:26px;font-weight:800;margin-bottom:6px}
215
- .settings-card .sub{color:#888;font-size:13px;margin-bottom:26px}
216
- .set-row{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:16px 0;
217
- border-bottom:1px solid rgba(255,255,255,.07)}
218
- .set-row .lbl{font-size:14px;font-weight:600}
219
- .set-row .hint{font-size:11px;color:#777;margin-top:3px}
220
- .swatches{display:flex;gap:10px;flex-wrap:wrap}
221
- .swatch{width:36px;height:36px;border-radius:12px;cursor:pointer;border:2px solid transparent;transition:all .25s}
222
- .swatch:hover{transform:scale(1.15)}
223
- .swatch.on{border-color:#fff;transform:scale(1.15);box-shadow:0 0 16px currentColor}
224
- input[type=text],input[type=range]{accent-color:var(--accent)}
225
- .set-input{background:rgba(255,255,255,.07);border:1px solid var(--glass-border);color:#fff;
226
- padding:10px 14px;border-radius:12px;font-size:14px;width:170px;outline:none;transition:border .25s}
227
- .set-input:focus{border-color:var(--accent)}
228
-
229
- /* ---------- AI ---------- */
230
- #ai{padding:0}
231
- .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:riseIn .6s both}
233
- .ai-orb{width:52px;height:52px;border-radius:50%;flex:none;position:relative;
234
- background:radial-gradient(circle at 32% 30%,color-mix(in srgb,var(--accent) 80%,#fff),var(--accent) 45%,#3a1500);
235
- animation:orbFloat 4s ease-in-out infinite;box-shadow:0 0 34px color-mix(in srgb,var(--accent) 45%,transparent)}
236
- @keyframes orbFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-7px)}}
237
- .ai-orb::after{content:"";position:absolute;inset:-7px;border-radius:50%;
238
- border:1px solid color-mix(in srgb,var(--accent) 45%,transparent);animation:orbSpin 7s linear infinite}
239
- @keyframes orbSpin{to{transform:rotate(360deg)}}
240
- .ai-head h2{font-size:26px;font-weight:800}
241
- .ai-head p{font-size:13px;color:#999}
242
- #chatLog{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:16px;padding:10px 4px;scrollbar-width:none}
243
- #chatLog::-webkit-scrollbar{display:none}
244
- .msg{max-width:82%;padding:15px 19px;border-radius:22px;font-size:15px;line-height:1.55;
245
- animation:msgIn .45s cubic-bezier(.22,1,.36,1) both;white-space:pre-wrap;word-break:break-word}
246
- @keyframes msgIn{from{opacity:0;transform:translateY(16px) scale(.97)}to{opacity:1;transform:none}}
247
- .msg.user{align-self:flex-end;background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 75%,#000));
248
- color:#0d0d0d;font-weight:500;border-bottom-right-radius:6px}
249
- .msg.bot{align-self:flex-start;background:var(--glass);backdrop-filter:blur(20px);
250
- border:1px solid var(--glass-border);border-bottom-left-radius:6px}
251
- .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
- .code-widget{margin:12px 0;border-radius:16px;overflow:hidden;border:1px solid var(--glass-border);
254
- background:#0b0b0f;box-shadow:0 8px 24px rgba(0,0,0,.4)}
255
- .code-head{display:flex;align-items:center;gap:10px;padding:9px 14px;background:rgba(255,255,255,.05);
256
- border-bottom:1px solid var(--glass-border)}
257
- .code-head .dots{display:flex;gap:6px}
258
- .code-head .dots i{width:10px;height:10px;border-radius:50%;background:rgba(255,255,255,.15)}
259
- .code-head .dots i:first-child{background:var(--accent)}
260
- .code-head .lang{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:#888;flex:1}
261
- .code-head .collapse,.code-head .copy{font-size:11px;font-weight:700;padding:5px 12px;border-radius:9px;
262
- background:rgba(255,255,255,.07);border:1px solid var(--glass-border);transition:all .2s}
263
- .code-head .copy:hover{background:var(--accent);color:#000}
264
- .code-widget pre{max-height:220px;overflow:auto;padding:15px;font-size:12.5px;line-height:1.6;
265
- font-family:"SF Mono",Menlo,Consolas,monospace;color:#d8d8e8;scrollbar-width:thin;transition:max-height .4s ease}
266
- .code-widget.collapsed pre{max-height:0;padding-top:0;padding-bottom:0}
267
- .code-widget pre::-webkit-scrollbar{width:6px;height:6px}
268
- .code-widget pre::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--accent) 50%,transparent);border-radius:3px}
269
- .typing{align-self:flex-start;display:flex;gap:6px;padding:16px 20px}
270
- .typing i{width:8px;height:8px;border-radius:50%;background:var(--accent);animation:tp 1.2s infinite}
271
- .typing i:nth-child(2){animation-delay:.18s}.typing i:nth-child(3){animation-delay:.36s}
272
- @keyframes tp{0%,60%,100%{transform:translateY(0);opacity:.4}30%{transform:translateY(-7px);opacity:1}}
273
- #aiInputBar{display:flex;gap:12px;margin-top:18px;padding:10px 10px 10px 22px;align-items:center;
274
- animation:riseIn .8s .2s both}
275
- #aiInput{flex:1;background:none;border:none;outline:none;color:#fff;font-size:15px;font-family:inherit}
276
- #aiInput::placeholder{color:#666}
277
- #sendBtn{width:48px;height:48px;border-radius:16px;flex:none;display:flex;align-items:center;justify-content:center;
278
- background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 70%,#000));color:#0a0a0a;
279
- font-size:19px;transition:transform .25s,box-shadow .25s;box-shadow:0 6px 20px color-mix(in srgb,var(--accent) 35%,transparent)}
280
- #sendBtn:hover{transform:scale(1.1) rotate(-8deg)}
281
- .chips{display:flex;gap:10px;margin-top:14px;flex-wrap:wrap}
282
- .chip{font-size:12px;padding:8px 16px;border-radius:99px;border:1px solid var(--glass-border);
283
- color:#aaa;background:rgba(255,255,255,.04);transition:all .25s}
284
- .chip:hover{color:#fff;border-color:var(--accent);transform:translateY(-2px)}
285
-
286
- /* toast */
287
- #toast{position:fixed;left:50%;bottom:96px;transform:translate(-50%,20px);z-index:99;opacity:0;
288
- background:rgba(15,15,15,.9);backdrop-filter:blur(14px);border:1px solid var(--glass-border);
289
- padding:11px 22px;border-radius:14px;font-size:13px;font-weight:600;pointer-events:none;
290
- transition:all .35s cubic-bezier(.22,1,.36,1)}
291
- #toast.on{opacity:1;transform:translate(-50%,0)}
292
- </style>
293
- <base target="_blank">
294
- </head>
295
- <body>
296
-
297
- <canvas id="particles"></canvas>
298
- <div class="glow g1"></div>
299
- <div class="glow g2"></div>
300
-
301
- <!-- ============ HOME ============ -->
302
- <div class="screen active" id="home">
303
- <div class="home-left">
304
- <div class="os-badge"><span class="dot"></span>IGNITE OS · v2.0</div>
305
- <h1 id="bigTitle">IGNITE<br><span>OS</span></h1>
306
- <div id="rotator"></div>
307
-
308
- <div class="widget-row">
309
- <div class="widget glass">
310
- <div class="wicon" id="wIcon">⛅</div>
311
- <div><div class="wlabel">Weather</div><div class="wvalue" id="wVal">--°</div></div>
312
- </div>
313
- <div class="widget glass">
314
- <svg class="ring" width="52" height="52" viewBox="0 0 52 52">
315
- <circle class="bg" cx="26" cy="26" r="21" fill="none" stroke-width="5"/>
316
- <circle class="fg" id="battRing" cx="26" cy="26" r="21" fill="none" stroke-width="5"
317
- stroke-dasharray="131.9" stroke-dashoffset="131.9"/>
318
- </svg>
319
- <div><div class="wlabel">Battery</div><div class="wvalue" id="battVal">--%</div></div>
320
- </div>
321
- <div class="widget glass">
322
- <div class="wicon">🕒</div>
323
- <div><div class="wlabel">Time</div><div class="wvalue" id="clockVal">--:--</div></div>
324
- </div>
325
- </div>
326
-
327
- <div class="home-nav">
328
- <button class="nav-btn primary glass" onclick="go('games')">Enter Games Hub <span class="arr">→</span></button>
329
- <button class="nav-btn glass" onclick="go('movies')">Movies <span class="arr">→</span></button>
330
- <button class="nav-btn glass" onclick="go('ai')">Ask IGNITE AI <span class="arr">→</span></button>
331
- </div>
332
- </div>
333
-
334
- <!-- library marquee -->
335
- <div class="library">
336
- <div class="lib-head">Game Library · hover to pause · click to play</div>
337
- <div class="rail-window"><div class="rail-track" id="railTrack"></div></div>
338
- <div class="rail-window"><div class="rail-track rev" id="railTrack2"></div></div>
339
- </div>
340
- </div>
341
-
342
-
343
- <!-- ============ GAMES HUB ============ -->
344
- <div class="screen" id="games">
345
- <div class="hub">
346
- <div class="hub-head">
347
- <h2>Games <em>Hub</em></h2>
348
- <div class="count" id="gameCount"></div>
349
- </div>
350
- <div class="games-grid" id="gamesGrid"></div>
351
- </div>
352
- </div>
353
-
354
- <!-- ============ MOVIE HUB ============ -->
355
- <div class="screen" id="movies">
356
- <div class="hub">
357
- <div class="hub-head">
358
- <h2>Movie <em>Theater</em></h2>
359
- <div class="count" id="movieCount"></div>
360
- </div>
361
- <div class="movies-grid" id="moviesGrid"></div>
362
- </div>
363
- </div>
364
-
365
- <!-- ============ AI ============ -->
366
- <div class="screen" id="ai">
367
- <div class="ai-wrap">
368
- <div class="ai-head">
369
- <div class="ai-orb"></div>
370
- <div>
371
- <h2>IGNITE <span style="color:var(--accent)">AI</span></h2>
372
- <p>Super-smart assistant · great at coding, answers & ideas</p>
373
- </div>
374
- </div>
375
- <div id="chatLog"></div>
376
- <div class="chips" id="chips">
377
- <button class="chip" onclick="quickAsk('Write a Python script that sorts a list and explain it')">💻 Give me code</button>
378
- <button class="chip" onclick="quickAsk('Explain quantum computing simply')">🧠 Teach me something</button>
379
- <button class="chip" onclick="quickAsk('Help me build a game in JavaScript')">🎮 Build a game</button>
380
- </div>
381
- <div id="aiInputBar" class="glass">
382
- <input id="aiInput" placeholder="Ask IGNITE AI anything… even code" autocomplete="off">
383
- <button id="sendBtn" onclick="sendMsg()">➤</button>
384
- </div>
385
- </div>
386
- </div>
387
-
388
- <!-- ============ DOCK ============ -->
389
- <nav id="dock" class="glass">
390
- <button class="dock-btn on" data-s="home" onclick="go('home')"><span class="dicon">⌂</span>Home</button>
391
- <button class="dock-btn" data-s="games" onclick="go('games')"><span class="dicon">🎮</span>Games</button>
392
- <button class="dock-btn" data-s="movies" onclick="go('movies')"><span class="dicon">🎬</span>Movies</button>
393
- <button class="dock-btn" data-s="ai" onclick="go('ai')"><span class="dicon">✦</span>AI</button>
394
- <button class="dock-btn" onclick="openSettings()"><span class="dicon">⚙</span></button>
395
- </nav>
396
-
397
- <!-- ============ PLAY MODAL ============ -->
398
- <div id="playModal">
399
- <div class="play-shell">
400
- <div class="play-bar">
401
- <span class="live"></span>
402
- <span class="ttl" id="playTitle">Now Playing</span>
403
- <button onclick="closePlay()">✕ Close</button>
404
- </div>
405
- <div style="position:relative;flex:1;display:flex">
406
- <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>
408
- </div>
409
- </div>
410
- </div>
411
-
412
- <!-- ============ SETTINGS ============ -->
413
- <div id="settingsModal" onclick="if(event.target===this)closeSettings()">
414
- <div class="settings-card glass">
415
- <h3>Settings</h3>
416
- <div class="sub">Customize IGNITE OS — accent color, weather & particles.</div>
417
-
418
- <div class="set-row">
419
- <div><div class="lbl">Accent Color</div><div class="hint">The tiny bit of orange — make it yours.</div></div>
420
- <div class="swatches" id="swatches"></div>
421
- </div>
422
-
423
- <div class="set-row">
424
- <div><div class="lbl">Weather City</div><div class="hint">Leave blank to use your location.</div></div>
425
- <input class="set-input" id="cityInput" type="text" placeholder="e.g. New York">
426
- </div>
427
-
428
- <div class="set-row">
429
- <div><div class="lbl">Particle Density</div><div class="hint">Snow intensity on the home screen.</div></div>
430
- <input type="range" id="particleRange" min="40" max="260" step="10">
431
- </div>
432
-
433
- <div class="set-row">
434
- <div><div class="lbl">AI Model</div><div class="hint">Switch the brain behind IGNITE AI.</div></div>
435
- <input class="set-input" id="modelInput" type="text" placeholder="model name">
436
- </div>
437
-
438
- <div style="display:flex;gap:12px;margin-top:26px">
439
- <button class="nav-btn primary glass" style="flex:1;justify-content:center" onclick="saveSettings()">Save</button>
440
- <button class="nav-btn glass" style="flex:1;justify-content:center" onclick="closeSettings()">Cancel</button>
441
- </div>
442
- </div>
443
- </div>
444
-
445
- <div id="toast"></div>
446
-
447
- <script>
448
- /* ================= DATA (links encoded — not exposed) ================= */
449
- const GAMES = [{id:'duck-math',name:'DUCK MATH',color:'#ffb26b',featured:true,u:'aHR0cHM6Ly91bnBrZy5jb20vaWduaXRlLWdvb2JlckAxLjEuNC9pbmRleC5odG1sIy9jbGFzcy9kcmlmdC1raW5n',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRJFXWvY3bIWxbR2SZEnbZaVFRYqFzZJZlOo4SYkWOexg&s'},
450
- {id:'cookie-clicker',name:'Cookie Clicker',color:'#22d3ee',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLWNvb2tpZS1jbGlja2VyQDUuMC4wL2luZGV4Lmh0bWw=',cover:'https://i.imgur.com/3ZQ3Z3Z.png'},
451
- {id:'recoil',name:'Recoil',color:'#ff6b1a',featured:false,u:'aHR0cHM6Ly9nZW5lcmljLWFscGFjYS0zMjUzMjEuZnJhbWVyLmFwcC8=',cover:'https://fancade.com/images/5E9F40DA7F9C9FA8.jpg'},
452
- {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
- {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'},
454
- {id:'tiny-fishing',name:'Tiny Fishing',color:'#facc15',featured:false,u:'aHR0cHM6Ly9nZW5lcmljLWFscGFjYS0zMjUzMjEuZnJhbWVyLmFwcC9wYWdlLTM=',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-I2lTQx2HkSPrPeyCNmAnGGd_c29Um34tPc8TpiyJjg&s=10'},
455
- {id:'small-world-cup',name:'A Small World Cup',color:'#34d399',featured:false,u:'aHR0cHM6Ly9zY3JpcHQuZ29vZ2xlLmNvbS9hL21hY3Jvcy9tY3BzbWQubmV0L3MvQUtmeWNid1NLNUlxTFhiWnBwTXo5em5JSlZ5Y0I0QlpDSG9kRTN1U2dVRjRDMWZSZUVxbU1TRFl1YTgxRXc3UnAtQ244NWdvamcvZXhlYw==',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTY4AGQkfiAEPBItQdxMlfKm0Wz7eUOzt-SsZUGejt7cA&s=10'},
456
- {id:'air-hockey',name:'Air Hockey CUP',color:'#f43f5e',featured:false,u:'aHR0cHM6Ly9zY3JpcHQuZ29vZ2xlLmNvbS9tYWNyb3Mvcy9BS2Z5Y2J3N1ZuaFlLV0lUbEpvOXA4cXlUOEV4T2Z2bmp2aXpxNTdfamo3TXpEbnlKV1R1SHROYmVlM05Ib0VvUmh1UzZlcW8vZXhlYw==',cover:'https://play-lh.googleusercontent.com/EFevQ0zkoUL5FEPIsI8-yFKoK6QCyu3TSZRXEJiLkRaWrCidW3b6ZKNiNzuvfeaLKW9FyHeY3WYh4RR839Qanck'},
457
- {id:'slope-remake',name:'Slope REMAKE',color:'#fb7185',featured:false,u:'aHR0cHM6Ly9zY3JpcHQuZ29vZ2xlLmNvbS9hL21hY3Jvcy9tY3BzbWQubmV0L3MvQUtmeWNieWVuZFN6Zld6aml2R1VBb05nSDVRRHBKSXhKRHlKdlNZd1hXeGNWXzhnbDl4a2RUTVYyQnZEcGppV053NXBHYVZUL2V4ZWM=',cover:'https://play-lh.googleusercontent.com/Ev5gkPTONr-1k1r7erT0iiW-pUZoGUH_6FVQdD91e9ghSAqZRMTaFVGQW5Z6PLOfFgxZnJhdEBE2z-TgfZ1bsg'},
458
- {id:'subway-surfers',name:'Subway Surfers',color:'#fb7185',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vc3Vid2F5c3RwZXRlcnNidXJnQDEuMC4wL2luZGV4Lmh0bWw=',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTzwmhMeCmyvXSpjVLHUUCok1FZhyrP-D9klmlq8Pt-Ww&s=10'},
459
- {id:'bacon-may-die',name:'Bacon May Die',color:'#fb7185',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vc2Nob29sdWstYmFjb24tbWF5LWRpZUAxLjAuMC9pbmRleC5odG1s',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRG8Ra7wjHyaMeLnHp70ql98oi25b33UsPI63N-Jwbapw&s=10'},
460
- {id:'paper-fly',name:'Paper Fly',color:'#22d3ee',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vcGFwZXJnbWZseUAxLjAuMC9pbmRleC5odG1s',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQQFa7pNRwbmpuk0rwFYmYYjwAdFMI6qH18R1rO_rd8XQ&s=10'},
461
- {id:'slope-505',name:'Slope 505',color:'#fb7185',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vc2xvZXBsdXNAMS4wLjAvaW5kZXguaHRtbA==',cover:'https://play-lh.googleusercontent.com/Ev5gkPTONr-1k1r7erT0iiW-pUZoGUH_6FVQdD91e9ghSAqZRMTaFVGQW5Z6PLOfFgxZnJhdEBE2z-TgfZ1bsg'},
462
- {id:'boat-game',name:'Boat Game',color:'#3b82f6',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vYm9hdGVtYW5AMS4wLjAvaW5kZXguaHRtbA==',cover:'https://play-lh.googleusercontent.com/k80-V4CxUpsoNUTiZCasfAF4yTxy428anUQiM_AieHnLRMq2qmCPIHIYWT8dYATGyo1eTjZLZEa3aa3b4kyingA'},
463
- {id:'1v1-lol',name:'1v1.lol',color:'#22d3ee',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLTF2MS1sb2xANS4wLjAvaW5kZXguaHRtbA==',cover:'https://play-lh.googleusercontent.com/NAE7nd8mxERLlT-eIM68aEQi1RthPUzVd8KN_C-RPmvDgBLJ-C_kBHrBQFYPi8wQwr_nkxGUadoS0xStbU_jc7s=w240-h480-rw'},
464
- {id:'crossy-road',name:'Crossy Road',color:'#facc15',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLWNyb3NzeS1yb2FkQDUuMC4wL2luZGV4Lmh0bWw=',cover:'https://play-lh.googleusercontent.com/LX__Y8tKCvkvEgboZtQfDsvYiNFa6kwWSpqObipZI2MLK5rFVd5tEU8xgMNoMj1ICOf9TO7PFoFmiKGeIpf1=w240-h480-rw'},
465
- {id:'basketball-stars',name:'Basketball Stars',color:'#ff6b1a',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLWJhc2tldGJhbGwtc3RhcnNANS4wLjAvaW5kZXguaHRtbA==',cover:'https://m.media-amazon.com/images/I/81BL1Hx2KuL.png'},
466
- {id:'bitlife',name:'Bitlife',color:'#34d399',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLWJpdGxpZmVANS4wLjAvaW5kZXguaHRtbA==',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZdo5cBqkv1uAcfCofpC-WAViocRNLlysohwHMV2Lqzw&s=10'},
467
- {id:'tag',name:'Tag',color:'#facc15',featured:false,u:'aHR0cHM6Ly91bnBrZy5jb20vZWRjdWJlLXRhZ0AxLjAuMC9pbmRleC5odG1s',cover:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFwGQ9vG6ZifxDpWHtuu8oSzYqll79xZ9rW_KwPwzCdA&s'},
468
- {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'}];
470
- const MOVIES = [{name:'Spiderman: Far From Home',u:'aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xdDYyWVk1VjJXRnFQQTgwMWNERUN3dzFFUVlrNGZNbmsvcHJldmlldw==',poster:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSjdXbHSbJUSaJdgj45vDisJUiPj1qljxkOPbfojU3M1w&s=10'},
471
- {name:'Spiderman: Homecoming',u:'aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xaFVJeDA1RzNOX3VjZzhTd2RaSFJ0XzVNZHFMUVp0YWkvcHJldmlldw==',poster:'https://resizing.flixster.com/-XZAfHZM39UwaGJIFWKAE8fS0ak=/v3/t/assets/p12798844_p_v8_ao.jpg'},
472
- {name:'F1',u:'aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xa196UkR0NFJuXzlGb3RZSlVmcmhKWjBaREtmd3FRazEvcHJldmlldw==',poster:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSr2SgmDLkFhLGuF1CnP_xJv1stiKvK027DkN6m6wdqdg&s=10'},
473
- {name:'Obsession',u:'aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xRkVOMTZMd001WnpUQlNiQnRrWTk1THJJemxzSFhGeDcvcHJldmlldw==',poster:'https://images.contentstack.io/v3/assets/blt13adb7e2033fcee5/blt5c8bcbfee5dade5c/6a2b47a8c284bac540ef3353/Obsession_keyart_poster_2000x3000.jpg?width=2560'}];
474
- const dec = s => atob(s);
475
- const AI_KEY = "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";
476
-
477
- /* ================= SETTINGS ================= */
478
- const DEFAULTS = {accent:"#ff6b1a", city:"", particles:140, model:"gpt-4o-mini"};
479
- let S = {...DEFAULTS, ...JSON.parse(localStorage.getItem("igniteos")||"{}")};
480
- const saveS = () => localStorage.setItem("igniteos", JSON.stringify(S));
481
- const applyAccent = () => document.documentElement.style.setProperty("--accent", S.accent);
482
-
483
- /* ================= NAV ================= */
484
- function go(id){
485
- document.querySelectorAll(".screen").forEach(s=>s.classList.remove("active"));
486
- document.getElementById(id).classList.add("active");
487
- document.querySelectorAll(".dock-btn[data-s]").forEach(b=>b.classList.toggle("on", b.dataset.s===id));
488
- if(id==="home") startParticles(); else stopParticles();
489
- }
490
-
491
- /* ================= PARTICLES (falling snow) ================= */
492
- const cv = document.getElementById("particles"), ctx = cv.getContext("2d");
493
- let flakes = [], raf = null;
494
- function sizeCanvas(){ cv.width = innerWidth; cv.height = innerHeight; }
495
- addEventListener("resize", sizeCanvas); sizeCanvas();
496
- function makeFlakes(){
497
- flakes = Array.from({length:S.particles}, () => ({
498
- x: Math.random()*cv.width, y: Math.random()*cv.height,
499
- r: Math.random()*2.4+.6, s: Math.random()*.9+.35,
500
- a: Math.random()*Math.PI*2, w: Math.random()*.6+.15, o: Math.random()*.55+.2
501
- }));
502
- }
503
- function drawFlakes(){
504
- ctx.clearRect(0,0,cv.width,cv.height);
505
- const acc = getComputedStyle(document.documentElement).getPropertyValue("--accent").trim() || "#ff6b1a";
506
- for(const f of flakes){
507
- f.y += f.s; f.a += .012; f.x += Math.sin(f.a)*f.w;
508
- if(f.y > cv.height+6){ f.y = -6; f.x = Math.random()*cv.width; }
509
- const tw = .75 + Math.sin(f.a*2)*.25;
510
- ctx.beginPath(); ctx.arc(f.x, f.y, f.r, 0, Math.PI*2);
511
- ctx.fillStyle = f.r > 1.9 ? hexA(acc, f.o*tw*.9) : `rgba(255,255,255,${f.o*tw})`;
512
- ctx.fill();
513
- }
514
- raf = requestAnimationFrame(drawFlakes);
515
- }
516
- function hexA(h, a){
517
- const n = parseInt(h.slice(1),16);
518
- return `rgba(${n>>16&255},${n>>8&255},${n&255},${a})`;
519
- }
520
- function startParticles(){ if(!raf){ makeFlakes(); drawFlakes(); } }
521
- function stopParticles(){ cancelAnimationFrame(raf); raf = null; ctx.clearRect(0,0,cv.width,cv.height); }
522
-
523
- /* ================= ROTATING DESCRIPTION ================= */
524
- const LINES = [
525
- "21 hand-picked games. Zero loading pain.",
526
- "A private movie theater, right in your browser.",
527
- "An AI that codes, explains and builds with you.",
528
- "Liquid glass. Falling light. Pure black.",
529
- "Your arcade. Your cinema. Your OS."
530
- ];
531
- const rot = document.getElementById("rotator");
532
- LINES.forEach((t,i)=>{
533
- const d = document.createElement("div");
534
- d.className = "line" + (i===0?" on":"");
535
- d.innerHTML = `<span class="tick"></span>${t}`;
536
- rot.appendChild(d);
537
- });
538
- let li = 0;
539
- setInterval(()=>{
540
- const lines = rot.children;
541
- lines[li].classList.replace("on","off");
542
- const prev = li; li = (li+1)%lines.length;
543
- setTimeout(()=>lines[prev].classList.remove("off"), 600);
544
- lines[li].classList.add("on");
545
- }, 3800);
546
-
547
- /* ================= CLOCK ================= */
548
- setInterval(()=>{
549
- const d = new Date();
550
- document.getElementById("clockVal").textContent =
551
- d.toLocaleTimeString([], {hour:"2-digit", minute:"2-digit"});
552
- }, 1000);
553
-
554
- /* ================= BATTERY ================= */
555
- (async ()=>{
556
- try{
557
- const b = await navigator.getBattery();
558
- const upd = ()=>{
559
- const pct = Math.round(b.level*100);
560
- document.getElementById("battVal").textContent = pct + "%" + (b.charging?" ⚡":"");
561
- document.getElementById("battRing").style.strokeDashoffset = 131.9*(1-b.level);
562
- };
563
- b.onlevelchange = b.onchargingchange = upd; upd();
564
- }catch(e){ document.getElementById("battVal").textContent = "N/A"; }
565
- })();
566
-
567
- /* ================= WEATHER (Open-Meteo, no key needed) ================= */
568
- const WMO = {0:"☀️",1:"🌤️",2:"⛅",3:"☁️",45:"🌫️",48:"🌫️",51:"🌦️",53:"🌦️",55:"🌧️",56:"🌧️",57:"🌧️",
569
- 61:"🌧️",63:"🌧️",65:"🌧️",66:"🌧️",67:"🌧️",71:"🌨️",73:"🌨️",75:"🌨️",77:"🌨️",80:"🌦️",81:"🌧️",82:"⛈️",
570
- 85:"🌨️",86:"🌨️",95:"⛈️",96:"⛈️",99:"⛈️"};
571
- async function loadWeather(){
572
- const val = document.getElementById("wVal"), ic = document.getElementById("wIcon");
573
- try{
574
- let lat, lon, name = "";
575
- if(S.city){
576
- const g = await fetch(`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(S.city)}&count=1`).then(r=>r.json());
577
- if(!g.results?.length) throw 0;
578
- ({latitude:lat, longitude:lon, name} = g.results[0]);
579
- } else {
580
- const p = await new Promise((ok,no)=>navigator.geolocation?navigator.geolocation.getCurrentPosition(ok,no,{timeout:5000}):no());
581
- lat = p.coords.latitude; lon = p.coords.longitude;
582
- }
583
- const w = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}&current_weather=true&temperature_unit=fahrenheit`).then(r=>r.json());
584
- const cw = w.current_weather;
585
- val.textContent = Math.round(cw.temperature) + "°F" + (name?` · ${name}`:"");
586
- ic.textContent = WMO[cw.weathercode] || "⛅";
587
- }catch(e){ val.textContent = "Set city ⚙"; ic.textContent = "🌍"; }
588
- }
589
-
590
- /* ================= BUILD GAMES ================= */
591
- const gamesGrid = document.getElementById("gamesGrid");
592
- GAMES.forEach((g,i)=>{
593
- const t = document.createElement("div");
594
- t.className = "game-tile"; t.style.setProperty("--gc", g.color); t.style.setProperty("--d", (i*0.04)+"s");
595
- t.innerHTML = `<img src="${g.cover}" alt="" loading="lazy" onerror="this.style.display='none'">
596
- ${g.featured?'<span class="feat-tag">★ FEATURED</span>':''}
597
- <div class="shine"></div>
598
- <div class="play-hint"><div class="tri"></div></div>
599
- <div class="tip">${g.name}</div>`;
600
- t.onclick = ()=>openPlay(g.name, dec(g.u));
601
- gamesGrid.appendChild(t);
602
- });
603
- document.getElementById("gameCount").textContent = GAMES.length + " titles · click to play";
604
-
605
- /* library marquee — two counter-scrolling rows, duplicated for seamless loop */
606
- function buildRail(el, list){
607
- [...list, ...list].forEach(g=>{
608
- const d = document.createElement("div");
609
- d.className = "rail-game"; d.style.setProperty("--gc", g.color);
610
- d.innerHTML = `<img src="${g.cover}" alt="" loading="lazy" onerror="this.style.display='none'">`;
611
- d.title = g.name;
612
- d.onclick = ()=>openPlay(g.name, dec(g.u));
613
- el.appendChild(d);
614
- });
615
- }
616
- buildRail(document.getElementById("railTrack"), GAMES);
617
- buildRail(document.getElementById("railTrack2"), [...GAMES].reverse());
618
-
619
- /* ================= BUILD MOVIES ================= */
620
- const mg = document.getElementById("moviesGrid");
621
- MOVIES.forEach((m,i)=>{
622
- const t = document.createElement("div");
623
- t.className = "movie-tile"; t.style.setProperty("--d", (i*0.08)+"s");
624
- t.innerHTML = `<img src="${m.poster}" alt="" loading="lazy"><div class="veil"><div class="tri"></div></div>`;
625
- t.onclick = ()=>openPlay(m.name, dec(m.u));
626
- mg.appendChild(t);
627
- });
628
- document.getElementById("movieCount").textContent = MOVIES.length + " now streaming";
629
-
630
- /* ================= PLAY MODAL (no new tabs, no exposed links) ================= */
631
- const pm = document.getElementById("playModal"), pf = document.getElementById("playFrame"),
632
- pl = document.getElementById("playLoading");
633
- function openPlay(title, url){
634
- document.getElementById("playTitle").textContent = title;
635
- pl.classList.remove("gone");
636
- pm.classList.add("open");
637
- pf.src = url;
638
- pf.onload = ()=>setTimeout(()=>pl.classList.add("gone"), 400);
639
- document.body.style.overflow = "hidden";
640
- }
641
- function closePlay(){
642
- pm.classList.remove("open");
643
- pf.src = "about:blank";
644
- document.body.style.overflow = "";
645
- }
646
- addEventListener("keydown", e=>{ if(e.key==="Escape"){ closePlay(); closeSettings(); } });
647
-
648
- /* ================= SETTINGS UI ================= */
649
- const COLORS = ["#ff6b1a","#ff3b30","#ff9500","#ffd60a","#34c759","#00c7be","#32ade6","#7d7aff","#bf5af2","#ff375f"];
650
- const sw = document.getElementById("swatches");
651
- COLORS.forEach(c=>{
652
- const b = document.createElement("div");
653
- b.className = "swatch" + (S.accent===c?" on":""); b.style.background = c; b.style.color = c;
654
- b.onclick = ()=>{ S.accent = c; applyAccent(); saveS();
655
- sw.querySelectorAll(".swatch").forEach(x=>x.classList.remove("on")); b.classList.add("on"); toast("Accent updated"); };
656
- sw.appendChild(b);
657
- });
658
- function openSettings(){
659
- document.getElementById("cityInput").value = S.city;
660
- document.getElementById("particleRange").value = S.particles;
661
- document.getElementById("modelInput").value = S.model;
662
- document.getElementById("settingsModal").classList.add("open");
663
- }
664
- function closeSettings(){ document.getElementById("settingsModal").classList.remove("open"); }
665
- function saveSettings(){
666
- S.city = document.getElementById("cityInput").value.trim();
667
- S.particles = +document.getElementById("particleRange").value;
668
- S.model = document.getElementById("modelInput").value.trim() || DEFAULTS.model;
669
- saveS(); makeFlakes(); loadWeather(); closeSettings(); toast("Settings saved");
670
- }
671
- function toast(t){
672
- const el = document.getElementById("toast");
673
- el.textContent = t; el.classList.add("on");
674
- clearTimeout(el._t); el._t = setTimeout(()=>el.classList.remove("on"), 2200);
675
- }
676
-
677
- /* ================= AI ================= */
678
- const chatLog = document.getElementById("chatLog");
679
- const history = [];
680
- function addMsg(text, who){
681
- const d = document.createElement("div");
682
- d.className = "msg " + who;
683
- if(who==="bot"){
684
- d.innerHTML = '<div class="who">IGNITE AI</div>' + renderBot(text);
685
- } else d.textContent = text;
686
- chatLog.appendChild(d); chatLog.scrollTop = chatLog.scrollHeight;
687
- return d;
688
- }
689
- function renderBot(text){
690
- const parts = text.split(/```(\w*)\n?([\s\S]*?)(?:```|$)/g);
691
- let out = "";
692
- for(let i=0;i<parts.length;i++){
693
- if(i%3===0){ out += esc(parts[i]).replace(/\n/g,"<br>"); }
694
- else if(i%3===2){
695
- const lang = parts[i-1] || "code";
696
- out += `<div class="code-widget collapsed">
697
- <div class="code-head"><div class="dots"><i></i><i></i><i></i></div>
698
- <span class="lang">${esc(lang)||"code"}</span>
699
- <button class="collapse">Expand</button>
700
- <button class="copy">Copy</button></div>
701
- <pre>${esc(parts[i])}</pre></div>`;
702
- }
703
- }
704
- return out;
705
- }
706
- function esc(s){ return (s||"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"); }
707
- chatLog.addEventListener("click", e=>{
708
- if(e.target.classList.contains("copy")){
709
- const w = e.target.closest(".code-widget");
710
- navigator.clipboard.writeText(w.querySelector("pre").textContent).then(()=>toast("Code copied ✦"));
711
- }
712
- if(e.target.classList.contains("collapse")){
713
- const w = e.target.closest(".code-widget");
714
- w.classList.toggle("collapsed");
715
- e.target.textContent = w.classList.contains("collapsed") ? "Expand" : "Collapse";
716
- }
717
- });
718
- function quickAsk(q){ document.getElementById("aiInput").value = q; sendMsg(); }
719
- async function sendMsg(){
720
- const inp = document.getElementById("aiInput"), q = inp.value.trim();
721
- if(!q) return;
722
- inp.value = ""; addMsg(q, "user");
723
- const tp = document.createElement("div");
724
- tp.className = "msg bot typing"; tp.innerHTML = "<i></i><i></i><i></i>";
725
- chatLog.appendChild(tp); chatLog.scrollTop = chatLog.scrollHeight;
726
- try{
727
- const res = await fetch("https://api.openai.com/v1/chat/completions", {
728
- method:"POST",
729
- headers:{ "Content-Type":"application/json", "Authorization":"Bearer " + AI_KEY },
730
- body: JSON.stringify({
731
- model: S.model,
732
- messages: [
733
- {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."},
734
- ...history.slice(-10),
735
- {role:"user", content:q}
736
- ]
737
- })
738
- });
739
- const data = await res.json();
740
- 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
- history.push({role:"user",content:q},{role:"assistant",content:reply});
744
- addMsg(reply, "bot");
745
- }catch(err){
746
- tp.remove();
747
- addMsg("⚠️ Couldn't reach the AI right now. Check the API key / model in Settings, or try again. (" + esc(err.message||"") + ")", "bot");
748
- }
749
- }
750
- document.getElementById("aiInput").addEventListener("keydown", e=>{ if(e.key==="Enter") sendMsg(); });
751
-
752
- /* ================= BOOT ================= */
753
- applyAccent(); startParticles(); loadWeather();
754
- 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");
755
- </script>
756
- </body>
757
- </html>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <script>
7
+ (function(){var w=window,s={ps:History.prototype.pushState,rs:History.prototype.replaceState};w.__lcHs=s;var h=history,f=function(){try{Object.defineProperty(h,"pushState",{value:s.ps.bind(h),configurable:!0,writable:!0}),Object.defineProperty(h,"replaceState",{value:s.rs.bind(h),configurable:!0,writable:!0})}catch(e){}};f(),setInterval(f,400)})();
8
+ </script>
9
+ <link rel="icon" type="image/png" href="./branding/ignite-os-browser-834cc7f9f1eda4fb.png" />
10
+ <title>Ignite OS</title>
11
+ <script async src="https://www.googletagmanager.com/gtag/js?id=G-0VL3ZSBXDH"></script>
12
+ <script>
13
+ window.dataLayer = window.dataLayer || [];
14
+ function gtag() { dataLayer.push(arguments); }
15
+ gtag("js", new Date());
16
+ gtag("config", "G-0VL3ZSBXDH");
17
+ </script>
18
+ <script src="jr1n9/4m74rv.js"></script>
19
+ <script src="equ4q/8tzsxm.js"></script>
20
+ <script type="module" crossorigin src="./assets/index-COUSXtyQ-8068ec8f.js"></script>
21
+ <link rel="modulepreload" crossorigin href="./assets/react-BNEptbwn-8068ec8f.js">
22
+ <link rel="modulepreload" crossorigin href="./assets/motion-B1hdS1Lc-8068ec8f.js">
23
+ <link rel="stylesheet" crossorigin href="./assets/index-D4-Q3uqd-8068ec8f.css">
24
+ <link rel="stylesheet" href="./ignite-ember.css">
25
+ </head>
26
+ <body>
27
+ <div id="root"></div>
28
+ </body>
29
+ </html>