← Race the Sun results

Race the Sun

GPT 6 Luna · full

Initial view of Race the Sun

Browser check: Artifact runtime error. This is a technical check, not a quality review.

Reviews & generation details

Reviews

No human review yet. Unreviewed does not mean unsuccessful.

Generation context

Imported historical artifact. Its exact original instructions and lineage are not known.

Generation prompt · exact text unavailable

See the current prompt for reference. It may differ from the instructions used to generate this artifact.

Inspect original source 25,426 bytes · SHA-256 51a8c900b30e
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Solar Drift — endless flight</title>
<style>
:root{--cyan:#82fff0;--gold:#ffd67a;--ink:#080a1a}*{box-sizing:border-box}html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#090a1c;color:#fff;font-family:Inter,ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif}canvas{display:block;width:100vw;height:100vh;touch-action:none}.scan{pointer-events:none;position:fixed;inset:0;opacity:.12;background:repeating-linear-gradient(0deg,transparent 0 3px,rgba(255,255,255,.07) 4px);mix-blend-mode:soft-light}.vignette{pointer-events:none;position:fixed;inset:0;background:radial-gradient(ellipse at 50% 48%,transparent 38%,rgba(4,5,17,.3) 100%)}.hud{position:fixed;inset:0;pointer-events:none;padding:clamp(18px,3vw,42px);display:none}.toprow{display:flex;justify-content:space-between;align-items:flex-start}.brand{font-size:11px;letter-spacing:.25em;font-weight:800;color:#b8d8e5;text-transform:uppercase}.stat{font-variant-numeric:tabular-nums;text-align:right}.score{font-size:clamp(22px,3vw,37px);font-weight:800;letter-spacing:-.04em;text-shadow:0 2px 18px #ffbc6c66}.label{font-size:9px;letter-spacing:.2em;color:#b4c2dc;text-transform:uppercase}.metrics{position:absolute;left:clamp(18px,3vw,42px);top:105px;display:grid;gap:13px}.metric b{display:block;font-size:19px;font-variant-numeric:tabular-nums}.metric small{font-size:9px;letter-spacing:.18em;color:#aab9d2;text-transform:uppercase}.right-meter{position:absolute;right:clamp(18px,3vw,42px);top:115px;width:145px}.meter-title{font-size:9px;letter-spacing:.2em;color:#c6d5df;margin-bottom:8px}.meter{height:5px;background:#ffffff25;border-radius:5px;overflow:hidden}.meter>i{display:block;height:100%;width:100%;background:linear-gradient(90deg,#51ead7,#e9ffbf);box-shadow:0 0 12px #71fff2;transition:width .12s}.sunmeter{margin-top:20px}.sunmeter .meter>i{background:linear-gradient(90deg,#ff735c,#ffd272)}.multiplier{position:absolute;left:50%;top:20%;transform:translateX(-50%);font-size:15px;letter-spacing:.15em;color:#fff5b1;text-shadow:0 0 18px #ffc247;text-align:center;opacity:0;transition:opacity .25s}.multiplier.on{opacity:1}.hintline{position:absolute;bottom:28px;left:50%;transform:translateX(-50%);font-size:10px;letter-spacing:.2em;color:#d0d6e7aa;text-transform:uppercase;white-space:nowrap}.toast{position:absolute;left:50%;top:38%;transform:translate(-50%,-50%) scale(.8);font-size:13px;letter-spacing:.22em;text-transform:uppercase;color:#fff5a8;text-shadow:0 0 18px #ffbb55;opacity:0;transition:.25s}.toast.show{opacity:1;transform:translate(-50%,-50%) scale(1)}.screen{position:fixed;inset:0;display:grid;place-items:center;text-align:center;background:linear-gradient(180deg,rgba(8,8,24,.08),rgba(8,8,24,.48));transition:opacity .35s;pointer-events:auto}.screen.hidden{opacity:0;pointer-events:none}.card{max-width:600px;padding:32px 26px}.eyebrow{font-size:10px;letter-spacing:.38em;color:#88f9eb;font-weight:800;text-transform:uppercase;margin-bottom:17px}.title{font-size:clamp(48px,10vw,104px);line-height:.83;letter-spacing:-.09em;font-weight:900;margin:0;text-shadow:0 5px 50px #ffb26c66}.title span{display:block;color:#ffd080}.subtitle{max-width:430px;margin:24px auto 27px;color:#d1d4e0;font-size:14px;line-height:1.65}.start{cursor:pointer;border:1px solid #affff0aa;background:linear-gradient(110deg,#76f4dd,#d9ffbd);border-radius:3px;padding:15px 30px;color:#10202a;font-weight:900;font-size:11px;letter-spacing:.2em;text-transform:uppercase;box-shadow:0 0 35px #5bfae455;transition:transform .15s,box-shadow .2s}.start:hover{transform:translateY(-2px);box-shadow:0 0 55px #5bfae488}.keyrow{margin-top:23px;color:#aebbd0;font-size:10px;letter-spacing:.1em;line-height:2}.key{display:inline-block;border:1px solid #ffffff38;background:#ffffff0c;padding:2px 6px;border-radius:3px;color:#e7f9f8;margin:0 2px}.best{margin-top:16px;color:#ffd580;font-size:11px;letter-spacing:.17em;text-transform:uppercase}.mobile-controls{position:fixed;bottom:22px;left:0;right:0;display:none;justify-content:space-between;padding:0 20px;pointer-events:none}.touchbtn{pointer-events:auto;border:1px solid #ffffff50;background:#17223a77;color:#fff;border-radius:50%;width:57px;height:57px;font-size:20px;backdrop-filter:blur(6px);touch-action:none}.touchcluster{display:flex;gap:12px}.boostbtn{border-color:#ffd27a88;color:#ffe39b;width:66px;height:66px;font-size:10px;font-weight:800;letter-spacing:.1em}@media(max-width:700px){.mobile-controls{display:flex}.metrics{top:96px}.right-meter{width:105px;top:100px}.hintline{bottom:100px;font-size:8px}.brand{font-size:9px}}
</style>
</head>
<body>
<canvas id="game"></canvas><div class="scan"></div><div class="vignette"></div>
<div class="hud" id="hud"><div class="toprow"><div class="brand">☼ &nbsp;SOLAR DRIFT <span style="opacity:.45">/ FLIGHT 01</span></div><div class="stat"><div class="label">Flight score</div><div class="score" id="score">000000</div></div></div><div class="metrics"><div class="metric"><small>Distance</small><b id="distance">0.0 <small>km</small></b></div><div class="metric"><small>Velocity</small><b id="speed">0 <small>km/h</small></b></div></div><div class="right-meter"><div class="meter-title">☼ &nbsp;SOLAR CHARGE</div><div class="meter"><i id="energybar"></i></div><div class="meter-title sunmeter">HORIZON / SUNSET</div><div class="meter"><i id="sunbar"></i></div></div><div class="multiplier" id="multi">×1.0<br><span style="font-size:9px;opacity:.7">COMBO</span></div><div class="toast" id="toast">ENERGY +</div><div class="hintline">A / D or ← / → &nbsp; STEER &nbsp; · &nbsp; W / S PITCH &nbsp; · &nbsp; SPACE BOOST</div></div>
<div class="screen" id="screen"><div class="card"><div class="eyebrow" id="overline">A SOLAR FLIGHT EXPERIMENT</div><h1 class="title" id="title">SOLAR<span>DRIFT</span></h1><p class="subtitle" id="subtitle">Ride the last light. Thread the geometric ruins, harvest energy, and stay ahead of the horizon.</p><button class="start" id="start">Begin flight&nbsp; →</button><div class="keyrow" id="keys"><span class="key">A</span><span class="key">D</span> steer &nbsp; <span class="key">W</span><span class="key">S</span> pitch &nbsp; <span class="key">SPACE</span> boost</div><div class="best" id="best">BEST FLIGHT &nbsp; 0</div></div></div>
<div class="mobile-controls" id="mobile"><div class="touchcluster"><button class="touchbtn" data-key="ArrowLeft">←</button><button class="touchbtn" data-key="ArrowRight">→</button></div><button class="touchbtn boostbtn" data-key="Space">BOOST</button></div>
<script>
// === TUNABLE CONSTANTS ===
const CFG={baseSpeed:205,maxSpeed:470,accel:2.55,steer:8.4,pitch:5.2,energyDrain:.008,shadowDrain:.055,sunDuration:115,spawnEvery:1.05,worldWidth:1.55,boostCost:22,boostTime:1.15,colors:{cyan:'#73f8df',gold:'#ffd47d',coral:'#ff796f',violet:'#a894ff'}};
// === SETUP ===
const canvas=document.getElementById('game'),ctx=canvas.getContext('2d');let W=innerWidth,H=innerHeight,DPR=1;
function resize(){DPR=Math.min(devicePixelRatio||1,2);W=innerWidth;H=innerHeight;canvas.width=W*DPR;canvas.height=H*DPR;ctx.setTransform(DPR,0,0,DPR,0,0)}addEventListener('resize',resize);resize();
const ui={hud:document.getElementById('hud'),screen:document.getElementById('screen'),start:document.getElementById('start'),title:document.getElementById('title'),subtitle:document.getElementById('subtitle'),overline:document.getElementById('overline'),best:document.getElementById('best'),score:document.getElementById('score'),distance:document.getElementById('distance'),speed:document.getElementById('speed'),energybar:document.getElementById('energybar'),sunbar:document.getElementById('sunbar'),multi:document.getElementById('multi'),toast:document.getElementById('toast')};
let state='title',last=0,run,keys={},particles=[],objects=[],stars=[],toastTimer=0,audio=null;
// === SEEDED RANDOM ===
function RNG(seed){this.s=seed>>>0}RNG.prototype.next=function(){this.s=(this.s*1664525+1013904223)>>>0;return this.s/4294967296};
function rand(a,b){return a+(b-a)*run.rng.next()}
// === AUDIO ===
function initAudio(){if(audio)return;try{const AC=window.AudioContext||window.webkitAudioContext;if(!AC)return;let ac=new AC(),master=ac.createGain();master.gain.value=.28;master.connect(ac.destination);let osc=ac.createOscillator(),gain=ac.createGain();osc.type='sawtooth';osc.frequency.value=58;gain.gain.value=0;osc.connect(gain);gain.connect(master);osc.start();audio={ac,master,osc,gain}}catch(e){}}
function blip(freq=600,dur=.11,type='sine',vol=.18){if(!audio)return;let {ac,master}=audio,o=ac.createOscillator(),g=ac.createGain();o.type=type;o.frequency.setValueAtTime(freq,ac.currentTime);o.frequency.exponentialRampToValueAtTime(Math.max(70,freq*.55),ac.currentTime+dur);g.gain.setValueAtTime(vol,ac.currentTime);g.gain.exponentialRampToValueAtTime(.001,ac.currentTime+dur);o.connect(g);g.connect(master);o.start();o.stop(ac.currentTime+dur)}
function updateAudio(){if(audio&&state==='playing'){audio.gain.gain.setTargetAtTime(.018+run.speed/CFG.maxSpeed*.085,audio.ac.currentTime,.12);audio.osc.frequency.setTargetAtTime(48+run.speed*.12,audio.ac.currentTime,.15)}}
// === GAME STATE ===
function startRun(){initAudio();if(audio&&audio.ac.state==='suspended')audio.ac.resume();let seed=(Date.now()^Math.floor(Math.random()*1e9))>>>0;run={rng:new RNG(seed),seed,time:0,distance:0,speed:CFG.baseSpeed,x:0,y:0,vx:0,vy:0,energy:100,sun:100,score:0,multi:1,combo:0,boost:0,spawn:0,shake:0,flash:0,near:0,dead:false,seedLabel:seed.toString(16).toUpperCase()};objects=[];particles=[];stars=[];for(let i=0;i<90;i++)stars.push({x:Math.random(),y:Math.random()*.58,r:Math.random()*1.6,a:.2+Math.random()*.7});state='playing';ui.screen.classList.add('hidden');ui.hud.style.display='block';ui.start.blur();last=performance.now();requestAnimationFrame(frame)}
function endRun(reason){if(state!=='playing')return;state='over';run.dead=true;run.shake=18;burst(W*.5,H*.68,'#ff765f',46,260);blip(90,.48,'triangle',.45);if(audio)audio.gain.gain.setTargetAtTime(0,audio.ac.currentTime,.2);let best=Number(localStorage.getItem('solardrift-best')||0);let score=Math.floor(run.score);if(score>best){best=score;localStorage.setItem('solardrift-best',best)}ui.hud.style.display='none';ui.screen.classList.remove('hidden');ui.overline.textContent=reason==='sun'?'THE LIGHT HAS LEFT YOU':'FLIGHT ENDED';ui.title.innerHTML='KEEP<span>DRIFTING</span>';ui.subtitle.innerHTML=`${reason==='sun'?'The horizon swallowed the last light.':'The ruins won this round.'}<br><b style="color:#ffe19a">${score.toLocaleString()}</b> points &nbsp;·&nbsp; ${(run.distance/1000).toFixed(2)} km flown &nbsp;·&nbsp; seed ${run.seedLabel}`;ui.start.textContent='Fly again  ↻';ui.best.textContent='BEST FLIGHT  ·  '+best.toLocaleString();ui.keys.innerHTML='<span class="key">R</span> or click to relaunch · a new world every flight'}
// === INPUT ===
function keydown(e){if(['ArrowLeft','ArrowRight','ArrowUp','ArrowDown','Space'].includes(e.code))e.preventDefault();keys[e.code]=true;if((state==='title'||state==='over')&&(e.code==='Enter'||e.code==='Space'||e.code==='KeyR'))startRun();if(state==='playing'&&e.code==='Space'&&!e.repeat&&run.energy>8&&run.boost<=0){run.energy-=CFG.boostCost;run.boost=CFG.boostTime;blip(230,.2,'sawtooth',.25);burst(W*.5,H*.78,CFG.colors.cyan,14,90)}}function keyup(e){keys[e.code]=false}addEventListener('keydown',keydown);addEventListener('keyup',keyup);ui.start.addEventListener('click',()=>{if(state!=='playing')startRun()});document.querySelectorAll('.touchbtn').forEach(b=>{b.addEventListener('pointerdown',e=>{e.preventDefault();b.setPointerCapture(e.pointerId);if(b.dataset.key==='Space'){keydown({code:'Space',repeat:false,preventDefault(){}})}else keys[b.dataset.key]=true});b.addEventListener('pointerup',()=>{keys[b.dataset.key]=false});b.addEventListener('pointercancel',()=>{keys[b.dataset.key]=false})});
// === PROCEDURAL WORLD ===
function spawnWave(){let r=run.rng.next(),type,lanes=[-.92,0,.92];if(r<.49){type='rock';let lane=lanes[Math.floor(rand(0,3))];objects.push({type,x:lane,z:1450+rand(-60,70),size:rand(.22,.37),height:rand(.38,.72),color:run.rng.next()<.5?'#534263':'#415164',passed:false})}else if(r<.72){type='gate';let safe=lanes[Math.floor(rand(0,3))];lanes.filter(x=>x!==safe).forEach((x,i)=>objects.push({type:'rock',x,z:1480+i*32,size:.33,height:.66,color:'#533d56',passed:false}));objects.push({type:'cell',x:safe,z:1500,size:.19})}else if(r<.91){let x=lanes[Math.floor(rand(0,3))];for(let i=0;i<4;i++)objects.push({type:'token',x:x+Math.sin(i*.7)*.12,z:1390+i*90,size:.13})}else{let x=lanes[Math.floor(rand(0,3))];objects.push({type:'orb',x,z:1460,size:.2})}}
function project(x,z,lift=0){let horizon=H*.37+run.y*24;let depth=760/(z+130);let scale=Math.min(3.3,depth);let perspective=Math.min(1,scale/3.3);let halfSpan=W*(.025+.405*perspective);let px=W*.5+(x-run.x)*halfSpan;let py=horizon+(H*.79-horizon)*Math.min(1,depth)-lift*scale*60;return{x:px,y:py,s:scale,horizon}}
// === PARTICLES & FEEDBACK ===
function burst(x,y,color,n=12,power=120){for(let i=0;i<n;i++){let a=Math.random()*Math.PI*2,s=power*(.2+Math.random()*.8);particles.push({x,y,vx:Math.cos(a)*s,vy:Math.sin(a)*s,life:.35+Math.random()*.55,max:.9,size:1.5+Math.random()*3,color})}}
function spawnTrail(dt){if(Math.random()<dt*45){let px=W*.5+run.x*W*.25;particles.push({x:px+(Math.random()-.5)*13,y:H*.79+10,vx:(Math.random()-.5)*45,vy:80+Math.random()*150,life:.22+Math.random()*.2,max:.42,size:1+Math.random()*2,color:run.boost>0?'#fff2ae':'#55e9ff'})}}
function showToast(text){ui.toast.textContent=text;ui.toast.classList.add('show');toastTimer=.9}
function collect(o){if(o.type==='cell'){run.energy=Math.min(100,run.energy+29);run.score+=250*run.multi;burst(project(o.x,o.z).x,project(o.x,o.z).y,CFG.colors.cyan,22,150);showToast('SOLAR CHARGE +');blip(780,.14,'sine',.24);blip(1120,.18,'sine',.1)}else if(o.type==='token'){run.combo++;run.multi=Math.min(5,1+Math.floor(run.combo/3)*.5);run.score+=500*run.multi;let p=project(o.x,o.z);burst(p.x,p.y,CFG.colors.gold,14,110);blip(880+run.combo*35,.1,'triangle',.15);showToast('✦  SCORE SHARD')}else if(o.type==='orb'){run.combo+=2;run.multi=Math.min(5,run.multi+.5);run.score+=900*run.multi;let p=project(o.x,o.z);burst(p.x,p.y,CFG.colors.violet,26,180);blip(440,.28,'sine',.28);showToast('CHAIN MULTIPLIER')}}
// === COLLISION & SIMULATION ===
function update(dt){if(state!=='playing')return;run.time+=dt;run.distance+=run.speed*dt;run.speed=Math.min(CFG.maxSpeed,CFG.baseSpeed+run.time*CFG.accel+(run.boost>0?100:0));let left=keys.ArrowLeft||keys.KeyA,right=keys.ArrowRight||keys.KeyD,up=keys.ArrowUp||keys.KeyW,down=keys.ArrowDown||keys.KeyS;let targetX=(right?1:0)-(left?1:0),targetY=(down?1:0)-(up?1:0);run.vx+=(targetX*CFG.steer-run.vx)*Math.min(1,dt*13);run.vy+=(targetY*CFG.pitch-run.vy)*Math.min(1,dt*11);run.x+=run.vx*dt;run.y+=run.vy*dt;run.x=Math.max(-1.28,Math.min(1.28,run.x));run.y=Math.max(-1,Math.min(1,run.y));if(run.boost>0)run.boost-=dt;run.sun=Math.max(0,100-run.time/CFG.sunDuration*100);let offSun=Math.abs(run.x)>.92||Math.abs(run.y)>.75;let shadow=objects.some(o=>o.type==='rock'&&o.z<420&&o.z>80&&Math.abs(o.x-run.x)<.55);run.energy-=dt*(CFG.energyDrain+(offSun?CFG.shadowDrain:0)+(shadow?.018:0));if(run.energy<=0){endRun('sun');return}if(run.sun<=0){endRun('sun');return}
run.spawn-=dt;if(run.spawn<=0){spawnWave();run.spawn=Math.max(.58,CFG.spawnEvery-run.time*.002)+rand(-.13,.16)}
for(let i=objects.length-1;i>=0;i--){let o=objects[i];o.z-=run.speed*dt;if(o.z<95&&o.z>-45&&Math.abs(o.x-run.x)<(o.type==='rock'?o.size+.17:.23)&&Math.abs(run.y)<.9){if(o.type==='rock'){run.flash=.22;run.shake=11;burst(W*.5+run.x*W*.2,H*.78,'#ff785e',32,230);endRun('crash');return}else{collect(o);objects.splice(i,1);continue}}if(o.type==='rock'&&!o.passed&&o.z<140&&o.z>35){if(Math.abs(o.x-run.x)<o.size+.45){o.passed=true;run.score+=180*run.multi;run.shake=Math.max(run.shake,4);run.near=.35;blip(270,.09,'triangle',.09);showToast('NEAR MISS  +180')}}if(o.z<-80){objects.splice(i,1);if(o.type==='token'||o.type==='orb')run.combo=0}}
run.shake=Math.max(0,run.shake-dt*20);run.flash=Math.max(0,run.flash-dt);run.near=Math.max(0,run.near-dt);run.score+=run.speed*dt*.12*run.multi;spawnTrail(dt);for(let i=particles.length-1;i>=0;i--){let p=particles[i];p.x+=p.vx*dt;p.y+=p.vy*dt;p.vy+=30*dt;p.life-=dt;if(p.life<=0)particles.splice(i,1)}if(toastTimer>0){toastTimer-=dt;if(toastTimer<=0)ui.toast.classList.remove('show')}
ui.score.textContent=Math.floor(run.score).toLocaleString('en-US');ui.distance.innerHTML=(run.distance/1000).toFixed(2)+' <small>km</small>';ui.speed.innerHTML=Math.floor(run.speed*1.28)+' <small>km/h</small>';ui.energybar.style.width=Math.max(0,run.energy)+'%';ui.sunbar.style.width=run.sun+'%';ui.multi.innerHTML='×'+run.multi.toFixed(1)+'<br><span style="font-size:9px;opacity:.7">COMBO</span>';ui.multi.classList.toggle('on',run.combo>0);updateAudio()}
// === DRAWING ===
function polygon(points,fill,stroke=null,lw=1){ctx.beginPath();points.forEach((p,i)=>i?ctx.lineTo(p.x,p.y):ctx.moveTo(p.x,p.y));ctx.closePath();ctx.fillStyle=fill;ctx.fill();if(stroke){ctx.strokeStyle=stroke;ctx.lineWidth=lw;ctx.stroke()}}
function drawSky(){let g=ctx.createLinearGradient(0,0,0,H*.68);g.addColorStop(0,'#11152c');g.addColorStop(.44,'#61405e');g.addColorStop(.76,'#e47a69');g.addColorStop(1,'#ffbd78');ctx.fillStyle=g;ctx.fillRect(0,0,W,H);let sunProgress=run?run.time/CFG.sunDuration:0;let sx=W*.5+Math.sin((run?.time||0)*.035)*W*.055,sy=H*.36+sunProgress*H*.16;let radius=Math.min(W,H)*.09;let halo=ctx.createRadialGradient(sx,sy,3,sx,sy,radius*2.7);halo.addColorStop(0,'#ffda9a99');halo.addColorStop(.48,'#ff996455');halo.addColorStop(1,'#ff825500');ctx.fillStyle=halo;ctx.fillRect(sx-radius*3,sy-radius*3,radius*6,radius*6);ctx.save();ctx.beginPath();ctx.arc(sx,sy,radius,0,Math.PI*2);ctx.clip();let sg=ctx.createLinearGradient(0,sy-radius,0,sy+radius);sg.addColorStop(0,'#fff1bd');sg.addColorStop(.48,'#ffca85');sg.addColorStop(1,'#f47b67');ctx.fillStyle=sg;ctx.fillRect(sx-radius,sy-radius,radius*2,radius*2);for(let i=0;i<7;i++){let yy=sy-radius*.48+i*radius*.22;ctx.fillStyle=`rgba(117,56,76,${.12+i*.015})`;ctx.fillRect(sx-radius,yy,radius*2,Math.max(2,radius*.035))}ctx.restore();for(let s of stars){ctx.globalAlpha=s.a*(.55+Math.sin((run?.time||0)*2+s.x*20)*.25);ctx.fillStyle='#fff';ctx.fillRect(s.x*W,s.y*H,s.r,s.r)}ctx.globalAlpha=1;
// distant angular mountains
let horizon=H*.53;ctx.fillStyle='#292c4c';ctx.beginPath();ctx.moveTo(0,horizon);for(let x=0;x<=W+60;x+=60){ctx.lineTo(x,horizon-15-Math.sin(x*.012)*25-Math.sin(x*.033)*10)}ctx.lineTo(W,H);ctx.lineTo(0,H);ctx.fill();ctx.fillStyle='#3b304c';ctx.beginPath();ctx.moveTo(0,horizon+12);for(let x=0;x<=W+40;x+=40)ctx.lineTo(x,horizon+8-Math.sin(x*.019+2)*20);ctx.lineTo(W,H);ctx.lineTo(0,H);ctx.fill()}
function drawRoad(){let hz=H*.53;let bottom=H*1.12;let center=W*.5-run.x*W*.17;let topW=W*.035,bottomW=W*.85;let gg=ctx.createLinearGradient(0,hz,0,H);gg.addColorStop(0,'#343047');gg.addColorStop(.55,'#24253a');gg.addColorStop(1,'#171a30');polygon([{x:center-topW,y:hz},{x:center+topW,y:hz},{x:center+bottomW,y:bottom},{x:center-bottomW,y:bottom}],gg,'#ffa67766',1);
// broad shoulders
polygon([{x:center-topW,y:hz},{x:center-topW*.45,y:hz},{x:center-bottomW*.43,y:bottom},{x:center-bottomW,y:bottom}],'#ffffff07');polygon([{x:center+topW*.45,y:hz},{x:center+topW,y:hz},{x:center+bottomW,y:bottom},{x:center+bottomW*.43,y:bottom}],'#ffffff07');
// perspective lane lines
for(let lane of [-.5,0,.5]){let x1=center+lane*topW*1.8,x2=center+lane*bottomW*1.85;ctx.strokeStyle=lane===0?'#ffdb9d31':'#a8d9e129';ctx.lineWidth=lane===0?1:2;ctx.beginPath();ctx.moveTo(x1,hz);ctx.lineTo(x2,bottom);ctx.stroke()}
let scroll=(run.distance%145);for(let i=0;i<17;i++){let d=((i*145-scroll+145)%145)/145;let y=hz+(bottom-hz)*d*d;let half=topW+(bottomW-topW)*d*d;ctx.strokeStyle=`rgba(255,190,143,${.03+d*.14})`;ctx.lineWidth=1+d*2;ctx.beginPath();ctx.moveTo(center-half,y);ctx.lineTo(center+half,y);ctx.stroke()}
// glowing horizon stripe
let lg=ctx.createLinearGradient(0,hz-9,0,hz+8);lg.addColorStop(0,'#ffb98200');lg.addColorStop(.5,'#ffb98288');lg.addColorStop(1,'#ffb98200');ctx.fillStyle=lg;ctx.fillRect(0,hz-9,W,18)}
function drawRock(o){let p=project(o.x,o.z),s=p.s*70*o.size;if(s<1)return;let x=p.x,y=p.y;let h=s*(1.35+o.height);ctx.save();ctx.translate(x,y);let shade=o.color;polygon([{x:-s*.72,y:0},{x:-s*.56,y:-h*.55},{x:-s*.22,y:-h},{x:s*.36,y:-h*.86},{x:s*.72,y:-h*.3},{x:s*.55,y:0}],shade,'#e8a38455',Math.max(1,s*.025));polygon([{x:-s*.56,y:-h*.55},{x:-s*.22,y:-h},{x:s*.36,y:-h*.86},{x:s*.08,y:-h*.42}],o.color==='#415164'?'#8195a0':'#886b7a');polygon([{x:s*.08,y:-h*.42},{x:s*.36,y:-h*.86},{x:s*.72,y:-h*.3},{x:s*.55,y:0}], '#211f35');ctx.fillStyle='#ffad7960';ctx.fillRect(-s*.23,-h*.75,s*.13,Math.max(2,s*.07));ctx.restore()}
function drawItem(o){let p=project(o.x,o.z),s=Math.max(2,25*p.s*o.size),x=p.x,y=p.y-Math.sin((run.time*5+o.z)*.02)*s*.2;ctx.save();ctx.translate(x,y);ctx.rotate(run.time*1.5);let color=o.type==='cell'?CFG.colors.cyan:o.type==='orb'?CFG.colors.violet:CFG.colors.gold;ctx.shadowColor=color;ctx.shadowBlur=s*1.2;if(o.type==='cell'){polygon([{x:0,y:-s},{x:s*.72,y:0},{x:0,y:s},{x:-s*.72,y:0}], '#b3fff0',color,2);ctx.strokeStyle='#39bdb7';ctx.lineWidth=Math.max(1,s*.12);ctx.beginPath();ctx.moveTo(s*.08,-s*.58);ctx.lineTo(-s*.2,s*.02);ctx.lineTo(s*.1,s*.02);ctx.lineTo(-s*.08,s*.58);ctx.stroke()}else if(o.type==='orb'){ctx.beginPath();ctx.arc(0,0,s*.72,0,Math.PI*2);ctx.fillStyle='#c7afff';ctx.fill();ctx.strokeStyle='#fff';ctx.lineWidth=2;ctx.stroke();ctx.beginPath();ctx.arc(0,0,s*1.15,0,Math.PI*2);ctx.strokeStyle='#b29aff88';ctx.stroke()}else{polygon([{x:0,y:-s},{x:s*.65,y:-s*.25},{x:s*.65,y:s*.45},{x:0,y:s},{x:-s*.65,y:s*.45},{x:-s*.65,y:-s*.25}], '#ffe7a5',color,1);ctx.fillStyle='#ff9f60';ctx.fillRect(-s*.12,-s*.44,s*.24,s*.5)}ctx.restore()}
function drawCraft(){let x=W*.5+run.x*W*.21,y=H*.79-run.y*H*.055;let bank=Math.max(-.55,Math.min(.55,-run.vx*.055));let pitch=run.vy*.009;ctx.save();ctx.translate(x,y);ctx.rotate(bank);ctx.transform(1,0,pitch,1,0,0);let glow=ctx.createRadialGradient(0,15,1,0,15,70);glow.addColorStop(0,run.boost>0?'#fff7ba':'#56edff');glow.addColorStop(1,'#55edff00');ctx.fillStyle=glow;ctx.fillRect(-75,-12,150,95);
// stylized solar glider silhouette
polygon([{x:0,y:-31},{x:8,y:-3},{x:54,y:16},{x:64,y:25},{x:14,y:18},{x:5,y:37},{x:-5,y:37},{x:-14,y:18},{x:-64,y:25},{x:-54,y:16},{x:-8,y:-3}], '#d8f9f4','#ffffff',1.5);polygon([{x:0,y:-30},{x:5,y:12},{x:0,y:31},{x:-5,y:12}], '#48bcca');polygon([{x:-53,y:17},{x:-17,y:12},{x:-22,y:18}], '#ffb875');polygon([{x:53,y:17},{x:17,y:12},{x:22,y:18}], '#ffb875');ctx.fillStyle=run.boost>0?'#fff7b4':'#5cfff0';ctx.shadowColor=ctx.fillStyle;ctx.shadowBlur=18;ctx.beginPath();ctx.moveTo(-4,29);ctx.lineTo(0,29+10+Math.random()*13);ctx.lineTo(4,29);ctx.fill();ctx.restore()}
function drawParticles(){for(let p of particles){ctx.globalAlpha=Math.max(0,p.life/p.max);ctx.fillStyle=p.color;ctx.shadowColor=p.color;ctx.shadowBlur=8;ctx.beginPath();ctx.arc(p.x,p.y,p.size,0,Math.PI*2);ctx.fill()}ctx.globalAlpha=1;ctx.shadowBlur=0}
function drawSpeedLines(){if(run.speed<310)return;let a=Math.min(.44,(run.speed-310)/480);ctx.strokeStyle=`rgba(192,238,255,${a})`;ctx.lineWidth=1;for(let i=0;i<35;i++){let x=((i*137.7+run.distance*1.7)%W),y=((i*91.3+run.distance*3.5)%(H*.68));let len=(run.speed-280)*.075;ctx.beginPath();ctx.moveTo(x,y);ctx.lineTo(x+(x-W/2)*.018,y+len);ctx.stroke()}if(run.speed>400){ctx.fillStyle='#ff5fbd12';ctx.fillRect(0,0,W,H);ctx.globalCompositeOperation='screen';ctx.fillStyle='#24e6ff0d';ctx.fillRect(4,0,W,H);ctx.globalCompositeOperation='source-over'}}
function render(){let shake=run&&run.shake>0?run.shake:0;ctx.save();ctx.translate((Math.random()-.5)*shake,(Math.random()-.5)*shake);drawSky();if(state==='playing'||state==='over'){drawRoad();let sorted=objects.slice().sort((a,b)=>b.z-a.z);for(let o of sorted){if(o.type==='rock')drawRock(o);else drawItem(o)}drawParticles();if(state==='playing')drawCraft();drawSpeedLines()}else{drawRoad();drawCraft()}ctx.restore();if(run&&run.flash>0){ctx.fillStyle=`rgba(255,92,81,${run.flash*1.2})`;ctx.fillRect(0,0,W,H)}}
// === MAIN LOOP ===
function frame(now){if(state!=='playing')return;let dt=Math.min(.033,(now-last)/1000||0);last=now;update(dt);render();if(state==='playing')requestAnimationFrame(frame)}
// === TITLE PREVIEW ===
function preview(){if(state==='title'){ctx.save();ctx.fillStyle='rgba(8,9,26,.18)';ctx.fillRect(0,0,W,H);let t=performance.now()/1000;ctx.translate(Math.sin(t*.35)*8,Math.cos(t*.3)*4);let fake=run;run=run||{distance:t*120,time:t*.12,x:0,y:0,vx:0,vy:0,speed:220,boost:0};drawSky();drawRoad();drawCraft();run=fake;ctx.restore()}if(state==='title')requestAnimationFrame(preview)}
ui.best.textContent='BEST FLIGHT  ·  '+Number(localStorage.getItem('solardrift-best')||0).toLocaleString();requestAnimationFrame(preview);
</script>
</body></html>
<!-- agent-meta {"model":"openai/gpt-6-luna","provider":"openrouter","persona":"full","sessionId":"bb9ea273-1988-4016-8ea2-a44c64c744d8","tokensIn":89527,"tokensOut":12400,"tokensTotal":101927,"cost":0.008789385,"turns":7,"toolCalls":6,"failedToolCalls":0,"timestamp":"2026-09-23T02:54:36.885Z"} -->