commit 666218035ca89389b247eaf9f203a3e0932d31b0 Author: Codex Date: Tue Jul 7 08:34:01 2026 +0530 Initial decks site diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/gurusetu-update-slides/assets/fonts/heliotrope_3_bold.woff2 b/gurusetu-update-slides/assets/fonts/heliotrope_3_bold.woff2 new file mode 100644 index 0000000..9156122 Binary files /dev/null and b/gurusetu-update-slides/assets/fonts/heliotrope_3_bold.woff2 differ diff --git a/gurusetu-update-slides/assets/fonts/heliotrope_3_bold_italic.woff2 b/gurusetu-update-slides/assets/fonts/heliotrope_3_bold_italic.woff2 new file mode 100644 index 0000000..42c7dff Binary files /dev/null and b/gurusetu-update-slides/assets/fonts/heliotrope_3_bold_italic.woff2 differ diff --git a/gurusetu-update-slides/assets/fonts/heliotrope_3_italic.woff2 b/gurusetu-update-slides/assets/fonts/heliotrope_3_italic.woff2 new file mode 100644 index 0000000..73a5949 Binary files /dev/null and b/gurusetu-update-slides/assets/fonts/heliotrope_3_italic.woff2 differ diff --git a/gurusetu-update-slides/assets/fonts/heliotrope_3_regular.woff2 b/gurusetu-update-slides/assets/fonts/heliotrope_3_regular.woff2 new file mode 100644 index 0000000..00ea57b Binary files /dev/null and b/gurusetu-update-slides/assets/fonts/heliotrope_3_regular.woff2 differ diff --git a/gurusetu-update-slides/assets/images/sprouts-guiding-principles.png b/gurusetu-update-slides/assets/images/sprouts-guiding-principles.png new file mode 100644 index 0000000..a7f4aed Binary files /dev/null and b/gurusetu-update-slides/assets/images/sprouts-guiding-principles.png differ diff --git a/gurusetu-update-slides/assets/videos/process-oriented-learning-hindi.mp4 b/gurusetu-update-slides/assets/videos/process-oriented-learning-hindi.mp4 new file mode 100644 index 0000000..bb11bf3 Binary files /dev/null and b/gurusetu-update-slides/assets/videos/process-oriented-learning-hindi.mp4 differ diff --git a/gurusetu-update-slides/assets/videos/process-oriented-learning-original.mp4 b/gurusetu-update-slides/assets/videos/process-oriented-learning-original.mp4 new file mode 100644 index 0000000..6b8413b Binary files /dev/null and b/gurusetu-update-slides/assets/videos/process-oriented-learning-original.mp4 differ diff --git a/gurusetu-update-slides/index.html b/gurusetu-update-slides/index.html new file mode 100644 index 0000000..01054a7 --- /dev/null +++ b/gurusetu-update-slides/index.html @@ -0,0 +1,744 @@ + + + + + + Gurusetu Update + + + + + + + + + + + + + + + +
+
+
+

Gurusetu

+

Content production and experiments

+
+ Focus. Status of video content verticals, edited course assets, and exploratory production pipelines from IIT Gandhinagar. +
+

Internal update deck. July 7, 2026.

+
+ +
+
Part A
+

Content

+

Vertical-wise production status and course adaptation work.

+
+ +
+
Career vertical
+

FLY content pipeline

+

Our work on the career vertical work is mostly provided by the CMI team via the pedagogy that has proven successful in the FLY framework.

+

A part of this content went through the pilot and is being edited based on feedback. New shoots are underway and we expect edits to be complete by the end of this month for three pillars.

+
+
+
40%
done
+
30%
WIP
+
30%
August
+
+
+
Done
Material cleared through the current production pass.
+
WIP
Editing and production work currently active.
+
August
Remaining portion to be taken up next month.
+
+
+
+ +
+
Pedagogy + Assessments
+

Three content streams

+
+
+ 3.5h to 1.5h + Prof. Pankaj Jalote's course: raw material edited into a compact course. +
+
+ Prof. Pankaj Jalote's course. Edited course duration is about 01:31:27. The sequence reframes teaching around learning, outcomes, activities, assessment, and motivation. +
+
+ 5h+ to 2.5h + Learner-Centric-MOOC adaptation in progress, led by Prof. Sameer Sahasrabudhe and on track for end of July. +
+
+ Learner-Centric-MOOC adaptation. Current plan compresses source material into crisp sections on learner connect, LCM design, practice, feedback, extension resources, and adoption. +
+
+
+ +
+
Pankaj Jalote course summary, 1 of 2
+

From teaching to learning

+ + + + + + + + + +
#VideoDurationSummary
1Teaching Is For Learning07:06Reframes teaching away from syllabus coverage and toward what students actually learn.
2How Students Learn09:55Explains learning as durable change in knowledge, built actively by students through doing and thinking.
3Understanding And Skills09:11Distinguishes conceptual understanding from skill development, including component skills and expert blind spots.
4Integrated Course Design09:52Shows how learning outcomes, teaching activities, and assessment must align.
5Writing Learning Outcomes With Bloom09:33Introduces Bloom's taxonomy as a practical vocabulary for stating course learning outcomes.
+
+ +
+
Pankaj Jalote course summary, 2 of 2
+

Designing practice and assessment

+ + + + + + + + + +
#VideoDurationSummary
6Good Outcomes In Practice09:51Demonstrates how to turn vague outcomes into measurable, course-specific learning outcomes.
7Planning Learning Activities09:35Maps outcomes into in-class and out-of-class activities that make students practice, observe, and reflect.
8Active Lectures: The 15-Minute Reset07:36Explains how to make lectures active using short tasks, peer discussion, quizzes, and feedback.
9Assessment That Supports Learning08:48Clarifies formative vs summative assessment and how assessment supports both learning and grading.
10Motivating Students To Learn09:55Covers motivation through value, expectancy, support, appropriate challenge, and real-world relevance.
+
Full edited course duration: 01:31:27.
+
+ +
+
Learner-Centric-MOOC adaptation, 1 of 4
+

Core learner-centric frame

+ + + + + + + + + + +
#Section / video summaryEst.
1Why learner-centric design matters beyond simply "delivering content."6m
2What learners expect, why engagement drops, and what "learner connect" means.8m
3The LCM model as a reusable active-learning design pattern.6m
4Learning Dialogue: turning explanation into a two-way learning moment.7m
5Chunking an existing lecture into short, meaningful classroom units.7m
6Reflection spots: where to pause, what to ask, and how to resume.7m
+
+ +
+
Learner-Centric-MOOC adaptation, 2 of 4
+

Format, delivery, practice, feedback

+ + + + + + + + + + +
#Section / video summaryEst.
7Choosing the right format: board, slides, demo, discussion, video, activity.8m
8Practical delivery guidance: clarity, pacing, readability, demonstrations.7m
9LeD takeaway: chunk, engage, and close the loop.3m
10Learning by Doing: practice as formative assessment, not just grading.7m
11Designing good practice tasks from learning goals and common student needs.8m
12Feedback for objective questions: use wrong answers to address misconceptions.8m
+
+ +
+
Learner-Centric-MOOC adaptation, 3 of 4
+

Extension and peer learning

+ + + + + + + + + + +
#Section / video summaryEst.
13Feedback for open-ended work using rubrics, peer review, and performance levels.6m
14Effective practice design: variety, frequency, feedback, and increasing complexity.5m
15Learning Extension Trajectories: supporting mixed-background learners.6m
16Curating extension resources without overwhelming or distracting students.8m
17Assimilation checks: small incentives to make extension resources actually used.7m
18Learner Experience Interaction: making peer learning intentional.8m
+
+ +
+
Learner-Centric-MOOC adaptation, 4 of 4
+

Orchestration and adoption

+ + + + + + + + + + + +
#Section / video summaryEst.
19Designing focused discussions, peer critique, and reflection quizzes.8m
20Orchestration: planning the learning flow, monitoring response, adapting live.9m
21Assessment design: mixing formative checks, summative tasks, and peer mechanisms.8m
22Maintaining learner connect through presence, timely feedback, and active tasks.8m
23Responsible resource use: LLMs, OER, attribution, and licensing basics.7m
24LCM Lite: a practical minimal version for real classroom constraints.8m
25Short case wrap: what adoption looks like when instructors actually try it.8m
+
+ +
+
Pedagogy + Assessments
+

