Files
roast_command_center/public/index.html
T

767 lines
51 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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 &amp; 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 &amp; 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 4351%</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 3339%</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 1220%</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, 176187 °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&nbsp;#</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 &gt;±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 &amp; 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:302: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">4351 %</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">3339 %</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">1220 %</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">&lt; 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 &amp; 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 &amp; 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">133195 °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">77100 °C @ 0:471: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">148166 °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">176187 °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">183197 °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, 176187 °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>