// app/screen-cook.jsx — hands-busy cook mode. One step at a time, ingredient // check-off, and count-up (stopwatch) timers that tick gently upward. // match the current step to an ingredient group by keyword overlap function activeGroupForStep(groups, stepText) { if (!groups.length) return null; const t = (stepText || '').toLowerCase(); let best = null, bestScore = 0; groups.forEach((g) => { if (!g.title) return; const words = g.title.toLowerCase().split(/\s+/).filter((w) => w.length > 2); const score = words.reduce((s, w) => s + (t.includes(w) ? 1 : 0), 0); if (score > bestScore) { bestScore = score; best = g; } }); return bestScore > 0 ? best : null; } function CookCheckRow({ id, line, highlight, scale }) { const { checkedFor, toggleChecked, scaleQuantities } = useApp(); const checked = checkedFor(id).has(line); const display = scale && scale !== 1 ? scaleQuantities(line, scale) : line; return (
  • ); } function CookIngredients({ recipe, activeGroup, dense, scale }) { const { parseIngredientGroups } = useApp(); const groups = parseIngredientGroups(recipe.ingredients); if (groups.length <= 1 && !groups[0]?.title) { return ( ); } return (
    {groups.map((g, gi) => { const isActive = activeGroup && g.title === activeGroup.title; return (
    {g.title && (
    {g.title} {isActive && now}
    )}
    ); })}
    ); } // ── Timers ── function TimerChip({ t }) { const { toggleTimer, removeTimer } = useApp(); const now = useNow(t.running); const secs = timerElapsed(t, now); return (
    {fmtTime(secs)} {t.label}
    ); } function StepNumeral({ n, size, stroke }) { return ( {String(n).padStart(2, '0')} ); } function CookMode({ recipe }) { const { layout, back, openRecipe, cookStep, setCookStep, state, addTimer, parseIngredientGroups, settings } = useApp(); const total = recipe.directions.length; const step = Math.min(cookStep(recipe.id), Math.max(0, total - 1)); const groups = parseIngredientGroups(recipe.ingredients); const activeGroup = activeGroupForStep(groups, recipe.directions[step]); const isMobile = layout === 'mobile'; const isTablet = layout === 'tablet'; const goPrev = () => setCookStep(recipe.id, Math.max(0, step - 1)); const goNext = () => { if (step >= total - 1) { setCookStep(recipe.id, 0); openRecipe(recipe.id); } else setCookStep(recipe.id, step + 1); }; const last = step >= total - 1; // ── servings scaler — scales displayed quantities + the cost figure live ── // baseServings is the recipe's NATIVE serving count (the scale reference — the // listed quantities are for this many). The initial "cook for" count follows // the user's intent: a planned meal → its plannedServings; an unplanned cook → // the user's default planning preference; falling back to the recipe's own. const baseServings = window.LCDomain.costInfo(recipe).servingsCount || 4; const plannedEntry = React.useMemo(() => Object.entries(state.plan || {}) .filter(([, e]) => e && !e.skip && e.recipeId === recipe.id) .sort((a, b) => (a[0] < b[0] ? -1 : 1)) .map(([, e]) => e)[0] || null, [state.plan, recipe.id]); const initialServings = (plannedEntry && plannedEntry.plannedServings) || (settings && settings.defaultPlanningServings) || baseServings; const [servings, setServings] = React.useState(initialServings); const scale = baseServings ? servings / baseServings : 1; const TopDock = (
    {recipe.name.split(' with ')[0]} Cook · {step + 1}/{total}
    {!isMobile && (
    {Array.from({ length: total }).map((_, i) => ( ))}
    )}
    {!isMobile && } {state.timers.map((t) => )}
    ); // mobile progress pips under dock const MobilePips = (
    {Array.from({ length: total }).map((_, i) => ( ))}
    ); const StepBlock = (
    Method · step {step + 1}{activeGroup ? ` · ${activeGroup.title}` : ''}

    {recipe.directions[step]}

    ); const FooterBtns = (
    ←{isMobile ? '' : ' Previous step'} {last ? 'Finish cooking' : 'Done — next step'}
    ); const IngredientPanel = ( <>
    {activeGroup ? 'For this step' : 'Ingredients'}
    {activeGroup && (

    {activeGroup.title}.

    )}
    Tap items to check them off as you measure.
    ); if (isMobile) { return ( {TopDock} {MobilePips}
    {StepBlock}
    {FooterBtns}
    ); } return ( {TopDock}
    {StepBlock}
    {FooterBtns}
    ); } function CookScreen() { const { getRecipe, state } = useApp(); const recipe = getRecipe(state.params.recipeId); if (!recipe) return
    Recipe not found.
    ; return ; } Object.assign(window, { CookScreen });