Additional modules under revision

+
+
+
+ Active learning ideas
+ Resource person: Prof. Manish Jain
+ Current state: under revision. +
+
+ Assessments at scale
+ Resource person: Prof. Madhavan
+ Current state: under revision. +
+
+
+ Expected total length: about 1 hour. +
+
+
+ +
+
Psychological Literacy + Technology
+

Next shoots

+
+
+

Psychological Literacy

+

Content proposal complete.

+

Shooting to begin later in July.

+
+
+

Technology

+

Multiple content proposals complete.

+

Shooting is underway.

+
+
+
+ +
+
Part B
+

Experiments

+

Production formats, language access, and interactive learning evidence.

+
+ +
+
Experiment 1
+

Dubbing the Sprouts video library

+

Testing whether high-quality Indian-language versions can extend the reach of existing educational video assets.

+
+
+

Original

+ +
+
+

Hindi translation

+ +
+
+
+ We make all our lessons, including all videos that are published on this website without background music, available under the Creative Commons CC BY-NC-SA license. This means that if you are a non-profit organization, government agency, public school, or private person without commercial interest, you can download, edit, and share these videos free of charge. You can also embed our videos in your online courses, upload them to your website, or use them for training. Just make sure you always credit us as: "Video by Sprouts (https://sproutsschools.com)" +
+
+ +
+ Sprouts guiding principles screenshot +
+ +
+
Experiment 3
+

Interactive assessment

+
+
+ Prototype direction. Move beyond passive video watching by testing an interactive assessment layer that asks learners to respond, apply, and receive feedback. +
+ +
+
+
+
+ + + + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..2cfbe0d --- /dev/null +++ b/index.html @@ -0,0 +1,11 @@ + + + + + + Decks + + + hello world + + diff --git a/learning-outcomes-assessment/assets/clips/assessment-feedback.mp4 b/learning-outcomes-assessment/assets/clips/assessment-feedback.mp4 new file mode 100644 index 0000000..e092dac Binary files /dev/null and b/learning-outcomes-assessment/assets/clips/assessment-feedback.mp4 differ diff --git a/learning-outcomes-assessment/assets/clips/attention-reset.mp4 b/learning-outcomes-assessment/assets/clips/attention-reset.mp4 new file mode 100644 index 0000000..21e8c50 Binary files /dev/null and b/learning-outcomes-assessment/assets/clips/attention-reset.mp4 differ diff --git a/learning-outcomes-assessment/assets/clips/learning-activities.mp4 b/learning-outcomes-assessment/assets/clips/learning-activities.mp4 new file mode 100644 index 0000000..c31637e Binary files /dev/null and b/learning-outcomes-assessment/assets/clips/learning-activities.mp4 differ diff --git a/learning-outcomes-assessment/assets/clips/learning-outcomes.mp4 b/learning-outcomes-assessment/assets/clips/learning-outcomes.mp4 new file mode 100644 index 0000000..17db3e6 Binary files /dev/null and b/learning-outcomes-assessment/assets/clips/learning-outcomes.mp4 differ diff --git a/learning-outcomes-assessment/assets/clips/motivation-expectancy.mp4 b/learning-outcomes-assessment/assets/clips/motivation-expectancy.mp4 new file mode 100644 index 0000000..702db99 Binary files /dev/null and b/learning-outcomes-assessment/assets/clips/motivation-expectancy.mp4 differ diff --git a/learning-outcomes-assessment/assets/clips/teaching-is-for-learning.mp4 b/learning-outcomes-assessment/assets/clips/teaching-is-for-learning.mp4 new file mode 100644 index 0000000..cf5ed4b Binary files /dev/null and b/learning-outcomes-assessment/assets/clips/teaching-is-for-learning.mp4 differ diff --git a/learning-outcomes-assessment/assets/posters/activities.jpg b/learning-outcomes-assessment/assets/posters/activities.jpg new file mode 100644 index 0000000..ba6b3a7 Binary files /dev/null and b/learning-outcomes-assessment/assets/posters/activities.jpg differ diff --git a/learning-outcomes-assessment/assets/posters/assessment.jpg b/learning-outcomes-assessment/assets/posters/assessment.jpg new file mode 100644 index 0000000..83fd5a7 Binary files /dev/null and b/learning-outcomes-assessment/assets/posters/assessment.jpg differ diff --git a/learning-outcomes-assessment/assets/posters/attention.jpg b/learning-outcomes-assessment/assets/posters/attention.jpg new file mode 100644 index 0000000..58b4ecc Binary files /dev/null and b/learning-outcomes-assessment/assets/posters/attention.jpg differ diff --git a/learning-outcomes-assessment/assets/posters/motivation.jpg b/learning-outcomes-assessment/assets/posters/motivation.jpg new file mode 100644 index 0000000..630c8ca Binary files /dev/null and b/learning-outcomes-assessment/assets/posters/motivation.jpg differ diff --git a/learning-outcomes-assessment/assets/posters/outcomes.jpg b/learning-outcomes-assessment/assets/posters/outcomes.jpg new file mode 100644 index 0000000..6f7c733 Binary files /dev/null and b/learning-outcomes-assessment/assets/posters/outcomes.jpg differ diff --git a/learning-outcomes-assessment/assets/posters/teaching.jpg b/learning-outcomes-assessment/assets/posters/teaching.jpg new file mode 100644 index 0000000..01fd69a Binary files /dev/null and b/learning-outcomes-assessment/assets/posters/teaching.jpg differ diff --git a/learning-outcomes-assessment/index.html b/learning-outcomes-assessment/index.html new file mode 100644 index 0000000..4b493d2 --- /dev/null +++ b/learning-outcomes-assessment/index.html @@ -0,0 +1,462 @@ + + + + + + Redesign the Course - A Playable Teaching Essay + + + + + + + + +
+ + RC + Redesign the Course + + +
+ +
+
+
+

A course-design simulation in essay form

+

The Course That Covers Everything

+

+ You inherit a course that looks complete. Students still cannot use it. Your job is to + redesign one course file, and every choice changes the same first class and the same learner. +

+
+ Open the course file + +
+
+ + +
+ +
+ + +
+
+

1 / Diagnose

+

The first problem is not that the course is empty. It is that the course is full.

+

+ The inherited course is familiar: a list of important topics, a lecture for each topic, + and two exams. It looks responsible because nothing obvious is missing. It fails quietly + because the design never says what students should be able to do with the knowledge. +

+ +
+
+

Old plan

+ + + + + + + + +
+ +
+
+

Run the semester

+ +
+
+
+

Before the run, the course looks complete on paper.

+
+
+
+ +
+
+

Course voice

+

The course's central turn

+

+ Teaching becomes design when the object of attention moves from what the teacher + covers to what students learn, practice, and revise. +

+
+ +
+
+ +
+

2 / Outcomes

+

Now write the sentence the course has been avoiding.

+

+ A learning outcome is not a topic. It is a claim about the student's end state: + what the student understands or can do after the course. The sentence has to be + visible enough that activities and assessment can answer to it. +

+ +
+
+

Decision

+

Which outcome can actually design the course?

+

Pick one. Watch what it does to the living course file.

+
+
+ + + +
+
+ No outcome chosen yet. + The course still has topics, not a destination. +
+
+ +
+
+

Retrieval check

+

What does a learning outcome name?

+
+
+ + + +
+

Choose before moving on.

+
+
+ +
+

3 / Alignment

+

Assessment is the hidden course. Students study what the course rewards.

+

+ If the outcome asks students to justify a choice, but the exam rewards definitions, + the actual course is definitions. Alignment is not administrative neatness. It is how + the course tells students where effort belongs. +

+ +
+
+ + + + + + + + outcome + not written + + + + practice + listening + + + + assessment + recall exam + + + + student + effort + + + + feedback + after exam + + +
+ +
+
+

