From 2e1b8d24f90774ef80ee3341afa06c787560d53b Mon Sep 17 00:00:00 2001 From: Shane Maynard Date: Sun, 9 Aug 2026 10:06:30 -0400 Subject: [PATCH] Academy v3: screenshot-verified scenes, transform-override fix, hero bean-journey slide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of the broken diagrams found and fixed: CSS transform animations were overriding the SVG positioning transform on the same element, throwing animated elements (beans, flames) to the canvas origin — the bean/flame helpers now split position (outer group) from animation (inner group). Every scene was then rendered in headless Chromium and screenshot- inspected, with fixes applied and re-verified: drying-scene label collision, RoR ideal-line label overlap, first-crack dot off the curve, composition bar stagger orphaning its labels, moka flame hidden behind the base. New opening slide (user request): 'The whole journey, in one bean' — a large bean on a 14-second loop living the full roast (heat in, drying steam out, green→yellow→brown, pressure swell, crack) synced to a stage timeline with a riding marker; narrated like the rest. Co-Authored-By: Claude Fable 5 --- public/academy-audio/rj-journey.mp3 | Bin 0 -> 106848 bytes public/app.css | 30 ++ public/js/academy-content.js | 7 + public/js/academy-scenes.js | 551 ++++++++++++++++++++++++++++ public/js/academy.js | 506 +------------------------ 5 files changed, 590 insertions(+), 504 deletions(-) create mode 100644 public/academy-audio/rj-journey.mp3 create mode 100644 public/js/academy-scenes.js diff --git a/public/academy-audio/rj-journey.mp3 b/public/academy-audio/rj-journey.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..1252330e2b09e86b728bf258c584d7e60495971c GIT binary patch literal 106848 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

