My first web page.
\n \n' }, { type:'video', title:'Headings, Paragraphs & Text Formatting', dur:'18:00', free:true, ov:'Learn the core text tags: h1-h6 for headings, p for paragraphs, and inline tags for bold, italic, and more.
', nt:'h1 to h6: heading hierarchy (h1 = most important)\np: paragraph text\nstrong: bold (semantic)\nem: italic (semantic)\nspan: inline container\nbr: line break\nhr: horizontal rule', cd:'This is a paragraph with bold text and italic text.
\nLine break
here
CSS selectors are how you target HTML elements to style them. Master all selector types.
', nt:'element: p { color: red }\nclass: .box { margin: 10px }\nid: #header { font-size: 2rem }\nattribute: input[type="text"] { border: 1px solid }\nDescendant: .nav a { ... }\nPseudo-class: a:hover { ... }', cd:'/* Element selector */\np { color: #333; }\n\n/* Class selector */\n.card { background: white; border-radius: 8px; }\n\n/* ID selector */\n#main-title { font-size: 2rem; }\n\n/* Hover pseudo-class */\na:hover { color: blue; }\n\n/* Child combinator */\n.nav > a { text-decoration: none; }' }, { type:'video', title:'The Box Model — margin, padding, border, content', dur:'22:00', free:false }, { type:'video', title:'Colors — hex, rgb, hsl, named colors', dur:'14:00', free:false }, { type:'video', title:'Typography — font-family, size, weight, line-height', dur:'18:00', free:false }, { type:'quiz', title:'CSS Basics Quiz', dur:'10:00', free:false }, ]}, { title:'CSS Layout — Flexbox & Grid', dur:'4h 00m', items:[ { type:'video', title:'Display Property — block, inline, inline-block, none', dur:'14:00', free:false }, { type:'video', title:'Flexbox — Container Properties (display, flex-direction, justify-content, align-items)', dur:'30:00', free:false, ov:'Flexbox is the most powerful 1D layout tool in CSS. Master the container properties first.
', nt:'display: flex → creates flex container\nflex-direction: row | column\njustify-content: flex-start | center | space-between | space-around\nalign-items: flex-start | center | flex-end | stretch\nflex-wrap: wrap | nowrap', cd:'.container {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n}\n\n/* Center anything perfectly */\n.centered {\n display: flex;\n justify-content: center;\n align-items: center;\n}' }, { type:'video', title:'Flexbox — Item Properties (flex-grow, flex-shrink, flex-basis, order)', dur:'25:00', free:false }, { type:'video', title:'CSS Grid — Defining Rows & Columns', dur:'28:00', free:false, ov:'CSS Grid is the go-to for 2D layouts. Define rows and columns with grid-template-columns and rows.
', nt:'display: grid → grid container\ngrid-template-columns: 1fr 2fr 1fr\ngrid-template-rows: auto\ngap: spacing between cells\ngrid-column: span 2 → item spans 2 cols\nfr unit = fractional unit of available space', cd:'.grid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 20px;\n}\n\n/* Responsive grid without media queries */\n.auto-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: 16px;\n}' }, { type:'video', title:'CSS Grid — Placing Items & Named Areas', dur:'25:00', free:false }, { type:'video', title:'Position — static, relative, absolute, fixed, sticky', dur:'22:00', free:false }, { type:'project', title:'Project 2 — CSS Layout Challenge (Flexbox + Grid)', dur:'60:00', free:false }, ]}, { title:'Responsive Design & Media Queries', dur:'2h 30m', items:[ { type:'video', title:'Mobile-First Design Philosophy', dur:'14:00', free:false }, { type:'video', title:'Media Queries — Breakpoints & Syntax', dur:'22:00', free:false, nt:'Mobile-first: write CSS for mobile, then scale up\n/* Small screens first */\n.nav { flex-direction: column; }\n/* Tablets (≥768px) */\n@media (min-width: 768px) { .nav { flex-direction: row; } }\n/* Desktop (≥1024px) */\n@media (min-width: 1024px) { ... }', cd:'/* Mobile first */\n.container { padding: 1rem; }\n.grid { grid-template-columns: 1fr; }\n\n/* Tablet */\n@media (min-width: 768px) {\n .container { padding: 2rem; }\n .grid { grid-template-columns: 1fr 1fr; }\n}\n\n/* Desktop */\n@media (min-width: 1024px) {\n .grid { grid-template-columns: repeat(3, 1fr); }\n}' }, { type:'video', title:'CSS Variables (Custom Properties)', dur:'18:00', free:false }, { type:'video', title:'Viewport Units — vh, vw, vmin, vmax', dur:'12:00', free:false }, { type:'project', title:'Project 3 — Responsive Portfolio Website', dur:'75:00', free:false }, ]}, { title:'CSS Animations & Visual Effects', dur:'2h 00m', items:[ { type:'video', title:'Transitions — timing, easing, properties', dur:'18:00', free:false }, { type:'video', title:'CSS Animations — @keyframes', dur:'25:00', free:false, nt:'transition: property duration timing-function delay\ntransform: translate, scale, rotate, skew\n@keyframes name { from{} to{} }\nanimation: name duration timing iteration-count', cd:'.btn {\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n.btn:hover {\n transform: translateY(-3px);\n box-shadow: 0 8px 24px rgba(0,0,0,0.2);\n}\n\n@keyframes fadeIn {\n from { opacity: 0; transform: translateY(20px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.hero { animation: fadeIn 0.6s ease; }' }, { type:'video', title:'Pseudo-elements — ::before and ::after', dur:'20:00', free:false }, { type:'video', title:'CSS Gradients, Shadows & Filters', dur:'18:00', free:false }, { type:'project', title:'Project 4 — Animated Landing Page', dur:'70:00', free:false }, ]}, { title:'Final Projects & Best Practices', dur:'3h 00m', items:[ { type:'video', title:'CSS Naming Conventions — BEM Methodology', dur:'15:00', free:false }, { type:'video', title:'CSS Reset & Normalize', dur:'10:00', free:false }, { type:'video', title:'Google Fonts & Icon Libraries', dur:'12:00', free:false }, { type:'video', title:'Browser DevTools — Debug Like a Pro', dur:'18:00', free:false }, { type:'project', title:'Project 5 — E-Commerce Product Page', dur:'80:00', free:false }, { type:'project', title:'Final Project — Full Responsive Website (3 pages)', dur:'100:00', free:false }, { type:'quiz', title:'Final Mastery Quiz', dur:'15:00', free:false }, ]}, ]; const TOTAL=45; const CID='html'; let done=new Set(JSON.parse(localStorage.getItem('bwb_'+CID)||'[]')); let cur=null,tab='ov'; function dec(s){try{return decodeURIComponent(escape(atob(s)));}catch(e){return s||'';}} function key(si,li){return si+'_'+li;} function pct(){return TOTAL?Math.round(done.size/TOTAL*100):0;} function updateProg(){ const p=pct(); ['pbf1','pbf2'].forEach(id=>{const e=document.getElementById(id);if(e)e.style.width=p+'%';}); ['pct1','pct2'].forEach(id=>{const e=document.getElementById(id);if(e)e.textContent=p+'%';}); ['cnt1','cnt2'].forEach(id=>{const e=document.getElementById(id);if(e)e.textContent=done.size+'/'+TOTAL+' lessons';}); document.getElementById('ptop').style.width=p+'%'; SECS.forEach((_,si)=>{ const items=SECS[si].items; const n=items.filter((_,li)=>done.has(key(si,li))).length; const pp=items.length?Math.round(n/items.length*100):0; ['sp','nf'].forEach(px=>{const e=document.getElementById(px+si);if(e)e.style.width=pp+'%';}); }); } function buildCurriculum(){ const cur_el=document.getElementById('curriculum'); const snav=document.getElementById('snav'); cur_el.innerHTML='';snav.innerHTML=''; SECS.forEach((sec,si)=>{ const totalLess=sec.items.length; cur_el.innerHTML+=`Watch the video above to learn this concept.
'; }else if(tab==='nt'){ if(item.nt){ const safe=item.nt.replace(/&/g,'&').replace(//g,'>'); vc.innerHTML=''+safe+''; }else{ vc.innerHTML='
No notes for this lesson yet.
'; } }else{ if(item.cd){ const safe=item.cd.replace(/&/g,'&').replace(//g,'>'); vc.innerHTML=''+safe+'
No code sample for this lesson.
'; } } } function showTab(t,btn){ tab=t; document.querySelectorAll('.tab').forEach(x=>x.classList.remove('active')); if(btn)btn.classList.add('active'); renderTab(); } function togglePlay(){ const ov=document.getElementById('vpov'); if(ov)ov.style.display=ov.style.display==='none'?'flex':'none'; } function markDone(){ if(!cur)return; const k=key(cur.si,cur.li); done.add(k); localStorage.setItem('bwb_'+CID,JSON.stringify([...done])); updateProg(); const row=document.getElementById('lr'+cur.si+'_'+cur.li); if(row)row.classList.add('done'); const ld=document.getElementById('ld'+cur.si+'_'+cur.li); if(ld)ld.textContent='✓'; toast('Marked complete ✓'); } let tt; function toast(msg){ const t=document.getElementById('toast'); t.textContent=msg;t.classList.add('show'); clearTimeout(tt);tt=setTimeout(()=>t.classList.remove('show'),2600); } window.addEventListener('scroll',()=>{ const h=document.documentElement.scrollHeight-window.innerHeight; if(h>0)document.getElementById('ptop').style.width=(window.scrollY/h*100)+'%'; }); buildCurriculum(); document.addEventListener('DOMContentLoaded',()=>{ SECS.forEach((sec,si)=>{ sec.items.forEach((_,li)=>{ if(done.has(key(si,li))){ const row=document.getElementById('lr'+si+'_'+li); if(row)row.classList.add('done'); const ld=document.getElementById('ld'+si+'_'+li); if(ld)ld.textContent='✓'; } }); }); updateProg(); toggleSec(0); });