Choose a practice structure

+
+ + + +
+
+ +
+

Choose an assessment signal

+
+ + + +
+
+
+
+ +
+ The hidden course is still recall. + Students will protect marks by memorizing definitions. +
+
+ +
+

4 / Class session

+

A lecture can stay a lecture. It cannot stay a monologue.

+

+ The course's active-learning advice is modest and powerful: every 10 to 15 minutes, + ask students to do something with the idea. Predict, compare, explain, answer, reflect. + The activity is short because it is not replacing the lecture. It is making the lecture learnable. +

+ +
+
+

Choose a move, then place it in the hour

+
+ + + + + +
+
+ +
+
+ + + + + + +
+
+
+ Place an opening problem and two short thinking moves. +
+
+
+ +
+
+

Watch when useful

+

The 15-minute reset

+

+ This clip explains why active lectures use short cycles of attention, activity, + and feedback rather than one long stream of explanation. +

+
+ +
+ +
+
+

Retrieval check

+

If a final exam rewards recall, what will students optimize for?

+
+
+ + + +
+

Choose the signal students can see.

+
+
+ +
+

5 / Feedback

+

Practice without feedback lets mistakes become architecture.

+

+ Formative assessment is valuable because it is frequent, low stakes, and fast enough + to change what students do next. Summative assessment still matters, but it cannot be + the first moment students learn whether their thinking works. +

+ + +
+ +
+

6 / Motivation

+

Motivation is designed through value, expectancy, and support.

+

+ The student has many goals. Your course competes with all of them. Motivation grows + when the outcome has value, the student believes effort can work, and the environment + makes support visible. +

+ +
+
+

Pick the first five minutes of class

+
+ + + +
+
+
+ Maya is waiting to see what this course values. + The opening has not yet told her why effort will be worth it. +
+
+ +
+
+

Retrieval check

+

What three factors shape motivation in this course?

+
+
+ + + +
+

Choose the model that helps a teacher act.

+
+
+ +
+

7 / Launch

+

The redesigned course is not prettier. It is more legible to the learner.

+

+ You now have the pieces of a first class that tells students what matters, gives them + something to do, and shows how feedback will help them improve. The file below is built + from your choices. +

+ +
+
+
+

Your first-class plan

+ +
+

+                

The plan updates as the course file changes.

+
+ +
+

The durable idea

+

Teach by designing what students do, think, practice, and revise.

+

+ Outcomes name the destination. Activities create practice. Assessment sends the + signal. Feedback helps students steer. Motivation keeps effort alive long enough + for knowledge to change. +