NTQ$^b4uq>Rk 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 literal 0 HcmV?d00001 diff --git a/public/app.css b/public/app.css index 3be283d..ca9e797 100644 --- a/public/app.css +++ b/public/app.css @@ -3270,3 +3270,33 @@ select.f { .ac-needle { animation: ac-needle-kf 7s ease-in-out infinite; } @keyframes ac-pulse-soft-kf { 0%, 100% { opacity: 1; } 50% { opacity: 0.75; } } .ac-pulse-soft { animation: ac-pulse-soft-kf 2.4s ease-in-out infinite; } + +/* The 14-second "bean journey" clock — every piece of the hero scene rides it together. */ +@keyframes ac-jb-color-kf { + 0%, 30% { fill: #7a8c5e; } + 47% { fill: #d9ba5a; } + 66% { fill: #b98d54; } + 84%, 100% { fill: #8a5a30; } +} +.ac-jb-color { animation: ac-jb-color-kf 14s linear infinite; } +@keyframes ac-jb-grow-kf { + 0%, 40% { transform: scale(1); } + 84%, 100% { transform: scale(1.12); } +} +.ac-jb-grow { transform-box: fill-box; transform-origin: center; animation: ac-jb-grow-kf 14s linear infinite; } +@keyframes ac-jb-crack-kf { + 0%, 82% { opacity: 0; } + 86%, 100% { opacity: 1; } +} +.ac-jb-crack { animation: ac-jb-crack-kf 14s linear infinite; } +@keyframes ac-jb-steam-kf { + 0%, 8% { opacity: 0; } + 18%, 42% { opacity: 1; } + 52%, 100% { opacity: 0; } +} +.ac-jb-steam { animation: ac-jb-steam-kf 14s linear infinite; } +@keyframes ac-jb-marker-kf { + from { transform: translateX(0); } + to { transform: translateX(400px); } +} +.ac-jb-marker { animation: ac-jb-marker-kf 14s linear infinite; } diff --git a/public/js/academy-content.js b/public/js/academy-content.js index 826d937..2965ab1 100644 --- a/public/js/academy-content.js +++ b/public/js/academy-content.js @@ -20,6 +20,13 @@ export const ACADEMY_TRACKS = [ title: "The roast, start to finish", minutes: 9, slides: [ + { + id: "rj-journey", + title: "The whole journey, in one bean", + scene: ["beanJourney", {}], + transcript: + "Watch one bean live the whole roast. Heat pours in from below; first the bean sweats its water out, then it turns yellow and browns as aromas build, swelling under internal pressure until it cracks open — and we drop it. Everything in this lesson is just slowing this loop down.", + }, { id: "gb-seed", title: "A seed, not a bean", diff --git a/public/js/academy-scenes.js b/public/js/academy-scenes.js new file mode 100644 index 0000000..1cd4b8a --- /dev/null +++ b/public/js/academy-scenes.js @@ -0,0 +1,551 @@ +import { BREW_SILHOUETTES, findBrewMethod } from "/shared/brew-data.js?v=__ASSET_VERSION__"; + +const NS = "http://www.w3.org/2000/svg"; + +// ── Layout discipline ────────────────────────────────────────────────────── +// Canvas is 560×300. Everything must live inside the safe area x∈[30,530] y∈[24,266]; +// the single caption line sits on the BASELINE at y=286 and stays ≤ 78 characters. +// Every animation must depict the mechanism the narration is describing — no decoration. + +const C = { + green: "#7a8c5e", + greenDark: "#5d6b45", + yellow: "#d9ba5a", + tan: "#b98d54", + brown: "#8a5a30", + dark: "#54371f", + ember: "#a8481a", + emberSoft: "#fbefe6", + ink: "#1b1614", + ink2: "#5b524b", + line: "#e4dcd2", + water: "#5f8cb0", + paper: "#fbf8f4", + pass: "#2f6f4e", + fail: "#b03a22", +}; + +function el(tag, attrs = {}, ...children) { + const node = document.createElementNS(NS, tag); + for (const [k, v] of Object.entries(attrs)) node.setAttribute(k, v); + node.append(...children); + return node; +} +const text = (x, y, str, size = 12.5, fill = C.ink2, anchor = "middle", weight = "400") => + el("text", { x, y, fill, "font-size": size, "text-anchor": anchor, "font-weight": weight }, str); +const caption = (str, fill = C.ink2) => text(280, 286, str, 12.5, fill); + +export const sceneFallbackText = (title) => text(280, 150, title, 16, C.ink2); + +/** Coffee bean, side profile with centre cut, centred on (x,y). Height ≈ 72·scale. + * CRITICAL: the positional transform lives on the OUTER group and any animated class on an + * INNER group — a CSS transform animation on the same element would silently override the + * SVG transform attribute and throw the bean to the canvas origin. */ +function bean(x, y, scale = 1, fill = C.green, opts = {}) { + const inner = el("g", { class: opts.class ?? "" }); + inner.append( + el("ellipse", { cx: 0, cy: 0, rx: 26, ry: 36, fill }), + el("path", { d: "M0 -34 C 6 -16, 6 16, 0 34 C -3 16, -3 -16, 0 -34 Z", fill: "rgba(0,0,0,0.22)" }), + ); + if (opts.crack) + inner.append( + el("path", { + d: "M-2 -30 L 5 -12 L -4 4 L 4 20 L -1 32", + fill: "none", + stroke: C.paper, + "stroke-width": 2.4, + class: "ac-crackline", + }), + ); + return el("g", { transform: `translate(${x} ${y}) scale(${scale})` }, inner); +} + +function steamWisps(x, y, n = 3) { + const g = el("g"); + for (let i = 0; i < n; i++) + g.append( + el("path", { + d: `M${x + (i - (n - 1) / 2) * 18} ${y} c -5 -10, 5 -16, 0 -26 c -4 -8, 4 -14, 0 -22`, + fill: "none", + stroke: C.ink2, + "stroke-width": 2.4, + "stroke-linecap": "round", + class: `ac-steam ac-delay-${i}`, + opacity: 0.5, + }), + ); + return g; +} + +function flame(x, y, scale = 1) { + // Same outer/inner split as bean(): position on the outer, animation class on the inner. + return el("g", { transform: `translate(${x} ${y}) scale(${scale})` }, + el("g", { class: "ac-flame" }, + el("path", { d: "M0 0 C 11 -12, 4 -22, 0 -32 C -4 -22, -11 -12, 0 0 Z", fill: C.ember }), + el("path", { d: "M0 -3 C 5 -10, 2 -15, 0 -21 C -2 -15, -5 -10, 0 -3 Z", fill: C.yellow }), + ), + ); +} + +const SIL_SCALE = 2.6; +const SIL_X = 280 - 32 * SIL_SCALE; // silhouette 64-box centred horizontally +const SIL_Y = 34; +function silhouette(methodKey) { + const g = el("g", { transform: `translate(${SIL_X} ${SIL_Y}) scale(${SIL_SCALE})`, fill: C.ink2 }); + for (const d of BREW_SILHOUETTES[methodKey] ?? []) g.append(el("path", { d })); + return g; +} +/** Convert silhouette-local (0..64) coords to scene coords. */ +const sil = (lx, ly) => [SIL_X + lx * SIL_SCALE, SIL_Y + ly * SIL_SCALE]; +// Where each brewer holds its slurry / receives its water, in silhouette-local coords. +const BOWL = { + "french-press": [32, 34], aeropress: [32, 34], clever: [30, 22], "hario-switch": [32, 20], + "cold-brew": [32, 32], cupping: [32, 36], v60: [31, 20], chemex: [32, 16], kalita: [32, 22], + batch: [37, 33], percolator: [31, 30], espresso: [32, 38], moka: [32, 16], +}; + +// ── Scene builders (each returns children for the 560×300 canvas) ───────── + +export const SCENES = { + /** The hero: one large bean living the whole roast — heat in, water out, color, swell, + * crack — synced to a stage timeline underneath. All keyframes share one 14s loop. */ + beanJourney() { + const cx = 190, cy = 120; + const seg = (x, w, color, label) => [ + el("rect", { x, y: 236, width: w, height: 12, rx: 3, fill: color, opacity: 0.55 }), + text(x + w / 2, 264, label, 11.5, C.ink2), + ]; + return [ + // Heat under the bean, always on + flame(cx - 34, 226, 0.85), flame(cx, 232, 1.05), flame(cx + 34, 226, 0.85), + ...[0, 1, 2].map((i) => + el("path", { d: `M${cx - 26 + i * 26} 214 v -12`, stroke: C.ember, "stroke-width": 3, "stroke-linecap": "round", class: `ac-pulse ac-delay-${i}` }), + ), + text(cx, 228, "", 1), + // The bean itself: color, swell, crack all on the 14s journey clock + el("g", { transform: `translate(${cx} ${cy}) scale(2.15)` }, + el("g", { class: "ac-jb-grow" }, + el("ellipse", { cx: 0, cy: 0, rx: 26, ry: 36, fill: C.green, class: "ac-jb-color" }), + el("path", { d: "M0 -34 C 6 -16, 6 16, 0 34 C -3 16, -3 -16, 0 -34 Z", fill: "rgba(0,0,0,0.22)" }), + el("path", { d: "M-2 -30 L 5 -12 L -4 4 L 4 20 L -1 32", fill: "none", stroke: C.paper, "stroke-width": 2.4, class: "ac-jb-crack" }), + ), + ), + // Moisture leaving — fades out as drying ends + el("g", { class: "ac-jb-steam" }, steamWisps(cx, 46, 3)), + // Physics callouts + text(322, 60, "water out early —", 12.5, C.water, "start", "700"), + text(322, 78, "the drying sweat", 12, C.ink2, "start"), + text(322, 116, "then browning:", 12.5, C.tan, "start", "700"), + text(322, 134, "Maillard aromas build", 12, C.ink2, "start"), + text(322, 172, "pressure swells the bean", 12.5, C.ink2, "start"), + text(322, 190, "until it cracks — then drop", 12.5, C.ember, "start", "700"), + // Stage timeline with a marker riding the same clock + ...seg(80, 188, C.yellow, "drying"), + ...seg(270, 144, C.tan, "Maillard"), + ...seg(416, 64, C.brown, "development"), + el("circle", { cx: 80, cy: 242, r: 7, fill: C.ember, class: "ac-jb-marker" }), + caption("one bean, one loop: green → yellow → brown → crack → drop"), + ]; + }, + beanAnatomy() { + const cx = 180, cy = 145; + return [ + el("ellipse", { cx, cy, rx: 108, ry: 95, fill: C.green, class: "ac-breathe" }), + el("ellipse", { cx, cy, rx: 92, ry: 80, fill: "#8ea06f" }), + el("path", { d: `M${cx} ${cy - 86} C ${cx + 27} ${cy - 36}, ${cx + 27} ${cy + 36}, ${cx} ${cy + 86} C ${cx - 18} ${cy + 36}, ${cx - 18} ${cy - 36}, ${cx} ${cy - 86} Z`, fill: "#6a7a50" }), + ...[[cx - 55, cy - 45, 0], [cx + 48, cy - 30, 1], [cx - 30, cy + 50, 2], [cx + 40, cy + 42, 0], [cx + 4, cy - 4, 1]].map(([x, y, d]) => + el("circle", { cx: x, cy: y, r: 5, fill: C.water, class: `ac-pulse ac-delay-${d}` }), + ), + // Legend, leader lines rooted on the feature they name + el("line", { x1: cx + 96, y1: cy - 62, x2: 366, y2: 70, stroke: C.line, "stroke-width": 1.5 }), + text(374, 74, "silverskin — the chaff", 12.5, C.ink2, "start"), + el("line", { x1: cx + 88, y1: cy, x2: 366, y2: 140, stroke: C.line, "stroke-width": 1.5 }), + text(374, 136, "endosperm — the pantry:", 12.5, C.ink2, "start"), + text(374, 154, "sugars, acids, proteins", 12.5, C.ink2, "start"), + el("line", { x1: cx + 60, y1: cy + 52, x2: 366, y2: 212, stroke: C.line, "stroke-width": 1.5 }), + text(374, 210, "≈11% water", 12.5, C.water, "start", "700"), + text(374, 228, "(it all must leave)", 11.5, C.ink2, "start"), + caption("the seed of a coffee cherry, in cross-section"), + ]; + }, + composition() { + const parts = [ + ["Cellulose", 48, C.ink2], + ["Sugars", 12, C.tan], + ["Lipids", 12, C.yellow], + ["Water", 11, C.water], + ["Proteins", 9, C.brown], + ["Acids", 8, C.ember], + ]; + const out = [bean(110, 140, 1.9, C.green, { class: "ac-breathe" })]; + parts.forEach(([name, pct, color], i) => { + const y = 52 + i * 34; + const w = pct * 4.4; + out.push( + text(248, y + 16, name, 12.5, C.ink2, "end"), + el("rect", { x: 258, y, width: 0, height: 21, rx: 4, fill: color, class: "ac-grow-w", style: `--w:${w}px` }), + text(266 + w, y + 16, `${pct}%`, 12, C.ink2, "start"), + ); + }); + out.push(caption("half scaffolding, half flavor pantry — plus the water")); + return out; + }, + charge() { + return [ + // Drum with tumbling beans + el("circle", { cx: 150, cy: 138, r: 76, fill: "none", stroke: C.ink2, "stroke-width": 4 }), + el("g", { class: "ac-tumble" }, + bean(126, 118, 0.5, C.green), bean(172, 132, 0.5, C.green), + bean(140, 162, 0.5, "#8ea06f"), bean(182, 168, 0.5, C.green)), + flame(150, 250, 1), + el("line", { x1: 254, y1: 120, x2: 205, y2: 132, stroke: C.ink, "stroke-width": 3, "stroke-linecap": "round" }), + el("circle", { cx: 205, cy: 132, r: 4, fill: C.ink }), + text(260, 116, "probe", 11.5, C.ink2, "start"), + // Temperature dip-and-turn, drawn live + el("path", { d: "M310 230 H 520 M310 230 V 60", stroke: C.line, "stroke-width": 1.5, fill: "none" }), + el("path", { d: "M316 78 L 372 196 Q 384 216 398 196 L 512 92", fill: "none", stroke: C.ember, "stroke-width": 3, class: "ac-draw" }), + el("circle", { cx: 385, cy: 208, r: 5, fill: C.ember, class: "ac-pulse" }), + text(415, 246, "turning point", 12.5, C.ember, "middle", "700"), + caption("the probe reads the beans — where the line turns is your machine's fingerprint"), + ]; + }, + steam() { + return [ + flame(170, 272, 1.1), + bean(170, 150, 1.9, C.green, { class: "ac-dry-shift" }), + steamWisps(170, 92, 3), + text(226, 56, "water out", 12, C.water, "start", "700"), + text(206, 262, "heat in", 12, C.ember, "start", "700"), + // Contained thermometer: the slow, stubborn climb + el("rect", { x: 392, y: 64, width: 18, height: 140, rx: 9, fill: C.paper, stroke: C.ink2, "stroke-width": 2 }), + el("circle", { cx: 401, cy: 216, r: 14, fill: C.ember }), + el("rect", { x: 396, y: 74, width: 10, height: 126, rx: 5, fill: C.ember, class: "ac-fill-up" }), + text(430, 140, "temperature climbs", 12, C.ink2, "start"), + text(430, 158, "stubbornly — the", 12, C.ink2, "start"), + text(430, 176, "endothermic phase", 12, C.ember, "start", "700"), + text(430, 216, "43–51% of the roast", 12, C.ink2, "start"), + caption("evaporation soaks up energy while the bean fades green → yellow"), + ]; + }, + maillard() { + return [ + bean(160, 148, 1.9, C.yellow, { class: "ac-maillard-shift ac-breathe" }), + // Chaff flaking off the bean, drifting up-right + ...[0, 1, 2].map((i) => + el("path", { + d: `M${208 + i * 6} ${104 - i * 10} q 10 4 16 -4`, + stroke: C.yellow, "stroke-width": 3, fill: "none", + class: `ac-drift ac-delay-${i}`, "stroke-linecap": "round", + }), + ), + // Aroma compounds appearing + ...[[320, 92, 0], [356, 120, 1], [336, 156, 2], [386, 88, 1], [372, 178, 0], [402, 140, 2]].map(([x, y, d]) => + el("circle", { cx: x, cy: y, r: 4.5, fill: d === 1 ? C.ember : C.tan, class: `ac-sparkle ac-delay-${d}` }), + ), + text(452, 116, "amino acids", 12.5, C.ink2, "start"), + text(452, 134, "+ sugars →", 12.5, C.ink2, "start"), + text(452, 152, "aroma", 12.5, C.ember, "start", "700"), + text(160, 250, "≈150 °C — browning begins", 12), + caption("the bean swells, chaff lifts away, hundreds of new compounds appear"), + ]; + }, + crack({ phase = "during" } = {}) { + const during = phase === "during"; + return [ + bean(280, 140, 2, during ? C.brown : C.tan, { crack: true, class: during ? "ac-shake" : "" }), + ...[0, 1, 2].map((i) => + el("circle", { cx: 280, cy: 140, r: 58, fill: "none", stroke: C.ember, "stroke-width": 2, class: `ac-ring ac-delay-${i}` }), + ), + // Pressure pushing outward (left), heat released (right) + ...[[-118, "≈8 bar", "of steam inside"], [118, "the exotherm —", "heat released"]].map(([dx, l1, l2], side) => + el("g", {}, + text(280 + dx, 118, l1, 12.5, side ? C.ember : C.water, "middle", "700"), + text(280 + dx, 136, l2, 12, C.ink2), + ), + ), + ...[0, 1, 2].map((i) => + el("path", { d: `M${332 + i * 12} 156 l 12 8`, stroke: C.ember, "stroke-width": 2.5, "stroke-linecap": "round", class: `ac-pulse ac-delay-${i}` }), + ), + text(280, 244, "≈196 °C — the pop, like popcorn", 12.5, C.ink, "middle", "700"), + caption("the heat cut happens BEFORE this moment — gently, a minute upstream"), + ]; + }, + dtr() { + return [ + text(280, 60, "one roast, on a timeline", 12.5), + el("rect", { x: 70, y: 110, width: 420, height: 44, rx: 8, fill: C.line }), + el("rect", { x: 70, y: 110, width: 280, height: 44, rx: 8, fill: C.tan, opacity: 0.45 }), + el("rect", { x: 350, y: 110, width: 0, height: 44, rx: 8, fill: C.ember, class: "ac-grow-w", style: "--w:140px" }), + el("line", { x1: 350, y1: 92, x2: 350, y2: 172, stroke: C.ink, "stroke-width": 2, "stroke-dasharray": "4 3" }), + text(350, 84, "first crack", 12, C.ink, "middle", "700"), + text(210, 138, "drying + Maillard", 12.5, C.ink2), + text(420, 138, "development", 12.5, C.paper, "middle", "700"), + text(70, 172, "0:00", 11.5, C.ink2, "start"), + text(490, 172, "drop", 11.5, C.ink2, "end"), + text(280, 214, "development ÷ total time = 12–20%", 14, C.ember, "middle", "700"), + caption("the strongest single lever on the cup — the app computes it from every log"), + ]; + }, + weightLoss() { + return [ + bean(150, 128, 1.5, C.green), + text(150, 208, "250 g green", 13, C.ink, "middle", "700"), + el("line", { x1: 226, y1: 128, x2: 302, y2: 128, stroke: C.ink2, "stroke-width": 2.5, class: "ac-draw" }), + el("path", { d: "M300 121 l 12 7 l -12 7 Z", fill: C.ink2 }), + bean(390, 128, 1.62, C.brown, { crack: true }), + text(390, 208, "≈220 g roasted", 13, C.ink, "middle", "700"), + text(280, 244, "−11–13% for a light roast", 13.5, C.ember, "middle", "700"), + caption("time, temperature and development — measured by a kitchen scale"), + ]; + }, + curve({ focus = "all" } = {}) { + const band = (x, w, color, key) => + el("rect", { x, y: 62, width: w, height: 168, fill: color, opacity: focus === "all" || focus === key ? 0.16 : 0.05 }); + return [ + band(60, 150, C.yellow, "drying"), + band(210, 158, C.tan, "maillard"), + band(368, 132, C.brown, "development"), + el("path", { d: "M60 230 H 500 M60 230 V 62", stroke: C.line, "stroke-width": 1.5, fill: "none" }), + el("path", { d: "M64 96 L 96 198 Q 104 216 116 198 C 180 108, 300 96, 494 72", fill: "none", stroke: C.ember, "stroke-width": 3, class: "ac-draw" }), + el("circle", { cx: 100, cy: 207, r: 4.5, fill: C.ember }), + text(100, 250, "TP", 11.5, C.ink2), + el("circle", { cx: 375, cy: 86, r: 5, fill: C.ink, class: "ac-pulse" }), + text(375, 56, "first crack", 12, C.ink, "middle", "700"), + text(165, 250, "drying", 12), text(289, 250, "Maillard", 12), text(434, 250, "development", 12), + caption("bean temperature — dip, turn, climb, crack, drop: the story of the roast"), + ]; + }, + ror() { + return [ + el("path", { d: "M60 230 H 500 M60 230 V 62", stroke: C.line, "stroke-width": 1.5, fill: "none" }), + text(52, 76, "RoR", 11.5, C.ink2, "end"), + // The ideal: steady decline + el("path", { d: "M64 92 C 160 128, 300 168, 494 194", fill: "none", stroke: C.pass, "stroke-width": 2.5, "stroke-dasharray": "6 5" }), + text(216, 90, "ideal: always falling", 12, C.pass, "middle", "700"), + // The failure: crash, then flick + el("path", { d: "M64 92 C 150 130, 230 152, 292 162 C 330 168, 336 224, 366 226 C 392 228, 398 176, 442 184 L 494 194", fill: "none", stroke: C.fail, "stroke-width": 3, class: "ac-draw" }), + el("circle", { cx: 352, cy: 224, r: 5.5, fill: C.fail, class: "ac-pulse" }), + text(340, 252, "crash", 12, C.fail, "middle", "700"), + el("circle", { cx: 420, cy: 179, r: 5.5, fill: C.fail, class: "ac-pulse ac-delay-1" }), + text(432, 160, "flick", 12, C.fail, "middle", "700"), + // The stall + el("line", { x1: 200, y1: 148, x2: 300, y2: 148, stroke: C.warnColor ?? "#a8741a", "stroke-width": 3, "stroke-dasharray": "2 4" }), + text(250, 136, "stall = baking", 12, "#a8741a", "middle", "700"), + caption("crash bakes out sweetness · flick tastes roasty · the fix is always upstream"), + ]; + }, + oneChange() { + const cards = [ + ["batch 1", "baseline", false], + ["batch 2", "FC +0:30", false], + ["batch 3", "dev +0:15", true], + ]; + return [ + ...cards.map(([label, change, active], i) => + el("g", { class: active ? "ac-pulse-soft" : "" }, + el("rect", { x: 84 + i * 146, y: 78, width: 116, height: 76, rx: 8, fill: active ? C.emberSoft : C.paper, stroke: active ? C.ember : C.line, "stroke-width": 1.6 }), + text(142 + i * 146, 106, label, 12.5, C.ink2), + text(142 + i * 146, 134, change, 13.5, active ? C.ember : C.ink, "middle", "700"), + ), + ), + el("path", { d: "M202 116 h 24 M348 116 h 24", stroke: C.ember, "stroke-width": 2.5, class: "ac-draw" }), + text(280, 196, "papery → FC +0:30 · savory → FC −0:30 · sharp → dev +0:15", 12.5, C.ink), + text(280, 224, "one variable per batch — the only experiment you can afford", 13, C.ember, "middle", "700"), + caption("your note rides into the next plan's ± Refine automatically"), + ]; + }, + + // ── Brewing scenes ── + dissolve() { + return [ + el("circle", { cx: 150, cy: 140, r: 52, fill: C.brown }), + text(150, 218, "ground coffee", 12, C.ink2), + ...[0, 1, 2, 3, 4, 5].map((i) => + el("circle", { + cx: 196, cy: 112 + (i % 3) * 26, r: 5, + fill: [C.yellow, C.tan, C.dark][i % 3], + class: `ac-dissolve ac-delay-${i % 3}`, + }), + ), + ...[ + ["1. acids — bright, sour", C.yellow], + ["2. sugars — sweet", C.tan], + ["3. bitters — heavy, dry", C.dark], + ].map(([label, color], i) => + el("g", {}, + el("circle", { cx: 312, cy: 96 + i * 44, r: 8, fill: color }), + text(330, 101 + i * 44, label, 13, C.ink2, "start"), + ), + ), + caption("hot water dissolves them in this order — brewing is choosing when to stop"), + ]; + }, + yieldMap() { + return [ + text(150, 92, "sour · thin", 12.5, C.fail, "middle", "700"), + text(280, 78, "sweet spot", 13, C.pass, "middle", "700"), + text(280, 96, "18–22%", 13, C.pass, "middle", "700"), + text(412, 92, "bitter · drying", 12.5, C.fail, "middle", "700"), + el("rect", { x: 90, y: 112, width: 380, height: 56, rx: 10, fill: C.paper, stroke: C.line }), + el("rect", { x: 90, y: 112, width: 128, height: 56, rx: 10, fill: C.fail, opacity: 0.1 }), + el("rect", { x: 342, y: 112, width: 128, height: 56, rx: 10, fill: C.fail, opacity: 0.1 }), + el("rect", { x: 218, y: 112, width: 124, height: 56, fill: C.pass, opacity: 0.16 }), + el("circle", { cx: 280, cy: 140, r: 7, fill: C.ember, class: "ac-slide-x" }), + text(280, 194, "extraction yield →", 12, C.ink2), + text(280, 230, "strength = coffee in the water", 12.5, C.ink2), + text(280, 248, "extraction = what you took from the grounds", 12.5, C.ink2), + caption("aim the dot at the middle: every dial below exists to move it"), + ]; + }, + grind() { + const pile = (x, label, sub, circles) => { + const g = el("g", {}); + for (const [dx, dy, r] of circles) g.append(el("circle", { cx: x + dx, cy: 128 + dy, r, fill: C.brown })); + g.append(text(x, 196, label, 13, C.ink, "middle", "700"), text(x, 216, sub, 11.5, C.ink2)); + return g; + }; + return [ + text(280, 62, "the same 20 grams of coffee", 12.5), + pile(130, "coarse", "less surface · fast flow", [[-16, -10, 19], [16, -8, 19], [0, 18, 19]]), + pile(280, "medium", "the middle path", [[-24, -14, 10], [0, -18, 10], [24, -14, 10], [-14, 4, 10], [12, 4, 10], [-2, 22, 10], [22, 20, 10]]), + pile(430, "fine", "more surface · slow flow", [...Array(16)].map((_, i) => [((i % 4) - 1.5) * 16, (Math.floor(i / 4) - 1.5) * 15, 5])), + caption("grind is the master dial — it moves extraction and contact time together"), + ]; + }, + tempTime() { + return [ + // Temperature: contained thermometer + el("rect", { x: 108, y: 68, width: 18, height: 118, rx: 9, fill: C.paper, stroke: C.ink2, "stroke-width": 2 }), + el("circle", { cx: 117, cy: 198, r: 13, fill: C.ember }), + el("rect", { x: 112, y: 76, width: 10, height: 106, rx: 5, fill: C.ember, class: "ac-fill-up" }), + text(117, 240, "90–96 °C", 12.5, C.ink, "middle", "700"), + // Time: a gauge whose needle sweeps + el("path", { d: "M220 190 A 62 62 0 0 1 340 190", fill: "none", stroke: C.line, "stroke-width": 10, "stroke-linecap": "round" }), + el("line", { x1: 280, y1: 190, x2: 280, y2: 138, stroke: C.ink, "stroke-width": 4, class: "ac-needle", "transform-origin": "280px 190px" }), + el("circle", { cx: 280, cy: 190, r: 8, fill: C.ink }), + text(280, 240, "time = how far down the list", 12.5, C.ink, "middle", "700"), + // Ratio: one bean to many drops + bean(420, 110, 0.62, C.brown), + text(446, 116, "1 :", 15, C.ink, "start", "700"), + ...[0, 1, 2].map((i) => + el("path", { d: `M${480 + i * 18} 104 c 5 8 5 14 0 18 c -5 -4 -5 -10 0 -18 Z`, fill: C.water, class: `ac-pulse ac-delay-${i}` }), + ), + text(466, 240, "1:15–1:17", 12.5, C.ink, "middle", "700"), + caption("three dials on one cup — and grind, from the previous slide, is the fourth"), + ]; + }, + tasteDial() { + return [ + el("path", { d: "M130 198 A 156 156 0 0 1 430 198", fill: "none", stroke: C.line, "stroke-width": 15, "stroke-linecap": "round" }), + el("path", { d: "M130 198 A 156 156 0 0 1 232 72", fill: "none", stroke: C.fail, "stroke-width": 15, "stroke-linecap": "round", opacity: 0.5 }), + el("path", { d: "M328 72 A 156 156 0 0 1 430 198", fill: "none", stroke: C.fail, "stroke-width": 15, "stroke-linecap": "round", opacity: 0.5 }), + text(126, 232, "sour · sharp", 12.5, C.fail, "middle", "700"), + text(280, 48, "sweet & balanced", 13, C.pass, "middle", "700"), + text(434, 232, "bitter · drying", 12.5, C.fail, "middle", "700"), + el("line", { x1: 280, y1: 198, x2: 280, y2: 92, stroke: C.ink, "stroke-width": 4, class: "ac-dial", "transform-origin": "280px 198px" }), + el("circle", { cx: 280, cy: 198, r: 10, fill: C.ink }), + text(280, 246, "sour? extract more · bitter? extract less", 13, C.ink, "middle", "700"), + caption("finer, hotter, longer ← the dial → coarser, cooler, shorter"), + ]; + }, + bloom() { + const [bx, by] = [280, 118]; + return [ + silhouette("v60"), + // CO₂ bubbles rising out of the cone + ...[0, 1, 2, 3].map((i) => + el("circle", { cx: bx - 18 + i * 12, cy: by - i * 3, r: 4 - i * 0.5, fill: C.tan, class: `ac-rise ac-delay-${i}` }), + ), + text(430, 96, "CO₂ escaping —", 12.5, C.tan, "start", "700"), + text(430, 114, "the bed swells", 12.5, C.ink2, "start"), + text(430, 132, "and bubbles", 12.5, C.ink2, "start"), + text(130, 96, "2× the coffee's", 12.5, C.ink2, "end"), + text(130, 114, "weight in water", 12.5, C.ink2, "end"), + text(130, 132, "wait 30–45 s", 12.5, C.ember, "end", "700"), + caption("gas pushes water away from coffee — bloom first, then brew"), + ]; + }, + tamp() { + return [ + // Tamper descending onto the basket + el("g", { class: "ac-tamp" }, + el("rect", { x: 262, y: 44, width: 16, height: 26, rx: 5, fill: C.ink }), + el("rect", { x: 238, y: 70, width: 64, height: 20, rx: 5, fill: C.ink })), + el("rect", { x: 206, y: 118, width: 148, height: 54, rx: 8, fill: C.ink2 }), + el("rect", { x: 216, y: 128, width: 128, height: 36, rx: 4, fill: C.brown }), + el("line", { x1: 216, y1: 128, x2: 344, y2: 128, stroke: C.paper, "stroke-width": 1.5, "stroke-dasharray": "4 4" }), + text(390, 140, "level, even,", 12.5, C.ink2, "start"), + text(390, 158, "no gaps", 12.5, C.ink2, "start"), + text(170, 140, "dose to 0.1 g", 12.5, C.ink2, "end"), + text(280, 220, "distribute · tamp level · no ritual, just channel prevention", 13, C.ink, "middle", "700"), + caption("pressurized water exploits any weakness in the puck"), + ]; + }, + shot() { + return [ + el("rect", { x: 230, y: 56, width: 100, height: 32, rx: 6, fill: C.ink }), + el("line", { x1: 268, y1: 88, x2: 268, y2: 122, stroke: C.brown, "stroke-width": 5, class: "ac-drip" }), + el("line", { x1: 292, y1: 88, x2: 292, y2: 122, stroke: C.brown, "stroke-width": 5, class: "ac-drip ac-delay-1" }), + el("path", { d: "M248 130 h 64 l -7 40 h -50 Z", fill: C.paper, stroke: C.ink2, "stroke-width": 2 }), + el("rect", { x: 252, y: 146, width: 56, height: 0, fill: C.tan, class: "ac-grow-h-down" }), + text(392, 108, "18 g in → 36 g out", 13, C.ink, "start", "700"), + text(392, 130, "in 25–32 seconds", 12.5, C.ink2, "start"), + text(392, 152, "flows like warm honey", 12.5, C.tan, "start"), + text(168, 130, "9 bar, above", 12.5, C.ink2, "end"), + text(280, 220, "blonde & gushing → grind finer · choked drips → coarser", 12.5, C.ink), + caption("the stream itself tells you which way the grind is wrong"), + ]; + }, + brewAnim({ method, mode }) { + const m = findBrewMethod(method); + const [bx, by] = sil(...(BOWL[method] ?? [32, 30])); + const out = [silhouette(method), text(280, 262, m?.name ?? method, 13.5, C.ink, "middle", "700")]; + const hint = (lines, color = C.ink2) => + lines.forEach((s, i) => out.push(text(432, 100 + i * 19, s, 12.5, color, "start", i === 0 ? "700" : "400"))); + + if (mode === "steep" || mode === "valve") { + out.push( + ...[...Array(6)].map((_, i) => + el("circle", { + cx: bx - 22 + (i % 3) * 22, cy: by - 8 + Math.floor(i / 3) * 16, r: 4, + fill: C.brown, class: `ac-float ac-delay-${i % 3}`, + }), + ), + ); + hint(mode === "valve" ? ["steep closed…", "then open the", "valve and drain"] : ["all the water,", "all the grounds,", "the whole time"]); + } + if (mode === "plunge" || mode === "press") { + out.push( + el("g", { class: "ac-tamp" }, + el("path", { d: `M${bx} ${by - 52} v 30`, stroke: C.ember, "stroke-width": 5, "stroke-linecap": "round" }), + el("path", { d: `M${bx - 9} ${by - 20} h 18`, stroke: C.ember, "stroke-width": 4, "stroke-linecap": "round" })), + ); + hint(mode === "press" ? ["steep 1:30,", "press 0:30,", "gently"] : ["press slowly,", "stop above the", "grounds"]); + } + if (mode === "pour" || mode === "spiral" || mode === "drip") { + out.push( + ...[0, 1, 2].map((i) => + el("line", { x1: bx - 10 + i * 10, y1: by - 34, x2: bx - 10 + i * 10, y2: by - 14, stroke: C.water, "stroke-width": 2.5, class: `ac-drip ac-delay-${i}` }), + ), + ); + if (mode === "spiral") + out.push(el("path", { d: `M${bx} ${by} m -16 0 a 16 16 0 1 1 32 0 a 12 12 0 1 1 -24 0`, fill: "none", stroke: C.water, "stroke-width": 2, class: "ac-pourline" })); + hint(mode === "spiral" ? ["slow spirals,", "centre out,", "keep it level"] : mode === "drip" ? ["the robot pours;", "you choose grind", "and ratio"] : ["fresh water,", "always passing", "through the bed"]); + } + if (mode === "pressure") { + out.push( + ...[0, 1, 2].map((i) => + el("path", { d: `M${bx - 26 + i * 26} ${by - 26} v 14`, stroke: C.ember, "stroke-width": 3.5, "stroke-linecap": "round", class: `ac-pulse ac-delay-${i}` }), + ), + ); + hint(["9 bar pushes", "water through", "the puck"], C.ember); + } + if (mode === "flame") { + out.push(flame(bx, sil(32, 74)[1], 1.2)); + hint(["≈1.5 bar of", "boiler steam", "pushes upward"]); + } + return out; + }, +}; + + diff --git a/public/js/academy.js b/public/js/academy.js index 0c5438d..2913f56 100644 --- a/public/js/academy.js +++ b/public/js/academy.js @@ -1,509 +1,7 @@ import { protectedFetch } from "./api.js?v=__ASSET_VERSION__"; import { initSideNav, loadNavUser } from "./nav.js?v=__ASSET_VERSION__"; import { ACADEMY_TRACKS } from "./academy-content.js?v=__ASSET_VERSION__"; -import { BREW_SILHOUETTES, findBrewMethod } from "/shared/brew-data.js?v=__ASSET_VERSION__"; - -const NS = "http://www.w3.org/2000/svg"; - -// ── Layout discipline ────────────────────────────────────────────────────── -// Canvas is 560×300. Everything must live inside the safe area x∈[30,530] y∈[24,266]; -// the single caption line sits on the BASELINE at y=286 and stays ≤ 78 characters. -// Every animation must depict the mechanism the narration is describing — no decoration. - -const C = { - green: "#7a8c5e", - greenDark: "#5d6b45", - yellow: "#d9ba5a", - tan: "#b98d54", - brown: "#8a5a30", - dark: "#54371f", - ember: "#a8481a", - emberSoft: "#fbefe6", - ink: "#1b1614", - ink2: "#5b524b", - line: "#e4dcd2", - water: "#5f8cb0", - paper: "#fbf8f4", - pass: "#2f6f4e", - fail: "#b03a22", -}; - -function el(tag, attrs = {}, ...children) { - const node = document.createElementNS(NS, tag); - for (const [k, v] of Object.entries(attrs)) node.setAttribute(k, v); - node.append(...children); - return node; -} -const text = (x, y, str, size = 12.5, fill = C.ink2, anchor = "middle", weight = "400") => - el("text", { x, y, fill, "font-size": size, "text-anchor": anchor, "font-weight": weight }, str); -const caption = (str, fill = C.ink2) => text(280, 286, str, 12.5, fill); - -/** Coffee bean, side profile with centre cut, centred on (x,y). Height ≈ 72·scale. */ -function bean(x, y, scale = 1, fill = C.green, opts = {}) { - const g = el("g", { - transform: `translate(${x} ${y}) scale(${scale})`, - class: opts.class ?? "", - }); - g.append( - el("ellipse", { cx: 0, cy: 0, rx: 26, ry: 36, fill }), - el("path", { d: "M0 -34 C 6 -16, 6 16, 0 34 C -3 16, -3 -16, 0 -34 Z", fill: "rgba(0,0,0,0.22)" }), - ); - if (opts.crack) - g.append( - el("path", { - d: "M-2 -30 L 5 -12 L -4 4 L 4 20 L -1 32", - fill: "none", - stroke: C.paper, - "stroke-width": 2.4, - class: "ac-crackline", - }), - ); - return g; -} - -function steamWisps(x, y, n = 3) { - const g = el("g"); - for (let i = 0; i < n; i++) - g.append( - el("path", { - d: `M${x + (i - (n - 1) / 2) * 18} ${y} c -5 -10, 5 -16, 0 -26 c -4 -8, 4 -14, 0 -22`, - fill: "none", - stroke: C.ink2, - "stroke-width": 2.4, - "stroke-linecap": "round", - class: `ac-steam ac-delay-${i}`, - opacity: 0.5, - }), - ); - return g; -} - -function flame(x, y, scale = 1) { - return el("g", { transform: `translate(${x} ${y}) scale(${scale})`, class: "ac-flame" }, - el("path", { d: "M0 0 C 11 -12, 4 -22, 0 -32 C -4 -22, -11 -12, 0 0 Z", fill: C.ember }), - el("path", { d: "M0 -3 C 5 -10, 2 -15, 0 -21 C -2 -15, -5 -10, 0 -3 Z", fill: C.yellow }), - ); -} - -const SIL_SCALE = 2.6; -const SIL_X = 280 - 32 * SIL_SCALE; // silhouette 64-box centred horizontally -const SIL_Y = 34; -function silhouette(methodKey) { - const g = el("g", { transform: `translate(${SIL_X} ${SIL_Y}) scale(${SIL_SCALE})`, fill: C.ink2 }); - for (const d of BREW_SILHOUETTES[methodKey] ?? []) g.append(el("path", { d })); - return g; -} -/** Convert silhouette-local (0..64) coords to scene coords. */ -const sil = (lx, ly) => [SIL_X + lx * SIL_SCALE, SIL_Y + ly * SIL_SCALE]; -// Where each brewer holds its slurry / receives its water, in silhouette-local coords. -const BOWL = { - "french-press": [32, 34], aeropress: [32, 34], clever: [30, 22], "hario-switch": [32, 20], - "cold-brew": [32, 32], cupping: [32, 36], v60: [31, 20], chemex: [32, 16], kalita: [32, 22], - batch: [37, 33], percolator: [31, 30], espresso: [32, 38], moka: [32, 16], -}; - -// ── Scene builders (each returns children for the 560×300 canvas) ───────── - -const SCENES = { - beanAnatomy() { - const cx = 180, cy = 145; - return [ - el("ellipse", { cx, cy, rx: 108, ry: 95, fill: C.green, class: "ac-breathe" }), - el("ellipse", { cx, cy, rx: 92, ry: 80, fill: "#8ea06f" }), - el("path", { d: `M${cx} ${cy - 86} C ${cx + 27} ${cy - 36}, ${cx + 27} ${cy + 36}, ${cx} ${cy + 86} C ${cx - 18} ${cy + 36}, ${cx - 18} ${cy - 36}, ${cx} ${cy - 86} Z`, fill: "#6a7a50" }), - ...[[cx - 55, cy - 45, 0], [cx + 48, cy - 30, 1], [cx - 30, cy + 50, 2], [cx + 40, cy + 42, 0], [cx + 4, cy - 4, 1]].map(([x, y, d]) => - el("circle", { cx: x, cy: y, r: 5, fill: C.water, class: `ac-pulse ac-delay-${d}` }), - ), - // Legend, leader lines rooted on the feature they name - el("line", { x1: cx + 96, y1: cy - 62, x2: 366, y2: 70, stroke: C.line, "stroke-width": 1.5 }), - text(374, 74, "silverskin — the chaff", 12.5, C.ink2, "start"), - el("line", { x1: cx + 88, y1: cy, x2: 366, y2: 140, stroke: C.line, "stroke-width": 1.5 }), - text(374, 136, "endosperm — the pantry:", 12.5, C.ink2, "start"), - text(374, 154, "sugars, acids, proteins", 12.5, C.ink2, "start"), - el("line", { x1: cx + 60, y1: cy + 52, x2: 366, y2: 212, stroke: C.line, "stroke-width": 1.5 }), - text(374, 210, "≈11% water", 12.5, C.water, "start", "700"), - text(374, 228, "(it all must leave)", 11.5, C.ink2, "start"), - caption("the seed of a coffee cherry, in cross-section"), - ]; - }, - composition() { - const parts = [ - ["Cellulose", 48, C.ink2], - ["Sugars", 12, C.tan], - ["Lipids", 12, C.yellow], - ["Water", 11, C.water], - ["Proteins", 9, C.brown], - ["Acids", 8, C.ember], - ]; - const out = [bean(110, 140, 1.9, C.green, { class: "ac-breathe" })]; - parts.forEach(([name, pct, color], i) => { - const y = 52 + i * 34; - const w = pct * 4.4; - out.push( - text(248, y + 16, name, 12.5, C.ink2, "end"), - el("rect", { x: 258, y, width: 0, height: 21, rx: 4, fill: color, class: `ac-grow-w ac-delay-${Math.min(i, 4)}`, style: `--w:${w}px` }), - text(266 + w, y + 16, `${pct}%`, 12, C.ink2, "start"), - ); - }); - out.push(caption("half scaffolding, half flavor pantry — plus the water")); - return out; - }, - charge() { - return [ - // Drum with tumbling beans - el("circle", { cx: 150, cy: 138, r: 76, fill: "none", stroke: C.ink2, "stroke-width": 4 }), - el("g", { class: "ac-tumble" }, - bean(126, 118, 0.5, C.green), bean(172, 132, 0.5, C.green), - bean(140, 162, 0.5, "#8ea06f"), bean(182, 168, 0.5, C.green)), - flame(150, 250, 1), - el("line", { x1: 254, y1: 120, x2: 205, y2: 132, stroke: C.ink, "stroke-width": 3, "stroke-linecap": "round" }), - el("circle", { cx: 205, cy: 132, r: 4, fill: C.ink }), - text(260, 116, "probe", 11.5, C.ink2, "start"), - // Temperature dip-and-turn, drawn live - el("path", { d: "M310 230 H 520 M310 230 V 60", stroke: C.line, "stroke-width": 1.5, fill: "none" }), - el("path", { d: "M316 78 L 372 196 Q 384 216 398 196 L 512 92", fill: "none", stroke: C.ember, "stroke-width": 3, class: "ac-draw" }), - el("circle", { cx: 385, cy: 208, r: 5, fill: C.ember, class: "ac-pulse" }), - text(415, 246, "turning point", 12.5, C.ember, "middle", "700"), - caption("the probe reads the beans — where the line turns is your machine's fingerprint"), - ]; - }, - steam() { - return [ - flame(170, 262, 1.1), - bean(170, 150, 1.9, C.green, { class: "ac-dry-shift" }), - steamWisps(170, 92, 3), - text(170, 250, "water out ↑ · heat in ↓", 12, C.ink2), - // Contained thermometer: the slow, stubborn climb - el("rect", { x: 392, y: 64, width: 18, height: 140, rx: 9, fill: C.paper, stroke: C.ink2, "stroke-width": 2 }), - el("circle", { cx: 401, cy: 216, r: 14, fill: C.ember }), - el("rect", { x: 396, y: 74, width: 10, height: 126, rx: 5, fill: C.ember, class: "ac-fill-up" }), - text(430, 140, "temperature climbs", 12, C.ink2, "start"), - text(430, 158, "stubbornly — the", 12, C.ink2, "start"), - text(430, 176, "endothermic phase", 12, C.ember, "start", "700"), - text(430, 216, "43–51% of the roast", 12, C.ink2, "start"), - caption("evaporation soaks up energy while the bean fades green → yellow"), - ]; - }, - maillard() { - return [ - bean(160, 148, 1.9, C.yellow, { class: "ac-maillard-shift ac-breathe" }), - // Chaff flaking off the bean, drifting up-right - ...[0, 1, 2].map((i) => - el("path", { - d: `M${208 + i * 6} ${104 - i * 10} q 10 4 16 -4`, - stroke: C.yellow, "stroke-width": 3, fill: "none", - class: `ac-drift ac-delay-${i}`, "stroke-linecap": "round", - }), - ), - // Aroma compounds appearing - ...[[320, 92, 0], [356, 120, 1], [336, 156, 2], [386, 88, 1], [372, 178, 0], [402, 140, 2]].map(([x, y, d]) => - el("circle", { cx: x, cy: y, r: 4.5, fill: d === 1 ? C.ember : C.tan, class: `ac-sparkle ac-delay-${d}` }), - ), - text(452, 116, "amino acids", 12.5, C.ink2, "start"), - text(452, 134, "+ sugars →", 12.5, C.ink2, "start"), - text(452, 152, "aroma", 12.5, C.ember, "start", "700"), - text(160, 250, "≈150 °C — browning begins", 12), - caption("the bean swells, chaff lifts away, hundreds of new compounds appear"), - ]; - }, - crack({ phase = "during" } = {}) { - const during = phase === "during"; - return [ - bean(280, 140, 2, during ? C.brown : C.tan, { crack: true, class: during ? "ac-shake" : "" }), - ...[0, 1, 2].map((i) => - el("circle", { cx: 280, cy: 140, r: 58, fill: "none", stroke: C.ember, "stroke-width": 2, class: `ac-ring ac-delay-${i}` }), - ), - // Pressure pushing outward (left), heat released (right) - ...[[-118, "≈8 bar", "of steam inside"], [118, "the exotherm —", "heat released"]].map(([dx, l1, l2], side) => - el("g", {}, - text(280 + dx, 118, l1, 12.5, side ? C.ember : C.water, "middle", "700"), - text(280 + dx, 136, l2, 12, C.ink2), - ), - ), - ...[0, 1, 2].map((i) => - el("path", { d: `M${332 + i * 12} 156 l 12 8`, stroke: C.ember, "stroke-width": 2.5, "stroke-linecap": "round", class: `ac-pulse ac-delay-${i}` }), - ), - text(280, 244, "≈196 °C — the pop, like popcorn", 12.5, C.ink, "middle", "700"), - caption("the heat cut happens BEFORE this moment — gently, a minute upstream"), - ]; - }, - dtr() { - return [ - text(280, 60, "one roast, on a timeline", 12.5), - el("rect", { x: 70, y: 110, width: 420, height: 44, rx: 8, fill: C.line }), - el("rect", { x: 70, y: 110, width: 280, height: 44, rx: 8, fill: C.tan, opacity: 0.45 }), - el("rect", { x: 350, y: 110, width: 0, height: 44, rx: 8, fill: C.ember, class: "ac-grow-w", style: "--w:140px" }), - el("line", { x1: 350, y1: 92, x2: 350, y2: 172, stroke: C.ink, "stroke-width": 2, "stroke-dasharray": "4 3" }), - text(350, 84, "first crack", 12, C.ink, "middle", "700"), - text(210, 138, "drying + Maillard", 12.5, C.ink2), - text(420, 138, "development", 12.5, C.paper, "middle", "700"), - text(70, 172, "0:00", 11.5, C.ink2, "start"), - text(490, 172, "drop", 11.5, C.ink2, "end"), - text(280, 214, "development ÷ total time = 12–20%", 14, C.ember, "middle", "700"), - caption("the strongest single lever on the cup — the app computes it from every log"), - ]; - }, - weightLoss() { - return [ - bean(150, 128, 1.5, C.green), - text(150, 208, "250 g green", 13, C.ink, "middle", "700"), - el("line", { x1: 226, y1: 128, x2: 302, y2: 128, stroke: C.ink2, "stroke-width": 2.5, class: "ac-draw" }), - el("path", { d: "M300 121 l 12 7 l -12 7 Z", fill: C.ink2 }), - bean(390, 128, 1.62, C.brown, { crack: true }), - text(390, 208, "≈220 g roasted", 13, C.ink, "middle", "700"), - text(280, 244, "−11–13% for a light roast", 13.5, C.ember, "middle", "700"), - caption("time, temperature and development — measured by a kitchen scale"), - ]; - }, - curve({ focus = "all" } = {}) { - const band = (x, w, color, key) => - el("rect", { x, y: 62, width: w, height: 168, fill: color, opacity: focus === "all" || focus === key ? 0.16 : 0.05 }); - return [ - band(60, 150, C.yellow, "drying"), - band(210, 158, C.tan, "maillard"), - band(368, 132, C.brown, "development"), - el("path", { d: "M60 230 H 500 M60 230 V 62", stroke: C.line, "stroke-width": 1.5, fill: "none" }), - el("path", { d: "M64 96 L 96 198 Q 104 216 116 198 C 180 108, 300 96, 494 72", fill: "none", stroke: C.ember, "stroke-width": 3, class: "ac-draw" }), - el("circle", { cx: 100, cy: 207, r: 4.5, fill: C.ember }), - text(100, 250, "TP", 11.5, C.ink2), - el("circle", { cx: 375, cy: 79, r: 5, fill: C.ink, class: "ac-pulse" }), - text(375, 56, "first crack", 12, C.ink, "middle", "700"), - text(135, 250, "drying", 12), text(289, 250, "Maillard", 12), text(434, 250, "development", 12), - caption("bean temperature — dip, turn, climb, crack, drop: the story of the roast"), - ]; - }, - ror() { - return [ - el("path", { d: "M60 230 H 500 M60 230 V 62", stroke: C.line, "stroke-width": 1.5, fill: "none" }), - text(52, 76, "RoR", 11.5, C.ink2, "end"), - // The ideal: steady decline - el("path", { d: "M64 92 C 160 128, 300 168, 494 194", fill: "none", stroke: C.pass, "stroke-width": 2.5, "stroke-dasharray": "6 5" }), - text(150, 106, "ideal: always falling", 12, C.pass, "middle", "700"), - // The failure: crash, then flick - el("path", { d: "M64 92 C 150 130, 230 152, 292 162 C 330 168, 336 224, 366 226 C 392 228, 398 176, 442 184 L 494 194", fill: "none", stroke: C.fail, "stroke-width": 3, class: "ac-draw" }), - el("circle", { cx: 352, cy: 224, r: 5.5, fill: C.fail, class: "ac-pulse" }), - text(340, 252, "crash", 12, C.fail, "middle", "700"), - el("circle", { cx: 420, cy: 179, r: 5.5, fill: C.fail, class: "ac-pulse ac-delay-1" }), - text(432, 160, "flick", 12, C.fail, "middle", "700"), - // The stall - el("line", { x1: 200, y1: 148, x2: 300, y2: 148, stroke: C.warnColor ?? "#a8741a", "stroke-width": 3, "stroke-dasharray": "2 4" }), - text(250, 136, "stall = baking", 12, "#a8741a", "middle", "700"), - caption("crash bakes out sweetness · flick tastes roasty · the fix is always upstream"), - ]; - }, - oneChange() { - const cards = [ - ["batch 1", "baseline", false], - ["batch 2", "FC +0:30", false], - ["batch 3", "dev +0:15", true], - ]; - return [ - ...cards.map(([label, change, active], i) => - el("g", { class: active ? "ac-pulse-soft" : "" }, - el("rect", { x: 84 + i * 146, y: 78, width: 116, height: 76, rx: 8, fill: active ? C.emberSoft : C.paper, stroke: active ? C.ember : C.line, "stroke-width": 1.6 }), - text(142 + i * 146, 106, label, 12.5, C.ink2), - text(142 + i * 146, 134, change, 13.5, active ? C.ember : C.ink, "middle", "700"), - ), - ), - el("path", { d: "M202 116 h 24 M348 116 h 24", stroke: C.ember, "stroke-width": 2.5, class: "ac-draw" }), - text(280, 196, "papery → FC +0:30 · savory → FC −0:30 · sharp → dev +0:15", 12.5, C.ink), - text(280, 224, "one variable per batch — the only experiment you can afford", 13, C.ember, "middle", "700"), - caption("your note rides into the next plan's ± Refine automatically"), - ]; - }, - - // ── Brewing scenes ── - dissolve() { - return [ - el("circle", { cx: 150, cy: 140, r: 52, fill: C.brown }), - text(150, 218, "ground coffee", 12, C.ink2), - ...[0, 1, 2, 3, 4, 5].map((i) => - el("circle", { - cx: 196, cy: 112 + (i % 3) * 26, r: 5, - fill: [C.yellow, C.tan, C.dark][i % 3], - class: `ac-dissolve ac-delay-${i % 3}`, - }), - ), - ...[ - ["1. acids — bright, sour", C.yellow], - ["2. sugars — sweet", C.tan], - ["3. bitters — heavy, dry", C.dark], - ].map(([label, color], i) => - el("g", {}, - el("circle", { cx: 312, cy: 96 + i * 44, r: 8, fill: color }), - text(330, 101 + i * 44, label, 13, C.ink2, "start"), - ), - ), - caption("hot water dissolves them in this order — brewing is choosing when to stop"), - ]; - }, - yieldMap() { - return [ - text(150, 92, "sour · thin", 12.5, C.fail, "middle", "700"), - text(280, 78, "sweet spot", 13, C.pass, "middle", "700"), - text(280, 96, "18–22%", 13, C.pass, "middle", "700"), - text(412, 92, "bitter · drying", 12.5, C.fail, "middle", "700"), - el("rect", { x: 90, y: 112, width: 380, height: 56, rx: 10, fill: C.paper, stroke: C.line }), - el("rect", { x: 90, y: 112, width: 128, height: 56, rx: 10, fill: C.fail, opacity: 0.1 }), - el("rect", { x: 342, y: 112, width: 128, height: 56, rx: 10, fill: C.fail, opacity: 0.1 }), - el("rect", { x: 218, y: 112, width: 124, height: 56, fill: C.pass, opacity: 0.16 }), - el("circle", { cx: 280, cy: 140, r: 7, fill: C.ember, class: "ac-slide-x" }), - text(280, 194, "extraction yield →", 12, C.ink2), - text(280, 230, "strength = coffee in the water", 12.5, C.ink2), - text(280, 248, "extraction = what you took from the grounds", 12.5, C.ink2), - caption("aim the dot at the middle: every dial below exists to move it"), - ]; - }, - grind() { - const pile = (x, label, sub, circles) => { - const g = el("g", {}); - for (const [dx, dy, r] of circles) g.append(el("circle", { cx: x + dx, cy: 128 + dy, r, fill: C.brown })); - g.append(text(x, 196, label, 13, C.ink, "middle", "700"), text(x, 216, sub, 11.5, C.ink2)); - return g; - }; - return [ - text(280, 62, "the same 20 grams of coffee", 12.5), - pile(130, "coarse", "less surface · fast flow", [[-16, -10, 19], [16, -8, 19], [0, 18, 19]]), - pile(280, "medium", "the middle path", [[-24, -14, 10], [0, -18, 10], [24, -14, 10], [-14, 4, 10], [12, 4, 10], [-2, 22, 10], [22, 20, 10]]), - pile(430, "fine", "more surface · slow flow", [...Array(16)].map((_, i) => [((i % 4) - 1.5) * 16, (Math.floor(i / 4) - 1.5) * 15, 5])), - caption("grind is the master dial — it moves extraction and contact time together"), - ]; - }, - tempTime() { - return [ - // Temperature: contained thermometer - el("rect", { x: 108, y: 68, width: 18, height: 118, rx: 9, fill: C.paper, stroke: C.ink2, "stroke-width": 2 }), - el("circle", { cx: 117, cy: 198, r: 13, fill: C.ember }), - el("rect", { x: 112, y: 76, width: 10, height: 106, rx: 5, fill: C.ember, class: "ac-fill-up" }), - text(117, 240, "90–96 °C", 12.5, C.ink, "middle", "700"), - // Time: a gauge whose needle sweeps - el("path", { d: "M220 190 A 62 62 0 0 1 340 190", fill: "none", stroke: C.line, "stroke-width": 10, "stroke-linecap": "round" }), - el("line", { x1: 280, y1: 190, x2: 280, y2: 138, stroke: C.ink, "stroke-width": 4, class: "ac-needle", "transform-origin": "280px 190px" }), - el("circle", { cx: 280, cy: 190, r: 8, fill: C.ink }), - text(280, 240, "time = how far down the list", 12.5, C.ink, "middle", "700"), - // Ratio: one bean to many drops - bean(420, 110, 0.62, C.brown), - text(446, 116, "1 :", 15, C.ink, "start", "700"), - ...[0, 1, 2].map((i) => - el("path", { d: `M${480 + i * 18} 104 c 5 8 5 14 0 18 c -5 -4 -5 -10 0 -18 Z`, fill: C.water, class: `ac-pulse ac-delay-${i}` }), - ), - text(466, 240, "1:15–1:17", 12.5, C.ink, "middle", "700"), - caption("three dials on one cup — and grind, from the previous slide, is the fourth"), - ]; - }, - tasteDial() { - return [ - el("path", { d: "M130 198 A 156 156 0 0 1 430 198", fill: "none", stroke: C.line, "stroke-width": 15, "stroke-linecap": "round" }), - el("path", { d: "M130 198 A 156 156 0 0 1 232 72", fill: "none", stroke: C.fail, "stroke-width": 15, "stroke-linecap": "round", opacity: 0.5 }), - el("path", { d: "M328 72 A 156 156 0 0 1 430 198", fill: "none", stroke: C.fail, "stroke-width": 15, "stroke-linecap": "round", opacity: 0.5 }), - text(126, 232, "sour · sharp", 12.5, C.fail, "middle", "700"), - text(280, 48, "sweet & balanced", 13, C.pass, "middle", "700"), - text(434, 232, "bitter · drying", 12.5, C.fail, "middle", "700"), - el("line", { x1: 280, y1: 198, x2: 280, y2: 92, stroke: C.ink, "stroke-width": 4, class: "ac-dial", "transform-origin": "280px 198px" }), - el("circle", { cx: 280, cy: 198, r: 10, fill: C.ink }), - text(280, 246, "sour? extract more · bitter? extract less", 13, C.ink, "middle", "700"), - caption("finer, hotter, longer ← the dial → coarser, cooler, shorter"), - ]; - }, - bloom() { - const [bx, by] = [280, 118]; - return [ - silhouette("v60"), - // CO₂ bubbles rising out of the cone - ...[0, 1, 2, 3].map((i) => - el("circle", { cx: bx - 18 + i * 12, cy: by - i * 3, r: 4 - i * 0.5, fill: C.tan, class: `ac-rise ac-delay-${i}` }), - ), - text(430, 96, "CO₂ escaping —", 12.5, C.tan, "start", "700"), - text(430, 114, "the bed swells", 12.5, C.ink2, "start"), - text(430, 132, "and bubbles", 12.5, C.ink2, "start"), - text(130, 96, "2× the coffee's", 12.5, C.ink2, "end"), - text(130, 114, "weight in water", 12.5, C.ink2, "end"), - text(130, 132, "wait 30–45 s", 12.5, C.ember, "end", "700"), - caption("gas pushes water away from coffee — bloom first, then brew"), - ]; - }, - tamp() { - return [ - // Tamper descending onto the basket - el("g", { class: "ac-tamp" }, - el("rect", { x: 262, y: 44, width: 16, height: 26, rx: 5, fill: C.ink }), - el("rect", { x: 238, y: 70, width: 64, height: 20, rx: 5, fill: C.ink })), - el("rect", { x: 206, y: 118, width: 148, height: 54, rx: 8, fill: C.ink2 }), - el("rect", { x: 216, y: 128, width: 128, height: 36, rx: 4, fill: C.brown }), - el("line", { x1: 216, y1: 128, x2: 344, y2: 128, stroke: C.paper, "stroke-width": 1.5, "stroke-dasharray": "4 4" }), - text(390, 140, "level, even,", 12.5, C.ink2, "start"), - text(390, 158, "no gaps", 12.5, C.ink2, "start"), - text(170, 140, "dose to 0.1 g", 12.5, C.ink2, "end"), - text(280, 220, "distribute · tamp level · no ritual, just channel prevention", 13, C.ink, "middle", "700"), - caption("pressurized water exploits any weakness in the puck"), - ]; - }, - shot() { - return [ - el("rect", { x: 230, y: 56, width: 100, height: 32, rx: 6, fill: C.ink }), - el("line", { x1: 268, y1: 88, x2: 268, y2: 122, stroke: C.brown, "stroke-width": 5, class: "ac-drip" }), - el("line", { x1: 292, y1: 88, x2: 292, y2: 122, stroke: C.brown, "stroke-width": 5, class: "ac-drip ac-delay-1" }), - el("path", { d: "M248 130 h 64 l -7 40 h -50 Z", fill: C.paper, stroke: C.ink2, "stroke-width": 2 }), - el("rect", { x: 252, y: 146, width: 56, height: 0, fill: C.tan, class: "ac-grow-h-down" }), - text(392, 108, "18 g in → 36 g out", 13, C.ink, "start", "700"), - text(392, 130, "in 25–32 seconds", 12.5, C.ink2, "start"), - text(392, 152, "flows like warm honey", 12.5, C.tan, "start"), - text(168, 130, "9 bar, above", 12.5, C.ink2, "end"), - text(280, 220, "blonde & gushing → grind finer · choked drips → coarser", 12.5, C.ink), - caption("the stream itself tells you which way the grind is wrong"), - ]; - }, - brewAnim({ method, mode }) { - const m = findBrewMethod(method); - const [bx, by] = sil(...(BOWL[method] ?? [32, 30])); - const out = [silhouette(method), text(280, 262, m?.name ?? method, 13.5, C.ink, "middle", "700")]; - const hint = (lines, color = C.ink2) => - lines.forEach((s, i) => out.push(text(432, 100 + i * 19, s, 12.5, color, "start", i === 0 ? "700" : "400"))); - - if (mode === "steep" || mode === "valve") { - out.push( - ...[...Array(6)].map((_, i) => - el("circle", { - cx: bx - 22 + (i % 3) * 22, cy: by - 8 + Math.floor(i / 3) * 16, r: 4, - fill: C.brown, class: `ac-float ac-delay-${i % 3}`, - }), - ), - ); - hint(mode === "valve" ? ["steep closed…", "then open the", "valve and drain"] : ["all the water,", "all the grounds,", "the whole time"]); - } - if (mode === "plunge" || mode === "press") { - out.push( - el("g", { class: "ac-tamp" }, - el("path", { d: `M${bx} ${by - 52} v 30`, stroke: C.ember, "stroke-width": 5, "stroke-linecap": "round" }), - el("path", { d: `M${bx - 9} ${by - 20} h 18`, stroke: C.ember, "stroke-width": 4, "stroke-linecap": "round" })), - ); - hint(mode === "press" ? ["steep 1:30,", "press 0:30,", "gently"] : ["press slowly,", "stop above the", "grounds"]); - } - if (mode === "pour" || mode === "spiral" || mode === "drip") { - out.push( - ...[0, 1, 2].map((i) => - el("line", { x1: bx - 10 + i * 10, y1: by - 34, x2: bx - 10 + i * 10, y2: by - 14, stroke: C.water, "stroke-width": 2.5, class: `ac-drip ac-delay-${i}` }), - ), - ); - if (mode === "spiral") - out.push(el("path", { d: `M${bx} ${by} m -16 0 a 16 16 0 1 1 32 0 a 12 12 0 1 1 -24 0`, fill: "none", stroke: C.water, "stroke-width": 2, class: "ac-pourline" })); - hint(mode === "spiral" ? ["slow spirals,", "centre out,", "keep it level"] : mode === "drip" ? ["the robot pours;", "you choose grind", "and ratio"] : ["fresh water,", "always passing", "through the bed"]); - } - if (mode === "pressure") { - out.push( - ...[0, 1, 2].map((i) => - el("path", { d: `M${bx - 26 + i * 26} ${by - 26} v 14`, stroke: C.ember, "stroke-width": 3.5, "stroke-linecap": "round", class: `ac-pulse ac-delay-${i}` }), - ), - ); - hint(["9 bar pushes", "water through", "the puck"], C.ember); - } - if (mode === "flame") { - out.push(flame(bx, sil(32, 66)[1], 1)); - hint(["≈1.5 bar of", "boiler steam", "pushes upward"]); - } - return out; - }, -}; +import { SCENES, sceneFallbackText } from "./academy-scenes.js?v=__ASSET_VERSION__"; // ── Progress ─────────────────────────────────────────────────────────────── @@ -625,7 +123,7 @@ function renderSlide() { try { svg.append(...SCENES[slide.scene[0]](slide.scene[1] ?? {})); } catch { - svg.append(text(280, 150, slide.title, 16, C.ink2)); + svg.append(sceneFallbackText(slide.title)); } $("player-caption").textContent = slide.transcript;