// app/screen-recipe.jsx — read a recipe & decide. All actions live: // start cooking · edit · favourite · add to shopping · plan this · share · rate · notes. const overlayGhost = { background: 'rgba(12,12,14,0.55)', backdropFilter: 'blur(10px)', border: '1px solid rgba(255,255,255,0.18)', color: '#fff', boxShadow: 'none' }; function HeroDot() { return ; } function heroTime(r) { const info = (window.LCDomain && window.LCDomain.effortInfo) ? window.LCDomain.effortInfo(r) : null; return info && info.known ? info.label : '—'; } // ── interactive rating ── function RatingStars({ recipe, size = 16 }) { const { ratingFor, setRating } = useApp(); const v = ratingFor(recipe); const [hover, setHover] = React.useState(0); return ( setHover(0)}> {[1, 2, 3, 4, 5].map((i) => { const on = (hover || v) >= i; return ( ); })} ); } function portalToast(node) { const host = (typeof document !== 'undefined') && document.getElementById('lc-screen'); return host ? ReactDOM.createPortal(node, host) : node; } function Toast({ msg, action, onAction, onClose, top = 'calc(var(--lc-mobile-top, 14px) + 8px)' }) { React.useEffect(() => { const t = setTimeout(onClose, 4200); return () => clearTimeout(t); }, [msg]); // Portal into #lc-screen (the fixed device frame), NOT the scrolling content — // so toasts always sit at the top of the visible screen regardless of scroll. return portalToast(
{msg} {action && ( )}
); } function Popover({ children, onClose, align = 'left', up = false }) { return ( <>
{children}
); } function PlanPopover({ recipe, onClose, onPlanned, up, plannedDay }) { const { WEEK_DAYS, setPlanDay, state } = useApp(); const plannedKey = Object.keys(state.plan || {}).find( (k) => state.plan[k] && !state.plan[k].skip && state.plan[k].recipeId === recipe.id); return (
{plannedDay ? 'Planned for ' + plannedDay : 'Plan for…'}
{WEEK_DAYS.map((d) => { const on = plannedKey === d.key; return ( ); })}
{plannedDay && (
Tap {plannedDay.slice(0, 3)} again to remove · or pick another day to move it.
)}
); } function SharePopover({ recipe, onClose }) { const [copied, setCopied] = React.useState(false); const link = `luiscooks.app/r/${recipe.id}/shared/k3jf9`; return (
Share this recipe
Read-only · attribution always shown
{ try { navigator.clipboard.writeText(link); } catch (e) {} setCopied(true); setTimeout(() => setCopied(false), 1600); }}>{copied ? 'Copied' : 'Copy'}
); } // ── method list ── function MethodList({ recipe, mini }) { return (
{recipe.directions.map((d, i) => (
{String(i + 1).padStart(2, '0')}

{d}

))}
); } function NotesCard({ recipe }) { const { noteFor, setNote } = useApp(); const [editing, setEditing] = React.useState(false); const note = noteFor(recipe); return (
Your notes {editing ? (