+
+
+
+
+
+
+ + diff --git a/learning-outcomes-assessment/script.js b/learning-outcomes-assessment/script.js new file mode 100644 index 0000000..bcd1320 --- /dev/null +++ b/learning-outcomes-assessment/script.js @@ -0,0 +1,616 @@ +/* + * ANIMATION STORYBOARD + * + * 0ms old course run starts, all weeks reset + * 260ms next week activates, student log receives one consequence + * 1200ms active week reaches exam signal, learner state updates + * 2400ms run ends with diagnosis visible in course file + */ +const TIMING = { + oldCourseStep: 260, + feedbackDelay: 900 +}; + +const $ = (selector, root = document) => root.querySelector(selector); +const $$ = (selector, root = document) => Array.from(root.querySelectorAll(selector)); + +const course = { + outcome: null, + practice: null, + assessment: null, + feedback: null, + opening: null, + classMoves: {}, + memory: new Set() +}; + +const labels = { + outcome: { + vague: "understand trees, graphs, and hashing", + usable: "choose and justify a data structure for a stated constraint", + tooBig: "design industrial-scale storage systems from scratch" + }, + practice: { + lecture: "lecture examples only", + compare: "compare structures for a constraint", + debug: "debug a bad choice in pairs" + }, + assessment: { + definitions: "definition-heavy exam", + justify: "scenario justification task", + project: "mini-project with design memo" + }, + feedback: { + late: "after the midterm", + quick: "same-class comparison feedback", + revision: "revision attempt after feedback" + }, + opening: { + rules: "grading rules first", + mystery: "real design failure first", + support: "outcome, practice, and help route first" + }, + move: { + hook: "opening problem", + predict: "prediction", + pair: "pair talk", + quiz: "quick quiz", + paper: "minute paper" + } +}; + +function clamp(value, min, max) { + return Math.max(min, Math.min(max, value)); +} + +function setText(selector, text) { + const node = typeof selector === "string" ? $(selector) : selector; + if (node) node.textContent = text; +} + +function initProgress() { + const bar = $(".progress-line span"); + const update = () => { + const max = document.documentElement.scrollHeight - window.innerHeight; + const percent = max <= 0 ? 0 : (window.scrollY / max) * 100; + bar.style.width = `${clamp(percent, 0, 100)}%`; + }; + update(); + window.addEventListener("scroll", update, { passive: true }); +} + +function initNav() { + const links = $$(".topbar nav a"); + const byId = new Map(links.map((link) => [link.getAttribute("href").slice(1), link])); + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (!entry.isIntersecting) return; + links.forEach((link) => link.classList.remove("active")); + const link = byId.get(entry.target.id); + if (link) link.classList.add("active"); + }); + }, + { rootMargin: "-36% 0px -54% 0px", threshold: 0.01 } + ); + links.forEach((link) => { + const section = $(link.getAttribute("href")); + if (section) observer.observe(section); + }); +} + +function initWeeks() { + const track = $("#weekTrack"); + if (!track) return; + track.replaceChildren(); + for (let i = 1; i <= 12; i += 1) { + const week = document.createElement("div"); + week.className = "week"; + week.textContent = `W${i}`; + track.append(week); + } +} + +function runOldCourse() { + const weeks = $$(".week"); + const log = $("#studentLog"); + const entries = [ + "Week 2: Maya copies the list implementation. It works, but she cannot explain the design choice.", + "Week 5: Trees arrive. The course has moved on before her earlier misconception is visible.", + "Week 8: The midterm asks definitions. Her effort shifts toward remembering names.", + "Week 12: She passes many recall items. Transfer is still fragile." + ]; + weeks.forEach((week) => week.classList.remove("active")); + log.replaceChildren(); + setText(log.appendChild(document.createElement("p")), "The run starts from the topic list."); + + let i = 0; + const timer = window.setInterval(() => { + if (i > 0) weeks[i - 1]?.classList.remove("active"); + if (i >= weeks.length) { + window.clearInterval(timer); + updateLearnerNotes("diagnosed"); + updateCourseFile(); + return; + } + weeks[i].classList.add("active"); + if ([1, 4, 7, 11].includes(i)) { + const p = document.createElement("p"); + p.textContent = entries.shift(); + log.append(p); + } + i += 1; + }, TIMING.oldCourseStep); +} + +function outcomeFeedback(kind) { + const node = $("#outcomeFeedback"); + const messages = { + vague: [ + "This is a topic in disguise.", + "It does not tell you what students must produce, so assessment will drift." + ], + usable: [ + "This can design the course.", + "It names a student action, a judgment, and a realistic course-level capability." + ], + tooBig: [ + "This overpromises.", + "Ambition helps only when students can practice the component skills inside the course." + ] + }; + const [title, detail] = messages[kind]; + node.innerHTML = `${title}${detail}`; +} + +function initOutcomes() { + $$("#outcomeChoices .choice-card").forEach((button) => { + button.addEventListener("click", () => { + $$("#outcomeChoices .choice-card").forEach((item) => item.classList.toggle("selected", item === button)); + course.outcome = button.dataset.outcome; + outcomeFeedback(course.outcome); + updateLearnerNotes("outcome"); + updateCourseFile(); + updateAlignmentMap(); + updatePlan(); + }); + }); +} + +function initAlignmentControls() { + $$("#practiceChoices button").forEach((button) => { + button.addEventListener("click", () => { + $$("#practiceChoices button").forEach((item) => item.classList.toggle("selected", item === button)); + course.practice = button.dataset.practice; + updateAlignmentMap(); + updateLearnerNotes("alignment"); + updateCourseFile(); + updatePlan(); + }); + }); + $$("#assessmentChoices button").forEach((button) => { + button.addEventListener("click", () => { + $$("#assessmentChoices button").forEach((item) => item.classList.toggle("selected", item === button)); + course.assessment = button.dataset.assessment; + updateAlignmentMap(); + updateLearnerNotes("alignment"); + updateCourseFile(); + updatePlan(); + }); + }); +} + +function updateAlignmentMap() { + const outcome = course.outcome ? labels.outcome[course.outcome] : "not written"; + const practice = course.practice ? labels.practice[course.practice] : "listening"; + const assessment = course.assessment ? labels.assessment[course.assessment] : "recall exam"; + const feedback = course.feedback ? labels.feedback[course.feedback] : "after exam"; + + setText("#mapOutcome", shorten(outcome, 24)); + setText("#mapPractice", shorten(practice, 24)); + setText("#mapAssessment", shorten(assessment, 24)); + setText("#mapFeedback", shorten(feedback, 24)); + + const goodOutcome = course.outcome === "usable"; + const goodPractice = course.practice === "compare" || course.practice === "debug"; + const goodAssessment = course.assessment === "justify" || course.assessment === "project"; + const goodFeedback = course.feedback === "quick" || course.feedback === "revision"; + + $(".wire-a")?.classList.toggle("strong", goodOutcome); + $(".wire-b")?.classList.toggle("strong", goodPractice); + $(".wire-c")?.classList.toggle("strong", goodAssessment); + $(".wire-d")?.classList.toggle("strong", goodFeedback); + $(".wire-c")?.classList.toggle("warn", course.assessment === "definitions"); + + const hidden = $("#hiddenCourse"); + if (!course.assessment || course.assessment === "definitions") { + hidden.classList.remove("good"); + hidden.innerHTML = "The hidden course is still recall.Students will protect marks by memorizing definitions."; + } else if (goodOutcome && goodPractice && goodAssessment) { + hidden.classList.add("good"); + hidden.innerHTML = "The hidden course now matches the stated course.Students can see that practice and marks both point toward justified choice."; + } else { + hidden.classList.remove("good"); + hidden.innerHTML = "The signals are mixed.One corner has improved, but students still receive competing messages about effort."; + } +} + +function shorten(text, limit) { + return text.length > limit ? `${text.slice(0, limit - 3)}...` : text; +} + +function initClassBuilder() { + const palette = $$("#movePalette button"); + const slotRow = $("#slotRow"); + let selectedMove = null; + + palette.forEach((button) => { + button.addEventListener("click", () => { + selectedMove = button.dataset.move; + palette.forEach((item) => item.classList.toggle("selected", item === button)); + }); + }); + + slotRow.replaceChildren(); + [0, 10, 20, 30, 40, 50].forEach((minute) => { + const slot = document.createElement("button"); + slot.type = "button"; + slot.className = "slot"; + slot.dataset.minute = String(minute); + slot.textContent = `${minute} min`; + slot.addEventListener("click", () => { + if (!selectedMove) { + setText("#classFeedback", "Choose a move first, then place it in the hour."); + return; + } + course.classMoves[minute] = selectedMove; + slot.classList.add("filled"); + slot.textContent = `${minute}: ${labels.move[selectedMove]}`; + updateAttention(); + updateLearnerNotes("class"); + updateCourseFile(); + updatePlan(); + }); + slotRow.append(slot); + }); + + updateAttention(); +} + +function attentionAt(minute) { + const placed = Object.entries(course.classMoves) + .map(([key, value]) => ({ minute: Number(key), move: value })) + .sort((a, b) => a.minute - b.minute); + const previous = placed.filter((item) => item.minute <= minute).pop(); + const since = previous ? minute - previous.minute : minute; + const reset = previous && since < 5 ? 11 : 0; + const endLift = minute > 54 ? (minute - 54) * 2 : 0; + return clamp(86 - since * 2.15 + reset + endLift, 26, 94); +} + +function updateAttention() { + const path = $("#attentionCurve"); + const markers = $("#attentionMarkers"); + if (!path || !markers) return; + const points = []; + for (let minute = 0; minute <= 60; minute += 2) { + const x = 42 + (minute / 60) * 700; + const y = 232 - (attentionAt(minute) / 100) * 190; + points.push(`${x},${y}`); + } + path.setAttribute("d", `M ${points.join(" L ")}`); + markers.replaceChildren(); + Object.entries(course.classMoves).forEach(([minute, move]) => { + const x = 42 + (Number(minute) / 60) * 700; + const y = 232 - (attentionAt(Number(minute)) / 100) * 190; + const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle"); + circle.setAttribute("cx", x); + circle.setAttribute("cy", y); + circle.setAttribute("r", 8); + const text = document.createElementNS("http://www.w3.org/2000/svg", "text"); + text.setAttribute("x", x); + text.setAttribute("y", y - 15); + text.setAttribute("text-anchor", "middle"); + text.textContent = labels.move[move]; + markers.append(circle, text); + }); + const moves = Object.values(course.classMoves); + const hasHook = moves.includes("hook"); + const thinkingMoves = moves.filter((move) => ["predict", "pair", "quiz", "paper"].includes(move)).length; + if (hasHook && thinkingMoves >= 2) { + setText("#classFeedback", "This hour now asks students to predict, explain, or retrieve before the idea goes cold."); + } else if (thinkingMoves >= 1) { + setText("#classFeedback", "Good start. Add one more thinking move so the middle of the hour does not sag."); + } else { + setText("#classFeedback", "Place an opening problem and two short thinking moves."); + } +} + +function initFeedbackLab() { + const bars = $("#persistenceBars"); + bars.replaceChildren(); + ["same day", "one week", "midterm"].forEach((label) => { + const row = document.createElement("div"); + row.className = "persistence-row"; + row.innerHTML = `${label}
`; + bars.append(row); + }); + updatePersistence("late"); + + $$(".feedback-choices button").forEach((button) => { + button.addEventListener("click", () => { + $$(".feedback-choices button").forEach((item) => item.classList.toggle("selected", item === button)); + course.feedback = button.dataset.feedback; + updatePersistence(course.feedback); + updateAlignmentMap(); + updateLearnerNotes("feedback"); + updateCourseFile(); + updatePlan(); + }); + }); +} + +function updatePersistence(kind) { + const levels = { + late: [80, 72, 58], + quick: [58, 30, 18], + revision: [62, 24, 10] + }; + $$(".bar-shell span").forEach((bar, index) => { + bar.style.setProperty("--amount", `${levels[kind][index]}%`); + bar.style.background = kind === "late" ? "var(--coral)" : "var(--teal)"; + }); +} + +function initOpening() { + $$("#openingChoices button").forEach((button) => { + button.addEventListener("click", () => { + $$("#openingChoices button").forEach((item) => item.classList.toggle("selected", item === button)); + course.opening = button.dataset.opening; + const response = $("#motivationResponse"); + if (course.opening === "rules") { + response.classList.remove("good"); + response.innerHTML = "Maya hears that marks matter.Value, expectancy, and support are still mostly implicit."; + } else if (course.opening === "mystery") { + response.classList.add("good"); + response.innerHTML = "Maya sees value first.The opening gives the outcome a reason to exist before naming the machinery."; + } else { + response.classList.add("good"); + response.innerHTML = "Maya sees the route.The opening joins value with expectancy: here is the goal, the practice path, and where help lives."; + } + updateLearnerNotes("motivation"); + updateCourseFile(); + updatePlan(); + }); + }); +} + +function initMemoryChecks() { + $$(".memory-check").forEach((check) => { + $$("button", check).forEach((button) => { + button.addEventListener("click", () => { + $$("button", check).forEach((item) => item.classList.remove("correct", "incorrect")); + const isRight = button.dataset.answer === "right"; + button.classList.add(isRight ? "correct" : "incorrect"); + const feedback = $(".check-feedback", check); + if (isRight) { + course.memory.add(check.dataset.check); + feedback.textContent = "Settled. This will show up in the course file."; + } else { + feedback.textContent = "Not yet. Try the option that changes what the teacher designs next."; + } + updateCourseFile(); + }); + }); + }); +} + +function updateLearnerNotes(stage) { + const notes = { + diagnosed: [ + "She can repeat definitions after lecture.", + "She waits until the exam to find out what counts.", + "She cannot yet transfer the ideas to a new problem." + ], + outcome: [ + course.outcome === "usable" ? "She can see the course is about justified choices, not names alone." : "The destination is still hard to recognize from a student's seat.", + "She needs practice that matches the promise.", + "The exam will decide what she actually studies." + ], + alignment: [ + course.practice === "compare" || course.practice === "debug" ? "She has a place to practice choosing, not just hearing." : "She is still mostly watching someone else reason.", + course.assessment === "justify" || course.assessment === "project" ? "Marks now reward the capability the outcome names." : "The visible reward still points toward recall.", + "Alignment is becoming a message she can read." + ], + class: [ + Object.values(course.classMoves).length >= 3 ? "She has to predict, explain, and retrieve during class." : "The class has started to ask for thinking, but the rhythm is still thin.", + "Short tasks make confusion visible before the exam.", + "Attention is being used as a design material." + ], + feedback: [ + course.feedback === "late" ? "Her misconception survives until the midterm." : "Her misconception gets interrupted while it is still fixable.", + "Feedback now changes the next attempt, not just the grade record.", + "Formative work has become part of teaching." + ], + motivation: [ + course.opening === "rules" ? "She hears the grading system first." : "She sees why the outcome matters before the syllabus details.", + course.opening === "support" ? "She also sees how effort can succeed." : "Support still needs to be named clearly.", + "Motivation is being designed, not wished for." + ] + }; + const list = $("#learnerNotes"); + list.replaceChildren(); + notes[stage].forEach((note) => { + const item = document.createElement("li"); + item.textContent = note; + list.append(item); + }); +} + +function designLevels() { + let use = 22; + let confidence = 18; + let transfer = 14; + if (course.outcome === "usable") { + use += 18; + transfer += 16; + } else if (course.outcome) { + use += 6; + } + if (course.practice === "compare" || course.practice === "debug") { + use += 16; + transfer += 14; + } + if (course.assessment === "justify" || course.assessment === "project") { + use += 16; + confidence += 14; + transfer += 12; + } + if (Object.values(course.classMoves).length >= 3) { + confidence += 14; + use += 10; + } + if (course.feedback === "quick" || course.feedback === "revision") { + confidence += 18; + transfer += 10; + } + if (course.opening === "mystery" || course.opening === "support") { + confidence += 10; + use += 8; + } + return { + use: clamp(use, 8, 96), + confidence: clamp(confidence, 8, 96), + transfer: clamp(transfer, 8, 96) + }; +} + +function updateCourseFile() { + setText("#spineOutcome", course.outcome ? labels.outcome[course.outcome] : "not yet written"); + setText("#spinePractice", course.practice ? labels.practice[course.practice] : "mostly listening"); + setText("#spineAssessment", course.assessment ? labels.assessment[course.assessment] : "midterm plus final"); + setText("#spineFeedback", course.feedback ? labels.feedback[course.feedback] : "late and scarce"); + setText("#spineMotivation", course.opening ? labels.opening[course.opening] : "grades carry the message"); + + const levels = designLevels(); + $("#meterUse").style.setProperty("--fill", `${levels.use}%`); + $("#meterConfidence").style.setProperty("--fill", `${levels.confidence}%`); + $("#meterTransfer").style.setProperty("--fill", `${levels.transfer}%`); + + const memory = $("#memoryTrace"); + memory.replaceChildren(); + if (course.memory.size === 0) { + const span = document.createElement("span"); + span.textContent = "0 checks settled"; + memory.append(span); + } else { + course.memory.forEach((check) => { + const span = document.createElement("span"); + span.className = "settled"; + span.textContent = check; + memory.append(span); + }); + } + + const aligned = + course.outcome === "usable" && + (course.practice === "compare" || course.practice === "debug") && + (course.assessment === "justify" || course.assessment === "project") && + (course.feedback === "quick" || course.feedback === "revision"); + if (aligned) { + setText("#fileStatus", "The course now gives students one coherent message."); + } else if (course.outcome || course.practice || course.assessment || course.feedback || course.opening) { + setText("#fileStatus", "The course is improving, but at least one signal still needs work."); + } else { + setText("#fileStatus", "Topic coverage is still driving the course."); + } +} + +function updatePlan() { + const moves = Object.entries(course.classMoves) + .sort((a, b) => Number(a[0]) - Number(b[0])) + .map(([minute, move]) => `${minute} min: ${labels.move[move]}`); + const plan = `Data Structures I - first class redesign + +Learning outcome +${course.outcome ? labels.outcome[course.outcome] : "Write one observable course outcome before class."} + +Opening +${course.opening ? labels.opening[course.opening] : "Open by showing why the outcome matters to a real design problem."} + +In-class practice +${moves.length ? moves.join("\n") : "0 min: opening problem\n15 min: prediction\n30 min: think-pair-share\n45 min: one-minute quiz"} + +Assessment signal +${course.assessment ? labels.assessment[course.assessment] : "Use a scenario task that asks students to justify a structure."} + +Feedback route +${course.feedback ? labels.feedback[course.feedback] : "Give quick formative feedback before the first high-stakes exam."} + +Teacher check +Students should leave knowing what they are trying to learn, how they will practice it, how it will be assessed, and where to get help.`; + setText("#finalPlan", plan); +} + +function initCopy() { + $("#copyPlan")?.addEventListener("click", async () => { + try { + await navigator.clipboard.writeText($("#finalPlan").textContent); + setText("#copyStatus", "Copied."); + } catch { + const range = document.createRange(); + range.selectNodeContents($("#finalPlan")); + const selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(range); + setText("#copyStatus", "Selected the plan text."); + } + }); +} + +function initReset() { + $$("[data-action='reset']").forEach((button) => { + button.addEventListener("click", () => { + course.outcome = null; + course.practice = null; + course.assessment = null; + course.feedback = null; + course.opening = null; + course.classMoves = {}; + course.memory.clear(); + $$(".selected, .correct, .incorrect, .filled").forEach((node) => node.classList.remove("selected", "correct", "incorrect", "filled")); + $$(".slot").forEach((slot) => { + slot.textContent = `${slot.dataset.minute} min`; + }); + updateLearnerNotes("diagnosed"); + updateAlignmentMap(); + updateAttention(); + updatePersistence("late"); + updateCourseFile(); + updatePlan(); + setText("#classFeedback", "Place an opening problem and two short thinking moves."); + $("#outcomeFeedback").innerHTML = "No outcome chosen yet.The course still has topics, not a destination."; + $("#motivationResponse").innerHTML = "Maya is waiting to see what this course values.The opening has not yet told her why effort will be worth it."; + $("#hiddenCourse").innerHTML = "The hidden course is still recall.Students will protect marks by memorizing definitions."; + }); + }); +} + +document.addEventListener("DOMContentLoaded", () => { + initProgress(); + initNav(); + initWeeks(); + initOutcomes(); + initAlignmentControls(); + initClassBuilder(); + initFeedbackLab(); + initOpening(); + initMemoryChecks(); + initCopy(); + initReset(); + $("#runOldCourse")?.addEventListener("click", runOldCourse); + updateLearnerNotes("diagnosed"); + updateAlignmentMap(); + updateCourseFile(); + updatePlan(); +}); diff --git a/learning-outcomes-assessment/styles.css b/learning-outcomes-assessment/styles.css new file mode 100644 index 0000000..94301eb --- /dev/null +++ b/learning-outcomes-assessment/styles.css @@ -0,0 +1,1277 @@ +:root { + --canvas: #f3efe7; + --surface: #fffcf5; + --surface-2: #e9e1d4; + --ink: #20272a; + --ink-2: #4c585c; + --muted: #6f7b7e; + --line: rgba(32, 39, 42, 0.14); + --line-strong: rgba(32, 39, 42, 0.26); + --teal: #0c766f; + --teal-soft: #d6efeb; + --blue: #315b72; + --blue-soft: #dce8ef; + --coral: #bd5a3c; + --coral-soft: #f2dcd2; + --gold: #a77720; + --gold-soft: #f0dfb8; + --green: #557a4d; + --green-soft: #deead8; + --plum: #6d4b64; + --shadow: 0 18px 44px rgba(54, 44, 32, 0.12); + --radius: 8px; + --z-header: 30; + --z-file: 10; + --ease-out: cubic-bezier(0.165, 0.84, 0.44, 1); + --ease-move: cubic-bezier(0.77, 0, 0.175, 1); + color-scheme: light; +} + +* { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + margin: 0; + background: + linear-gradient(90deg, rgba(32, 39, 42, 0.04) 1px, transparent 1px), + linear-gradient(rgba(32, 39, 42, 0.03) 1px, transparent 1px), + var(--canvas); + background-size: 36px 36px; + color: var(--ink); + font-family: + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + sans-serif; + line-height: 1.55; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} + +body::before { + content: ""; + position: fixed; + inset: 0; + z-index: -1; + pointer-events: none; + background: + linear-gradient(180deg, rgba(243, 239, 231, 0.1), rgba(243, 239, 231, 0.94) 42%), + linear-gradient(124deg, rgba(12, 118, 111, 0.08), transparent 38%, rgba(189, 90, 60, 0.07) 72%, transparent); +} + +button, +input, +select { + font: inherit; +} + +button, +a { + touch-action: manipulation; +} + +button { + border: 0; + cursor: pointer; +} + +button:focus-visible, +a:focus-visible, +pre:focus-visible { + outline: 2px solid var(--ink); + outline-offset: 3px; +} + +h1, +h2, +h3, +p { + margin: 0; +} + +h1, +h2 { + font-family: Georgia, "Times New Roman", serif; + line-height: 1.04; + text-wrap: balance; +} + +h1 { + max-width: 12ch; + font-size: clamp(3.05rem, 5.9vw, 6.2rem); +} + +h2 { + max-width: 13ch; + font-size: clamp(2.25rem, 4.7vw, 4.8rem); +} + +h3 { + line-height: 1.16; + font-size: clamp(1.1rem, 1.6vw, 1.45rem); + text-wrap: balance; +} + +a { + color: inherit; + text-decoration-thickness: 1px; + text-underline-offset: 4px; +} + +video { + display: block; + width: 100%; + aspect-ratio: 16 / 9; + object-fit: cover; + background: #11191c; +} + +.skip-link { + position: fixed; + top: 12px; + left: 12px; + z-index: 60; + transform: translateY(-140%); + border-radius: 6px; + background: var(--ink); + color: var(--surface); + padding: 10px 14px; + text-decoration: none; + transition: transform 180ms var(--ease-out); +} + +.skip-link:focus { + transform: translateY(0); +} + +.progress-line { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 50; + height: 4px; + background: rgba(32, 39, 42, 0.08); +} + +.progress-line span { + display: block; + width: 0; + height: 100%; + background: linear-gradient(90deg, var(--teal), var(--gold), var(--coral)); +} + +.topbar { + position: sticky; + top: 4px; + z-index: var(--z-header); + display: grid; + grid-template-columns: auto 1fr; + align-items: center; + gap: 22px; + width: min(1240px, calc(100% - 28px)); + min-height: 62px; + margin: 10px auto 0; + padding: 9px 12px; + border-radius: var(--radius); + background: rgba(255, 252, 245, 0.9); + box-shadow: 0 0 0 1px var(--line), 0 12px 34px rgba(54, 44, 32, 0.09); + backdrop-filter: blur(14px); +} + +.brand { + display: inline-flex; + align-items: center; + gap: 10px; + min-height: 44px; + color: var(--ink); + font-weight: 760; + text-decoration: none; +} + +.mark { + display: grid; + place-items: center; + width: 38px; + height: 38px; + border-radius: 6px; + background: var(--ink); + color: var(--surface); + font-size: 0.82rem; + font-weight: 820; +} + +.topbar nav { + display: flex; + justify-content: flex-end; + gap: 4px; + overflow-x: auto; +} + +.topbar nav a { + display: inline-flex; + align-items: center; + min-height: 44px; + padding: 0 10px; + border-radius: 6px; + color: var(--ink-2); + font-weight: 680; + text-decoration: none; + white-space: nowrap; +} + +.topbar nav a.active { + background: rgba(12, 118, 111, 0.1); + color: var(--teal); +} + +.scene, +.chapter { + padding-inline: max(20px, calc((100vw - 1240px) / 2)); +} + +.hero { + display: grid; + grid-template-columns: minmax(0, 0.96fr) minmax(420px, 1.04fr); + align-items: center; + gap: clamp(28px, 6vw, 72px); + min-height: calc(100dvh - 112px); + padding-top: clamp(24px, 5vw, 52px); + padding-bottom: clamp(42px, 6vw, 66px); + overflow: clip; +} + +.hero-copy { + display: grid; + gap: 22px; +} + +.eyebrow, +.section-number { + color: var(--plum); + font-size: 0.78rem; + font-weight: 820; + letter-spacing: 0; + text-transform: uppercase; +} + +.lede { + max-width: 58ch; + color: var(--ink-2); + font-size: clamp(1.08rem, 1.7vw, 1.34rem); +} + +.hero-actions { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-top: 6px; +} + +.primary-link, +.ghost-link, +.choice-card, +.select-list button, +.move-list button, +.slot, +.memory-check button, +.feedback-choices button, +#runOldCourse, +#copyPlan, +.topic-pill { + min-height: 44px; + border-radius: 7px; + font-weight: 740; + transition: + transform 140ms var(--ease-out), + background-color 150ms ease, + color 150ms ease, + box-shadow 150ms ease; +} + +.primary-link, +#runOldCourse, +#copyPlan { + display: inline-flex; + align-items: center; + justify-content: center; + background: var(--ink); + color: var(--surface); + padding: 11px 15px; + text-decoration: none; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08); +} + +.ghost-link { + background: rgba(32, 39, 42, 0.08); + color: var(--ink); + padding: 11px 15px; +} + +@media (hover: hover) and (pointer: fine) { + .primary-link:hover, + .ghost-link:hover, + .choice-card:hover, + .select-list button:hover, + .move-list button:hover, + .slot:hover, + .memory-check button:hover, + .feedback-choices button:hover, + #runOldCourse:hover, + #copyPlan:hover, + .topic-pill:hover { + transform: translateY(-1px); + } +} + +button:active, +.primary-link:active { + transform: scale(0.98); +} + +.hero-art { + position: relative; + min-height: min(500px, 58vw); +} + +.folder { + position: relative; + min-height: min(500px, 58vw); + border-radius: var(--radius); + background: + linear-gradient(180deg, rgba(255, 252, 245, 0.94), rgba(233, 225, 212, 0.82)), + linear-gradient(90deg, rgba(49, 91, 114, 0.08), rgba(12, 118, 111, 0.08)); + box-shadow: var(--shadow), 0 0 0 1px var(--line); + overflow: hidden; +} + +.folder::before { + content: ""; + position: absolute; + left: 48px; + top: 112px; + right: 48px; + height: 1px; + background: var(--line); +} + +.folder-tab { + position: absolute; + left: 42px; + top: 38px; + border-radius: 8px 8px 0 0; + background: var(--blue); + color: var(--surface); + padding: 13px 18px; + font-weight: 780; +} + +.folder-page { + position: absolute; + display: grid; + gap: 10px; + width: min(300px, 44%); + border-radius: var(--radius); + background: var(--surface); + padding: 18px; + box-shadow: 0 12px 30px rgba(54, 44, 32, 0.14), 0 0 0 1px var(--line); +} + +.folder-page strong { + margin-bottom: 6px; +} + +.folder-page span { + border-radius: 5px; + background: rgba(49, 91, 114, 0.1); + padding: 8px 10px; + color: var(--ink-2); + font-weight: 680; +} + +.page-a { + left: 58px; + top: 138px; + transform: rotate(-2deg); +} + +.page-b { + right: 58px; + top: 174px; + transform: rotate(2deg); +} + +.page-b span { + background: var(--teal-soft); + color: #0b5f59; +} + +.learner-note { + position: absolute; + left: 50%; + bottom: 36px; + display: grid; + gap: 6px; + width: min(410px, calc(100% - 64px)); + transform: translateX(-50%); + border-left: 5px solid var(--coral); + border-radius: 0 8px 8px 0; + background: #fff5e8; + padding: 16px; + box-shadow: 0 0 0 1px var(--line); +} + +.learner-note span { + color: var(--ink-2); +} + +.experience-shell { + display: grid; + grid-template-columns: minmax(280px, 360px) minmax(0, 1fr); + gap: clamp(28px, 5vw, 60px); + align-items: start; + width: min(1240px, calc(100% - 40px)); + margin: 0 auto; +} + +.course-file { + position: sticky; + top: 86px; + z-index: var(--z-file); + display: grid; + gap: 18px; + max-height: calc(100dvh - 104px); + overflow: auto; + border-radius: var(--radius); + background: rgba(255, 252, 245, 0.94); + padding: 20px; + box-shadow: var(--shadow), 0 0 0 1px var(--line); +} + +.file-head { + display: grid; + gap: 8px; +} + +.file-head h2 { + max-width: none; + font-size: 1.6rem; +} + +.file-head p:last-child { + color: var(--ink-2); +} + +.file-section { + display: grid; + gap: 12px; + padding-top: 16px; + border-top: 1px solid var(--line); +} + +.file-section h3 { + font-size: 1rem; +} + +.spine-list { + display: grid; + gap: 10px; + margin: 0; +} + +.spine-list div { + display: grid; + grid-template-columns: 84px 1fr; + gap: 10px; + align-items: start; +} + +.spine-list dt { + color: var(--muted); + font-size: 0.86rem; + font-weight: 760; +} + +.spine-list dd { + margin: 0; + color: var(--ink); + font-size: 0.94rem; + font-weight: 680; +} + +.learner-state { + display: grid; + gap: 12px; +} + +.state-meter { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 6px; +} + +.state-meter span { + position: relative; + min-height: 64px; + overflow: hidden; + border-radius: 6px; + background: rgba(32, 39, 42, 0.08); + box-shadow: inset 0 0 0 1px rgba(32, 39, 42, 0.06); +} + +.state-meter span::before { + content: ""; + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: var(--fill, 22%); + background: var(--bar, var(--teal)); + transition: height 300ms var(--ease-move); +} + +#meterUse { --bar: var(--teal); --fill: 28%; } +#meterConfidence { --bar: var(--gold); --fill: 20%; } +#meterTransfer { --bar: var(--coral); --fill: 16%; } + +.learner-state ul, +.found-list { + display: grid; + gap: 8px; + margin: 0; + padding: 0; + list-style: none; +} + +.learner-state li { + border-radius: 6px; + background: rgba(32, 39, 42, 0.05); + padding: 9px 10px; + color: var(--ink-2); + font-size: 0.92rem; +} + +.memory-row { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.memory-row span { + border-radius: 999px; + background: rgba(32, 39, 42, 0.07); + padding: 6px 9px; + color: var(--ink-2); + font-size: 0.86rem; + font-weight: 720; +} + +.memory-row span.settled { + background: var(--green-soft); + color: var(--green); +} + +.story { + min-width: 0; +} + +.chapter { + padding: clamp(76px, 11vw, 136px) 0; + border-top: 1px solid rgba(32, 39, 42, 0.1); +} + +.chapter:first-child { + border-top: 0; + padding-top: 18px; +} + +.chapter > p:not(.section-number), +.chapter > h2 { + max-width: 760px; +} + +.chapter > p:not(.section-number) { + margin-top: 18px; + color: var(--ink-2); + font-size: clamp(1.04rem, 1.45vw, 1.22rem); +} + +.section-number { + margin-bottom: 14px; + color: var(--coral); +} + +.old-course-lab, +.decision-lab, +.alignment-studio, +.class-builder, +.feedback-lab, +.opening-lab, +.launch-board, +.instructor-note, +.memory-check { + margin-top: clamp(28px, 5vw, 48px); +} + +.old-course-lab { + display: grid; + grid-template-columns: minmax(220px, 0.85fr) minmax(360px, 1.15fr); + gap: 18px; + align-items: stretch; +} + +.topic-board, +.semester-sim, +.prompt-card, +.decision-feedback, +.wire-map, +.alignment-controls, +.move-palette, +.hour-stage, +.misconception-board, +.feedback-choices, +.opening-scene, +.motivation-response, +.plan-panel, +.closing-claim { + border-radius: var(--radius); + background: rgba(255, 252, 245, 0.94); + padding: 18px; + box-shadow: 0 0 0 1px var(--line); +} + +.topic-board { + display: flex; + flex-wrap: wrap; + align-content: start; + gap: 10px; +} + +.topic-board h3 { + flex: 0 0 100%; +} + +.topic-pill { + background: var(--blue-soft); + color: #244a5e; + padding: 9px 11px; +} + +.semester-sim { + display: grid; + gap: 16px; +} + +.sim-head, +.panel-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; +} + +.week-track { + display: grid; + grid-template-columns: repeat(12, 1fr); + gap: 5px; +} + +.week { + display: grid; + place-items: center; + min-height: 58px; + border-radius: 5px; + background: rgba(49, 91, 114, 0.08); + color: var(--muted); + font-size: 0.78rem; + font-weight: 780; +} + +.week.active { + background: var(--coral-soft); + color: #8f3d28; + animation: flashWeek 500ms var(--ease-out); +} + +.student-log { + min-height: 132px; + border-radius: 7px; + background: #fff6e7; + padding: 14px; + color: var(--ink-2); + box-shadow: inset 0 0 0 1px var(--line); +} + +.student-log p + p { + margin-top: 10px; +} + +.instructor-note { + display: grid; + grid-template-columns: minmax(0, 0.84fr) minmax(320px, 1.16fr); + gap: 18px; + align-items: center; + border-radius: var(--radius); + background: #192326; + color: var(--surface); + padding: 20px; +} + +.instructor-note p:not(.eyebrow) { + color: rgba(255, 252, 245, 0.78); +} + +.instructor-note video { + border-radius: 7px; +} + +.compact-note { + grid-template-columns: minmax(0, 1fr) minmax(260px, 0.9fr); +} + +.decision-lab { + display: grid; + grid-template-columns: minmax(220px, 0.72fr) minmax(360px, 1.28fr); + gap: 18px; +} + +.prompt-card { + display: grid; + align-content: start; + gap: 12px; + background: #192326; + color: var(--surface); +} + +.prompt-card p { + color: rgba(255, 252, 245, 0.78); +} + +.choice-grid { + display: grid; + gap: 10px; +} + +.choice-card { + display: grid; + gap: 6px; + width: 100%; + border: 1px solid transparent; + background: var(--surface); + color: var(--ink); + padding: 15px; + text-align: left; + box-shadow: 0 0 0 1px var(--line); +} + +.choice-card span { + font-size: 1.04rem; +} + +.choice-card small { + color: var(--muted); +} + +.choice-card.selected { + background: var(--teal-soft); + color: #074f4a; + box-shadow: 0 0 0 2px var(--teal); +} + +.decision-feedback, +.hidden-course, +.class-feedback, +.motivation-response { + display: grid; + gap: 6px; + min-height: 94px; + border-left: 5px solid var(--coral); + background: #fff6e7; + color: var(--ink-2); +} + +.decision-feedback strong, +.hidden-course strong, +.motivation-response strong { + color: var(--ink); +} + +.memory-check { + display: grid; + grid-template-columns: minmax(220px, 0.74fr) minmax(360px, 1.26fr); + gap: 18px; + align-items: start; + border-radius: var(--radius); + background: linear-gradient(90deg, rgba(12, 118, 111, 0.1), rgba(49, 91, 114, 0.08)); + padding: 18px; + box-shadow: 0 0 0 1px var(--line); +} + +.check-options { + display: grid; + gap: 10px; +} + +.memory-check button { + background: var(--surface); + color: var(--ink); + padding: 12px; + text-align: left; + box-shadow: 0 0 0 1px var(--line); +} + +.memory-check button.correct { + background: var(--green-soft); + color: var(--green); + box-shadow: 0 0 0 2px var(--green); +} + +.memory-check button.incorrect { + background: var(--coral-soft); + color: #8f3d28; +} + +.check-feedback { + grid-column: 2; + color: var(--ink-2); +} + +.alignment-studio { + display: grid; + grid-template-columns: minmax(380px, 1.2fr) minmax(270px, 0.8fr); + gap: 18px; + align-items: stretch; +} + +.wire-map { + min-height: 440px; +} + +#wireSvg { + display: block; + width: 100%; + height: auto; +} + +.wire { + stroke: rgba(32, 39, 42, 0.18); + stroke-width: 5; + stroke-linecap: round; +} + +.wire.strong { + stroke: var(--teal); +} + +.wire.warn { + stroke: var(--coral); + stroke-dasharray: 12 12; +} + +.node rect, +.node circle { + fill: var(--surface); + stroke: var(--line-strong); + stroke-width: 2; +} + +.node text { + fill: var(--ink); + font-size: 18px; + font-weight: 760; +} + +.node text + text { + fill: var(--muted); + font-size: 15px; + font-weight: 680; +} + +.alignment-controls { + display: grid; + align-content: start; + gap: 22px; +} + +.select-list, +.move-list, +.feedback-choices { + display: grid; + gap: 10px; + margin-top: 12px; +} + +.select-list button, +.move-list button, +.feedback-choices button { + background: var(--surface); + color: var(--ink); + padding: 12px 13px; + text-align: left; + box-shadow: 0 0 0 1px var(--line); +} + +.select-list button.selected, +.move-list button.selected, +.feedback-choices button.selected { + background: var(--teal-soft); + color: #074f4a; + box-shadow: 0 0 0 2px var(--teal); +} + +.hidden-course { + margin-top: 18px; + padding: 16px; +} + +.hidden-course.good { + border-left-color: var(--teal); + background: var(--teal-soft); +} + +.class-builder { + display: grid; + grid-template-columns: minmax(220px, 0.7fr) minmax(420px, 1.3fr); + gap: 18px; +} + +.move-palette, +.hour-stage { + min-height: 420px; +} + +.attention-plot { + border-radius: var(--radius); + background: #fff6e7; + box-shadow: inset 0 0 0 1px var(--line); +} + +#attentionSvg { + display: block; + width: 100%; + height: auto; +} + +#attentionSvg line { + stroke: rgba(32, 39, 42, 0.18); + stroke-width: 2; +} + +#attentionCurve { + fill: none; + stroke: var(--coral); + stroke-width: 6; + stroke-linecap: round; + stroke-linejoin: round; +} + +#attentionMarkers circle { + fill: var(--teal); + stroke: var(--surface); + stroke-width: 4; +} + +#attentionMarkers text { + fill: var(--ink); + font-size: 13px; + font-weight: 780; +} + +.slot-row { + display: grid; + grid-template-columns: repeat(6, 1fr); + gap: 7px; + margin-top: 14px; +} + +.slot { + display: grid; + place-items: center; + min-height: 74px; + background: rgba(49, 91, 114, 0.09); + color: var(--ink-2); + padding: 8px; + text-align: center; + box-shadow: 0 0 0 1px var(--line); +} + +.slot.filled { + background: var(--teal-soft); + color: #074f4a; + box-shadow: 0 0 0 2px rgba(12, 118, 111, 0.48); +} + +.class-feedback { + margin-top: 14px; + padding: 14px; +} + +.feedback-lab, +.opening-lab, +.launch-board { + display: grid; + grid-template-columns: minmax(320px, 1fr) minmax(320px, 1fr); + gap: 18px; +} + +.misconception-board, +.feedback-choices, +.opening-scene, +.motivation-response { + min-height: 300px; +} + +.bug-line { + margin-top: 16px; + border-radius: 7px; + background: #fff6e7; + padding: 14px; + color: var(--ink); + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-weight: 740; +} + +.persistence-bars { + display: grid; + gap: 8px; + margin-top: 20px; +} + +.persistence-row { + display: grid; + grid-template-columns: 74px 1fr; + align-items: center; + gap: 10px; +} + +.persistence-row span:first-child { + color: var(--muted); + font-size: 0.86rem; + font-weight: 760; +} + +.bar-shell { + height: 18px; + overflow: hidden; + border-radius: 999px; + background: rgba(32, 39, 42, 0.08); +} + +.bar-shell span { + display: block; + width: var(--amount, 70%); + height: 100%; + border-radius: inherit; + background: var(--coral); + transition: width 300ms var(--ease-move); +} + +.motivation-response { + padding: 18px; +} + +.motivation-response.good { + border-left-color: var(--teal); + background: var(--teal-soft); +} + +.plan-panel { + min-height: 480px; +} + +pre { + min-height: 340px; + overflow: auto; + margin: 16px 0 0; + border-radius: var(--radius); + background: #172226; + color: #fff8ec; + padding: 18px; + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 0.94rem; + line-height: 1.62; + white-space: pre-wrap; +} + +.copy-status { + margin-top: 10px; + color: var(--muted); + font-size: 0.92rem; +} + +.closing-claim { + display: grid; + align-content: center; + gap: 14px; + background: #192326; + color: var(--surface); +} + +.closing-claim h3 { + font-family: Georgia, "Times New Roman", serif; + font-size: clamp(1.9rem, 3.2vw, 3.25rem); +} + +.closing-claim p:not(.eyebrow) { + color: rgba(255, 252, 245, 0.78); +} + +.final-chapter { + padding-bottom: clamp(90px, 14vw, 150px); +} + +@keyframes flashWeek { + 0% { + transform: scale(0.96); + } + 100% { + transform: scale(1); + } +} + +@media (max-width: 1080px) { + .hero, + .experience-shell, + .old-course-lab, + .decision-lab, + .alignment-studio, + .class-builder, + .feedback-lab, + .opening-lab, + .launch-board, + .instructor-note, + .memory-check { + grid-template-columns: 1fr; + } + + .experience-shell { + width: min(860px, calc(100% - 32px)); + } + + .course-file { + position: relative; + top: auto; + max-height: none; + } + + .check-feedback { + grid-column: auto; + } + + .hero-art { + min-height: 440px; + } + + .folder { + min-height: 440px; + } +} + +@media (max-width: 720px) { + .topbar { + grid-template-columns: 1fr; + gap: 6px; + width: calc(100% - 18px); + } + + .topbar nav { + justify-content: flex-start; + } + + .brand span:last-child { + display: none; + } + + .hero { + min-height: auto; + padding-top: 28px; + } + + h1 { + font-size: clamp(3rem, 15vw, 4.6rem); + } + + h2 { + font-size: clamp(2rem, 10vw, 3.3rem); + } + + .hero-art { + min-height: 520px; + } + + .folder { + min-height: 520px; + } + + .folder-page { + width: calc(100% - 54px); + } + + .page-a { + left: 24px; + top: 112px; + } + + .page-b { + right: 24px; + top: 245px; + } + + .learner-note { + bottom: 24px; + width: calc(100% - 44px); + } + + .scene, + .chapter { + padding-inline: 16px; + } + + .experience-shell { + width: calc(100% - 24px); + } + + .spine-list div { + grid-template-columns: 1fr; + gap: 2px; + } + + .week-track, + .slot-row { + grid-template-columns: repeat(3, 1fr); + } + + .wire-map { + overflow-x: auto; + } + + #wireSvg { + min-width: 620px; + } + + .sim-head, + .panel-head { + align-items: stretch; + flex-direction: column; + } +} + +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto; + } + + *, + *::before, + *::after { + animation: none; + transition: none; + } +}