767 lines
51 KiB
HTML
767 lines
51 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Roast Planner</title>
|
||
<meta name="theme-color" content="#A8481A">
|
||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||
<link rel="manifest" href="/manifest.webmanifest">
|
||
<link rel="icon" href="/icon.svg" type="image/svg+xml">
|
||
<link rel="apple-touch-icon" href="/icon.svg">
|
||
<link rel="stylesheet" href="/worksheet.css" media="print">
|
||
<link rel="stylesheet" href="/app.css">
|
||
</head>
|
||
<body>
|
||
|
||
<header class="app-header">
|
||
<div class="brand">
|
||
<span class="brand-mark" aria-hidden="true">◐</span>
|
||
<div class="brand-text">
|
||
<h1>Roast Planner</h1>
|
||
<p class="brand-sub" id="header-coffee-name">New plan</p>
|
||
</div>
|
||
</div>
|
||
|
||
<nav class="section-nav" id="section-nav" aria-label="Jump to section">
|
||
<a href="#sec-coffee">Coffee</a>
|
||
<a href="#sec-blend">Blend</a>
|
||
<a href="#sec-process">Roast target</a>
|
||
<a href="#sec-bean">Bean condition</a>
|
||
<a href="#sec-machine">Machine plan</a>
|
||
<a href="#sec-roastlog">Roast log</a>
|
||
<a href="#sec-after">After the roast</a>
|
||
</nav>
|
||
|
||
<div class="header-actions">
|
||
<button id="btn-toggle-fids" type="button" class="ghost-btn" aria-pressed="false" title="Show the worksheet reference codes (e.g. 1.4) on every field">Field IDs</button>
|
||
<button id="btn-toggle-prefill" type="button" class="ghost-btn">Prefill from URL</button>
|
||
<button id="btn-toggle-alog" type="button" class="ghost-btn">Reference curve</button>
|
||
<span class="header-divider" aria-hidden="true"></span>
|
||
<button id="btn-load" type="button" class="ghost-btn">Load</button>
|
||
<input id="file-load" type="file" accept="application/json">
|
||
<button id="btn-save" type="button" class="ghost-btn">Download</button>
|
||
<button id="btn-admin" type="button" class="ghost-btn hidden">Admin</button>
|
||
<button id="btn-print" type="button" class="primary-btn">Print</button>
|
||
<span class="autosave-chip" id="autosave-status"><span class="dot"></span><span class="autosave-text">Not saved yet</span></span>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="connection-status hidden" id="connection-status" role="status" aria-live="polite"></div>
|
||
<div class="drawer-overlay hidden" id="drawer-overlay"></div>
|
||
|
||
<aside class="drawer hidden" id="panel-prefill" aria-hidden="true">
|
||
<div class="drawer-head">
|
||
<h3>Prefill from a bean product URL</h3>
|
||
<button class="icon-btn" type="button" data-close-drawer aria-label="Close">✕</button>
|
||
</div>
|
||
<div class="drawer-body">
|
||
<label class="stack-label" for="prefill-url">Product page URL</label>
|
||
<input type="url" id="prefill-url" class="text-input" placeholder="https://roaster.example/shop/some-coffee">
|
||
<label class="checkbox-row"><input type="checkbox" id="prefill-overwrite"> Overwrite already-filled fields</label>
|
||
<div class="drawer-actions">
|
||
<button id="prefill-go" type="button" class="primary-btn">Fetch & prefill</button>
|
||
<button id="prefill-undo" type="button" class="ghost-btn" disabled>Undo prefill</button>
|
||
</div>
|
||
<div id="prefill-result" class="drawer-result"></div>
|
||
</div>
|
||
</aside>
|
||
|
||
<aside class="drawer hidden" id="panel-alog" aria-hidden="true">
|
||
<div class="drawer-head">
|
||
<h3>Attach an Artisan .alog reference curve</h3>
|
||
<button class="icon-btn" type="button" data-close-drawer aria-label="Close">✕</button>
|
||
</div>
|
||
<div class="drawer-body">
|
||
<label class="filebtn primary-btn">Choose .alog file<input type="file" id="alog-file" accept=".alog"></label>
|
||
<button id="alog-library-refresh" type="button" class="ghost-btn">Show local library</button>
|
||
<ul class="lib-list hidden" id="alog-library-list"></ul>
|
||
<div id="alog-result" class="drawer-result"></div>
|
||
</div>
|
||
</aside>
|
||
|
||
<form id="plan-form">
|
||
|
||
<div class="workspace-grid">
|
||
<div class="form-col">
|
||
|
||
<section class="panel-card" id="sec-coffee">
|
||
<div class="panel-head"><h2>The Coffee</h2></div>
|
||
<div class="panel-body">
|
||
<div class="field-grid">
|
||
<label class="field" data-fid="0.1"><span class="field-label">Coffee / lot</span><input class="field-input" name="0.1" placeholder="e.g. Finca El Ocaso"></label>
|
||
<label class="field" data-fid="0.2"><span class="field-label">Date</span><input class="field-input" type="date" name="0.2"></label>
|
||
<label class="field" data-fid="0.3"><span class="field-label">Batch #</span><input class="field-input" name="0.3"></label>
|
||
<label class="field" data-fid="0.4"><span class="field-label">Green in</span><div class="unit-input"><input class="field-input" name="0.4"><span class="unit">g</span></div></label>
|
||
</div>
|
||
|
||
<div class="subhead">Cultivar</div>
|
||
<div class="field-grid">
|
||
<label class="field" data-fid="1.1"><span class="field-label">Cultivar</span><input class="field-input" name="1.1" list="cultivar-list" placeholder="e.g. Caturra" autocomplete="off"></label>
|
||
<div class="field" data-fid="1.3"><span class="field-label">Origin</span><input class="field-input" name="1.3" placeholder="e.g. Huila, Colombia"></div>
|
||
<div class="field wide" data-fid="1.2">
|
||
<span class="field-label">Group</span>
|
||
<div class="segmented" data-radio-group="1.2">
|
||
<label class="seg-opt"><input type="radio" name="1.2" value="typica"><span>Typica</span></label>
|
||
<label class="seg-opt"><input type="radio" name="1.2" value="bourbon"><span>Bourbon</span></label>
|
||
<label class="seg-opt"><input type="radio" name="1.2" value="ethiopian"><span>Ethiopian</span></label>
|
||
<label class="seg-opt"><input type="radio" name="1.2" value="hybrid"><span>Hybrid</span></label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="field-grid">
|
||
<label class="field" data-fid="1.4"><span class="field-label">FC anchor <span class="hint" title="Feeds Time Ledger line 1">ⓘ</span></span><input class="field-input" name="1.4" placeholder="8:45"></label>
|
||
<label class="field" data-fid="1.5"><span class="field-label">Profile mm:ss|mm:ss|mm:ss</span><input class="field-input" name="1.5" placeholder="4:15|3:15|1:30"></label>
|
||
<label class="field" data-fid="1.6"><span class="field-label">± Refine <span class="hint" title="0 on the first cook of this cultivar, otherwise carried from Step 12">ⓘ</span></span><input class="field-input" name="1.6" placeholder="0"></label>
|
||
<label class="field" data-fid="1.7"><span class="field-label">± Dev modifier <span class="hint" title="Step 1's profile 3rd number, minus 1:30">ⓘ</span></span><input class="field-input" name="1.7"></label>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel-card" id="sec-blend">
|
||
<div class="panel-head">
|
||
<h2>Blend</h2>
|
||
<div class="segmented small" data-radio-group="2.1">
|
||
<label class="seg-opt"><input type="radio" name="2.1" value="single" checked><span>Single-origin</span></label>
|
||
<label class="seg-opt"><input type="radio" name="2.1" value="blend"><span>Blend</span></label>
|
||
</div>
|
||
</div>
|
||
<div class="panel-body" id="blend-body">
|
||
<div class="blend-cards" id="blend-cards"></div>
|
||
<div class="blend-total" id="blend-total">
|
||
<div class="blend-total-bar"><div class="blend-total-fill" id="blend-total-fill"></div></div>
|
||
<span class="blend-total-label" id="blend-total-label">0% of 100%</span>
|
||
</div>
|
||
<button type="button" class="ghost-btn small" id="btn-add-blend">+ Add component</button>
|
||
|
||
<div class="subhead">How the components combine</div>
|
||
<div class="field wide" data-fid="2.3">
|
||
<div class="segmented" data-radio-group="2.3">
|
||
<label class="seg-opt"><input type="radio" name="2.3" value="dominant"><span>Dominant (≥60%)</span></label>
|
||
<label class="seg-opt"><input type="radio" name="2.3" value="weighted"><span>Weighted average</span></label>
|
||
<label class="seg-opt"><input type="radio" name="2.3" value="split"><span>Split-roast, blend after</span></label>
|
||
</div>
|
||
</div>
|
||
<div class="field-grid">
|
||
<label class="field" data-fid="2.4"><span class="field-label">Resulting FC anchor</span><input class="field-input" name="2.4"></label>
|
||
<label class="field" data-fid="2.5"><span class="field-label">Resulting processing modifier</span><input class="field-input" name="2.5"></label>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel-card" id="sec-process">
|
||
<div class="panel-head"><h2>Roast Target</h2></div>
|
||
<div class="panel-body">
|
||
<div class="field wide" data-fid="3.1">
|
||
<span class="field-label">Process</span>
|
||
<div class="chip-group" data-radio-group="3.1">
|
||
<label class="chip-opt"><input type="radio" name="3.1" value="washed"><span>Washed</span></label>
|
||
<label class="chip-opt"><input type="radio" name="3.1" value="yellow-honey"><span>Yellow / white honey</span></label>
|
||
<label class="chip-opt"><input type="radio" name="3.1" value="red-black-honey"><span>Red / black honey</span></label>
|
||
<label class="chip-opt"><input type="radio" name="3.1" value="natural"><span>Natural</span></label>
|
||
<label class="chip-opt"><input type="radio" name="3.1" value="anaerobic"><span>Anaerobic / CM</span></label>
|
||
</div>
|
||
</div>
|
||
<div class="field-grid">
|
||
<label class="field" data-fid="3.2"><span class="field-label">Dev modifier</span><input class="field-input" name="3.2"></label>
|
||
</div>
|
||
|
||
<div class="subhead">Roast level</div>
|
||
<div class="field wide" data-fid="4.1">
|
||
<div class="chip-group" data-radio-group="4.1">
|
||
<label class="chip-opt"><input type="radio" name="4.1" value="light"><span>Light</span></label>
|
||
<label class="chip-opt"><input type="radio" name="4.1" value="light-medium"><span>Light-medium</span></label>
|
||
<label class="chip-opt"><input type="radio" name="4.1" value="medium"><span>Medium</span></label>
|
||
<label class="chip-opt"><input type="radio" name="4.1" value="dark"><span>Dark</span></label>
|
||
<label class="chip-opt"><input type="radio" name="4.1" value="very-dark"><span>Very dark</span></label>
|
||
</div>
|
||
</div>
|
||
<div class="field-grid">
|
||
<label class="field" data-fid="4.2"><span class="field-label">Target weight loss</span><div class="unit-input"><input class="field-input" name="4.2"><span class="unit">%</span></div></label>
|
||
<label class="field" data-fid="4.3"><span class="field-label">Dev base</span><input class="field-input" name="4.3"></label>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel-card" id="sec-bean">
|
||
<div class="panel-head"><h2>Bean Condition</h2></div>
|
||
<div class="panel-body">
|
||
<div class="field-grid">
|
||
<label class="field" data-fid="5.1"><span class="field-label">Moisture</span><div class="unit-input"><input class="field-input" name="5.1"><span class="unit">%</span></div></label>
|
||
<label class="field" data-fid="5.2"><span class="field-label">Density</span><div class="unit-input"><input class="field-input" name="5.2"><span class="unit">g/L</span></div></label>
|
||
<label class="field" data-fid="5.3"><span class="field-label">Altitude</span><input class="field-input" name="5.3"></label>
|
||
<label class="field" data-fid="5.4"><span class="field-label">Screen</span><input class="field-input" name="5.4"></label>
|
||
</div>
|
||
<div class="field-grid">
|
||
<div class="field" data-fid="5.5">
|
||
<span class="field-label">Sweet spot</span>
|
||
<div class="segmented" data-radio-group="5.5">
|
||
<label class="seg-opt"><input type="radio" name="5.5" value="narrow"><span>Narrow</span></label>
|
||
<label class="seg-opt"><input type="radio" name="5.5" value="med"><span>Medium</span></label>
|
||
<label class="seg-opt"><input type="radio" name="5.5" value="wide"><span>Wide</span></label>
|
||
</div>
|
||
</div>
|
||
<label class="field" data-fid="5.6"><span class="field-label">± Net correction <span class="hint" title="Judgment call — rarely more than ±0:15">ⓘ</span></span><input class="field-input" name="5.6"></label>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel-card" id="sec-machine">
|
||
<div class="panel-head"><h2>Machine Plan</h2></div>
|
||
<div class="panel-body">
|
||
<div class="subhead">Temperatures & rate-of-rise</div>
|
||
<div class="milestone-list">
|
||
<div class="milestone-row band-row" data-band-lo="133" data-band-hi="195">
|
||
<div class="milestone-label">Charge</div>
|
||
<output class="milestone-plan" data-out="t-charge">0:00</output>
|
||
<div class="band-track"><div class="band-range"></div><div class="band-marker"></div></div>
|
||
<div class="unit-input sm"><input class="field-input sm" name="temps.charge.tempC" placeholder="°C"><span class="unit">°C</span></div>
|
||
</div>
|
||
<div class="milestone-row band-row" data-band-lo="77" data-band-hi="100">
|
||
<div class="milestone-label">Turning point</div>
|
||
<input class="field-input sm milestone-time" name="temps.tp.time" placeholder="m:ss">
|
||
<div class="band-track"><div class="band-range"></div><div class="band-marker"></div></div>
|
||
<div class="unit-input sm"><input class="field-input sm" name="temps.tp.tempC" placeholder="°C"><span class="unit">°C</span></div>
|
||
</div>
|
||
<div class="milestone-row band-row" data-band-lo="148" data-band-hi="166">
|
||
<div class="milestone-label">Yellow</div>
|
||
<output class="milestone-plan" data-out="t-yellow">—</output>
|
||
<div class="band-track"><div class="band-range"></div><div class="band-marker"></div></div>
|
||
<div class="unit-input sm"><input class="field-input sm" name="temps.yellow.tempC" placeholder="°C"><span class="unit">°C</span></div>
|
||
</div>
|
||
<div class="milestone-row band-row" data-band-lo="176" data-band-hi="187">
|
||
<div class="milestone-label">First crack</div>
|
||
<output class="milestone-plan" data-out="t-fc">—</output>
|
||
<div class="band-track"><div class="band-range"></div><div class="band-marker"></div></div>
|
||
<div class="unit-input sm"><input class="field-input sm" name="temps.fc.tempC" placeholder="°C"><span class="unit">°C</span></div>
|
||
</div>
|
||
<div class="milestone-row band-row" data-band-lo="183" data-band-hi="197">
|
||
<div class="milestone-label">Drop</div>
|
||
<output class="milestone-plan" data-out="t-drop">—</output>
|
||
<div class="band-track"><div class="band-range"></div><div class="band-marker"></div></div>
|
||
<div class="unit-input sm"><input class="field-input sm" name="temps.drop.tempC" placeholder="°C"><span class="unit">°C</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="subhead">Actuator schedule (planned)</div>
|
||
<div class="actuator-timeline" id="actuator-timeline"></div>
|
||
<button type="button" class="ghost-btn small" id="btn-add-actuator">+ Add step</button>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel-card" id="sec-roastlog">
|
||
<div class="panel-head"><h2>Roast Log — Plan vs. Actual</h2></div>
|
||
<div class="panel-body">
|
||
<div class="milestone-list">
|
||
<div class="milestone-row log-row">
|
||
<div class="milestone-label">Charge</div>
|
||
<output class="milestone-plan" data-out="pa-charge">0:00</output>
|
||
<input class="field-input sm" name="planActual.charge.actualTime" placeholder="0:00">
|
||
<input class="field-input sm" name="planActual.charge.actualBt" placeholder="°C">
|
||
<input class="field-input note" name="planActual.charge.note" placeholder="Note">
|
||
</div>
|
||
<div class="milestone-row log-row">
|
||
<div class="milestone-label">Turning point</div>
|
||
<output class="milestone-plan" data-out="pa-tp">—</output>
|
||
<input class="field-input sm" name="planActual.tp.actualTime" placeholder="0:00">
|
||
<input class="field-input sm" name="planActual.tp.actualBt" placeholder="°C">
|
||
<input class="field-input note" name="planActual.tp.note" placeholder="Note">
|
||
</div>
|
||
<div class="milestone-row log-row">
|
||
<div class="milestone-label">Yellow</div>
|
||
<output class="milestone-plan" data-out="pa-yellow">—</output>
|
||
<input class="field-input sm" name="planActual.yellow.actualTime" placeholder="0:00">
|
||
<input class="field-input sm" name="planActual.yellow.actualBt" placeholder="°C">
|
||
<input class="field-input note" name="planActual.yellow.note" placeholder="Note">
|
||
</div>
|
||
<div class="milestone-row log-row">
|
||
<div class="milestone-label">First crack</div>
|
||
<output class="milestone-plan" data-out="pa-fc">—</output>
|
||
<input class="field-input sm" name="planActual.fc.actualTime" placeholder="0:00">
|
||
<input class="field-input sm" name="planActual.fc.actualBt" placeholder="°C">
|
||
<input class="field-input note" name="planActual.fc.note" placeholder="Note">
|
||
</div>
|
||
<div class="milestone-row log-row">
|
||
<div class="milestone-label">Drop</div>
|
||
<output class="milestone-plan" data-out="pa-drop">—</output>
|
||
<input class="field-input sm" name="planActual.drop.actualTime" placeholder="0:00">
|
||
<input class="field-input sm" name="planActual.drop.actualBt" placeholder="°C">
|
||
<input class="field-input note" name="planActual.drop.note" placeholder="Note">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel-card" id="sec-after">
|
||
<div class="panel-head"><h2>After the Roast</h2></div>
|
||
<div class="panel-body">
|
||
<div class="field-grid">
|
||
<label class="field"><span class="field-label">Green in</span><div class="unit-input"><input class="field-input" name="afterRoast.greenIn"><span class="unit">g</span></div></label>
|
||
<label class="field"><span class="field-label">Out</span><div class="unit-input"><input class="field-input" name="afterRoast.out"><span class="unit">g</span></div></label>
|
||
<label class="field"><span class="field-label">Weight loss</span><div class="unit-input"><input class="field-input" name="afterRoast.weightLossPct"><span class="unit">%</span></div></label>
|
||
<label class="field"><span class="field-label">Actual DTR</span><div class="unit-input"><input class="field-input" name="afterRoast.actualDtrPct"><span class="unit">%</span></div></label>
|
||
</div>
|
||
<div class="field-grid">
|
||
<label class="field"><span class="field-label">Colour WB/GR</span><input class="field-input" name="afterRoast.colour"></label>
|
||
<label class="field"><span class="field-label">Rested</span><div class="unit-input"><input class="field-input" name="afterRoast.restedDays"><span class="unit">days</span></div></label>
|
||
<label class="field"><span class="field-label">Brew ratio</span><input class="field-input" name="afterRoast.brewRatio"></label>
|
||
<label class="field"><span class="field-label">Method</span><input class="field-input" name="afterRoast.method"></label>
|
||
</div>
|
||
<label class="field"><span class="field-label">Cup notes</span><input class="field-input" name="afterRoast.cupNotes"></label>
|
||
<div class="field-grid">
|
||
<label class="field accent"><span class="field-label">One change next batch</span><input class="field-input" name="afterRoast.oneChange"></label>
|
||
<label class="field"><span class="field-label">What would prove it wrong</span><input class="field-input" name="afterRoast.disproof"></label>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
</div>
|
||
|
||
<aside class="dock">
|
||
<div class="dock-card ledger-card">
|
||
<div class="dock-card-head"><h2>Time Ledger</h2></div>
|
||
|
||
<div class="ledger-group">
|
||
<div class="ledger-row"><span class="l-fid">1.4</span><span class="l-label">Cultivar / blend anchor</span><output class="l-val" data-out="l1">—</output></div>
|
||
<div class="ledger-row"><span class="l-fid">1.6</span><span class="l-label">± Refinement</span><output class="l-val" data-out="l2">—</output></div>
|
||
<div class="ledger-row"><span class="l-fid">5.6</span><span class="l-label">± Bean condition</span><output class="l-val" data-out="l3">—</output></div>
|
||
<div class="ledger-row"><span class="l-fid">6.4</span><span class="l-label">± Batch size</span><input class="ledger-input" name="6.4" placeholder="0"></div>
|
||
</div>
|
||
<div class="ledger-total hero"><span>First crack</span><output data-out="A">—</output></div>
|
||
|
||
<div class="ledger-info">
|
||
<div class="info-pill"><span>Yellow</span><output data-out="yellow">—</output></div>
|
||
<div class="info-pill"><span>Maillard</span><output data-out="maillard">—</output></div>
|
||
<span class="info-note">informational — not summed into development</span>
|
||
</div>
|
||
|
||
<div class="ledger-group">
|
||
<div class="ledger-row"><span class="l-fid">4.3</span><span class="l-label">Development base</span><output class="l-val" data-out="l7">—</output></div>
|
||
<div class="ledger-row"><span class="l-fid">3.2</span><span class="l-label">± Processing modifier</span><output class="l-val" data-out="l8">—</output></div>
|
||
<div class="ledger-row"><span class="l-fid">1.7</span><span class="l-label">± Cultivar dev modifier</span><output class="l-val" data-out="l9">—</output></div>
|
||
</div>
|
||
<div class="ledger-total hero"><span>Development</span><output data-out="C">—</output></div>
|
||
<div class="ledger-total hero drop"><span>Drop (end of roast)</span><output data-out="D">—</output></div>
|
||
</div>
|
||
|
||
<div class="dock-card checks-card">
|
||
<div class="dock-card-head"><h2>Sanity Checks</h2></div>
|
||
<div class="checks-grid">
|
||
<div class="check-tile unknown" data-pass="drying">
|
||
<span class="check-name">Drying share</span>
|
||
<output class="check-value" data-out="check-drying">—</output>
|
||
<span class="check-band">target 43–51%</span>
|
||
</div>
|
||
<div class="check-tile unknown" data-pass="maillard">
|
||
<span class="check-name">Maillard share</span>
|
||
<output class="check-value" data-out="check-maillard">—</output>
|
||
<span class="check-band">target 33–39%</span>
|
||
</div>
|
||
<div class="check-tile unknown" data-pass="dtr">
|
||
<span class="check-name">Development ratio</span>
|
||
<output class="check-value" data-out="check-dtr">—</output>
|
||
<span class="check-band">target 12–20%</span>
|
||
</div>
|
||
<div class="check-tile unknown" data-pass="ceiling">
|
||
<span class="check-name">Development ceiling</span>
|
||
<output class="check-value" data-out="check-ceiling">—</output>
|
||
<span class="check-band">under 4:30</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dock-card curve-card">
|
||
<div class="dock-card-head"><h2>The Curve</h2><span class="curve-legend"><i class="sw sw-plan"></i>plan <i class="sw sw-ref"></i>reference</span></div>
|
||
<div class="curve-wrap">
|
||
<svg id="curve-svg-live" viewBox="0 0 714 334" width="100%" role="img" aria-label="Roast curve, live plan">
|
||
<defs><style>
|
||
#curve-svg-live .maj{stroke:var(--line);stroke-width:.7}
|
||
#curve-svg-live .min{stroke:var(--surface-sunken);stroke-width:.6}
|
||
#curve-svg-live .ax{stroke:var(--ink-3);stroke-width:1.1}
|
||
#curve-svg-live .al{font-size:8px;fill:var(--ink-3)}
|
||
#curve-svg-live .band{fill:var(--ember);opacity:.08}
|
||
#curve-svg-live .bandline{font-size:7.5px;fill:var(--ember)}
|
||
</style></defs>
|
||
<rect x="52" y="24" width="600" height="270" fill="var(--surface-raised)"/>
|
||
<rect class="band" x="52" y="65.4" width="600" height="19.8"/>
|
||
<text x="58" y="62.4" class="bandline">first-crack band, 176–187 °C</text>
|
||
<g class="min">
|
||
<line x1="72" y1="24" x2="72" y2="294"/><line x1="112" y1="24" x2="112" y2="294"/>
|
||
<line x1="152" y1="24" x2="152" y2="294"/><line x1="192" y1="24" x2="192" y2="294"/>
|
||
<line x1="232" y1="24" x2="232" y2="294"/><line x1="272" y1="24" x2="272" y2="294"/>
|
||
<line x1="312" y1="24" x2="312" y2="294"/><line x1="352" y1="24" x2="352" y2="294"/>
|
||
<line x1="392" y1="24" x2="392" y2="294"/><line x1="432" y1="24" x2="432" y2="294"/>
|
||
<line x1="472" y1="24" x2="472" y2="294"/><line x1="512" y1="24" x2="512" y2="294"/>
|
||
<line x1="552" y1="24" x2="552" y2="294"/><line x1="592" y1="24" x2="592" y2="294"/>
|
||
<line x1="632" y1="24" x2="632" y2="294"/>
|
||
</g>
|
||
<g class="maj">
|
||
<line x1="92" y1="24" x2="92" y2="294"/><line x1="132" y1="24" x2="132" y2="294"/>
|
||
<line x1="172" y1="24" x2="172" y2="294"/><line x1="212" y1="24" x2="212" y2="294"/>
|
||
<line x1="252" y1="24" x2="252" y2="294"/><line x1="292" y1="24" x2="292" y2="294"/>
|
||
<line x1="332" y1="24" x2="332" y2="294"/><line x1="372" y1="24" x2="372" y2="294"/>
|
||
<line x1="412" y1="24" x2="412" y2="294"/><line x1="452" y1="24" x2="452" y2="294"/>
|
||
<line x1="492" y1="24" x2="492" y2="294"/><line x1="532" y1="24" x2="532" y2="294"/>
|
||
<line x1="572" y1="24" x2="572" y2="294"/><line x1="612" y1="24" x2="612" y2="294"/>
|
||
</g>
|
||
<g class="min">
|
||
<line x1="52" y1="276" x2="652" y2="276"/><line x1="52" y1="240" x2="652" y2="240"/>
|
||
<line x1="52" y1="204" x2="652" y2="204"/><line x1="52" y1="168" x2="652" y2="168"/>
|
||
<line x1="52" y1="132" x2="652" y2="132"/><line x1="52" y1="96" x2="652" y2="96"/>
|
||
<line x1="52" y1="60" x2="652" y2="60"/>
|
||
</g>
|
||
<g class="maj">
|
||
<line x1="52" y1="258" x2="652" y2="258"/><line x1="52" y1="222" x2="652" y2="222"/>
|
||
<line x1="52" y1="186" x2="652" y2="186"/><line x1="52" y1="150" x2="652" y2="150"/>
|
||
<line x1="52" y1="114" x2="652" y2="114"/><line x1="52" y1="78" x2="652" y2="78"/>
|
||
<line x1="52" y1="42" x2="652" y2="42"/>
|
||
</g>
|
||
<line class="ax" x1="52" y1="24" x2="52" y2="294"/>
|
||
<line class="ax" x1="52" y1="294" x2="652" y2="294"/>
|
||
<line class="ax" x1="652" y1="24" x2="652" y2="294"/>
|
||
<g class="al" text-anchor="end">
|
||
<text x="47" y="296.8">60</text><text x="47" y="260.8">80</text><text x="47" y="224.8">100</text>
|
||
<text x="47" y="188.8">120</text><text x="47" y="152.8">140</text><text x="47" y="116.8">160</text>
|
||
<text x="47" y="80.8">180</text><text x="47" y="44.8">200</text>
|
||
</g>
|
||
<g class="al" text-anchor="middle">
|
||
<text x="52" y="304">0:00</text><text x="92" y="304">1:00</text><text x="132" y="304">2:00</text>
|
||
<text x="172" y="304">3:00</text><text x="212" y="304">4:00</text><text x="252" y="304">5:00</text>
|
||
<text x="292" y="304">6:00</text><text x="332" y="304">7:00</text><text x="372" y="304">8:00</text>
|
||
<text x="412" y="304">9:00</text><text x="452" y="304">10:00</text><text x="492" y="304">11:00</text>
|
||
<text x="532" y="304">12:00</text><text x="572" y="304">13:00</text><text x="612" y="304">14:00</text>
|
||
<text x="652" y="304">15:00</text>
|
||
</g>
|
||
<g id="plan-curve-live"></g>
|
||
<g id="ref-curve-live"></g>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
</div>
|
||
|
||
</form>
|
||
|
||
<!-- Kept OUTSIDE #plan-form on purpose: identically-named radios here must not fight for
|
||
mutual exclusivity with the screen form's radios (same name + same form owner would
|
||
silently uncheck one another). This whole block is display:none except when printing;
|
||
main.js re-syncs it from state.plan on beforeprint. -->
|
||
<div id="print-sheet">
|
||
<div class="sheet-wrap">
|
||
<div class="sheet">
|
||
|
||
<!-- ══════════════════ FRONT ══════════════════ -->
|
||
<section class="first">
|
||
<div class="wsbar">
|
||
<span class="t">Manual Roast Plan — Worksheet</span>
|
||
<span class="r">Sheet 1 of 2 · Plan | Hottop KN-8828B-2K+</span>
|
||
</div>
|
||
|
||
<div class="wsbox">
|
||
<div class="hd"><span class="id">THE COFFEE</span><span class="ref">[n.n] = field ID · cited everywhere it feeds a number</span></div>
|
||
<div class="bd wsline tightln">
|
||
<span class="fid">0.1</span><span class="lb">Coffee / lot</span> <input class="f ws-input" style="min-width:44mm" name="0.1"><span class="pv"></span>
|
||
<span class="sep">|</span><span class="fid">0.2</span><span class="lb">Date</span> <input class="f n ws-input" type="date" name="0.2"><span class="pv"></span>
|
||
<span class="sep">|</span><span class="fid">0.3</span><span class="lb">Batch #</span> <input class="f ws-input" style="min-width:10mm" name="0.3"><span class="pv"></span>
|
||
<span class="sep">|</span><span class="fid">0.4</span><span class="lb">Green in</span> <input class="f n ws-input" name="0.4">g<span class="pv"></span><br>
|
||
|
||
<span class="stepdot">1</span><span class="fid">1.1</span><span class="lb">Cultivar</span> <input class="f ws-input" style="min-width:30mm" name="1.1" list="cultivar-list"><span class="pv"></span>
|
||
<span class="sep">|</span><span class="fid">1.2</span><span class="lb">Group</span>
|
||
<span class="circ" data-radio-group="1.2">
|
||
<label class="opt"><input type="radio" name="1.2" value="typica"><span>Typica</span></label>
|
||
<label class="opt"><input type="radio" name="1.2" value="bourbon"><span>Bourbon</span></label>
|
||
<label class="opt"><input type="radio" name="1.2" value="ethiopian"><span>Ethiopian</span></label>
|
||
<label class="opt"><input type="radio" name="1.2" value="hybrid"><span>Hybrid</span></label>
|
||
</span>
|
||
<span class="sep">|</span><span class="fid">1.3</span><span class="lb">Origin</span> <input class="f ws-input" style="min-width:20mm" name="1.3"><span class="pv"></span><br>
|
||
|
||
<span class="fid" style="margin-left:4.6mm">1.4</span><span class="lb">FC anchor</span> <input class="f n ws-input" name="1.4"><span class="pv"></span>
|
||
<span class="sep">|</span><span class="fid">1.5</span><span class="lb">Profile mm:ss|mm:ss|mm:ss</span> <input class="f ws-input" style="min-width:22mm" name="1.5"><span class="pv"></span>
|
||
<span class="sep">|</span><small>your cultivar's row, Step 1 — not a group number</small><br>
|
||
|
||
<span class="fid" style="margin-left:4.6mm">1.6</span><span class="lb">± Refine → ledger 2</span> <input class="f n ws-input" name="1.6"><span class="pv"></span> <small>0 first cook, else Step 12</small>
|
||
<span class="sep">|</span><span class="fid">1.7</span><span class="lb">± Dev mod → ledger 9</span> <input class="f n ws-input" name="1.7"><span class="pv"></span> <small>Step 1's profile 3rd # −1:30</small><br>
|
||
|
||
<span class="stepdot">3</span><span class="fid">3.1</span><span class="lb">Process</span>
|
||
<span class="circ" data-radio-group="3.1">
|
||
<label class="opt"><input type="radio" name="3.1" value="washed"><span>washed</span></label>
|
||
<label class="opt"><input type="radio" name="3.1" value="yellow-honey"><span>yellow/white honey</span></label>
|
||
<label class="opt"><input type="radio" name="3.1" value="red-black-honey"><span>red/black honey</span></label>
|
||
<label class="opt"><input type="radio" name="3.1" value="natural"><span>natural</span></label>
|
||
<label class="opt"><input type="radio" name="3.1" value="anaerobic"><span>anaerobic/CM</span></label>
|
||
</span>
|
||
<span class="sep">|</span><span class="fid">3.2</span><span class="lb">Dev mod → ledger 8</span> <input class="f n ws-input" name="3.2"><span class="pv"></span> <small>Step 3 table</small><br>
|
||
|
||
<span class="stepdot">4</span><span class="fid">4.1</span><span class="lb">Roast level</span>
|
||
<span class="circ" data-radio-group="4.1">
|
||
<label class="opt"><input type="radio" name="4.1" value="light"><span>light</span></label>
|
||
<label class="opt"><input type="radio" name="4.1" value="light-medium"><span>light-med</span></label>
|
||
<label class="opt"><input type="radio" name="4.1" value="medium"><span>medium</span></label>
|
||
<label class="opt"><input type="radio" name="4.1" value="dark"><span>dark</span></label>
|
||
<label class="opt"><input type="radio" name="4.1" value="very-dark"><span>very dark</span></label>
|
||
</span>
|
||
<span class="sep">|</span><span class="fid">4.2</span><span class="lb">Target WL</span> <input class="f n ws-input" name="4.2">%<span class="pv"></span>
|
||
<span class="sep">|</span><span class="fid">4.3</span><span class="lb">Dev base → ledger 7</span> <input class="f n ws-input" style="min-width:12mm" name="4.3"><span class="pv"></span><br>
|
||
|
||
<span class="stepdot">5</span><span class="fid">5.1</span><span class="lb">Moisture</span> <input class="f n ws-input" name="5.1">%<span class="pv"></span>
|
||
<span class="sep">|</span><span class="fid">5.2</span><span class="lb">Density</span> <input class="f n ws-input" name="5.2">g/L<span class="pv"></span>
|
||
<span class="sep">|</span><span class="fid">5.3</span><span class="lb">Altitude</span> <input class="f n ws-input" name="5.3"><span class="pv"></span>
|
||
<span class="sep">|</span><span class="fid">5.4</span><span class="lb">Screen</span> <input class="f n ws-input" name="5.4"><span class="pv"></span>
|
||
<span class="sep">|</span><span class="fid">5.5</span><span class="lb">Sweet</span>
|
||
<span class="circ" data-radio-group="5.5">
|
||
<label class="opt"><input type="radio" name="5.5" value="narrow"><span>narrow</span></label>
|
||
<label class="opt"><input type="radio" name="5.5" value="med"><span>med</span></label>
|
||
<label class="opt"><input type="radio" name="5.5" value="wide"><span>wide</span></label>
|
||
</span><br>
|
||
<span class="fid" style="margin-left:4.6mm">5.6</span><span class="lb">± Net correction → ledger 3</span> <input class="f n ws-input" name="5.6"><span class="pv"></span> <small>judgment, rarely >±0:15</small>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wsbox">
|
||
<div class="hd"><span class="n">2 · BLEND</span><span class="ref">skip if single-origin → Step 2</span></div>
|
||
<div class="bd">
|
||
<div class="wsline tightln">
|
||
<span class="fid">2.1</span>This lot is:
|
||
<span class="circ" data-radio-group="2.1">
|
||
<label class="opt"><input type="radio" name="2.1" value="single" checked><span>single-origin — skip this box</span></label>
|
||
<label class="opt"><input type="radio" name="2.1" value="blend"><span>blend or community lot</span></label>
|
||
</span>
|
||
</div>
|
||
<table class="tight">
|
||
<thead><tr><th><span class="fid">2.2</span>Component</th><th style="width:22mm">Group</th><th style="width:24mm">Process</th>
|
||
<th class="num" style="width:14mm">Share %</th><th class="num" style="width:20mm">FC anchor</th></tr></thead>
|
||
<tbody id="blend-rows"></tbody>
|
||
</table>
|
||
<div class="wsline tightln">
|
||
<span class="fid">2.3</span>Method:
|
||
<span class="circ" data-radio-group="2.3">
|
||
<label class="opt"><input type="radio" name="2.3" value="dominant"><span>dominant (≥60%)</span></label>
|
||
<label class="opt"><input type="radio" name="2.3" value="weighted"><span>weighted average</span></label>
|
||
<label class="opt"><input type="radio" name="2.3" value="split"><span>split-roast, blend after</span></label>
|
||
</span>
|
||
</div>
|
||
<div class="wsline tightln">
|
||
<span class="fid">2.4</span><span class="lb">Resulting FC anchor → ledger line 1</span> <input class="f n ws-input" name="2.4"><span class="pv"></span>
|
||
<span class="sep">|</span><span class="fid">2.5</span><span class="lb">Resulting processing modifier → ledger line 8</span> <input class="f n ws-input" name="2.5"><span class="pv"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wsbox">
|
||
<div class="hd"><span class="n">6 · TIME LEDGER</span><span class="ref">method & why → Step 6</span></div>
|
||
<div class="bd">
|
||
<table class="ledger">
|
||
<tr class="row"><td class="ln">1</td><td class="desc">Cultivar/blend anchor
|
||
<span class="sub">from 1.4, or 2.4 if blend</span></td><td class="val"><output data-out="l1">—</output></td></tr>
|
||
<tr class="row"><td class="ln">2</td><td class="desc"><span class="op">±</span> Refinement — from 1.6
|
||
<span class="sub">0 first cook, else Step 12</span></td><td class="val"><output data-out="l2">—</output></td></tr>
|
||
<tr class="row"><td class="ln">3</td><td class="desc"><span class="op">±</span> Bean condition — from 5.6</td><td class="val"><output data-out="l3">—</output></td></tr>
|
||
<tr class="row"><td class="ln">4</td><td class="desc"><span class="op">±</span> Batch size vs. Step 9 reference weights
|
||
<span class="sub">225 g ≈ 1:30–2:00 later than 200 g</span></td><td class="val"><input class="f n ws-input" name="6.4" placeholder="0"><span class="pv"></span></td></tr>
|
||
<tr class="total"><td class="ln">A</td><td class="desc"><strong>FIRST CRACK</strong></td><td class="val"><output data-out="A">—</output></td></tr>
|
||
<tr class="grp"><td class="ln"></td><td class="desc" colspan="2">B · YELLOW / MAILLARD — informational only. NOT summed into C.</td></tr>
|
||
<tr class="row"><td class="ln">5</td><td class="desc"><strong>YELLOW</strong> = A × 0.56</td><td class="val"><output data-out="yellow">—</output></td></tr>
|
||
<tr class="row"><td class="ln">6</td><td class="desc"><strong>MAILLARD</strong> = A − line 5</td><td class="val"><output data-out="maillard">—</output></td></tr>
|
||
<tr class="grp"><td class="ln"></td><td class="desc" colspan="2">C · DEVELOPMENT — sum ONLY rows 7 + 8 + 9</td></tr>
|
||
<tr class="row"><td class="ln">7</td><td class="desc">Development base — from 4.3</td><td class="val"><output data-out="l7">—</output></td></tr>
|
||
<tr class="row"><td class="ln">8</td><td class="desc"><span class="op">±</span> Processing modifier — from 3.2, or 2.5 if blend</td><td class="val"><output data-out="l8">—</output></td></tr>
|
||
<tr class="row"><td class="ln">9</td><td class="desc"><span class="op">±</span> Cultivar dev modifier — from 1.7</td><td class="val"><output data-out="l9">—</output></td></tr>
|
||
<tr class="total"><td class="ln">C</td><td class="desc"><strong>DEVELOPMENT</strong> = 7 + 8 + 9 only</td><td class="val"><output data-out="C">—</output></td></tr>
|
||
<tr class="total"><td class="ln">D</td><td class="desc"><strong>DROP (end of roast)</strong> = A + C</td><td class="val"><output data-out="D">—</output></td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wsbox">
|
||
<div class="hd"><span class="n">7 · SANITY CHECKS</span><span class="ref">a fail sends you back to box 6 → Step 7</span></div>
|
||
<div class="bd">
|
||
<table class="tight">
|
||
<thead><tr><th style="width:44mm">Check</th><th class="num" style="width:24mm">Should be</th>
|
||
<th class="num" style="width:24mm">Yours</th><th class="num" style="width:16mm">Pass?</th><th>Failure means</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>Drying share</td><td class="num">43–51 %</td><td class="num"><output data-out="check-drying">—</output></td>
|
||
<td class="num passcell unknown" data-pass="drying"></td><td>high = late yellow · low = rushed</td></tr>
|
||
<tr><td>Maillard share</td><td class="num">33–39 %</td><td class="num"><output data-out="check-maillard">—</output></td>
|
||
<td class="num passcell unknown" data-pass="maillard"></td><td>low = too little browning</td></tr>
|
||
<tr><td>Development ratio</td><td class="num">12–20 %</td><td class="num"><output data-out="check-dtr">—</output></td>
|
||
<td class="num passcell unknown" data-pass="dtr"></td><td>under 12 % = under-developed</td></tr>
|
||
<tr><td>Development ceiling</td><td class="num">< 4:30</td><td class="num"><output data-out="check-ceiling">—</output></td>
|
||
<td class="num passcell unknown" data-pass="ceiling"></td><td>over 4:30 mutes any roast</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ══════════════════ BACK ══════════════════ -->
|
||
<section>
|
||
<div class="wsbar">
|
||
<span class="t">Roast & Record</span>
|
||
<span class="r">Sheet 2 of 2 | coffee: <span id="back-coffee-name"></span></span>
|
||
</div>
|
||
|
||
<div class="wsbox">
|
||
<div class="hd"><span class="n">8 · TEMPERATURES & RATE-OF-RISE</span><span class="ref">→ Step 8</span></div>
|
||
<div class="bd">
|
||
<table class="tight">
|
||
<thead><tr><th style="width:28mm">Milestone</th><th class="num" style="width:20mm">Time</th>
|
||
<th class="num" style="width:18mm">°C</th><th class="num" style="width:36mm">Your logged band</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>Charge</td><td class="num"><output data-out="t-charge">0:00</output></td>
|
||
<td class="num"><input class="f n ws-input" name="temps.charge.tempC"><span class="pv"></span></td><td class="num">133–195 °C</td></tr>
|
||
<tr><td>Turning point</td><td class="num"><input class="f n ws-input" name="temps.tp.time" placeholder="m:ss"><span class="pv"></span></td>
|
||
<td class="num"><input class="f n ws-input" name="temps.tp.tempC"><span class="pv"></span></td><td class="num">77–100 °C @ 0:47–1:15</td></tr>
|
||
<tr><td>Yellow</td><td class="num"><output data-out="t-yellow">—</output></td>
|
||
<td class="num"><input class="f n ws-input" name="temps.yellow.tempC"><span class="pv"></span></td><td class="num">148–166 °C</td></tr>
|
||
<tr><td>First crack</td><td class="num"><output data-out="t-fc">—</output></td>
|
||
<td class="num"><input class="f n ws-input" name="temps.fc.tempC"><span class="pv"></span></td><td class="num">176–187 °C</td></tr>
|
||
<tr><td>Drop</td><td class="num"><output data-out="t-drop">—</output></td>
|
||
<td class="num"><input class="f n ws-input" name="temps.drop.tempC"><span class="pv"></span></td><td class="num">183–197 °C light</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wsbox">
|
||
<div class="hd"><span class="n">9 · ACTUATOR SCHEDULE (planned)</span><span class="ref">→ Step 9</span></div>
|
||
<div class="bd">
|
||
<table class="tight">
|
||
<thead><tr><th class="num" style="width:20mm">Time</th><th class="num" style="width:18mm">Heat %</th>
|
||
<th class="num" style="width:18mm">Fan %</th><th class="num" style="width:26mm">Expected BT</th><th>Why this change</th></tr></thead>
|
||
<tbody id="actuator-rows"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wsbox wsgrid">
|
||
<div class="hd"><span class="n">10 · THE CURVE</span><span class="ref">plan drawn live · reference from an .alog if attached → Step 10</span></div>
|
||
<div class="bd">
|
||
<div class="grid-wrap">
|
||
<svg id="curve-svg" viewBox="0 0 714 334" width="100%" role="img" aria-label="Roast curve plotting grid">
|
||
<defs><style>
|
||
.maj{stroke:#8b8078;stroke-width:.7} .min{stroke:#e2dad2;stroke-width:.45}
|
||
.ax{stroke:#1a1512;stroke-width:1.3} .al{font-size:8px;fill:#5a5048}
|
||
.alr{font-size:8px;fill:#7a3b12} .band{fill:#7a3b12;opacity:.05}
|
||
.ttl{font-size:8px;font-weight:700;fill:#1a1512;letter-spacing:.5px}
|
||
</style></defs>
|
||
<rect x="52" y="24" width="600" height="270" fill="#fff"/>
|
||
<rect class="band" x="52" y="65.4" width="600" height="19.8"/>
|
||
<text x="58" y="62.4" class="alr" style="font-size:7px">your first-crack band, 176–187 °C</text>
|
||
<g class="min">
|
||
<line x1="72" y1="24" x2="72" y2="294"/><line x1="112" y1="24" x2="112" y2="294"/>
|
||
<line x1="152" y1="24" x2="152" y2="294"/><line x1="192" y1="24" x2="192" y2="294"/>
|
||
<line x1="232" y1="24" x2="232" y2="294"/><line x1="272" y1="24" x2="272" y2="294"/>
|
||
<line x1="312" y1="24" x2="312" y2="294"/><line x1="352" y1="24" x2="352" y2="294"/>
|
||
<line x1="392" y1="24" x2="392" y2="294"/><line x1="432" y1="24" x2="432" y2="294"/>
|
||
<line x1="472" y1="24" x2="472" y2="294"/><line x1="512" y1="24" x2="512" y2="294"/>
|
||
<line x1="552" y1="24" x2="552" y2="294"/><line x1="592" y1="24" x2="592" y2="294"/>
|
||
<line x1="632" y1="24" x2="632" y2="294"/>
|
||
</g>
|
||
<g class="maj">
|
||
<line x1="92" y1="24" x2="92" y2="294"/><line x1="132" y1="24" x2="132" y2="294"/>
|
||
<line x1="172" y1="24" x2="172" y2="294"/><line x1="212" y1="24" x2="212" y2="294"/>
|
||
<line x1="252" y1="24" x2="252" y2="294"/><line x1="292" y1="24" x2="292" y2="294"/>
|
||
<line x1="332" y1="24" x2="332" y2="294"/><line x1="372" y1="24" x2="372" y2="294"/>
|
||
<line x1="412" y1="24" x2="412" y2="294"/><line x1="452" y1="24" x2="452" y2="294"/>
|
||
<line x1="492" y1="24" x2="492" y2="294"/><line x1="532" y1="24" x2="532" y2="294"/>
|
||
<line x1="572" y1="24" x2="572" y2="294"/><line x1="612" y1="24" x2="612" y2="294"/>
|
||
</g>
|
||
<g class="min">
|
||
<line x1="52" y1="276" x2="652" y2="276"/><line x1="52" y1="240" x2="652" y2="240"/>
|
||
<line x1="52" y1="204" x2="652" y2="204"/><line x1="52" y1="168" x2="652" y2="168"/>
|
||
<line x1="52" y1="132" x2="652" y2="132"/><line x1="52" y1="96" x2="652" y2="96"/>
|
||
<line x1="52" y1="60" x2="652" y2="60"/>
|
||
</g>
|
||
<g class="maj">
|
||
<line x1="52" y1="258" x2="652" y2="258"/><line x1="52" y1="222" x2="652" y2="222"/>
|
||
<line x1="52" y1="186" x2="652" y2="186"/><line x1="52" y1="150" x2="652" y2="150"/>
|
||
<line x1="52" y1="114" x2="652" y2="114"/><line x1="52" y1="78" x2="652" y2="78"/>
|
||
<line x1="52" y1="42" x2="652" y2="42"/>
|
||
</g>
|
||
<line class="ax" x1="52" y1="24" x2="52" y2="294"/>
|
||
<line class="ax" x1="52" y1="294" x2="652" y2="294"/>
|
||
<line class="ax" x1="652" y1="24" x2="652" y2="294"/>
|
||
<g class="al" text-anchor="end">
|
||
<text x="47" y="296.8">60</text><text x="47" y="260.8">80</text><text x="47" y="224.8">100</text>
|
||
<text x="47" y="188.8">120</text><text x="47" y="152.8">140</text><text x="47" y="116.8">160</text>
|
||
<text x="47" y="80.8">180</text><text x="47" y="44.8">200</text>
|
||
</g>
|
||
<text x="14" y="159" class="ttl" transform="rotate(-90 14 159)" text-anchor="middle">BEAN TEMP °C</text>
|
||
<g class="al" text-anchor="middle">
|
||
<text x="52" y="304">0:00</text><text x="92" y="304">1:00</text><text x="132" y="304">2:00</text>
|
||
<text x="172" y="304">3:00</text><text x="212" y="304">4:00</text><text x="252" y="304">5:00</text>
|
||
<text x="292" y="304">6:00</text><text x="332" y="304">7:00</text><text x="372" y="304">8:00</text>
|
||
<text x="412" y="304">9:00</text><text x="452" y="304">10:00</text><text x="492" y="304">11:00</text>
|
||
<text x="532" y="304">12:00</text><text x="572" y="304">13:00</text><text x="612" y="304">14:00</text>
|
||
<text x="652" y="304">15:00</text>
|
||
</g>
|
||
<text x="368" y="320" style="font-size:8px;fill:#5a5048">TIME FROM CHARGE · solid = plan · dashed = reference (.alog)</text>
|
||
<g id="plan-curve"></g>
|
||
<g id="ref-curve"></g>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wsbox">
|
||
<div class="hd"><span class="n">11 · AT THE MACHINE — PLAN vs ACTUAL</span><span class="ref">→ Step 11</span></div>
|
||
<div class="bd">
|
||
<table class="tight">
|
||
<thead><tr><th style="width:28mm">Milestone</th><th class="num" style="width:20mm">Plan time</th>
|
||
<th class="num" style="width:22mm">Actual time</th><th class="num" style="width:18mm">Actual BT</th><th>Note</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>Charge</td><td class="num"><output data-out="pa-charge">0:00</output></td>
|
||
<td class="num"><input class="f n ws-input" name="planActual.charge.actualTime" placeholder="0:00"><span class="pv"></span></td>
|
||
<td class="num"><input class="f n ws-input" name="planActual.charge.actualBt"><span class="pv"></span></td>
|
||
<td><input class="f ws-input" style="min-width:52mm" name="planActual.charge.note"><span class="pv"></span></td></tr>
|
||
<tr><td>Turning point</td><td class="num"><output data-out="pa-tp">—</output></td>
|
||
<td class="num"><input class="f n ws-input" name="planActual.tp.actualTime"><span class="pv"></span></td>
|
||
<td class="num"><input class="f n ws-input" name="planActual.tp.actualBt"><span class="pv"></span></td>
|
||
<td><input class="f ws-input" style="min-width:52mm" name="planActual.tp.note"><span class="pv"></span></td></tr>
|
||
<tr><td>Yellow</td><td class="num"><output data-out="pa-yellow">—</output></td>
|
||
<td class="num"><input class="f n ws-input" name="planActual.yellow.actualTime"><span class="pv"></span></td>
|
||
<td class="num"><input class="f n ws-input" name="planActual.yellow.actualBt"><span class="pv"></span></td>
|
||
<td><input class="f ws-input" style="min-width:52mm" name="planActual.yellow.note"><span class="pv"></span></td></tr>
|
||
<tr><td>First crack</td><td class="num"><output data-out="pa-fc">—</output></td>
|
||
<td class="num"><input class="f n ws-input" name="planActual.fc.actualTime"><span class="pv"></span></td>
|
||
<td class="num"><input class="f n ws-input" name="planActual.fc.actualBt"><span class="pv"></span></td>
|
||
<td><input class="f ws-input" style="min-width:52mm" name="planActual.fc.note"><span class="pv"></span></td></tr>
|
||
<tr><td>Drop</td><td class="num"><output data-out="pa-drop">—</output></td>
|
||
<td class="num"><input class="f n ws-input" name="planActual.drop.actualTime"><span class="pv"></span></td>
|
||
<td class="num"><input class="f n ws-input" name="planActual.drop.actualBt"><span class="pv"></span></td>
|
||
<td><input class="f ws-input" style="min-width:52mm" name="planActual.drop.note"><span class="pv"></span></td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wsbox">
|
||
<div class="hd"><span class="n">12 · AFTER THE ROAST</span><span class="ref">→ Step 12</span></div>
|
||
<div class="bd wsline tightln">
|
||
<span class="lb">Green in</span> <input class="f n ws-input" name="afterRoast.greenIn"><span class="pv"></span>g
|
||
<span class="sep">|</span><span class="lb">Out</span> <input class="f n ws-input" name="afterRoast.out"><span class="pv"></span>g
|
||
<span class="sep">|</span><span class="lb">Weight loss</span> <input class="f n ws-input" name="afterRoast.weightLossPct"><span class="pv"></span>%
|
||
<span class="sep">|</span><span class="lb">Actual DTR</span> <input class="f n ws-input" name="afterRoast.actualDtrPct"><span class="pv"></span>%<br>
|
||
<span class="lb">Colour WB/GR</span> <input class="f ws-input" name="afterRoast.colour"><span class="pv"></span>
|
||
<span class="sep">|</span><span class="lb">Rested</span> <input class="f n ws-input" name="afterRoast.restedDays"><span class="pv"></span>days
|
||
<span class="sep">|</span><span class="lb">Brew ratio</span> <input class="f ws-input" name="afterRoast.brewRatio"><span class="pv"></span>
|
||
<span class="sep">|</span><span class="lb">Method</span> <input class="f w ws-input" name="afterRoast.method"><span class="pv"></span><br>
|
||
<span class="lb">Cup notes</span> <input class="f xw ws-input" style="min-width:152mm" name="afterRoast.cupNotes"><span class="pv"></span><br>
|
||
<span class="lb" style="color:var(--accent)">One change next batch</span> <input class="f ws-input" style="min-width:58mm" name="afterRoast.oneChange"><span class="pv"></span>
|
||
<span class="sep">|</span><span class="lb">What would prove it wrong</span> <input class="f ws-input" style="min-width:34mm" name="afterRoast.disproof"><span class="pv"></span>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<datalist id="cultivar-list"></datalist>
|
||
|
||
<script type="module" src="/js/main.js"></script>
|
||
</body>
|
||
</html>
|