Skip to content
LandingPagePrompts
Landing Pagegpt-5.5partial cross-check

Signal Room

Volumetric light shafts drift over a canvas field of audio-reactive bars

The exact prompt

A. Build one complete valid index.html for a single-viewport landing page for an audio-AI company named Signal. Document title: Signal Room — Audio AI for Live Work. Set html lang="en". ONE file only: plain HTML, inline CSS, and one small inline script at the end of body. No build step, no framework, no bundler, no React, no Tailwind, no GSAP, no Three.js, no Lottie, no external scripts, no external images, no video, no audio element, no GIF, no base64 photo blobs, and no third-party CDN URLs. Google Fonts is the only permitted network request; use it only for Inter and IBM Plex Mono with system fallback stacks. Every visible pixel must come from CSS gradients, inline SVG primitives, text, and one canvas. Desktop is exactly one frame with no scroll at width >= 901px: html and body height:100%; overflow:hidden; .page height:100dvh; overflow:hidden. Mobile and tablet at width <= 900px may scroll vertically but must never overflow horizontally. Accessibility is mandatory: real header, nav, main, and footer; exactly one h1; every control is a button or anchor with an accessible name; visible focus-visible rings; readable contrast; no inert clickable divs. The runtime telemetry hook must be exactly window.__DEMO__ = { name: 'signal-room', ready: false, frames: 0, effects: [], errors: [] }; and the script must set ready true after the first painted audio-bar frame, increment frames once per animation frame inside the requestAnimationFrame loop, push each implemented effect name into effects, and attach a window error listener that pushes errors into errors. Keep the finished index.html under 90 KB. Do NOT build extra sections, pricing, testimonials, blogs, dashboards, forms, cookie banners, scroll indicators, app screenshots, waveform audio players, modal dialogs, or a large footer sitemap. The single visual idea is a dark room built from CSS volumetric light shafts falling from above and slowly drifting over a soft floor glow, with a bottom canvas field of 64 vertical bars moving as if driven by audio; the bars are the only fast continuous motion.

