Zakia commited on
Commit
8e02946
·
verified ·
1 Parent(s): ad614b0

Update index.html - initial commit

Browse files
Files changed (1) hide show
  1. index.html +297 -19
index.html CHANGED
@@ -1,19 +1,297 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </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
+ <title>ZakCode: Python - Learn Python Through Play</title>
7
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
9
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.23.9/babel.min.js"></script>
10
+ <link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=DM+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
11
+ <style>
12
+ *{margin:0;padding:0;box-sizing:border-box}
13
+ html,body,#root{width:100%;min-height:100vh;background:#06080F}
14
+ body{font-family:'DM Sans','Segoe UI',system-ui,sans-serif;-webkit-font-smoothing:antialiased}
15
+ input:focus{outline:none} button{font-family:inherit}
16
+ ::selection{background:rgba(139,92,246,0.3)}
17
+ @keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-8px)}75%{transform:translateX(8px)}}
18
+ @keyframes fadeUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}
19
+ @keyframes float{0%{transform:translateY(0) translateX(0);opacity:0.1}50%{opacity:0.2}100%{transform:translateY(-40px) translateX(15px);opacity:0.05}}
20
+ @keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.05)}}
21
+ @keyframes slideIn{from{opacity:0;transform:translateX(20px)}to{opacity:1;transform:translateX(0)}}
22
+ @keyframes popIn{from{opacity:0;transform:scale(0.8)}to{opacity:1;transform:scale(1)}}
23
+ @keyframes starPop{0%{transform:scale(0) rotate(-20deg);opacity:0}60%{transform:scale(1.3) rotate(5deg);opacity:1}100%{transform:scale(1) rotate(0deg);opacity:1}}
24
+ ::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:rgba(148,163,184,0.15);border-radius:3px}
25
+ </style>
26
+ </head>
27
+ <body>
28
+ <div id="root"></div>
29
+ <script type="text/babel">
30
+ const {useState,useEffect,useCallback,useRef} = React;
31
+
32
+ const LEVELS = [
33
+ {id:1,name:"Variables & Types",icon:"📦",color:"#38BDF8",questions:[
34
+ {type:"quiz",question:"What type does Python assign to: x = 3.14?",code:'x = 3.14\nprint(type(x))',options:["int","float","str","double"],correct:1,explanation:"3.14 has a decimal point, so Python assigns the float type."},
35
+ {type:"fillblank",question:'Complete the code to convert "25" to an integer:',codeBefore:'age_str = "25"\nage = ',codeAfter:'(age_str)',answer:"int",hint:"Which built-in function converts to a whole number?",explanation:"int() converts a string to an integer."},
36
+ {type:"debug",question:"This code has a TypeError. Which line?",code:'name = "Zakia"\nage = "30"\nresult = name + " is " + age + 1',options:["Line 1","Line 2","Line 3: can't add int to str","No error"],correct:2,explanation:'age is a string, so age + 1 tries to add int to string. Fix: str(1)'},
37
+ {type:"quiz",question:"What is type(True)?",code:'print(type(True))',options:["<class 'int'>","<class 'str'>","<class 'bool'>","<class 'true'>"],correct:2,explanation:"True is a boolean, so type(True) returns <class 'bool'>."},
38
+ {type:"fillblank",question:"Complete the code to check a variable's type:",codeBefore:'x = "hello"\nresult = ',codeAfter:'(x)',answer:"type",hint:"Which function tells you what kind of data you have?",explanation:"type() returns the class/type of any Python object."},
39
+ ]},
40
+ {id:2,name:"Strings",icon:"✏️",color:"#A78BFA",questions:[
41
+ {type:"quiz",question:'What does "hello".upper() return?',code:'print("hello".upper())',options:['"Hello"','"HELLO"','"hello"',"Error"],correct:1,explanation:".upper() converts ALL characters to uppercase."},
42
+ {type:"fillblank",question:"Complete the f-string to include the variable:",codeBefore:'name = "Zakia"\nmsg = f"Hello, ',codeAfter:'!"',answer:"{name}",hint:"In f-strings, wrap variables in curly braces.",explanation:'f-strings use {variable_name} to embed values.'},
43
+ {type:"debug",question:'Expected output is "Pyt". Find the bug:',code:'text = "Python"\nfirst_three = text[1:3]\nprint(first_three)',options:["Should be text[0:3]","Should be text[1:4]","Should be text(1:3)","No error"],correct:0,explanation:'Indexing starts at 0. text[0:3] = "Pyt". text[1:3] = "yt".'},
44
+ {type:"quiz",question:'What does "Python"[-1] return?',code:'print("Python"[-1])',options:['"P"','"n"','"o"',"Error"],correct:1,explanation:"Negative indexing: -1 is the last character = 'n'."},
45
+ {type:"fillblank",question:"Complete the code to split into words:",codeBefore:'s = "I love Python"\nwords = s.',codeAfter:'()',answer:"split",hint:"Which method breaks a string into a list?",explanation:".split() breaks a string by whitespace into a list."},
46
+ ]},
47
+ {id:3,name:"Lists",icon:"📋",color:"#34D399",questions:[
48
+ {type:"quiz",question:"After this code, what is nums?",code:'nums = [1, 2, 3]\nnums.append(4)\nprint(nums)',options:["[1,2,3]","[4,1,2,3]","[1,2,3,4]","[1,2,4]"],correct:2,explanation:".append() adds to the END of the list."},
49
+ {type:"fillblank",question:"Complete the list comprehension:",codeBefore:'squares = [x**2 ',codeAfter:' range(6)]',answer:"for x in",hint:"'for variable in iterable'",explanation:"Syntax: [expression for variable in iterable]"},
50
+ {type:"debug",question:"This code crashes. Why?",code:'fruits = ["apple", "banana", "cherry"]\nprint(fruits[3])',options:["IndexError: out of range","Prints 'cherry'","Prints None","Use fruits.get(3)"],correct:0,explanation:"Indices are 0,1,2. Index 3 doesn't exist. Use [-1] for last."},
51
+ {type:"quiz",question:"What does len([10, 20, 30]) return?",code:'print(len([10, 20, 30]))',options:["30","3","60","2"],correct:1,explanation:"len() counts ELEMENTS, not their sum."},
52
+ {type:"fillblank",question:"Complete the code to sort the list:",codeBefore:'nums = [3, 1, 4, 1, 5]\nnums.',codeAfter:'()',answer:"sort",hint:"Which method arranges elements in order?",explanation:".sort() sorts ascending in place."},
53
+ ]},
54
+ {id:4,name:"Dictionaries",icon:"🔑",color:"#FBBF24",questions:[
55
+ {type:"quiz",question:'How do you access the value for key "name"?',code:'person = {"name": "Zakia", "age": 30}',options:['person.name','person["name"]','person.get[name]','person(name)'],correct:1,explanation:'Square brackets: dict["key"] to access values.'},
56
+ {type:"fillblank",question:"Get a default value if key is missing:",codeBefore:'d = {"a": 1}\nresult = d.',codeAfter:'("b", 0)',answer:"get",hint:"Which method returns a default instead of error?",explanation:'.get(key, default) avoids KeyError.'},
57
+ {type:"debug",question:"This code throws an error. Why?",code:'person = {"name": "Zakia"}\nprint(person["age"])',options:["KeyError: 'age'","Prints None","Prints 'Zakia'","Syntax error"],correct:0,explanation:'Missing key with [] raises KeyError. Use .get() instead.'},
58
+ {type:"quiz",question:"What does .keys() return?",code:'person = {"name": "Zakia", "city": "Durban"}\nprint(person.keys())',options:["['Zakia','Durban']","['name','city']","{'name','city'}","[('name','Zakia')]"],correct:1,explanation:".keys() returns all keys (not values)."},
59
+ {type:"fillblank",question:"Loop through key-value pairs:",codeBefore:'d = {"a":1, "b":2}\nfor k, v in d.',codeAfter:'():\n print(k, v)',answer:"items",hint:"Which method gives both keys and values?",explanation:".items() returns (key, value) pairs."},
60
+ ]},
61
+ {id:5,name:"Conditionals",icon:"🔀",color:"#FB7185",questions:[
62
+ {type:"quiz",question:"What does this print?",code:'x = 15\nif x > 20:\n print("big")\nelif x > 10:\n print("medium")\nelse:\n print("small")',options:['"big"','"medium"','"small"','Both big and medium'],correct:1,explanation:"15 > 20 is False, 15 > 10 is True → 'medium'."},
63
+ {type:"fillblank",question:"Complete the ternary conditional:",codeBefore:'age = 25\nstatus = "adult" ',codeAfter:' age >= 18 else "minor"',answer:"if",hint:"value_if_true IF condition ELSE value_if_false",explanation:'Ternary: result = value_a if condition else value_b'},
64
+ {type:"debug",question:"This code has a syntax error:",code:'x = 5\nif x > 3 or < 10:\n print("in range")',options:["Need: x > 3 or x < 10","Use 'and' not 'or'","Missing parentheses","No error"],correct:0,explanation:"Each side of 'or' needs a complete comparison."},
65
+ {type:"quiz",question:'What does "not True" evaluate to?',code:'print(not True)',options:["True","False","None","Error"],correct:1,explanation:"'not' inverts a boolean. not True = False."},
66
+ {type:"fillblank",question:"Check that BOTH conditions are true:",codeBefore:'age = 25\nhas_id = True\nif age >= 18 ',codeAfter:' has_id:\n print("allowed")',answer:"and",hint:"Which operator requires both to be True?",explanation:"'and' requires both sides to be True."},
67
+ ]},
68
+ {id:6,name:"Loops",icon:"🔄",color:"#2DD4BF",questions:[
69
+ {type:"quiz",question:"How many times does this print?",code:'for i in range(3):\n print(i)',options:["2","3","4","Infinite"],correct:1,explanation:"range(3) = 0, 1, 2 → 3 iterations."},
70
+ {type:"fillblank",question:"Get index AND value in a loop:",codeBefore:'fruits = ["a", "b", "c"]\nfor i, f in ',codeAfter:'(fruits):\n print(i, f)',answer:"enumerate",hint:"Which function gives index + value?",explanation:"enumerate() yields (index, value) pairs."},
71
+ {type:"debug",question:"This while loop has a critical problem:",code:'count = 0\nwhile count < 5:\n print(count)',options:["Infinite loop (no count += 1)","Should be count <= 5","count starts wrong","No error"],correct:0,explanation:"Without incrementing count → infinite loop!"},
72
+ {type:"quiz",question:"What does 'break' do in a loop?",code:'for i in range(10):\n if i == 5:\n break\n print(i)',options:["Skips iteration","Exits the loop","Restarts loop","Nothing"],correct:1,explanation:"break exits the entire loop. Prints 0,1,2,3,4."},
73
+ {type:"fillblank",question:"Skip odd numbers with:",codeBefore:'for x in range(10):\n if x % 2 != 0:\n ',codeAfter:'\n print(x)',answer:"continue",hint:"Which keyword skips to next iteration?",explanation:"continue skips the rest of current iteration."},
74
+ ]},
75
+ {id:7,name:"Functions",icon:"⚡",color:"#818CF8",questions:[
76
+ {type:"quiz",question:"What does this return?",code:'def add(a, b=10):\n return a + b\n\nprint(add(5))',options:["5","10","15","Error"],correct:2,explanation:"b defaults to 10. add(5) = 5 + 10 = 15."},
77
+ {type:"fillblank",question:"Create a lambda that doubles:",codeBefore:'double = ',codeAfter:' x: x * 2',answer:"lambda",hint:"Keyword for anonymous functions?",explanation:"lambda creates small inline functions."},
78
+ {type:"debug",question:"Why does this return None?",code:'def greet(name):\n message = f"Hello, {name}!"\n print(message)\n\nresult = greet("Zakia")\nprint(result)',options:["Missing return","f-string wrong","Missing param","It returns the message"],correct:0,explanation:"print() displays but doesn't return. Add 'return message'."},
79
+ {type:"quiz",question:"What does *args allow?",code:'def total(*args):\n return sum(args)\n\nprint(total(1,2,3,4))',options:["Only 1 arg","Exactly 4","Any number","Only keywords"],correct:2,explanation:"*args collects any number of positional arguments."},
80
+ {type:"fillblank",question:"Complete the function keyword:",codeBefore:'',codeAfter:' multiply(a, b):\n return a * b',answer:"def",hint:"Which keyword defines a function?",explanation:"def defines functions in Python."},
81
+ ]},
82
+ {id:8,name:"Files, Errors & More",icon:"🧰",color:"#F472B6",questions:[
83
+ {type:"quiz",question:"What does 'with' do for files?",code:'with open("data.txt", "r") as f:\n content = f.read()',options:["Opens faster","Auto-closes when done","Makes read-only","Encrypts"],correct:1,explanation:"'with' auto-closes the file, even if an error occurs."},
84
+ {type:"fillblank",question:"Complete the error handling:",codeBefore:'try:\n result = 10 / 0\n',codeAfter:' ZeroDivisionError:\n print("Can\'t divide by zero!")',answer:"except",hint:"Which keyword catches errors?",explanation:"except catches exceptions from the try block."},
85
+ {type:"debug",question:"What does this code output?",code:'try:\n num = int("hello")\nexcept:\n print("Error!")\nfinally:\n print("Done")',options:['"Error!" then "Done"','Only "Error!"','Crashes','Only "Done"'],correct:0,explanation:'int("hello") raises ValueError → except runs. finally ALWAYS runs.'},
86
+ {type:"quiz",question:"Tuples differ from lists because:",code:'t = (1, 2, 3)\nt[0] = 99 # What happens?',options:["Faster","Immutable (can't change)","Unordered","Numbers only"],correct:1,explanation:"Tuples are immutable. t[0] = 99 raises TypeError."},
87
+ {type:"fillblank",question:"Import with a shorter name:",codeBefore:'',codeAfter:' pandas as pd',answer:"import",hint:"Which keyword brings in modules?",explanation:"import module as alias for shorter names."},
88
+ ]},
89
+ ];
90
+
91
+ const BADGES=["Newcomer","Beginner","Learner","Coder","Explorer","Hacker","Developer","Pythonista"];
92
+ const SC={HOME:"home",LEVELS:"levels",PLAY:"play",DONE:"done"};
93
+
94
+ function Particles({color="#A78BFA",count=15}){
95
+ const ps=React.useMemo(()=>Array.from({length:count},(_,i)=>({id:i,x:Math.random()*100,y:Math.random()*100,sz:Math.random()*3+1,dur:Math.random()*20+10,del:Math.random()*10})),[count]);
96
+ return React.createElement('div',{style:{position:'fixed',inset:0,overflow:'hidden',pointerEvents:'none',zIndex:0}},ps.map(p=>React.createElement('div',{key:p.id,style:{position:'absolute',left:p.x+'%',top:p.y+'%',width:p.sz,height:p.sz,borderRadius:'50%',background:color,opacity:0.12,animation:`float ${p.dur}s ease-in-out ${p.del}s infinite alternate`}})));
97
+ }
98
+
99
+ function CodeBlock({code,style:s}){
100
+ return React.createElement('div',{style:{background:'#0A0E1B',border:'1px solid rgba(148,163,184,0.1)',borderRadius:14,padding:'16px 20px',fontFamily:"'Fira Code','Courier New',monospace",fontSize:14.5,lineHeight:1.75,color:'#CBD5E1',whiteSpace:'pre-wrap',...s}},
101
+ React.createElement('div',{style:{display:'flex',gap:6,marginBottom:12}},
102
+ React.createElement('div',{style:{width:10,height:10,borderRadius:'50%',background:'#EF4444'}}),
103
+ React.createElement('div',{style:{width:10,height:10,borderRadius:'50%',background:'#FBBF24'}}),
104
+ React.createElement('div',{style:{width:10,height:10,borderRadius:'50%',background:'#22C55E'}})),
105
+ code);
106
+ }
107
+
108
+ function ZakCode(){
109
+ const[screen,setScreen]=useState(SC.HOME);
110
+ const[levels,setLevels]=useState(LEVELS.map((l,i)=>({...l,unlocked:i===0})));
111
+ const[cLvl,setCLvl]=useState(0);
112
+ const[cQ,setCQ]=useState(0);
113
+ const[score,setScore]=useState(0);
114
+ const[totalXP,setTotalXP]=useState(0);
115
+ const[streak,setStreak]=useState(0);
116
+ const[bestStreak,setBestStreak]=useState(0);
117
+ const[sel,setSel]=useState(null);
118
+ const[fill,setFill]=useState("");
119
+ const[showR,setShowR]=useState(false);
120
+ const[ok,setOk]=useState(false);
121
+ const[shk,setShk]=useState(false);
122
+ const[lvlS,setLvlS]=useState(0);
123
+ const[xpG,setXpG]=useState(0);
124
+ const[lvlOk,setLvlOk]=useState(0);
125
+ const[hint,setHint]=useState(false);
126
+ const iRef=useRef(null);
127
+
128
+ const lv=levels[cLvl], q=lv?.questions?.[cQ], tQ=lv?.questions?.length||0;
129
+
130
+ useEffect(()=>{
131
+ if(screen===SC.PLAY&&q?.type==='fillblank'&&iRef.current)setTimeout(()=>iRef.current?.focus(),100);
132
+ setHint(false);
133
+ },[cQ,screen]);
134
+
135
+ const doOk=(pts)=>{setScore(s=>s+pts);setLvlS(s=>s+pts);setXpG(pts);setLvlOk(c=>c+1);setStreak(s=>{const n=s+1;if(n>bestStreak)setBestStreak(n);return n;});};
136
+ const doFail=()=>{setStreak(0);setXpG(0);setShk(true);setTimeout(()=>setShk(false),500);};
137
+
138
+ const handleQuiz=useCallback((i)=>{
139
+ if(showR)return;setSel(i);const c=i===q.correct;setOk(c);setShowR(true);
140
+ c?doOk(10+streak*2):doFail();
141
+ },[showR,q,streak,bestStreak]);
142
+
143
+ const handleFill=useCallback(()=>{
144
+ if(showR)return;const c=fill.trim().toLowerCase()===q.answer.toLowerCase();
145
+ setOk(c);setShowR(true);c?doOk(10+streak*2):doFail();
146
+ },[showR,fill,q,streak,bestStreak]);
147
+
148
+ const nextQ=useCallback(()=>{
149
+ if(cQ+1>=tQ){
150
+ setTotalXP(s=>s+lvlS);
151
+ if(cLvl+1<levels.length)setLevels(p=>p.map((l,i)=>i===cLvl+1?{...l,unlocked:true}:l));
152
+ setScreen(SC.DONE);
153
+ }else{setCQ(n=>n+1);setSel(null);setFill("");setShowR(false);}
154
+ },[cQ,tQ,cLvl,levels.length,lvlS]);
155
+
156
+ const startLvl=useCallback((i)=>{setCLvl(i);setCQ(0);setSel(null);setFill("");setShowR(false);setLvlS(0);setLvlOk(0);setScreen(SC.PLAY);},[]);
157
+
158
+ const base={width:'100%',minHeight:'100vh',background:'#06080F',color:'#E2E8F0',fontFamily:"'DM Sans','Segoe UI',system-ui,sans-serif",position:'relative'};
159
+ const wrap={maxWidth:600,margin:'0 auto',padding:'40px 24px',position:'relative',zIndex:2};
160
+ const btn={border:'none',borderRadius:12,padding:'14px 28px',fontSize:16,fontWeight:700,cursor:'pointer',transition:'all 0.2s',fontFamily:'inherit'};
161
+ const msh=(c1,c2)=>({position:'fixed',inset:0,background:`radial-gradient(ellipse 600px 500px at 10% 20%,${c1}15 0%,transparent 70%),radial-gradient(ellipse 500px 500px at 90% 80%,${c2}10 0%,transparent 70%)`,pointerEvents:'none',zIndex:0});
162
+
163
+ // HOME
164
+ if(screen===SC.HOME){
165
+ const rank=BADGES[Math.min(Math.floor(totalXP/40),7)];
166
+ const done=levels.filter((l,i)=>i>0&&l.unlocked).length;
167
+ return React.createElement('div',{style:base},
168
+ React.createElement('div',{style:msh('#6366F1','#06B6D4')}),
169
+ React.createElement(Particles,{color:'#A78BFA'}),
170
+ React.createElement('div',{style:{...wrap,textAlign:'center',paddingTop:70}},
171
+ React.createElement('div',{style:{width:100,height:100,borderRadius:24,background:'linear-gradient(145deg,rgba(99,102,241,0.2),rgba(6,182,212,0.12))',border:'2px solid rgba(99,102,241,0.3)',display:'inline-flex',alignItems:'center',justifyContent:'center',marginBottom:28,position:'relative'}},
172
+ React.createElement('div',{style:{position:'absolute',inset:4,borderRadius:20,border:'1px solid rgba(251,191,36,0.2)'}}),
173
+ React.createElement('span',{style:{fontFamily:"'Fira Code',monospace",fontWeight:800,fontSize:42,background:'linear-gradient(135deg,#38BDF8,#818CF8)',WebkitBackgroundClip:'text',WebkitTextFillColor:'transparent'}},'Py')),
174
+ React.createElement('h1',{style:{fontSize:52,fontWeight:900,letterSpacing:-2,background:'linear-gradient(135deg,#FFF,#94A3B8)',WebkitBackgroundClip:'text',WebkitTextFillColor:'transparent',marginBottom:6,lineHeight:1.1}},'ZakCode'),
175
+ React.createElement('p',{style:{fontSize:20,fontWeight:600,background:'linear-gradient(135deg,#A78BFA,#38BDF8)',WebkitBackgroundClip:'text',WebkitTextFillColor:'transparent',marginBottom:10}},'Python Edition'),
176
+ React.createElement('p',{style:{color:'#64748B',fontSize:15,marginBottom:40,lineHeight:1.6}},'Quiz · Fill in the Code · Debug the Bugs',React.createElement('br'),'8 levels · 40 challenges · Master the basics!'),
177
+ totalXP>0&&React.createElement('div',{style:{display:'flex',gap:12,justifyContent:'center',marginBottom:36,flexWrap:'wrap'}},
178
+ [{l:'Total XP',v:totalXP,i:'⚡'},{l:'Best Streak',v:bestStreak,i:'🔥'},{l:'Rank',v:rank,i:'🏆'},{l:'Levels',v:`${done}/8`,i:'📊'}].map((s,i)=>
179
+ React.createElement('div',{key:i,style:{background:'rgba(15,23,42,0.6)',border:'1px solid rgba(148,163,184,0.08)',borderRadius:14,padding:'14px 16px',textAlign:'center',flex:'1 1 100px',minWidth:80}},
180
+ React.createElement('div',{style:{fontSize:20,marginBottom:2}},s.i),
181
+ React.createElement('div',{style:{fontSize:20,fontWeight:800,color:'#E2E8F0'}},s.v),
182
+ React.createElement('div',{style:{fontSize:11,color:'#64748B',marginTop:2}},s.l)))),
183
+ React.createElement('button',{onClick:()=>setScreen(SC.LEVELS),style:{...btn,background:'linear-gradient(135deg,#6366F1,#8B5CF6)',color:'#FFF',fontSize:18,padding:'18px 52px',boxShadow:'0 8px 32px rgba(99,102,241,0.3)'},onMouseEnter:e=>e.target.style.transform='translateY(-2px)',onMouseLeave:e=>e.target.style.transform='translateY(0)'},totalXP>0?'Continue Learning →':'Start Learning →'),
184
+ React.createElement('div',{style:{marginTop:56,paddingTop:20,borderTop:'1px solid rgba(148,163,184,0.07)',color:'#4B5563',fontSize:13}},
185
+ 'Created by ',React.createElement('span',{style:{color:'#A78BFA',fontWeight:600}},'Dr Zakia Salod'),React.createElement('br'),'Software Developer & AI Researcher')));
186
+ }
187
+
188
+ // LEVELS
189
+ if(screen===SC.LEVELS){
190
+ return React.createElement('div',{style:base},
191
+ React.createElement('div',{style:msh('#6366F1','#06B6D4')}),
192
+ React.createElement(Particles,{color:'#38BDF8'}),
193
+ React.createElement('div',{style:wrap},
194
+ React.createElement('button',{onClick:()=>setScreen(SC.HOME),style:{...btn,background:'transparent',color:'#64748B',padding:'8px 0',fontSize:14,marginBottom:20}},'← Back'),
195
+ React.createElement('h2',{style:{fontSize:32,fontWeight:800,letterSpacing:-1,marginBottom:6,color:'#FFF'}},'Choose Your Level'),
196
+ React.createElement('p',{style:{color:'#64748B',marginBottom:32,fontSize:14}},'Complete each level to unlock the next'),
197
+ React.createElement('div',{style:{display:'flex',flexDirection:'column',gap:12}},
198
+ levels.map((l,i)=>{const lk=!l.unlocked;return React.createElement('button',{key:l.id,onClick:()=>!lk&&startLvl(i),disabled:lk,
199
+ style:{...btn,background:lk?'rgba(15,23,42,0.4)':'rgba(15,23,42,0.7)',border:`1px solid ${lk?'rgba(148,163,184,0.05)':l.color+'30'}`,borderRadius:16,padding:'18px 22px',display:'flex',alignItems:'center',gap:16,textAlign:'left',opacity:lk?0.4:1,cursor:lk?'not-allowed':'pointer',width:'100%',position:'relative',overflow:'hidden',animation:`slideIn 0.3s ease ${i*0.05}s both`},
200
+ onMouseEnter:e=>{if(!lk)e.currentTarget.style.borderColor=l.color+'60'},onMouseLeave:e=>{if(!lk)e.currentTarget.style.borderColor=l.color+'30'}},
201
+ !lk&&React.createElement('div',{style:{position:'absolute',top:0,left:0,right:0,height:3,background:`linear-gradient(90deg,${l.color},${l.color}88)`}}),
202
+ React.createElement('div',{style:{width:46,height:46,borderRadius:12,background:lk?'rgba(148,163,184,0.05)':l.color+'15',display:'flex',alignItems:'center',justifyContent:'center',fontSize:22,flexShrink:0}},lk?'🔒':l.icon),
203
+ React.createElement('div',{style:{flex:1}},
204
+ React.createElement('div',{style:{fontSize:16,fontWeight:700,color:lk?'#4B5563':'#E2E8F0'}},`Level ${l.id}: ${l.name}`),
205
+ React.createElement('div',{style:{fontSize:12,color:'#64748B',marginTop:2}},`${l.questions.length} challenges · ${lk?'Locked':'Ready'}`)),
206
+ !lk&&React.createElement('div',{style:{color:l.color,fontWeight:700,fontSize:20}},'→'));}))));
207
+ }
208
+
209
+ // COMPLETE
210
+ if(screen===SC.DONE){
211
+ const pct=Math.round((lvlOk/tQ)*100),stars=pct>=100?3:pct>=60?2:pct>=20?1:0,nx=cLvl+1<levels.length;
212
+ return React.createElement('div',{style:base},
213
+ React.createElement('div',{style:msh(lv.color,'#6366F1')}),
214
+ React.createElement(Particles,{color:lv.color,count:25}),
215
+ React.createElement('div',{style:{...wrap,textAlign:'center',paddingTop:70}},
216
+ React.createElement('div',{style:{fontSize:60,marginBottom:12,animation:'popIn 0.5s ease'}},stars>=3?'🏆':stars>=2?'⭐':stars>=1?'👍':'💪'),
217
+ React.createElement('h2',{style:{fontSize:34,fontWeight:800,color:'#FFF',marginBottom:6,letterSpacing:-1}},stars>=3?'Perfect!':stars>=2?'Great Job!':'Level Complete!'),
218
+ React.createElement('p',{style:{color:lv.color,fontSize:17,fontWeight:600,marginBottom:28}},`${lv.icon} ${lv.name}`),
219
+ React.createElement('div',{style:{fontSize:38,marginBottom:28,letterSpacing:8}},[0,1,2].map(i=>React.createElement('span',{key:i,style:{opacity:i<stars?1:0.15,filter:i<stars?'none':'grayscale(1)',display:'inline-block',animation:i<stars?`starPop 0.4s ease ${i*0.2}s both`:'none'}},'⭐'))),
220
+ React.createElement('div',{style:{background:'rgba(15,23,42,0.7)',border:'1px solid rgba(148,163,184,0.08)',borderRadius:16,padding:24,marginBottom:28,display:'flex',justifyContent:'space-around'}},
221
+ [{v:lvlS,l:'XP Earned',c:lv.color},{v:`${lvlOk}/${tQ}`,l:'Correct',c:'#34D399'},{v:pct+'%',l:'Accuracy',c:'#FBBF24'}].map((s,i)=>React.createElement(React.Fragment,{key:i},i>0&&React.createElement('div',{style:{width:1,background:'rgba(148,163,184,0.1)'}}),React.createElement('div',null,React.createElement('div',{style:{fontSize:26,fontWeight:800,color:s.c}},s.v),React.createElement('div',{style:{fontSize:11,color:'#64748B',marginTop:4}},s.l))))),
222
+ React.createElement('div',{style:{display:'flex',gap:12,justifyContent:'center'}},
223
+ React.createElement('button',{onClick:()=>startLvl(cLvl),style:{...btn,background:'rgba(15,23,42,0.7)',border:'1px solid rgba(148,163,184,0.15)',color:'#94A3B8'}},'🔄 Retry'),
224
+ nx?React.createElement('button',{onClick:()=>startLvl(cLvl+1),style:{...btn,background:`linear-gradient(135deg,${lv.color},${lv.color}CC)`,color:'#FFF',boxShadow:`0 8px 24px ${lv.color}30`}},'Next Level →'):
225
+ React.createElement('button',{onClick:()=>setScreen(SC.HOME),style:{...btn,background:'linear-gradient(135deg,#6366F1,#8B5CF6)',color:'#FFF'}},'🎉 Quest Complete!')),
226
+ React.createElement('button',{onClick:()=>setScreen(SC.LEVELS),style:{...btn,background:'transparent',color:'#4B5563',marginTop:14,fontSize:14}},'All Levels')));
227
+ }
228
+
229
+ // PLAYING
230
+ if(screen===SC.PLAY&&q){
231
+ const prog=(cQ/tQ)*100;
232
+ const tb={quiz:{bg:'rgba(56,189,248,0.1)',bd:'rgba(56,189,248,0.2)',c:'#38BDF8',l:'🧠 Quiz'},fillblank:{bg:'rgba(52,211,153,0.1)',bd:'rgba(52,211,153,0.2)',c:'#34D399',l:'✍️ Fill the Blank'},debug:{bg:'rgba(251,113,133,0.1)',bd:'rgba(251,113,133,0.2)',c:'#FB7185',l:'🐛 Debug'}}[q.type];
233
+
234
+ return React.createElement('div',{style:base},
235
+ React.createElement('div',{style:msh(lv.color,'#6366F1')}),
236
+ React.createElement('div',{style:wrap},
237
+ // Header
238
+ React.createElement('div',{style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:18}},
239
+ React.createElement('button',{onClick:()=>setScreen(SC.LEVELS),style:{...btn,background:'transparent',color:'#64748B',padding:'4px 0',fontSize:14}},'← Exit'),
240
+ React.createElement('div',{style:{display:'flex',gap:10,alignItems:'center'}},
241
+ streak>0&&React.createElement('div',{style:{background:'rgba(251,191,36,0.1)',border:'1px solid rgba(251,191,36,0.2)',borderRadius:20,padding:'3px 12px',fontSize:13,fontWeight:700,color:'#FBBF24',animation:streak>2?'pulse 1s infinite':'none'}},'🔥 '+streak),
242
+ React.createElement('div',{style:{background:'rgba(99,102,241,0.1)',border:'1px solid rgba(99,102,241,0.2)',borderRadius:20,padding:'3px 12px',fontSize:13,fontWeight:700,color:'#818CF8'}},'⚡ '+score))),
243
+ // Progress
244
+ React.createElement('div',{style:{background:'rgba(148,163,184,0.08)',borderRadius:8,height:5,marginBottom:6,overflow:'hidden'}},
245
+ React.createElement('div',{style:{height:'100%',borderRadius:8,background:`linear-gradient(90deg,${lv.color},${lv.color}AA)`,width:prog+'%',transition:'width 0.5s ease'}})),
246
+ React.createElement('div',{style:{display:'flex',justifyContent:'space-between',marginBottom:24}},
247
+ React.createElement('span',{style:{fontSize:12,color:'#4B5563'}},`${lv.icon} ${lv.name}`),
248
+ React.createElement('span',{style:{fontSize:12,color:'#4B5563'}},`${cQ+1} / ${tQ}`)),
249
+ // Badge
250
+ React.createElement('div',{style:{display:'inline-block',background:tb.bg,border:`1px solid ${tb.bd}`,borderRadius:20,padding:'4px 14px',fontSize:12,fontWeight:600,marginBottom:16,color:tb.c}},tb.l),
251
+ // Question
252
+ React.createElement('h3',{style:{fontSize:21,fontWeight:700,color:'#F1F5F9',lineHeight:1.45,marginBottom:18,animation:shk?'shake 0.5s ease':'fadeUp 0.3s ease'}},q.question),
253
+ q.code&&React.createElement(CodeBlock,{code:q.code,style:{marginBottom:22}}),
254
+
255
+ // Fill blank
256
+ q.type==='fillblank'?
257
+ React.createElement('div',{style:{marginBottom:22}},
258
+ React.createElement('div',{style:{background:'#0A0E1B',border:'1px solid rgba(148,163,184,0.1)',borderRadius:14,padding:'16px 20px',fontFamily:"'Fira Code','Courier New',monospace",fontSize:14.5,lineHeight:1.75,color:'#CBD5E1',whiteSpace:'pre-wrap'}},
259
+ React.createElement('div',{style:{display:'flex',gap:6,marginBottom:12}},
260
+ React.createElement('div',{style:{width:10,height:10,borderRadius:'50%',background:'#EF4444'}}),
261
+ React.createElement('div',{style:{width:10,height:10,borderRadius:'50%',background:'#FBBF24'}}),
262
+ React.createElement('div',{style:{width:10,height:10,borderRadius:'50%',background:'#22C55E'}})),
263
+ React.createElement('span',{style:{color:'#64748B'}},q.codeBefore),
264
+ React.createElement('input',{ref:iRef,type:'text',value:fill,onChange:e=>setFill(e.target.value),onKeyDown:e=>e.key==='Enter'&&!showR&&handleFill(),disabled:showR,placeholder:'type here...',
265
+ style:{background:showR?(ok?'rgba(52,211,153,0.15)':'rgba(251,113,133,0.15)'):'rgba(99,102,241,0.1)',border:`1px solid ${showR?(ok?'#34D399':'#FB7185'):'rgba(99,102,241,0.3)'}`,borderRadius:6,padding:'4px 10px',fontFamily:"'Fira Code','Courier New',monospace",fontSize:14.5,color:showR?(ok?'#34D399':'#FB7185'):'#E2E8F0',width:Math.max(120,fill.length*10+50)}}),
266
+ React.createElement('span',{style:{color:'#64748B'}},q.codeAfter)),
267
+ !showR&&React.createElement('div',{style:{display:'flex',gap:10,marginTop:14}},
268
+ React.createElement('button',{onClick:handleFill,style:{...btn,background:`linear-gradient(135deg,${lv.color},${lv.color}CC)`,color:'#FFF',padding:'12px 28px'}},'Submit'),
269
+ React.createElement('button',{onClick:()=>setHint(true),style:{...btn,background:'transparent',border:'1px solid rgba(148,163,184,0.12)',color:'#64748B',padding:'12px 18px',fontSize:14}},'💡 Hint')),
270
+ hint&&!showR&&React.createElement('div',{style:{marginTop:10,padding:'10px 16px',background:'rgba(251,191,36,0.06)',border:'1px solid rgba(251,191,36,0.15)',borderRadius:10,fontSize:14,color:'#D4A843',animation:'fadeUp 0.2s ease'}},q.hint))
271
+ :
272
+ // Quiz/Debug options
273
+ React.createElement('div',{style:{display:'flex',flexDirection:'column',gap:10,marginBottom:22}},
274
+ q.options.map((opt,i)=>{
275
+ let bg='rgba(15,23,42,0.7)',bd='rgba(148,163,184,0.08)',cl='#CBD5E1';
276
+ if(showR){if(i===q.correct){bg='rgba(52,211,153,0.12)';bd='#34D399';cl='#34D399';}else if(i===sel&&!ok){bg='rgba(251,113,133,0.12)';bd='#FB7185';cl='#FB7185';}}
277
+ return React.createElement('button',{key:i,onClick:()=>handleQuiz(i),disabled:showR,
278
+ style:{...btn,background:bg,border:`1px solid ${bd}`,color:cl,padding:'15px 18px',textAlign:'left',fontSize:14.5,fontWeight:500,display:'flex',alignItems:'center',gap:14,cursor:showR?'default':'pointer',animation:`slideIn 0.3s ease ${i*0.06}s both`},
279
+ onMouseEnter:e=>{if(!showR)e.currentTarget.style.borderColor=lv.color+'50'},onMouseLeave:e=>{if(!showR)e.currentTarget.style.borderColor='rgba(148,163,184,0.08)'}},
280
+ React.createElement('span',{style:{width:28,height:28,borderRadius:8,background:showR&&i===q.correct?'rgba(52,211,153,0.2)':showR&&i===sel&&!ok?'rgba(251,113,133,0.2)':'rgba(148,163,184,0.06)',display:'flex',alignItems:'center',justifyContent:'center',fontSize:12,fontWeight:700,flexShrink:0,color:showR&&i===q.correct?'#34D399':showR&&i===sel&&!ok?'#FB7185':'#64748B'}},showR&&i===q.correct?'✓':showR&&i===sel&&!ok?'✗':String.fromCharCode(65+i)),
281
+ opt);})),
282
+
283
+ // Feedback
284
+ showR&&React.createElement('div',{style:{background:ok?'rgba(52,211,153,0.08)':'rgba(251,113,133,0.08)',border:`1px solid ${ok?'rgba(52,211,153,0.2)':'rgba(251,113,133,0.2)'}`,borderRadius:14,padding:'16px 20px',marginBottom:18,animation:'fadeUp 0.3s ease'}},
285
+ React.createElement('div',{style:{fontSize:15,fontWeight:700,marginBottom:5,color:ok?'#34D399':'#FB7185'}},ok?`✅ Correct! +${xpG} XP`:'❌ Not quite!',ok&&streak>1?' 🔥 '+streak+' streak!':''),
286
+ React.createElement('div',{style:{fontSize:13.5,color:'#94A3B8',lineHeight:1.55}},q.explanation,q.type==='fillblank'&&!ok?React.createElement('span',{style:{color:'#34D399',fontWeight:600}},' Answer: '+q.answer):null)),
287
+
288
+ // Next
289
+ showR&&React.createElement('button',{onClick:nextQ,style:{...btn,width:'100%',background:`linear-gradient(135deg,${lv.color},${lv.color}CC)`,color:'#FFF',fontSize:16,boxShadow:`0 8px 24px ${lv.color}25`,animation:'fadeUp 0.3s ease'}},cQ+1>=tQ?'See Results →':'Next Challenge →')));
290
+ }
291
+ return null;
292
+ }
293
+
294
+ ReactDOM.render(React.createElement(ZakCode),document.getElementById('root'));
295
+ </script>
296
+ </body>
297
+ </html>