Mini Apps and Mini Games

Family Night Pomodoro Clock

Complete the Pomodoro timer in a family night setting: includes real content, actionable controls, clear status feedback, and responsive layouts.

Mini Apps and Mini GamesPomodoro timerHTMLCSSJavaScript
With JavaScript enabled, you can edit, run, and save this example. The fixed source is as follows:
<!doctype html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Family Night Pomodoro Clock</title>
  <style>
    :root { --ink:#18314f; --paper:#f7f8f2; --accent:#ff6b5e; --secondary:#71c9b5; --line:color-mix(in srgb, var(--ink) 18%, transparent); --shadow:0 24px 60px color-mix(in srgb, var(--ink) 16%, transparent); color-scheme:light; }
    * { box-sizing:border-box; }
    html { min-width:320px; background:var(--paper); }
    body { min-height:100vh; margin:0; overflow-x:hidden; color:var(--ink); font-family:Optima,"Songti SC",serif; background:radial-gradient(ellipse at top left,color-mix(in srgb,var(--secondary) 32%,transparent),transparent 42%),radial-gradient(ellipse at bottom right,color-mix(in srgb,var(--accent) 18%,transparent),transparent 45%),var(--paper); }
    button,input,select,textarea { color:inherit; font:inherit; }
    button,[role="button"],input,select,textarea { accent-color:var(--accent); }
    button { cursor:pointer; }
    button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible { outline:3px solid var(--accent); outline-offset:3px; }
    [hidden] { display:none !important; }
    @media (max-width:700px) { .mast h1 { line-height:1.08 !important; letter-spacing:-.035em !important; overflow-wrap:anywhere; } }
    @media (prefers-reduced-motion:reduce) { *,*::before,*::after { scroll-behavior:auto !important; animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important; } }
    .page{width:min(1100px,calc(100% - 34px));margin:auto;padding:68px 0}.mast{display:grid;grid-template-columns:1fr auto;align-items:center;gap:40px;margin:0 4vw 36px}.mast h1{font-family:Optima,"Songti SC",serif;font-weight:700;font-size:clamp(40px,8vw,86px);letter-spacing:-.025em;margin:0;line-height:1.02}.eyebrow{display:block;margin-bottom:12px;color:var(--accent);font-size:12px;letter-spacing:.2em}.intro{max-width:60ch;line-height:1.9}.scenario{display:grid;width:108px;height:108px;place-items:center;padding:12px;border:1px solid var(--line);border-radius:50%;text-align:center}.demo{border-radius:72px 18px 72px 18px;box-shadow:0 28px 80px color-mix(in srgb,var(--ink) 14%,transparent);position:relative;min-height:430px;overflow:hidden;padding:clamp(28px,5vw,58px);background:color-mix(in srgb,var(--paper) 84%,transparent)}@media(max-width:700px){.page{width:calc(100% - 18px);padding:24px 0}.mast{grid-template-columns:1fr;margin-inline:12px}.scenario{width:auto;height:auto;border-radius:999px}.demo{padding:18px}}
    .panel{padding:20px;border:1px solid color-mix(in srgb,var(--accent) 50%,transparent);border-radius:18px;background:color-mix(in srgb,var(--paper) 88%,transparent);box-shadow:inset 0 0 24px color-mix(in srgb,var(--accent) 7%,transparent)}.stack{display:grid;gap:16px}.row{display:flex;flex-wrap:wrap;gap:9px}.action{padding:11px 16px;border:1px solid var(--accent);border-radius:6px;color:var(--accent);background:transparent;box-shadow:0 0 14px color-mix(in srgb,var(--accent) 10%,transparent)}.action.primary,.action.is-active{color:var(--paper);background:var(--accent)}.status{min-height:24px;color:var(--secondary);text-shadow:0 0 10px currentColor}.metric{font-size:clamp(30px,7vw,64px);font-weight:900;text-shadow:0 0 18px color-mix(in srgb,var(--accent) 40%,transparent)}.muted{opacity:.7}.chip{padding:6px 9px;border:1px solid var(--secondary);border-radius:4px}.meter{height:7px;background:color-mix(in srgb,var(--accent) 15%,transparent)}.meter>i{display:block;height:100%;box-shadow:0 0 12px var(--accent);background:var(--accent)}
    .composition-index{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:18px}.index-mark{display:grid;align-content:space-between;width:76px;padding:16px 10px;border:1px solid var(--line);color:var(--accent);background:color-mix(in srgb,var(--paper) 82%,transparent);text-align:center}.index-mark strong{font:900 34px/1 ui-monospace,monospace}.index-mark span{writing-mode:vertical-rl;font:800 10px/1.2 ui-monospace,monospace;letter-spacing:.18em}.composition-index .demo{grid-column:1;grid-row:1}.composition-index::before{content:"";position:absolute;left:-12px;top:38px;width:5px;height:45%;background:linear-gradient(var(--accent),var(--secondary))}@media(max-width:700px){.composition-index{grid-template-columns:1fr}.index-mark{grid-row:1;width:auto;grid-template-columns:auto 1fr}.index-mark span{writing-mode:horizontal-tb}.composition-index .demo{grid-row:2}}
    .pomodoro-board{display:grid;gap:18px;max-width:760px;margin:auto;padding:clamp(24px,6vw,58px);border:1px solid var(--line);border-radius:28px;background:var(--paper)}.pomodoro-board header{display:grid;grid-template-columns:1fr auto;align-items:end}.pomodoro-board h2{margin:.25em 0}.pomodoro-board header output{grid-row:1/3;grid-column:2;font:900 clamp(44px,9vw,78px)/1 ui-monospace,monospace}.pomodoro-board ol{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;padding:0;margin:0;list-style:none}.pomodoro-board li{display:grid;gap:5px;padding:12px;border:1px solid var(--line);border-radius:12px}.pomodoro-board li[aria-current="step"]{color:var(--paper);background:var(--ink)}.pomodoro-actions{display:flex;flex-wrap:wrap;gap:8px}.pomodoro-board>output{text-align:right;font-weight:900}@media(max-width:600px){.pomodoro-board header{grid-template-columns:1fr}.pomodoro-board header output{grid-area:auto}.pomodoro-board ol{grid-template-columns:1fr 1fr}}.workflow-dispatch{display:grid;grid-template-columns:minmax(210px,.48fr) minmax(0,1.52fr);gap:18px}.dispatch-console{display:grid;align-content:start;gap:16px;padding:22px;border:1px solid var(--line);border-radius:18px;background:color-mix(in srgb,var(--secondary) 12%,var(--paper))}.dispatch-console h2{margin:.2em 0}.dispatch-console form,.dispatch-console label{display:grid;gap:7px}.dispatch-console input,.dispatch-console select{min-width:0;width:100%;padding:10px;border:1px solid var(--line);border-radius:8px;background:var(--paper)}.dispatch-console fieldset{display:flex;gap:12px;border:1px solid var(--line);border-radius:10px}.dispatch-console fieldset label{display:flex;align-items:center}.dispatch-workbench{--dispatch-load:.22;min-width:0;padding:14px;border-left:8px solid color-mix(in srgb,var(--accent) calc(var(--dispatch-load)*100%),var(--line));background:linear-gradient(90deg,color-mix(in srgb,var(--accent) 8%,transparent),transparent 28%)}.dispatch-workbench[data-dispatch-priority="urgent"]{box-shadow:inset 0 0 0 2px var(--accent)}@media(max-width:900px){.workflow-dispatch{grid-template-columns:1fr}.dispatch-console{order:2}}
  </style>
</head>
<body data-aesthetic="organic" data-composition="field-index">
  <main class="page">
    <header class="mast"><div><span class="eyebrow">organic / Pomodoro Timer / BEGINNER</span><h1>Family Night Pomodoro Clock</h1><p class="intro">Complete the Pomodoro timer in a family night setting: includes real content, actionable controls, clear status feedback, and responsive layouts.</p></div><span class="scenario">Family Night</span></header>
    <div class="composition-index"><section class="demo" aria-label="Family Night Pomodoro Clock Interactive Area"><div class="workflow-dispatch"><aside class="dispatch-console"><span class="eyebrow">Family Night DISPATCH</span><h2>Family Turn Scheduler</h2><form id="workflowDispatchForm"><label>Task Type<select id="workflowDispatchKind"><option>Elders’ Turn</option><option>Family Round</option><option>Family Round</option></select></label><label>Number of Participants<input id="workflowDispatchAmount" type="number" min="1" max="9999" value="39"><span>person</span></label><fieldset><legend>Processing priority</legend><label><input type="radio" name="workflowPriority" value="normal" checked>Regular</label><label><input type="radio" name="workflowPriority" value="urgent">Urgent</label></fieldset><button class="action primary" type="submit">Start Game</button></form><label>Current task<select id="workflowDispatchActive" aria-label="Switch current task"><option value="1">Elders’ Turn</option><option value="2">Family Round</option></select></label><output id="workflowDispatchSummary">Waiting for Dispatch</output></aside><section id="workflowCore" class="workflow-core dispatch-workbench" data-dispatch-priority="normal"><!-- 11DZ_CORE_START:mini-apps-games-pomodoro --><div class="pomodoro-board"><header><span class="eyebrow">POMODORO CYCLE</span><h2>Family Night Pomodoro Cycle</h2><output id="pomodoroClock">25:00</output></header><ol id="pomodoroPhases"><li data-pomodoro-phase="0" aria-current="step"><b>1</b><span>Focus</span><small>25:00</small></li><li data-pomodoro-phase="1"><b>2</b><span>Short Break</span><small>05:00</small></li><li data-pomodoro-phase="2"><b>3</b><span>Focus</span><small>25:00</small></li><li data-pomodoro-phase="3"><b>4</b><span>Long break</span><small>15:00</small></li></ol><div id="pomodoroProgress" class="meter" role="progressbar" aria-label="Current Pomodoro phase progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><i id="pomodoroMeter"></i></div><div class="pomodoro-actions"><button id="pomodoroToggle" class="action primary" type="button" data-core-bridge="mini-apps-games-pomodoro">Start Focusing</button><button id="pomodoroSkip" class="action" type="button">Jump to the next phase</button><button id="pomodoroReset" class="action" type="button">Reset Cycle</button></div><output id="pomodoroSummary">Completed 0 focus sessions</output></div><!-- 11DZ_CORE_END --></section></div><p id="status" class="status" role="status" aria-live="polite"></p></section><aside class="index-mark" aria-hidden="true"><strong>05</strong><span>Family Night FIELD INDEX</span></aside></div>
  </main>
  <script>
    'use strict';
    const statusOutput = document.querySelector('#status');
    const announce = message => { statusOutput.textContent = message; };
    /* 11DZ_CORE_SCRIPT_START:mini-apps-games-pomodoro */
const pomodoroPlan=[{"name":"Focus","seconds":1500},{"name":"Short Break","seconds":300},{"name":"Focus","seconds":1500},{"name":"Long break","seconds":900}];const pomodoroItems=[...document.querySelectorAll('[data-pomodoro-phase]')];const pomodoroState={phase:0,remaining:pomodoroPlan[0].seconds,running:false,completedFocus:0,timer:null};function renderPomodoro(){const current=pomodoroPlan[pomodoroState.phase];const elapsed=current.seconds-pomodoroState.remaining;const percent=Math.round(elapsed/current.seconds*100);document.querySelector('#pomodoroClock').textContent=String(Math.floor(pomodoroState.remaining/60)).padStart(2,'0')+':'+String(pomodoroState.remaining%60).padStart(2,'0');pomodoroItems.forEach((item,index)=>{if(index===pomodoroState.phase)item.setAttribute('aria-current','step');else item.removeAttribute('aria-current');});document.querySelector('#pomodoroProgress').setAttribute('aria-valuenow',String(percent));document.querySelector('#pomodoroMeter').style.width=percent+'%';document.querySelector('#pomodoroToggle').textContent=pomodoroState.running?'Pause'+current.name:'Start'+current.name;document.querySelector('#pomodoroSummary').textContent='Completed '+pomodoroState.completedFocus+' a focus block';}function advancePomodoro(){if(pomodoroPlan[pomodoroState.phase].name==='Focus'&&pomodoroState.remaining===0)pomodoroState.completedFocus+=1;pomodoroState.phase=(pomodoroState.phase+1)%pomodoroPlan.length;pomodoroState.remaining=pomodoroPlan[pomodoroState.phase].seconds;renderPomodoro();announce('Enter'+pomodoroPlan[pomodoroState.phase].name+'Stage');}function stopPomodoro(){clearInterval(pomodoroState.timer);pomodoroState.timer=null;pomodoroState.running=false;renderPomodoro();}document.querySelector('#pomodoroToggle').addEventListener('click',()=>{if(pomodoroState.running){stopPomodoro();announce('Pomodoro cycle paused');return;}pomodoroState.running=true;pomodoroState.timer=setInterval(()=>{pomodoroState.remaining=Math.max(0,pomodoroState.remaining-1);if(!pomodoroState.remaining){stopPomodoro();advancePomodoro();}else renderPomodoro();},1000);renderPomodoro();announce('Pomodoro session has started');});document.querySelector('#pomodoroSkip').addEventListener('click',()=>{stopPomodoro();pomodoroState.remaining=0;advancePomodoro();});document.querySelector('#pomodoroReset').addEventListener('click',()=>{stopPomodoro();pomodoroState.phase=0;pomodoroState.remaining=pomodoroPlan[0].seconds;pomodoroState.completedFocus=0;renderPomodoro();announce('Pomodoro cycle reset');});renderPomodoro();
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"mini-apps-games-pomodoro","selector":"[data-core-bridge=\"mini-apps-games-pomodoro\"]","mode":"click","key":"Enter"};const workflowBridgeCore=document.querySelector('#workflowCore');const workflowBridgeControl=workflowBridgeCore.querySelector(workflowBridgeSpec.selector);if(!workflowBridgeControl)throw new Error('Missing core bridge: '+workflowBridgeSpec.name);const workflowBridgeControlledId=workflowBridgeControl.getAttribute('aria-controls');const workflowBridgeControlled=workflowBridgeControlledId?document.getElementById(workflowBridgeControlledId):null;workflowBridgeCore.dataset.workflowBridge=workflowBridgeSpec.name;workflowBridgeCore.dataset.workflowVersion='0';function workflowBridgeSerialize(){const visualNode=workflowBridgeCore.firstElementChild||workflowBridgeCore;const visual=getComputedStyle(visualNode);const outputs=[...workflowBridgeCore.querySelectorAll('output,[role="status"],[aria-live],meter,progress')].map(node=>node.textContent.trim()+'|'+node.getAttribute('aria-valuenow')+'|'+node.getAttribute('value'));const canvas=[...workflowBridgeCore.querySelectorAll('canvas')].map(node=>{try{return node.toDataURL().slice(-160);}catch{return 'canvas-unavailable';}});return JSON.stringify({html:workflowBridgeCore.innerHTML,status:statusOutput.textContent,outputs,canvas,visual:[visual.display,visual.visibility,visual.opacity,visual.transform,visual.filter,visual.backgroundColor,visual.width,visual.height],scroll:workflowBridgeSpec.mode==='scroll'?workflowBridgeControl.scrollTop:null});}let workflowBridgeLastEffect=workflowBridgeSerialize();function workflowBridgeSummary(){const label=(workflowBridgeControl.getAttribute('aria-label')||workflowBridgeControl.textContent||workflowBridgeControl.value||workflowBridgeSpec.name).trim().replace(/\s+/g,' ').slice(0,72);return label+' · Core Version '+workflowBridgeCore.dataset.workflowVersion;}function workflowBridgeCommit(){const effect=workflowBridgeSerialize();if(effect===workflowBridgeLastEffect)return {changed:false,summary:workflowBridgeSummary()};workflowBridgeLastEffect=effect;workflowBridgeCore.dataset.workflowVersion=String(Number(workflowBridgeCore.dataset.workflowVersion||0)+1);return {changed:true,summary:workflowBridgeSummary()};}function workflowBridgeScheduleCommit(){queueMicrotask(workflowBridgeCommit);setTimeout(workflowBridgeCommit,0);}workflowBridgeControl.addEventListener("click",workflowBridgeScheduleCommit);const workflowBridgeStateTargets=new Set(workflowBridgeCore.querySelectorAll('dialog'));if(workflowBridgeControlled&&workflowBridgeCore.contains(workflowBridgeControlled))workflowBridgeStateTargets.add(workflowBridgeControlled);workflowBridgeStateTargets.forEach(target=>['close','cancel','toggle'].forEach(eventName=>target.addEventListener(eventName,workflowBridgeScheduleCommit)));function workflowBridgeActivate(){workflowBridgeControl.focus();workflowBridgeControl.click();const result=workflowBridgeCommit();setTimeout(workflowBridgeCommit,0);return result;}function workflowBridgeReset(){workflowBridgeCore.dataset.workflowVersion='0';workflowBridgeLastEffect=workflowBridgeSerialize();}
const workflowDispatchCore=document.querySelector('#workflowCore');const workflowDispatchForm=document.querySelector('#workflowDispatchForm');const workflowDispatchSelect=document.querySelector('#workflowDispatchActive');const workflowDispatchJobs=new Map([["1",{"label":"Elders’ Turn","amount":12,"priority":"normal","touches":0}],["2",{"label":"Family Round","amount":21,"priority":"urgent","touches":0}]]);let workflowDispatchSerial=workflowDispatchJobs.size;function workflowDispatchDrive(job,activate=false){workflowDispatchCore.dataset.dispatchPriority=job.priority;workflowDispatchCore.style.setProperty('--dispatch-load',Math.min(.95,.16+job.amount/120));const bridge=activate?workflowBridgeActivate():{changed:false,summary:workflowBridgeSummary()};document.querySelector('#workflowDispatchSummary').textContent=job.label+' · '+job.amount+' person · '+bridge.summary;announce('Family round current task:'+job.label);}function workflowDispatchRender(activeId,activate=false){workflowDispatchSelect.replaceChildren(...[...workflowDispatchJobs].map(([id,job])=>{const option=document.createElement('option');option.value=id;option.textContent=job.label+(job.priority==='urgent'?' · Urgent':'');return option;}));workflowDispatchSelect.value=activeId;workflowDispatchDrive(workflowDispatchJobs.get(activeId),activate);}workflowDispatchForm.addEventListener('submit',event=>{event.preventDefault();const data=new FormData(workflowDispatchForm);const id=String(++workflowDispatchSerial);workflowDispatchJobs.set(id,{label:document.querySelector('#workflowDispatchKind').value,amount:Math.max(1,Number(document.querySelector('#workflowDispatchAmount').value)||1),priority:data.get('workflowPriority'),touches:0});workflowDispatchRender(id,true);});workflowDispatchSelect.addEventListener('change',()=>workflowDispatchDrive(workflowDispatchJobs.get(workflowDispatchSelect.value),true));workflowDispatchCore.addEventListener('focusin',()=>{const job=workflowDispatchJobs.get(workflowDispatchSelect.value);if(!job)return;job.touches+=1;document.querySelector('#workflowDispatchSummary').textContent=job.label+' · '+job.amount+' person · '+workflowBridgeSummary();});workflowDispatchRender('1',false);
workflowBridgeReset();
  </script>
</body>
</html>
Page feedbackFound an issue or have suggestions for improvement?
Feedback features need to be used in the online version

Please enable JavaScript in the online version before submitting; local features of the current tool or example are not affected.

Go to the online version for feedback