B. THE BACKDROP — procedural cinematic room. Build the room with a fixed .backdrop at inset:0, overflow:hidden, pointer-events:none. The base room is .room-bg covering inset:0 with background layers, back to front: radial-gradient(ellipse at 50% 112%, rgba(119,232,255,0.18) 0%, rgba(119,232,255,0.075) 18%, rgba(119,232,255,0.022) 38%, transparent 62%); radial-gradient(circle at 20% 14%, rgba(94,134,255,0.14) 0%, rgba(94,134,255,0.045) 24%, transparent 52%); radial-gradient(circle at 78% 8%, rgba(205,238,255,0.11) 0%, rgba(205,238,255,0.035) 20%, transparent 46%); linear-gradient(180deg, #02040a 0%, #050915 39%, #03040a 74%, #010207 100%). Add .rear-haze at top:18%; left:50%; width:min(94vw, 1480px); height:34%; transform:translateX(-50%); background:radial-gradient(ellipse at 50% 50%, rgba(119,232,255,0.105) 0%, rgba(119,232,255,0.045) 34%, transparent 72%); filter:blur(42px); opacity:0.72. Add four shaft elements named .shaft--one through .shaft--four. Every shaft is position:absolute; top:-22%; transform-origin:50% 0%; filter:blur(var(--shaft-blur)); mix-blend-mode:screen; will-change:transform, opacity. Shaft one: left:13%; width:22vw; height:112vh; transform:skewX(-12deg) rotate(8deg); opacity:0.46; background:linear-gradient(180deg, rgba(202,244,255,0.00) 0%, rgba(202,244,255,0.25) 9%, rgba(119,232,255,0.145) 34%, rgba(119,232,255,0.052) 63%, rgba(119,232,255,0.00) 100%); animation:shaft-drift-a 24s ease-in-out infinite. Shaft two: left:36%; width:18vw; height:118vh; transform:skewX(10deg) rotate(-5deg); opacity:0.38; background:linear-gradient(180deg, rgba(255,255,255,0.00) 0%, rgba(220,249,255,0.20) 12%, rgba(125,180,255,0.11) 42%, rgba(125,180,255,0.040) 70%, transparent 100%); animation:shaft-drift-b 31s ease-in-out infinite. Shaft three: left:61%; width:24vw; height:116vh; transform:skewX(-8deg) rotate(6deg); opacity:0.42; background:linear-gradient(180deg, transparent 0%, rgba(216,248,255,0.21) 10%, rgba(119,232,255,0.125) 39%, rgba(119,232,255,0.046) 68%, transparent 100%); animation:shaft-drift-c 28s ease-in-out infinite. Shaft four: left:78%; width:15vw; height:104vh; transform:skewX(13deg) rotate(-9deg); opacity:0.30; background:linear-gradient(180deg, transparent 0%, rgba(196,226,255,0.17) 15%, rgba(119,232,255,0.082) 48%, rgba(119,232,255,0.026) 77%, transparent 100%); animation:shaft-drift-d 36s ease-in-out infinite. The soft floor glow is .floor-glow at left:50%; bottom:-11%; width:min(112vw, 1580px); height:38%; transform:translateX(-50%); border-radius:50% 50% 0 0; background:radial-gradient(ellipse at 50% 28%, rgba(119,232,255,0.24) 0%, rgba(119,232,255,0.112) 18%, rgba(83,113,190,0.050) 44%, transparent 72%); filter:blur(28px); opacity:0.82; animation:floor-breathe 13s ease-in-out infinite. Add .room-lines for the floor perspective: bottom:-4%; height:44%; width:100%; background-image:repeating-linear-gradient(90deg, rgba(161,239,255,0.060) 0 1px, transparent 1px 92px), repeating-linear-gradient(0deg, rgba(161,239,255,0.050) 0 1px, transparent 1px 64px); transform:perspective(840px) rotateX(68deg); transform-origin:50% 100%; opacity:0.32; mask-image:linear-gradient(180deg, transparent 0%, rgba(0,0,0,0.66) 20%, rgba(0,0,0,0.46) 58%, transparent 100%). Add .grain as inline SVG feTurbulence background at opacity 0.075, animated 1.1s steps(5), never above z-index 8.

The canvas is canvas#audio-bars, fixed left:50%; bottom:0; width:min(100vw, var(--bars-max-w)); height:var(--bars-h); transform:translateX(-50%); z-index:6; display:block; pointer-events:none. It draws exactly 64 bars at desktop, 52 bars at width <= 900px, and 44 bars at width <= 560px. Each bar is a rounded vertical capsule with width computed from available width and gap, minimum 3px, maximum 14px. Heights follow a deterministic sum of sines: base = 0.30 + 0.20*sin(t*2.6 + i*0.41) + 0.14*sin(t*4.9 + i*0.17) + 0.10*sin(t*8.2 + i*0.73); envelope = 0.62 + 0.28*sin(t*0.72) + 0.10*sin(t*1.13 + 1.7); height = clamp(0.10, 0.96, abs(base) * envelope + laneBoost). The centre 18 bars receive laneBoost 0.10 * (1 - abs(i - mid) / 18). Use canvas 2D only, no audio APIs. Gradient per bar: top rgba(210,250,255,0.94) 0%, mid rgba(119,232,255,0.70) 42%, base rgba(61,102,190,0.24) 100%. Draw a soft mirrored foot reflection with rgba(119,232,255,0.06) and blur 14px after the solid bars. Frame budget: 64 rounded rects plus 64 reflection rects and two global gradients per frame, under 140 draw primitives. Resolution trick: cap backing-store device pixel ratio at 1.75 on desktop and 1.5 on mobile, set canvas.width = cssWidth * dpr and canvas.height = cssHeight * dpr, then ctx.setTransform(dpr,0,0,dpr,0,0). Recompute dimensions on resize with one queued rAF, not a timer. If document.hidden, keep the rAF loop alive and increment frames, but skip paint until visible.

C. THE LAYER STACK, back to front. html and body are #02040a at z-index auto. .backdrop is fixed inset:0 z-index:0 pointer-events:none overflow:hidden. Inside .backdrop: .room-bg z-index:0, .rear-haze z-index:1, .shaft--one z-index:2, .shaft--two z-index:3, .shaft--three z-index:2, .shaft--four z-index:3, .floor-glow z-index:4, .room-lines z-index:5, canvas#audio-bars z-index:6, .grain z-index:8. .page is position:relative z-index:10 min-height:100dvh display:grid grid-template-rows:auto 1fr auto. header.site-header is z-index:30. main.hero is z-index:20. .hero-panel is z-index:22 and must not use backdrop-filter stronger than 10px. footer.signal-footer is z-index:30. .mobile-menu-panel, when open, is fixed z-index:80. .focus-ring and browser outlines remain above local stacking contexts. Do not put any content behind the canvas bars at the bottom where it can become unreadable; footer sits above the bars with a bottom scrim.

D. TOKEN TABLE. Define tokens in :root for the 1440px desktop default. Colors: --bg:#02040a; --bg-2:#050915; --text:#eff9fb; --text-soft:#cfe2e7; --muted:#91a6af; --muted-2:#617680; --accent:#77e8ff; --accent-2:#7b8cff; --accent-hot:#d2faff; --line:rgba(210,250,255,0.16); --line-strong:rgba(210,250,255,0.34); --line-soft:rgba(210,250,255,0.09); --panel:rgba(3,7,16,0.42); --panel-strong:rgba(5,10,22,0.66); --focus:#d2faff; --black:#000000. Type: --font-sans:"Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; --font-mono:"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; --logo:16px; --nav:13px; --eyebrow:12px; --h1:82px; --lead:18px; --fine:12.5px; --button:13px; --metric:12px; --small-caps-track:0.16em. Layout: --header-x:42px; --header-y:28px; --header-h:44px; --page-pad-x:42px; --hero-pad-top:20px; --hero-pad-bottom:118px; --hero-max:860px; --hero-gap:22px; --hero-panel-pad-y:30px; --hero-panel-pad-x:38px; --footer-x:42px; --footer-y:26px; --footer-gap:28px; --nav-gap:10px. Buttons and shapes: --radius-pill:999px; --radius-panel:28px; --radius-soft:16px; --button-h:42px; --nav-h:38px; --chip-h:30px; --focus-w:2px; --focus-offset:4px; --panel-border-w:1px. Backdrop dimensions: --shaft-blur:22px; --bars-h:210px; --bars-max-w:1680px; --bars-bottom-fade:118px; --floor-line-size-x:92px; --floor-line-size-y:64px. Motion: --ease-out:cubic-bezier(0.16,1,0.3,1); --ease-soft:cubic-bezier(0.22,1,0.36,1); --enter-dur:1.05s; --soft-dur:1.25s; --shaft-a-dur:24s; --shaft-b-dur:31s; --shaft-c-dur:28s; --shaft-d-dur:36s; --floor-dur:13s; --grain-dur:1.1s. Canvas JS constants mirror the CSS dimensions: barCountDesktop 64; barCountTablet 52; barCountPhone 44; barGapDesktop 10; barGapTablet 8; barGapPhone 6; barRadius 999; paintDprDesktop 1.75; paintDprMobile 1.5. Fonts are loaded with one preconnect to https://fonts.gstatic.com and one Google Fonts stylesheet for Inter weights 400,500,600,700 and IBM Plex Mono weights 400,500,600 with display=swap.

E. THE COMPOSITION. First CSS rule must be exactly html, body { background: #02040a !important; color: #eff9fb; } and the body tag must include style="background:#02040a;color:#eff9fb" to prevent a white flash. Body uses margin:0; min-width:320px; font-family:var(--font-sans); text-rendering:geometricPrecision; -webkit-font-smoothing:antialiased. Page grid: .page { position:relative; z-index:10; min-height:100dvh; display:grid; grid-template-rows:auto minmax(0, 1fr) auto; } Desktop lock at >=901px sets html, body { height:100%; overflow:hidden; } and .page { height:100dvh; overflow:hidden; }. Header build order: create header.site-header with display:flex; align-items:center; justify-content:space-between; height:var(--header-h); padding:var(--header-y) var(--header-x) 0; gap:24px. The brand is an anchor href="#" with accessible name "Signal home". It contains an inline SVG mark 22px by 22px: a rounded square rect x=2 y=2 width=18 height=18 rx=6 fill="none" stroke="currentColor" stroke-width="1.5" and three vertical signal strokes at x=7,11,15 with rounded caps, heights 6,12,8, color var(--accent). Brand text is SIGNAL, font-size var(--logo), font-weight 700, letter-spacing:0.17em, color var(--text), text-decoration:none. Header nav contains exactly three links: Platform, Intelligence, Security. Each link is a pill from the UI language. Header right CTA is an anchor with text Hear a demo. Mobile burger appears only at <=900px and is a button with aria-label="Open navigation", aria-expanded toggled, and three 16px bars.

Hero build order: main.hero is display:grid; place-items:center; min-width:0; padding:var(--hero-pad-top) var(--page-pad-x) var(--hero-pad-bottom); overflow:visible. Inside it, .hero-panel is width:100%; max-width:var(--hero-max); display:grid; justify-items:center; gap:var(--hero-gap); text-align:center; padding:var(--hero-panel-pad-y) var(--hero-panel-pad-x); border:var(--panel-border-w) solid var(--line); border-radius:var(--radius-panel); background:linear-gradient(180deg, rgba(5,10,22,0.50) 0%, rgba(3,7,16,0.30) 100%); box-shadow:0 28px 90px rgba(0,0,0,0.34), inset 0 1px 0 rgba(255,255,255,0.06); backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px). Place a chip above the h1: text REAL-TIME AUDIO AI, height var(--chip-h), padding 0 13px, border 1px solid var(--line), border-radius var(--radius-pill), font-size var(--eyebrow), font-family var(--font-mono), letter-spacing var(--small-caps-track), color var(--accent), background rgba(119,232,255,0.045). The H1 is exactly one element, text Hear the work before it slips., margin:0, max-width:800px, font-size:var(--h1), line-height:0.96, letter-spacing:-0.065em, font-weight:700, color:var(--text). Wrap the words in spans for entrance only, but do not split into extra headings. The lead paragraph exact copy is: Signal listens across meetings, calls, and customer conversations, then turns every live moment into searchable intelligence before context disappears. CSS: margin:0; max-width:680px; color:var(--text-soft); font-size:var(--lead); line-height:1.62; letter-spacing:-0.018em. Hero actions: a .button.button--primary with text Start with Signal, and a .button.button--ghost with text View security model; group display:flex; gap:12px; flex-wrap:wrap; justify-content:center. Footer: footer.signal-footer contains a ul with exactly three li metrics and no nav: 64 live bands, 18 ms analysis window, Private by design. Footer CSS: padding:0 var(--footer-x) var(--footer-y); display:flex; justify-content:center; align-items:center; position:relative. The ul is display:flex; gap:var(--footer-gap); list-style:none; padding:0; margin:0; flex-wrap:wrap; justify-content:center. Each li uses font-family:var(--font-mono); font-size:var(--metric); letter-spacing:0.10em; text-transform:uppercase; color:var(--muted). The numeric prefix or first word is a span color var(--accent-hot), opacity 0.92, margin-right:8px.

F. THE UI LANGUAGE. All clickable header pills and hero buttons share a precise glass-signal treatment. .pill and .button are inline-flex; align-items:center; justify-content:center; border-radius:var(--radius-pill); text-decoration:none; position:relative; overflow:hidden; transition:transform 220ms var(--ease-out), border-color 220ms var(--ease-out), background 220ms var(--ease-out), color 220ms var(--ease-out), box-shadow 220ms var(--ease-out). .pill height:var(--nav-h); padding:0 15px; border:1px solid rgba(210,250,255,0.13); color:var(--text-soft); font-size:var(--nav); font-weight:560; background:linear-gradient(180deg, rgba(210,250,255,0.060) 0%, rgba(210,250,255,0.018) 100%); box-shadow:inset 0 1px 0 rgba(255,255,255,0.08), 0 12px 32px rgba(0,0,0,0.20). .pill::before and .button::before are a 112deg moving glint: content:""; position:absolute; inset:-1px; background:linear-gradient(112deg, transparent 0%, transparent 36%, rgba(210,250,255,0.18) 50%, transparent 64%, transparent 100%); transform:translateX(-140%); transition:transform 680ms var(--ease-out); pointer-events:none. Hover moves any clickable up -1px, border-color rgba(210,250,255,0.36), color var(--text), and glint translateX(140%). Active returns translateY(0). .button height:var(--button-h); padding:0 18px; font-size:var(--button); font-weight:650; letter-spacing:-0.01em. .button--primary uses color:#031018; border-color rgba(210,250,255,0.56); background:linear-gradient(180deg, #d2faff 0%, #77e8ff 52%, #76a8ff 100%); box-shadow:0 18px 52px rgba(119,232,255,0.24), inset 0 1px 0 rgba(255,255,255,0.62). .button--primary:hover background:linear-gradient(180deg, #ffffff 0%, #98efff 48%, #8bb5ff 100%). .button--ghost uses color:var(--text-soft); border:1px solid var(--line); background:rgba(210,250,255,0.035). Focus: every a and button has :focus-visible outline var(--focus-w) solid var(--focus); outline-offset:var(--focus-offset); border-radius:var(--radius-pill). Selection: ::selection { background:rgba(119,232,255,0.30); color:#ffffff; }. The mobile panel uses background rgba(2,4,10,0.91), backdrop-filter blur(20px), border-top 1px solid var(--line), and stacked links at 24px with no extra pages.

G. MOTION — entrance stagger and named keyframes. Resting opacity is always 1 on .appear elements; animations define from states only, and the page remains readable if animation fails. Apply .appear plus a modifier to each animated element with inline --d. Entrance animations use animation-duration:var(--enter-dur); animation-fill-mode:both; animation-timing-function:var(--ease-out); animation-delay:var(--d). Stagger table: brand .appear--scale delay 0.06s; nav Platform .appear--soft delay 0.14s; nav Intelligence .appear--soft delay 0.20s; nav Security .appear--soft delay 0.26s; header CTA .appear--scale delay 0.32s; chip .appear--pop delay 0.34s; h1 word Hear .appear--word delay 0.48s; h1 word the delay 0.55s; h1 word work delay 0.62s; h1 word before delay 0.69s; h1 word it delay 0.76s; h1 word slips. delay 0.83s; lead paragraph .appear--soft delay 1.00s; primary button .appear--scale delay 1.14s; ghost button .appear--scale delay 1.22s; metric 64 .appear--stat delay 1.30s; metric 18 .appear--stat delay 1.40s; metric Private .appear--stat delay 1.50s. Named keyframes: in-scale from opacity:0 transform:scale(0.92) to opacity:1 transform:none. in-soft from opacity:0 transform:translateY(14px) filter:blur(5px) to opacity:1 transform:none filter:blur(0). in-pop from 0% opacity:0 transform:scale(0.94), 68% opacity:1 transform:scale(1.035), 100% opacity:1 transform:scale(1). in-word from opacity:0 transform:translateY(0.46em) rotateX(36deg); transform-origin:50% 100%; filter:blur(4px) to opacity:1 transform:none filter:blur(0). in-stat from opacity:0 transform:translateY(12px) to opacity:1 transform:none. Continuous keyframes: shaft-drift-a drifts translate3d(-1.6vw,0,0) skewX(-12deg) rotate(7deg) to translate3d(1.2vw,1.4vh,0) skewX(-10deg) rotate(9deg) and back over 24s. shaft-drift-b drifts translate3d(1.1vw,0,0) skewX(10deg) rotate(-5deg) to translate3d(-1.4vw,1.8vh,0) skewX(12deg) rotate(-7deg) and back over 31s. shaft-drift-c drifts translate3d(-1.0vw,0,0) skewX(-8deg) rotate(6deg) to translate3d(1.6vw,1.2vh,0) skewX(-6deg) rotate(4deg) and back over 28s. shaft-drift-d drifts translate3d(0.8vw,0,0) skewX(13deg) rotate(-9deg) to translate3d(-1.0vw,1.0vh,0) skewX(11deg) rotate(-8deg) and back over 36s. floor-breathe animates opacity 0.72 to 0.90 to 0.72 and transform translateX(-50%) scaleX(0.985) to translateX(-50%) scaleX(1.025) to start over 13s. grain-shift uses five stepped offsets: 0 0, -2% 1%, 1% -2%, -1% 2%, 2% 0. The canvas bars run continuously via JS; their frame-to-frame height changes are the only fast continuous motion.

H. RESPONSIVE TABLE — exact token overrides per breakpoint. Defaults above are for 1440x900. For width >= 1600px set --header-x:56px; --header-y:34px; --logo:17px; --nav:14px; --nav-h:40px; --button:14px; --button-h:44px; --h1:96px; --lead:19px; --hero-max:940px; --hero-gap:24px; --hero-panel-pad-y:34px; --hero-panel-pad-x:46px; --hero-pad-bottom:132px; --footer-x:56px; --footer-y:30px; --footer-gap:34px; --bars-h:232px; --bars-max-w:1840px; --shaft-blur:24px. For width >= 1920px set --header-x:72px; --header-y:38px; --logo:18px; --nav:14.5px; --nav-h:42px; --button-h:46px; --h1:112px; --lead:20px; --hero-max:1040px; --hero-gap:26px; --hero-panel-pad-y:38px; --hero-panel-pad-x:54px; --hero-pad-bottom:148px; --footer-y:34px; --footer-gap:42px; --bars-h:260px; --bars-max-w:2040px; --shaft-blur:26px. For 1280px to 1599px set --header-x:42px; --h1:78px; --lead:17px; --hero-max:820px; --hero-panel-pad-y:28px; --hero-panel-pad-x:34px; --hero-pad-bottom:112px; --bars-h:202px. For 901px to 1279px set --header-x:30px; --header-y:22px; --page-pad-x:30px; --footer-x:30px; --footer-y:22px; --nav:12.5px; --nav-h:36px; --button:12.5px; --button-h:40px; --logo:15px; --h1:60px; --lead:16px; --hero-max:720px; --hero-gap:18px; --hero-panel-pad-y:24px; --hero-panel-pad-x:28px; --hero-pad-bottom:98px; --footer-gap:22px; --bars-h:178px; --shaft-blur:20px. For desktop max-height <= 850px and width >= 901px set --header-y:20px; --header-h:40px; --hero-pad-top:10px; --hero-pad-bottom:86px; --hero-gap:16px; --hero-panel-pad-y:22px; --h1:58px; --lead:15px; --chip-h:28px; --footer-y:18px; --bars-h:168px; .hero-panel max-width:min(var(--hero-max), 760px). For desktop max-height <= 720px and width >= 901px set --header-y:14px; --header-h:36px; --hero-pad-top:4px; --hero-pad-bottom:72px; --hero-gap:12px; --hero-panel-pad-y:18px; --hero-panel-pad-x:26px; --h1:46px; --lead:13.5px; --eyebrow:11px; --chip-h:26px; --button-h:36px; --footer-y:12px; --metric:11px; --bars-h:138px; .hero-panel border-radius:22px; .floor-glow opacity:0.68. For width <= 900px remove the desktop height lock: html, body { min-height:100%; overflow-x:hidden; } .page { min-height:100dvh; height:auto; overflow:hidden; grid-template-rows:auto minmax(620px, auto) auto; } tokens: --header-x:22px; --header-y:20px; --header-h:42px; --page-pad-x:22px; --hero-pad-top:72px; --hero-pad-bottom:220px; --hero-max:100%; --hero-gap:18px; --hero-panel-pad-y:26px; --hero-panel-pad-x:22px; --h1:48px; --lead:16px; --button-h:42px; --bars-h:190px; --bars-max-w:980px; --shaft-blur:18px. At <=900px hide desktop nav and header CTA, show the burger, and create .mobile-menu-panel fixed inset:0 z-index:80 display:grid place-items:center transform:translateY(-100%) until html.menu-open transform:none. It contains the same three nav links and the CTA stacked with gap 22px. For width <=560px set --header-x:18px; --page-pad-x:18px; --hero-pad-top:54px; --hero-pad-bottom:190px; --hero-panel-pad-y:22px; --hero-panel-pad-x:18px; --radius-panel:22px; --h1:39px; --lead:14.5px; --eyebrow:10.5px; --chip-h:26px; --button:12.5px; --bars-h:170px; footer ul flex-direction:column; align-items:center; gap:10px. Canvas constants also scale: <=900px uses 52 bars and gap 8; <=560px uses 44 bars and gap 6; all widths keep zero horizontal overflow.

I. FAILURE GUARDS. The .appear class must have opacity:1 as its resting declaration before animation names are applied; animation keyframes handle initial opacity so a failed animation never leaves content invisible. Black-first guard: first CSS rule is html, body { background: #02040a !important; color: #eff9fb; } and body has the inline background style. Two-rAF entrance fallback: after two nested requestAnimationFrame callbacks, inspect every .appear element with el.getAnimations({ subtree:false }); if none of its animations has playState "running" or "finished", add .is-in to every .appear. If a browser lacks getAnimations, run the same .is-in fallback after the two rAFs. .is-in forces animation:none !important; opacity:1 !important; transform:none !important; filter:none !important; clip-path:none !important. Canvas fallback: if canvas or 2D context is missing, add .no-canvas to html and CSS must show a static bar field using repeating-linear-gradient(90deg, rgba(119,232,255,0.40) 0 4px, transparent 4px 18px) masked by a bottom gradient on .backdrop::after; the page remains readable and the telemetry errors array receives a short string. Reduced motion: inside @media (prefers-reduced-motion: reduce), set *, *::before, *::after { animation:none !important; transition:none !important; scroll-behavior:auto !important; }, force .appear and .appear.is-in to opacity:1 transform:none filter:none clip-path:none, freeze the shafts at their base transforms, hide the grain animation, and make the canvas draw one static bar frame with t=2.4, then stop scheduling further visual changes after ready is true. In reduced motion, window.__DEMO__.frames may stop after the first painted frame, but ready must still become true and content must be static and readable. Maintain contrast: main text #eff9fb on #02040a, lead #cfe2e7 on the panel, and muted metric #91a6af all remain readable; do not lower text opacity below 0.86. Add a window error listener before running any other animation code and push String(event.message || event.error || "unknown error") to window.__DEMO__.errors. No console.log, console.warn, or console.error in the happy path. Guard every optional element check so missing elements cannot throw.

J. THE EXACT JS. Keep the script as a small IIFE at the end of body. It must do only telemetry, canvas bars, animation fallback, reduced-motion handling, resize handling, and mobile menu behavior. First line inside the script sets window.__DEMO__ = { name: 'signal-room', ready: false, frames: 0, effects: [], errors: [] }; then push implemented effect names exactly once in this order: "volumetric-light-shafts", "floor-glow", "audio-bars-canvas", "grain-texture", "mobile-menu". Add the error listener immediately after creating the object. Cache document.documentElement, canvas#audio-bars, the 2D context, the menu button, the mobile panel, all panel links, and matchMedia('(prefers-reduced-motion: reduce)'). Use no timers and no console calls. Implement a resizeCanvas function that reads canvas.getBoundingClientRect(), sets cssWidth and cssHeight, caps dpr to 1.75 or 1.5 based on innerWidth <= 900, sets canvas.width and canvas.height from css dimensions times dpr, and calls ctx.setTransform(dpr,0,0,dpr,0,0). Resize is scheduled by a boolean resizeQueued and requestAnimationFrame only. Implement roundedRect(ctx,x,y,w,h,r) locally with moveTo, lineTo, quadraticCurveTo, and closePath. The drawBars(timeMs) function clears the CSS-sized canvas, paints a bottom fade linear gradient from transparent 0% to rgba(2,4,10,0.62) 100%, then draws exactly barCount bars based on width breakpoint. Compute t = timeMs / 1000, mid = (barCount - 1) / 2, gap from breakpoint, available = cssWidth - 2 * sidePad where sidePad is 26 desktop, 20 tablet, 16 phone, barW = clamp between 3 and 14, startX = (cssWidth - (barCount * barW + (barCount - 1) * gap)) / 2. For each i, compute the sine formula from section B, clamp height, y = cssHeight - 18 - h, x = startX + i * (barW + gap). Draw reflection first using globalAlpha 0.46, filter blur(14px), y = cssHeight - 16, h = h * 0.32, fillStyle rgba(119,232,255,0.12). Reset filter and globalAlpha, create a vertical gradient for the solid bar using the exact color stops in section B, and fill the rounded capsule. Add a final top glow gradient across the bar field: radial-gradient equivalent via ctx.createRadialGradient centered at cssWidth/2, cssHeight*0.62 with inner radius 0 and outer radius min(cssWidth, cssHeight)*0.72, colors rgba(119,232,255,0.10) to transparent. Start a requestAnimationFrame loop named tick. At the top of every tick increment window.__DEMO__.frames by exactly 1. If document.hidden is false and context exists, call drawBars unless reduced motion has already painted once. On the first completed draw, schedule one more requestAnimationFrame and set window.__DEMO__.ready = true inside it, so ready follows the first paint opportunity. Continue the loop unless reduced motion has painted and ready is true. Animation fallback: add animationend listeners to every .appear; on end add .is-in; then run the two-rAF fallback described in section I. Burger behavior: clicking the burger toggles class menu-open on documentElement, updates aria-expanded to "true" or "false", updates aria-label to "Close navigation" or "Open navigation", and sets panel aria-hidden to the inverse. Escape closes the menu. Clicking any link inside the mobile panel closes the menu. Resizing to width > 900 closes the menu. Closing means remove menu-open, button aria-expanded="false", button aria-label="Open navigation", panel aria-hidden="true". The script must not create visual DOM elements, must not fetch, must not use localStorage, and must not log.

---

TECHNICAL CONTRACT (non-negotiable):

1. Deliver ONE single file: a complete, valid `index.html`. No build step, no bundler,
   no framework, no package install. It must open correctly by double-clicking the file
   and also over http://.
2. Vanilla only. No React, no Tailwind CDN, no GSAP, no Three.js, no jQuery, no Lottie.
   Plain HTML + CSS + modern JavaScript in <style> and <script> tags.
3. NO external media. No .mp4, no .webm, no .gif, no remote images, no base64 blobs of
   photos. Every visual must be generated procedurally with CSS gradients, SVG, or
   <canvas>. This keeps the page free to host and impossible to break with a dead link.
4. Google Fonts is the ONLY permitted network request, and it must be declared with a
   <link rel="preconnect"> plus a system-font fallback stack so the page still looks
   intentional offline. If you prefer, skip it and use a pure system stack.
5. Responsive and correct at 390x844 (phone), 768x1024 (tablet) and 1440x900 (desktop).
   No horizontal scrollbar at any of those widths. Nothing may overflow its container.
6. Accessibility: exactly one <h1>; real <header>/<main>/<footer>/<nav> landmarks; every
   interactive element is a <button> or <a> with an accessible name; visible :focus-visible
   ring; body text contrast ratio >= 4.5:1 against its background.
7. Motion safety: wrap all continuous motion in
   `@media (prefers-reduced-motion: reduce)` rules that reduce it to a static or
   near-static state. The page must remain fully readable and usable with motion off.
8. Performance: no layout thrash. Cache DOM reads, batch writes inside a single
   requestAnimationFrame loop, use transform/opacity for animation, and never allocate
   inside the hot loop. Target 60fps on a 2019 laptop. Total file under 90 KB.
9. Runtime telemetry hook (used by the automated verifier — implement it exactly):
   at the top of your script define
     window.__DEMO__ = { name: '<slug>', ready: false, frames: 0, effects: [], errors: [] };
   then set `ready = true` after the first paint of your main effect, increment
   `frames` once per animation frame inside your rAF loop, and push the name of each
   implemented effect into `effects`. Add a `window.addEventListener('error', ...)`
   handler that pushes messages into `errors`. Do not rename these fields.
10. Zero console output in the happy path. No console.log left behind. No uncaught
    exceptions, no failed network requests.

RESPONSE FORMAT:
Return ONLY the raw HTML inside a single ```html fenced code block. No explanation, no
preamble, no commentary before or after the fence. The file must be complete and
immediately runnable — never truncate, never write "// rest of code here".

Acceptance criteria (15)

  1. the generated index.html contains exactly one h1 with the exact text 'Hear the work before it slips.' and uses semantic header, nav, main, and footer landmarks
  2. canvas#audio-bars exists, paints a non-blank 64-bar audio field at 1440x900, and window.__DEMO__.frames increments once per requestAnimationFrame tick while effects includes 'audio-bars-canvas'
  3. window.__DEMO__ is initialized with name 'signal-room', ready becomes true after the first painted bar frame, effects contains volumetric-light-shafts, floor-glow, audio-bars-canvas, grain-texture, and mobile-menu, and errors stays empty in the happy path
  4. at viewport widths 1440 and 1920, html/body and .page are locked to one 100dvh frame with overflow hidden; at 390px and 768px vertical scroll may exist but there is no horizontal overflow
  5. the document performs no network requests except Google Fonts, contains no external media or framework scripts, includes a prefers-reduced-motion reduce block, and every anchor or button has a visible focus-visible ring
  6. window.__DEMO__.ready becomes true within 5s
  7. window.__DEMO__.frames advances (>= 20 frames in 1.2s)
  8. window.__DEMO__.errors is empty
  9. zero console errors and zero page errors
  10. zero failed network requests
  11. exactly one <h1> with non-empty text
  12. header, main, footer landmarks present
  13. no horizontal overflow at 390 / 768 / 1440 widths
  14. no horizontal overflow after 2s of animation
  15. prefers-reduced-motion: reduce leaves the page usable and errors empty

More landing page prompts