Creative Visual Effects

Aurora Field Spotlight Stage

Complete a spotlight stage in an aurora field scene: includes realistic content, interactive controls, clear status 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>Aurora Field Spotlight Stage</title>
  <style>
    :root { --ink:#24213a; --paper:#f6f1e8; --accent:#e6a23c; --secondary:#a8a1d8; --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:"IBM Plex Sans","PingFang SC",sans-serif; background:linear-gradient(color-mix(in srgb,var(--ink) 5%,transparent) 1px,transparent 1px),var(--paper);background-size:100% 36px; }
    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(1280px,calc(100% - 24px));margin:auto;padding:28px 0 64px}.mast{display:flex;justify-content:space-between;padding:18px;border:1px solid var(--line);background:color-mix(in srgb,#fff 60%,transparent);gap:18px;margin-bottom:14px}.mast h1{font-family:"IBM Plex Sans","PingFang SC",sans-serif;font-weight:800;font-size:clamp(34px,6vw,66px);letter-spacing:-.045em;margin:0;line-height:1}.eyebrow{display:block;margin-bottom:6px;color:var(--accent);font:800 10px/1 ui-monospace,monospace;letter-spacing:.16em}.intro{max-width:720px;margin:10px 0 0;font-size:14px;line-height:1.6}.scenario{padding:7px 10px;border:1px solid var(--line);border-radius:8px;background:var(--paper);font-size:12px}.demo{border-radius:14px;box-shadow:0 14px 40px color-mix(in srgb,var(--ink) 11%,transparent);position:relative;min-height:390px;overflow:hidden;padding:24px;background:color-mix(in srgb,var(--paper) 90%,#fff)}@media(max-width:700px){.page{width:calc(100% - 12px);padding-top:12px}.mast{display:grid}.demo{padding:12px}}
    .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-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}}
    .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-compare{display:grid;grid-template-columns:minmax(230px,.55fr) minmax(0,1.45fr);gap:18px}.compare-stage{display:grid;gap:12px;min-width:0}.compare-stage>header{display:flex;justify-content:space-between;gap:16px;align-items:end}.compare-stage h2{margin:.2em 0}.compare-core{--compare-split:50%;min-width:0;padding:14px;clip-path:inset(0 calc(100% - var(--compare-split)) 0 0);outline:1px dashed var(--accent);outline-offset:-8px;transition:clip-path .25s,filter .25s}.compare-core[data-compare-channel="B"]{filter:hue-rotate(32deg) saturate(1.15)}.compare-controls{display:grid;align-content:start;gap:16px;padding:20px;border:1px solid var(--line);border-radius:24px 4px 24px 4px;background:var(--paper)}.compare-controls fieldset,.compare-controls>label{display:grid;gap:8px}.compare-controls input[type="range"]{width:100%}#workflowCompareShelf{display:grid;gap:6px;padding:0;margin:0;list-style:none}#workflowCompareShelf li{display:grid;grid-template-columns:auto 1fr auto;gap:8px;padding:9px;border-top:1px solid var(--line);font-size:12px}@media(max-width:900px){.workflow-compare{grid-template-columns:1fr}.compare-stage{order:-1}.compare-core{clip-path:none;border-left:8px solid var(--accent)}}
  </style>
