Creative Visual Effects

Deep Sea Spotlight Stage

Complete a spotlight stage in a deep-sea scenario: includes realistic content, interactive controls, clear state feedback, and responsive layouts across sizes.

Creative Visual EffectsSpotlight StageHTMLCanvasJavaScript
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>Deep Sea Spotlight Stage</title>
  <style>
    :root { --ink:#17241d; --paper:#f3f0e7; --accent:#af4f45; --secondary:#9eb49f; --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:"Kaiti SC",STKaiti,"Songti SC",serif; background:radial-gradient(circle at 12% 18%,color-mix(in srgb,var(--accent) 12%,transparent) 0 1px,transparent 2px),var(--paper);background-size:19px 19px; }
    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(980px,calc(100% - 32px));margin:auto;padding:72px 0 92px}.mast{display:grid;grid-template-columns:1fr auto;transform:rotate(-.25deg);gap:32px;align-items:center;margin-bottom:46px}.mast h1{font-family:"Kaiti SC",STKaiti,serif;font-weight:700;font-size:clamp(40px,8vw,84px);letter-spacing:.02em;margin:0;line-height:1.12}.intro{max-width:650px;margin-top:18px;line-height:2}.scenario{padding:12px;border:2px solid var(--accent);color:var(--accent);transform:rotate(3deg)}.eyebrow{display:block;margin-bottom:9px;color:var(--accent);letter-spacing:.18em}.demo{border-radius:2px;transform:rotate(.12deg);box-shadow:0 30px 70px color-mix(in srgb,var(--ink) 18%,transparent);position:relative;min-height:430px;overflow:hidden;padding:clamp(28px,6vw,66px);background:color-mix(in srgb,var(--paper) 92%,#fff)}@media(max-width:700px){.page{width:calc(100% - 20px);padding:28px 0}.mast{grid-template-columns:1fr}.scenario{justify-self:start}.demo{padding:20px}}
    .panel{padding:24px;border-block:1px solid var(--ink);background:transparent}.stack{display:grid;gap:22px}.row{display:flex;flex-wrap:wrap;gap:16px}.action{padding:8px 0;border:0;border-bottom:1px solid currentColor;background:transparent;letter-spacing:.08em}.action.primary,.action.is-active{color:var(--accent);border-bottom-width:4px}.status{min-height:28px;margin-top:20px;font-style:italic}.metric{font-family:Didot,serif;font-size:clamp(38px,8vw,76px)}.muted{max-width:54ch;line-height:1.8}.meter{position:relative;height:3px;background:var(--line)}.meter>i{position:absolute;inset:0 auto 0 0;background:var(--accent)}.chip{padding-bottom:3px;border-bottom:1px solid var(--ink);font-size:13px}
    .composition-gallery{margin:0;padding:clamp(8px,2vw,18px);border:1px solid var(--ink);background:color-mix(in srgb,var(--paper) 78%,transparent)}.gallery-caption{display:grid;grid-template-columns:auto 1fr auto;gap:16px;align-items:center;padding:15px 4px 2px;font-size:12px}.gallery-caption::before,.gallery-caption::after{content:"";height:1px;background:var(--line)}.gallery-caption strong{font:800 11px/1.2 ui-monospace,monospace;letter-spacing:.16em;text-transform:uppercase}.composition-gallery .demo{box-shadow:none}.composition-gallery .demo::before{content:"";position:absolute;inset:10px;border:1px dashed color-mix(in srgb,var(--accent) 36%,transparent);pointer-events:none}
    .spotlight-lab{display:grid;grid-template-columns:minmax(0,1.42fr) minmax(220px,.58fr);gap:16px}.spotlight-stage{--spot-x:50%;--spot-y:50%;--spot-size:190px;--ambient:.12;position:relative;min-height:460px;overflow:hidden;border:1px solid var(--line);border-radius:26px;background:#05070c;color:#fff;touch-action:none}.spotlight-stage::before{content:"";position:absolute;inset:0;z-index:3;pointer-events:none;background:radial-gradient(circle var(--spot-size) at var(--spot-x) var(--spot-y),transparent 0 58%,rgba(2,4,8,calc(1 - var(--ambient))) 100%)}.spotlight-copy{position:relative;z-index:2;max-width:650px;padding:clamp(32px,8vw,86px)}.spotlight-copy span{color:#fde68a;font-weight:900;letter-spacing:.16em}.spotlight-copy h2{font-size:clamp(38px,8vw,86px);line-height:.92}.spotlight-copy p{max-width:50ch;line-height:1.7}.spotlight-cards{position:absolute;inset:12% 7%}.spotlight-cards i{position:absolute;width:120px;height:160px;border:1px solid rgba(255,255,255,.35);border-radius:20px;background:linear-gradient(145deg,#2563eb55,#f9731655)}.spotlight-cards i:nth-child(1){right:3%;top:5%;transform:rotate(9deg)}.spotlight-cards i:nth-child(2){right:22%;bottom:3%;transform:rotate(-7deg)}.spotlight-cards i:nth-child(3){left:35%;top:44%;width:80px;height:80px}.spotlight-controls{display:grid;align-content:center;gap:17px}.spotlight-controls label{display:grid;grid-template-columns:1fr auto;gap:8px;font-weight:800}.spotlight-controls input{grid-column:1/-1}@media(max-width:740px){.spotlight-lab{grid-template-columns:1fr}.spotlight-stage{min-height:360px}}.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="paper" data-composition="gallery-frame">
  <main class="page">
    <header class="mast"><div><span class="eyebrow">paper / Spotlight Stage / BEGINNER</span><h1>Deep Sea Spotlight Stage</h1><p class="intro">Complete a spotlight stage in a deep-sea scenario: includes realistic content, interactive controls, clear state feedback, and responsive layouts across sizes.</p></div><span class="scenario">Deep Sea</span></header>
    <figure class="composition-gallery"><section class="demo" aria-label="Deep-sea Spotlight Stage interactive area"><div class="workflow-dispatch"><aside class="dispatch-console"><span class="eyebrow">Deep Sea DISPATCH</span><h2>Submarine mission control</h2><form id="workflowDispatchForm"><label>Task Type<select id="workflowDispatchKind"><option>Sonar Scan</option><option>Hot Spring Sampling</option><option>Return Beacon</option></select></label><label>Subsea Depth<input id="workflowDispatchAmount" type="number" min="1" max="9999" value="27"><span>m</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">Dive in</button></form><label>Current task<select id="workflowDispatchActive" aria-label="Switch current task"><option value="1">Sonar Scan</option><option value="2">Hot Spring Sampling</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:creative-effects-spotlight-stage --><div class="spotlight-lab"><section id="spotlightStage" class="spotlight-stage" tabindex="0" aria-label="Deep-Sea Spotlight Stage; move the pointer or use the arrow keys to control the light source" aria-describedby="spotlightHelp"><div class="spotlight-copy"><span>Deep Sea / LIVE</span><h2>Move attention to the place that truly matters</h2><p id="spotlightHelp">Move the pointer, touch the stage, or use the arrow keys to control the spotlight.</p></div><div class="spotlight-cards" aria-hidden="true"><i></i><i></i><i></i></div></section><aside class="spotlight-controls panel"><span class="eyebrow">SPOTLIGHT STAGE</span><h2>Spotlight Stage</h2><label>Aperture size <input id="spotlightSize" type="range" min="90" max="320" value="190" data-core-bridge="creative-effects-spotlight-stage"><output id="spotlightSizeValue">190px</output></label><label>Ambient brightness <input id="spotlightAmbient" type="range" min="4" max="34" value="12"><output id="spotlightAmbientValue">12%</output></label><button id="spotlightCenter" class="action" type="button">Back to center</button></aside></div><!-- 11DZ_CORE_END --></section></div><p id="status" class="status" role="status" aria-live="polite"></p></section><figcaption class="gallery-caption"><strong>Deep sea / GALLERY 03</strong></figcaption></figure>
  </main>
  <script>
    'use strict';
    const statusOutput = document.querySelector('#status');
    const announce = message => { statusOutput.textContent = message; };
    /* 11DZ_CORE_SCRIPT_START:creative-effects-spotlight-stage */
const spotlightStage=document.querySelector('#spotlightStage');const spotlightSize=document.querySelector('#spotlightSize');const spotlightAmbient=document.querySelector('#spotlightAmbient');let spotlightPoint={x:50,y:50};function setSpotlight(x,y){spotlightPoint.x=Math.max(0,Math.min(100,x));spotlightPoint.y=Math.max(0,Math.min(100,y));spotlightStage.style.setProperty('--spot-x',spotlightPoint.x+'%');spotlightStage.style.setProperty('--spot-y',spotlightPoint.y+'%');}function pointerSpotlight(event){const rect=spotlightStage.getBoundingClientRect();setSpotlight((event.clientX-rect.left)/rect.width*100,(event.clientY-rect.top)/rect.height*100);}spotlightStage.addEventListener('pointermove',pointerSpotlight);spotlightStage.addEventListener('pointerdown',pointerSpotlight);spotlightStage.addEventListener('keydown',event=>{if(!['ArrowLeft','ArrowRight','ArrowUp','ArrowDown'].includes(event.key))return;event.preventDefault();setSpotlight(spotlightPoint.x+(event.key==='ArrowRight'?4:event.key==='ArrowLeft'?-4:0),spotlightPoint.y+(event.key==='ArrowDown'?4:event.key==='ArrowUp'?-4:0));announce('Spotlight position '+Math.round(spotlightPoint.x)+'%,'+Math.round(spotlightPoint.y)+'%');});spotlightSize.addEventListener('input',()=>{spotlightStage.style.setProperty('--spot-size',spotlightSize.value+'px');document.querySelector('#spotlightSizeValue').textContent=spotlightSize.value+'px';announce('Aperture size '+spotlightSize.value+' pixels');});spotlightAmbient.addEventListener('input',()=>{spotlightStage.style.setProperty('--ambient',Number(spotlightAmbient.value)/100);document.querySelector('#spotlightAmbientValue').textContent=spotlightAmbient.value+'%';announce('Ambient brightness '+spotlightAmbient.value+'%');});document.querySelector('#spotlightCenter').addEventListener('click',()=>{setSpotlight(50,50);spotlightStage.focus();announce('The spotlight has returned to center stage');});
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"creative-effects-spotlight-stage","selector":"[data-core-bridge=\"creative-effects-spotlight-stage\"]","mode":"range","key":"ArrowRight"};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("input",workflowBridgeScheduleCommit);workflowBridgeControl.addEventListener('change',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();const step=Number(workflowBridgeControl.step)||1;const min=workflowBridgeControl.min===''?-Infinity:Number(workflowBridgeControl.min);const max=workflowBridgeControl.max===''?Infinity:Number(workflowBridgeControl.max);let next=Math.min(max,Math.max(min,(Number(workflowBridgeControl.value)||0)+step));if(next===Number(workflowBridgeControl.value))next=Math.max(min,Number(workflowBridgeControl.value)-step);workflowBridgeControl.value=String(next);workflowBridgeControl.dispatchEvent(new Event('input',{bubbles:true}));workflowBridgeControl.dispatchEvent(new Event('change',{bubbles:true}));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":"Sonar Scan","amount":12,"priority":"normal","touches":0}],["2",{"label":"Hot Spring Sampling","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+' m · '+bridge.summary;announce('Dive mission 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+' m · '+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