diff --git a/src/app.js b/src/app.js
index 67c4360..ed7ce1c 100644
--- a/src/app.js
+++ b/src/app.js
@@ -115,6 +115,11 @@ const elements = {
sectionProgressText: document.getElementById("section-progress-text"),
sectionIntro: document.getElementById("section-intro"),
+ // Reference page elements
+ referencePage: document.getElementById("reference-page"),
+ referenceNav: document.getElementById("reference-nav"),
+ referenceBody: document.getElementById("reference-body"),
+
// Left panel
instructionsSection: document.querySelector(".instructions"),
editorSection: document.querySelector(".editor-section"),
@@ -1282,6 +1287,445 @@ const sectionContent = {
`
};
+// ================= REFERENCE CHEATSHEET CONTENT =================
+
+const referenceContent = {
+ css: `
+
CSS Properties Reference
+ Quick reference for commonly used CSS properties. Click any property to see syntax and examples.
+
+
+ Colors & Backgrounds
+
+ | Property | Values | Example |
+
+ color | named, hex, rgb(), hsl() | color: steelblue; |
+ background | color, image, gradient | background: #f0f0f0; |
+ background-color | color value | background-color: white; |
+ background-image | url(), gradient | background-image: url(bg.png); |
+ opacity | 0 to 1 | opacity: 0.8; |
+
+
+
+
+
+ Typography
+
+ | Property | Values | Example |
+
+ font-family | font name, generic | font-family: system-ui, sans-serif; |
+ font-size | px, rem, em, % | font-size: 1rem; |
+ font-weight | normal, bold, 100-900 | font-weight: 600; |
+ line-height | number, length, % | line-height: 1.5; |
+ text-align | left, center, right, justify | text-align: center; |
+ text-decoration | none, underline, line-through | text-decoration: none; |
+ text-transform | none, uppercase, lowercase, capitalize | text-transform: uppercase; |
+ letter-spacing | length | letter-spacing: 0.05em; |
+
+
+
+
+
+ Box Model
+
+ | Property | Values | Example |
+
+ width | length, %, auto, fit-content | width: 100%; |
+ height | length, %, auto | height: 200px; |
+ max-width | length, %, none | max-width: 600px; |
+ padding | length (1-4 values) | padding: 1rem 2rem; |
+ margin | length, auto (1-4 values) | margin: 0 auto; |
+ border | width style color | border: 1px solid gray; |
+ border-radius | length (1-4 values) | border-radius: 8px; |
+ box-sizing | content-box, border-box | box-sizing: border-box; |
+
+
+
+
+
+ Layout
+
+ | Property | Values | Example |
+
+ display | block, inline, flex, grid, none | display: flex; |
+ position | static, relative, absolute, fixed, sticky | position: relative; |
+ top/right/bottom/left | length, %, auto | top: 0; left: 50%; |
+ z-index | integer, auto | z-index: 10; |
+ overflow | visible, hidden, scroll, auto | overflow: auto; |
+ float | none, left, right | float: left; |
+
+
+
+
+
+ Visual Effects
+
+ | Property | Values | Example |
+
+ box-shadow | x y blur spread color | box-shadow: 0 4px 8px rgba(0,0,0,0.1); |
+ text-shadow | x y blur color | text-shadow: 1px 1px 2px gray; |
+ transform | translate, rotate, scale | transform: translateY(-2px); |
+ transition | property duration easing | transition: all 0.3s ease; |
+ cursor | pointer, default, text, grab | cursor: pointer; |
+
+
+
+ `,
+
+ selectors: `
+ CSS Selectors Reference
+ Selectors determine which HTML elements your styles apply to. More specific selectors override less specific ones.
+
+
+ Basic Selectors
+
+ | Selector | Description | Example |
+
+ element | All elements of type | p { ... } |
+ .class | Elements with class | .btn { ... } |
+ #id | Element with ID | #header { ... } |
+ * | All elements | * { box-sizing: border-box; } |
+ [attr] | Elements with attribute | [disabled] { ... } |
+ [attr="value"] | Attribute equals value | [type="text"] { ... } |
+
+
+
+
+
+ Combinators
+
+ | Selector | Description | Example |
+
+ A B | B inside A (descendant) | nav a { ... } |
+ A > B | B direct child of A | ul > li { ... } |
+ A + B | B immediately after A | h2 + p { ... } |
+ A ~ B | B after A (sibling) | h2 ~ p { ... } |
+ A, B | A or B (grouping) | h1, h2, h3 { ... } |
+
+
+
+
+
+ Pseudo-classes
+
+ | Selector | Description | Example |
+
+ :hover | Mouse over element | a:hover { color: blue; } |
+ :focus | Element has focus | input:focus { outline: 2px solid; } |
+ :active | Being clicked | button:active { transform: scale(0.98); } |
+ :first-child | First child element | li:first-child { ... } |
+ :last-child | Last child element | li:last-child { ... } |
+ :nth-child(n) | nth child (1-based) | tr:nth-child(odd) { ... } |
+ :not(sel) | Elements not matching | :not(.hidden) { ... } |
+ :checked | Checked inputs | input:checked { ... } |
+ :disabled | Disabled form elements | button:disabled { opacity: 0.5; } |
+
+
+
+
+
+ Pseudo-elements
+
+ | Selector | Description | Example |
+
+ ::before | Insert before content | .icon::before { content: "→"; } |
+ ::after | Insert after content | .link::after { content: "↗"; } |
+ ::first-letter | First letter of text | p::first-letter { font-size: 2em; } |
+ ::first-line | First line of text | p::first-line { font-weight: bold; } |
+ ::placeholder | Input placeholder text | input::placeholder { color: gray; } |
+ ::selection | Selected/highlighted text | ::selection { background: yellow; } |
+
+
+
+
+
+ Specificity (Highest to Lowest)
+
+ - Inline styles -
style="..." attribute (1000 points)
+ - ID selectors -
#id (100 points)
+ - Class/pseudo-class/attribute -
.class, :hover, [attr] (10 points)
+ - Element/pseudo-element -
div, ::before (1 point)
+ - Universal selector -
* (0 points)
+
+
+ `,
+
+ flexbox: `
+ Flexbox Reference
+ Flexbox is a one-dimensional layout system. Apply display: flex to a container, and its children become flex items.
+
+
+ Container Properties
+
+ | Property | Values | Description |
+
+ display | flex, inline-flex | Enable flex container |
+ flex-direction | row, row-reverse, column, column-reverse | Main axis direction |
+ flex-wrap | nowrap, wrap, wrap-reverse | Allow items to wrap |
+ justify-content | flex-start, flex-end, center, space-between, space-around, space-evenly | Main axis alignment |
+ align-items | stretch, flex-start, flex-end, center, baseline | Cross axis alignment |
+ align-content | stretch, flex-start, flex-end, center, space-between, space-around | Multi-line alignment |
+ gap | length | Space between items |
+
+
+
+
+
+ Item Properties
+
+ | Property | Values | Description |
+
+ flex-grow | number (default: 0) | How much item grows |
+ flex-shrink | number (default: 1) | How much item shrinks |
+ flex-basis | length, auto | Initial size before grow/shrink |
+ flex | grow shrink basis | Shorthand (e.g., flex: 1) |
+ align-self | auto, flex-start, flex-end, center, stretch | Override align-items |
+ order | integer (default: 0) | Visual order of item |
+
+
+
+
+
+ Common Patterns
+
+
/* Center horizontally and vertically */
+.center {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+/* Space items evenly */
+.navbar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+/* Equal-width columns */
+.columns {
+ display: flex;
+ gap: 1rem;
+}
+.columns > * {
+ flex: 1;
+}
+
+/* Sticky footer */
+.page {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+}
+.main { flex: 1; }
+
+
+ `,
+
+ grid: `
+ CSS Grid Reference
+ CSS Grid is a two-dimensional layout system for complex row and column layouts. Apply display: grid to a container.
+
+
+ Container Properties
+
+ | Property | Values | Description |
+
+ display | grid, inline-grid | Enable grid container |
+ grid-template-columns | track sizes | Define column widths |
+ grid-template-rows | track sizes | Define row heights |
+ gap | length | Space between cells |
+ justify-items | start, end, center, stretch | Horizontal alignment in cells |
+ align-items | start, end, center, stretch | Vertical alignment in cells |
+ justify-content | start, end, center, space-between, space-around | Horizontal grid alignment |
+ align-content | start, end, center, space-between, space-around | Vertical grid alignment |
+
+
+
+
+
+ Track Sizing
+
+ | Value | Description | Example |
+
+ px, rem, % | Fixed or relative sizes | 200px 1rem 50% |
+ fr | Fraction of available space | 1fr 2fr 1fr |
+ auto | Size to content | auto 1fr auto |
+ minmax(min, max) | Size range | minmax(100px, 1fr) |
+ repeat(n, size) | Repeat n times | repeat(3, 1fr) |
+ repeat(auto-fill, ...) | Fill available space | repeat(auto-fill, minmax(200px, 1fr)) |
+ repeat(auto-fit, ...) | Fill and stretch | repeat(auto-fit, minmax(200px, 1fr)) |
+
+
+
+
+
+ Item Properties
+
+ | Property | Values | Description |
+
+ grid-column | start / end | Column span |
+ grid-row | start / end | Row span |
+ grid-area | row-start / col-start / row-end / col-end | Shorthand for both |
+ justify-self | start, end, center, stretch | Horizontal alignment |
+ align-self | start, end, center, stretch | Vertical alignment |
+
+
+
+
+
+ Common Patterns
+
+
/* 3 equal columns */
+.grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 1rem;
+}
+
+/* Responsive auto-fill */
+.responsive {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
+ gap: 1rem;
+}
+
+/* Holy grail layout */
+.layout {
+ display: grid;
+ grid-template-columns: 200px 1fr 200px;
+ grid-template-rows: auto 1fr auto;
+ min-height: 100vh;
+}
+
+/* Span multiple cells */
+.wide {
+ grid-column: 1 / -1; /* Full width */
+}
+.tall {
+ grid-row: span 2; /* 2 rows */
+}
+
+
+ `,
+
+ html: `
+ HTML Elements Reference
+ Semantic HTML elements that describe their meaning to browsers and assistive technologies.
+
+
+ Document Structure
+
+ | Element | Purpose | Example |
+
+ <html> | Root element | <html lang="en"> |
+ <head> | Document metadata | Contains title, meta, links |
+ <body> | Document content | All visible content |
+ <header> | Introductory content | Logo, nav, title |
+ <nav> | Navigation links | Main site navigation |
+ <main> | Main content (one per page) | Primary page content |
+ <footer> | Footer content | Copyright, links |
+ <aside> | Sidebar/tangential content | Related links, ads |
+
+
+
+
+
+ Content Sectioning
+
+ | Element | Purpose | Example |
+
+ <article> | Self-contained content | Blog post, comment |
+ <section> | Thematic grouping | Chapter, tab panel |
+ <h1>-<h6> | Headings (hierarchy) | One h1 per page, nest others |
+ <p> | Paragraph | Block of text |
+ <div> | Generic container | When no semantic element fits |
+
+
+
+
+
+ Text Content
+
+ | Element | Purpose | Example |
+
+ <a> | Hyperlink | <a href="url">Link</a> |
+ <strong> | Important text (bold) | <strong>Warning</strong> |
+ <em> | Emphasized text (italic) | <em>really</em> |
+ <code> | Inline code | <code>const x</code> |
+ <pre> | Preformatted text | Code blocks |
+ <span> | Generic inline container | Styling inline text |
+ <br> | Line break | Address, poem lines |
+ <hr> | Thematic break | Scene change, topic shift |
+
+
+
+
+
+ Lists
+
+ | Element | Purpose | Example |
+
+ <ul> | Unordered list | Bulleted items |
+ <ol> | Ordered list | Numbered steps |
+ <li> | List item | Inside ul or ol |
+ <dl> | Description list | Term/definition pairs |
+ <dt> | Description term | The term being defined |
+ <dd> | Description details | Definition of the term |
+
+
+
+
+
+ Forms
+
+ | Element | Purpose | Key Attributes |
+
+ <form> | Form container | action, method |
+ <input> | Input field | type, name, required, placeholder |
+ <textarea> | Multi-line text | rows, cols, name |
+ <select> | Dropdown menu | name, multiple |
+ <option> | Select option | value, selected |
+ <button> | Clickable button | type (submit/button/reset) |
+ <label> | Input label | for (matches input id) |
+ <fieldset> | Group form controls | With legend for title |
+
+
+
+
+
+ Media
+
+ | Element | Purpose | Key Attributes |
+
+ <img> | Image | src, alt (required), width, height |
+ <figure> | Self-contained media | Contains img + figcaption |
+ <figcaption> | Figure caption | Description of figure |
+ <video> | Video player | src, controls, autoplay |
+ <audio> | Audio player | src, controls |
+ <picture> | Responsive images | Contains source + img |
+
+
+
+
+
+ Tables
+
+ | Element | Purpose | Notes |
+
+ <table> | Table container | For tabular data only |
+ <thead> | Table header group | Contains header rows |
+ <tbody> | Table body group | Contains data rows |
+ <tfoot> | Table footer group | Summary row |
+ <tr> | Table row | Contains cells |
+ <th> | Header cell | scope="col" or "row" |
+ <td> | Data cell | colspan, rowspan for spanning |
+
+
+
+ `
+};
+
// ================= URL ROUTING & PAGE SWITCHING =================
function initRouter() {
@@ -1314,8 +1758,7 @@ function handleRoute(shouldUpdateUrl = true) {
showSectionPage(route.sectionId);
break;
case RouteType.REFERENCE:
- // Reference pages - TODO: implement later
- showLandingPage();
+ showReferencePage(route.refId);
break;
case RouteType.LESSON:
navigateToLesson(route.moduleId, route.lessonIndex, shouldUpdateUrl);
@@ -1333,6 +1776,7 @@ function handleRoute(shouldUpdateUrl = true) {
function hideAllPages() {
elements.landingPage?.classList.add("hidden");
elements.sectionPage?.classList.add("hidden");
+ elements.referencePage?.classList.add("hidden");
elements.gameLayout?.classList.add("hidden");
}
@@ -1420,6 +1864,63 @@ function showSectionPage(sectionId) {
if (elements.sectionProgressText) elements.sectionProgressText.textContent = `${completed} of ${total} lessons complete`;
}
+/**
+ * Show reference/cheatsheet page
+ */
+function showReferencePage(refId) {
+ hideAllPages();
+ elements.referencePage?.classList.remove("hidden");
+
+ // Default to CSS if no refId
+ const activeRef = refId || "css";
+
+ // Track reference page view
+ track("reference_view", { ref: activeRef });
+
+ // Update nav highlighting
+ const navLinks = elements.referenceNav?.querySelectorAll(".ref-nav-link");
+ navLinks?.forEach((link) => {
+ link.classList.toggle("active", link.dataset.ref === activeRef);
+ });
+
+ // Load reference content
+ if (elements.referenceBody && referenceContent[activeRef]) {
+ elements.referenceBody.innerHTML = referenceContent[activeRef];
+ // Highlight code blocks
+ highlightReferenceCodeBlocks();
+ } else if (elements.referenceBody) {
+ elements.referenceBody.innerHTML = `Reference for "${activeRef}" coming soon...
`;
+ }
+}
+
+/**
+ * Highlight code blocks in reference pages with CodeMirror
+ */
+function highlightReferenceCodeBlocks() {
+ // Clean up previous views
+ sectionCodeViews.forEach((view) => view.destroy());
+ sectionCodeViews = [];
+
+ const codeBlocks = elements.referenceBody?.querySelectorAll("pre code");
+ codeBlocks?.forEach((block) => {
+ const code = block.textContent;
+ const isHtml = block.classList.contains("language-html");
+ const parent = block.parentElement;
+
+ parent.innerHTML = "";
+ parent.classList.add("cm-code-block");
+
+ const view = new EditorView({
+ state: EditorState.create({
+ doc: code,
+ extensions: [isHtml ? html() : css(), oneDark, readOnlyTheme, EditorState.readOnly.of(true), EditorView.editable.of(false)]
+ }),
+ parent
+ });
+ sectionCodeViews.push(view);
+ });
+}
+
/**
* Show lesson UI (game layout)
*/
diff --git a/src/index.html b/src/index.html
index 43c412c..aef4a7a 100644
--- a/src/index.html
+++ b/src/index.html
@@ -135,6 +135,22 @@
+
+
+
diff --git a/src/main.css b/src/main.css
index de0c7ba..5d9d840 100644
--- a/src/main.css
+++ b/src/main.css
@@ -1999,6 +1999,163 @@ input:checked + .toggle-slider::before {
font-weight: 500;
}
+/* ================= REFERENCE PAGES ================= */
+.reference-page {
+ flex: 1;
+ overflow-y: auto;
+ background: var(--bg-color);
+}
+
+.reference-content {
+ max-width: 900px;
+ margin: 0 auto;
+ padding: var(--spacing-lg);
+}
+
+.reference-nav {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--spacing-sm);
+ padding: var(--spacing-md);
+ background: var(--panel-bg);
+ border-radius: var(--border-radius-md);
+ margin-bottom: var(--spacing-lg);
+ position: sticky;
+ top: 0;
+ z-index: 10;
+ box-shadow: var(--shadow);
+}
+
+.ref-nav-link {
+ padding: var(--spacing-xs) var(--spacing-sm);
+ border-radius: var(--border-radius-sm);
+ text-decoration: none;
+ color: var(--text-color);
+ font-size: 0.9rem;
+ font-weight: 500;
+ transition: background 0.2s, color 0.2s;
+}
+
+.ref-nav-link:hover {
+ background: var(--hover-bg);
+}
+
+.ref-nav-link.active {
+ background: var(--primary-color);
+ color: white;
+}
+
+.reference-body h1 {
+ font-size: 1.75rem;
+ margin-bottom: var(--spacing-sm);
+ color: var(--primary-dark);
+}
+
+.ref-intro {
+ font-size: 1rem;
+ color: var(--light-text);
+ margin-bottom: var(--spacing-lg);
+ line-height: 1.6;
+}
+
+.ref-section {
+ margin-bottom: var(--spacing-xl);
+}
+
+.ref-section h2 {
+ font-size: 1.2rem;
+ margin-bottom: var(--spacing-md);
+ color: var(--text-color);
+ border-bottom: 2px solid var(--border-color);
+ padding-bottom: var(--spacing-xs);
+}
+
+.ref-table {
+ width: 100%;
+ border-collapse: collapse;
+ font-size: 0.9rem;
+ background: var(--panel-bg);
+ border-radius: var(--border-radius-md);
+ overflow: hidden;
+ box-shadow: var(--shadow);
+}
+
+.ref-table thead {
+ background: var(--hover-bg);
+}
+
+.ref-table th,
+.ref-table td {
+ padding: var(--spacing-sm) var(--spacing-md);
+ text-align: left;
+ border-bottom: 1px solid var(--border-color);
+}
+
+.ref-table th {
+ font-weight: 600;
+ color: var(--text-color);
+}
+
+.ref-table tr:last-child td {
+ border-bottom: none;
+}
+
+.ref-table tr:hover {
+ background: var(--hover-bg);
+}
+
+.ref-table code {
+ background: var(--code-bg);
+ padding: 0.15rem 0.4rem;
+ border-radius: 4px;
+ font-size: 0.85em;
+ color: var(--primary-dark);
+}
+
+.ref-list {
+ background: var(--panel-bg);
+ border-radius: var(--border-radius-md);
+ padding: var(--spacing-md) var(--spacing-md) var(--spacing-md) var(--spacing-xl);
+ box-shadow: var(--shadow);
+}
+
+.ref-list li {
+ padding: var(--spacing-xs) 0;
+ line-height: 1.6;
+}
+
+.ref-list code {
+ background: var(--code-bg);
+ padding: 0.15rem 0.4rem;
+ border-radius: 4px;
+ font-size: 0.85em;
+}
+
+/* Reference page code blocks */
+.reference-body .code-block {
+ margin: var(--spacing-md) 0;
+}
+
+/* Responsive reference tables */
+@media (max-width: 600px) {
+ .ref-table {
+ font-size: 0.8rem;
+ }
+
+ .ref-table th,
+ .ref-table td {
+ padding: var(--spacing-xs) var(--spacing-sm);
+ }
+
+ .reference-nav {
+ position: static;
+ }
+
+ .ref-nav-link {
+ font-size: 0.8rem;
+ }
+}
+
/* ================= UTILITY ================= */
.hidden {
display: none !important;