</head>
<body data-aesthetic="dashboard" data-composition="field-index">
  <main class="page">
    <header class="mast"><div><span class="eyebrow">dashboard / Spotlight Stage / ADVANCED</span><h1>Aurora Field Spotlight Stage</h1><p class="intro">Complete a spotlight stage in an aurora field scene: includes realistic content, interactive controls, clear status feedback, and responsive layouts across sizes.</p></div><span class="scenario">Aurora Field</span></header>
    <div class="composition-index"><section class="demo" aria-label="Aurora field spotlight stage interaction area"><div class="workflow-compare"><form id="workflowCompareControls" class="compare-controls"><fieldset><legend>Reference Channel</legend><label><input type="radio" name="workflowChannel" value="A" checked>A · Green Light Curtain</label><label><input type="radio" name="workflowChannel" value="B">B · magenta light band</label></fieldset><label>Exposure Time Weight<input id="workflowCompareWeight" type="range" min="10" max="90" value="50"><output id="workflowCompareWeightValue">50 seconds</output></label><label><input id="workflowCompareFreeze" type="checkbox">Freeze current version</label><button id="workflowCompareCapture" class="action primary" type="button">Sample and save exposure</button><ol id="workflowCompareShelf" aria-label="Version Sampling Record"></ol></form><section class="compare-stage"><header><span class="eyebrow">Aurora Field COMPARE</span><h2>Aurora A/B Comparison</h2><output id="workflowCompareLive">Version A waiting for sampling</output></header><section id="workflowCore" class="workflow-core compare-core" data-compare-channel="A" style="--compare-split:50%"><!-- 11DZ_CORE_START:creative-effects-spotlight-stage --><div class="spotlight-lab"><section id="spotlightStage" class="spotlight-stage" tabindex="0" aria-label="Aurora field spotlight stage; move the pointer or use the arrow keys to control the light source" aria-describedby="spotlightHelp"><div class="spotlight-copy"><span>Aurora Field / 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></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>Aurora Field FIELD INDEX</span></aside></div>
  </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 workflowCompareCore=document.querySelector('#workflowCore');const workflowCompareWeight=document.querySelector('#workflowCompareWeight');const workflowCompareState={channel:'A',weight:50,frozen:false,snapshots:[]};function workflowCompareFingerprint(){const controls=[...workflowCompareCore.querySelectorAll('input,select,textarea')];const outputs=[...workflowCompareCore.querySelectorAll('output,[role="status"],strong')].map(node=>node.textContent.trim()).filter(Boolean);return {controlValues:controls.map(control=>control.type==='checkbox'||control.type==='radio'?control.checked:control.value),summary:outputs.slice(0,4).join(' / '),nodes:workflowCompareCore.querySelectorAll('*').length};}function workflowCompareDrive(){workflowCompareCore.dataset.compareChannel=workflowCompareState.channel;workflowCompareCore.style.setProperty('--compare-split',workflowCompareState.weight+'%');document.querySelector('#workflowCompareWeightValue').textContent=workflowCompareState.weight+' sec';document.querySelector('#workflowCompareLive').textContent=workflowCompareState.channel+' Version · '+workflowCompareState.weight+' sec'+(workflowCompareState.frozen?' · Frozen':'');announce('Aurora comparison in progress '+workflowCompareState.channel+' Version');}function workflowCompareCapture(source){const bridge=workflowBridgeActivate();const snapshot={...workflowCompareFingerprint(),channel:workflowCompareState.channel,weight:workflowCompareState.weight,source,bridge:bridge.summary};workflowCompareState.snapshots.push(snapshot);const item=document.createElement('li');item.innerHTML='<b>'+snapshot.channel+'</b><span>'+(snapshot.summary||snapshot.bridge)+'</span><small>'+snapshot.weight+' seconds · '+snapshot.bridge+'</small>';document.querySelector('#workflowCompareShelf').prepend(item);announce('sampled '+snapshot.channel+' Save exposure version · '+bridge.summary);}document.querySelectorAll('[name="workflowChannel"]').forEach(input=>input.addEventListener('change',()=>{workflowCompareState.channel=input.value;workflowCompareDrive();}));workflowCompareWeight.addEventListener('input',()=>{workflowCompareState.weight=Number(workflowCompareWeight.value);workflowCompareDrive();});document.querySelector('#workflowCompareFreeze').addEventListener('change',event=>{workflowCompareState.frozen=event.currentTarget.checked;workflowCompareDrive();});document.querySelector('#workflowCompareCapture').addEventListener('click',()=>workflowCompareCapture('Button Sampling'));workflowCompareCore.addEventListener('dblclick',()=>workflowCompareCapture('Main view double-click'));workflowCompareDrive();
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