@liveloop · 5/15/2026, 11:18:23 PM
Initial version — all lines are new.
+<style>+ html, body { background: #fffbeb; color: #1f2937; font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; }+ .wrap { display: flex; flex-direction: column; height: 100%; padding: 1.25rem 1.25rem 1.5rem; overflow-y: auto; -webkit-overflow-scrolling: touch; }+ header { padding-bottom: 0.75rem; border-bottom: 1px dashed #92400e33; }+ h1 { margin: 0; font-size: 1.4rem; line-height: 1.2; letter-spacing: -0.01em; color: #92400e; }+ .serves { margin: 0.35rem 0 0; font-size: 0.78rem; letter-spacing: 0.08em; text-transform: uppercase; color: #78716c; }+ .progress { margin: 0.6rem 0 0; height: 6px; border-radius: 9999px; background: #92400e1f; overflow: hidden; }+ .progress > span { display: block; height: 100%; width: 0%; background: #92400e; transition: width 0.25s ease; }+ .progress-label { margin: 0.3rem 0 0; font-size: 0.72rem; color: #78716c; }+ section { padding: 0.9rem 0 0.25rem; }+ h2 { margin: 0 0 0.5rem; font-size: 0.8rem; letter-spacing: 0.12em; text-transform: uppercase; color: #78716c; font-weight: 600; }+ ul, ol { list-style: none; padding: 0; margin: 0; }+ li { border-bottom: 1px solid #92400e14; }+ li:last-child { border-bottom: 0; }+ .check { display: flex; align-items: flex-start; gap: 0.6rem; width: 100%; padding: 0.5rem 0.15rem; background: none; border: 0; text-align: left; font: inherit; color: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }+ .check .lbl { font-size: 0.92rem; line-height: 1.45; }+ .box { flex: 0 0 auto; width: 1.15rem; height: 1.15rem; margin-top: 0.05rem; border: 2px solid #92400e80; border-radius: 0.4rem; position: relative; transition: background 0.15s, border-color 0.15s; }+ .num { flex: 0 0 auto; width: 1.4rem; height: 1.4rem; border-radius: 9999px; background: #92400e1f; color: #92400e; font-size: 0.78rem; font-weight: 700; display: flex; align-items: center; justify-content: center; transition: background 0.15s, color 0.15s; }+ .check[aria-pressed="true"] .lbl { text-decoration: line-through; color: #a8a29e; }+ .check[aria-pressed="true"] .box { background: #92400e; border-color: #92400e; }+ .check[aria-pressed="true"] .box::after { content: ""; position: absolute; left: 0.3rem; top: 0.08rem; width: 0.3rem; height: 0.55rem; border: solid #fffbeb; border-width: 0 2px 2px 0; transform: rotate(45deg); }+ .check[aria-pressed="true"] .num { background: #92400e; color: #fffbeb; }+ .check:active { transform: scale(0.99); }+ footer { margin-top: auto; padding-top: 0.75rem; font-size: 0.72rem; color: #a8a29e; text-align: center; }+ .done-note { color: #92400e; font-weight: 600; }+</style>+<div class="wrap">+ <header>+ <h1>Bolo de bolacha</h1>+ <p class="serves">Serves · 8 slices</p>+ <div class="progress" aria-hidden="true"><span id="bar"></span></div>+ <p class="progress-label" id="plabel">Tap a step as you go.</p>+ </header>+ <section>+ <h2>Ingredients</h2>+ <ul><li><button type="button" class="check" data-kind="ing" data-i="0" aria-pressed="false"><span class="box"></span><span class="lbl">200g Maria biscuits</span></button></li><li><button type="button" class="check" data-kind="ing" data-i="1" aria-pressed="false"><span class="box"></span><span class="lbl">200g butter</span></button></li><li><button type="button" class="check" data-kind="ing" data-i="2" aria-pressed="false"><span class="box"></span><span class="lbl">200g icing sugar</span></button></li><li><button type="button" class="check" data-kind="ing" data-i="3" aria-pressed="false"><span class="box"></span><span class="lbl">4 egg yolks</span></button></li><li><button type="button" class="check" data-kind="ing" data-i="4" aria-pressed="false"><span class="box"></span><span class="lbl">200ml strong coffee</span></button></li><li><button type="button" class="check" data-kind="ing" data-i="5" aria-pressed="false"><span class="box"></span><span class="lbl">Cocoa powder for dusting</span></button></li></ul>+ </section>+ <section>+ <h2>Steps</h2>+ <ol><li><button type="button" class="check step" data-kind="step" data-i="0" aria-pressed="false"><span class="num">1</span><span class="lbl">Beat butter and sugar until pale.</span></button></li><li><button type="button" class="check step" data-kind="step" data-i="1" aria-pressed="false"><span class="num">2</span><span class="lbl">Whisk in egg yolks, one at a time.</span></button></li><li><button type="button" class="check step" data-kind="step" data-i="2" aria-pressed="false"><span class="num">3</span><span class="lbl">Dip each biscuit in coffee for ~1 second.</span></button></li><li><button type="button" class="check step" data-kind="step" data-i="3" aria-pressed="false"><span class="num">4</span><span class="lbl">Layer biscuits + cream; repeat 6 times.</span></button></li><li><button type="button" class="check step" data-kind="step" data-i="4" aria-pressed="false"><span class="num">5</span><span class="lbl">Chill for 4h. Dust with cocoa before serving.</span></button></li></ol>+ </section>+ <footer id="footer">Tap ❤︎ if it worked out · Remix to share your version</footer>+</div>+<script>+(function(){+ var STEP_COUNT = 5;+ var bar = document.getElementById('bar');+ var plabel = document.getElementById('plabel');+ var footer = document.getElementById('footer');+ var buttons = Array.prototype.slice.call(document.querySelectorAll('.check'));+ var state = { ing: {}, step: {} };++ function key(btn){ return btn.getAttribute('data-kind'); }++ function render(){+ var doneSteps = 0;+ buttons.forEach(function(btn){+ var k = key(btn), i = btn.getAttribute('data-i');+ var on = !!(state[k] && state[k][i]);+ btn.setAttribute('aria-pressed', on ? 'true' : 'false');+ if (k === 'step' && on) doneSteps++;+ });+ var pct = STEP_COUNT ? Math.round(100 * doneSteps / STEP_COUNT) : 0;+ bar.style.width = pct + '%';+ if (doneSteps === 0) {+ plabel.textContent = 'Tap a step as you go.';+ } else if (doneSteps >= STEP_COUNT) {+ plabel.innerHTML = '<span class="done-note">All steps done — enjoy!</span>';+ } else {+ plabel.textContent = doneSteps + ' of ' + STEP_COUNT + ' steps done';+ }+ }++ function persist(){+ if (window.liveloop && window.liveloop.storage) {+ try { window.liveloop.storage.set(state); } catch (e) {}+ }+ }++ buttons.forEach(function(btn){+ btn.addEventListener('click', function(){+ var k = key(btn), i = btn.getAttribute('data-i');+ if (!state[k]) state[k] = {};+ state[k][i] = !state[k][i];+ render();+ persist();+ });+ });++ if (window.liveloop && window.liveloop.storage) {+ window.liveloop.storage.get().then(function(saved){+ if (saved && typeof saved === 'object') {+ if (saved.ing && typeof saved.ing === 'object') state.ing = saved.ing;+ if (saved.step && typeof saved.step === 'object') state.step = saved.step;+ }+ render();+ }, function(){ render(); });+ } else {+ render();+ }+})();+</script>+<script>/*ll-media-controls*/+(function(){+ function wire(){+ var ll = window.liveloop; if(!ll || !ll.declareMedia) return;+ var nodes = [].slice.call(document.querySelectorAll('video,audio')).filter(function(el){+ return !(el.id && el.id.indexOf('ll-')===0) && !el.hasAttribute('data-ll-unmanaged');+ });+ if(!nodes.length) return;+ var hasVideo = nodes.some(function(el){ return el.tagName==='VIDEO'; });+ ll.declareMedia({ sound:true, playback:hasVideo });+ var paused=false;+ function play(el){ try{ var p=el.play&&el.play(); if(p&&p.catch)p.catch(function(){}); }catch(e){} }+ function applyMuted(m){ nodes.forEach(function(el){ try{ el.muted=m; }catch(e){} if(!m&&!paused) play(el); }); }+ function applyPaused(p){ paused=p; nodes.forEach(function(el){ try{ if(p){ el.pause&&el.pause(); } else { play(el); } }catch(e){} }); }+ applyMuted(!!ll.muted);+ if(ll.onMute) ll.onMute(applyMuted);+ if(ll.onPause) ll.onPause(applyPaused);+ }+ if(document.readyState==='loading'){ document.addEventListener('DOMContentLoaded', wire); } else { wire(); }+})();+</script>