Despite its calm surface, Zen is made of a handful of carefully composed files working together:Documentation Index
Fetch the complete documentation index at: https://mintlify.com/mr-sunset/zen/llms.txt
Use this file to discover all available pages before exploring further.
index.html defines the structure and embeds the audio, style.css handles layout, theming, and animations, and script.js wires the two interactive controls. This page traces each of those moving parts from first page load to the moment the welcome screen disappears and the scene takes over.
Welcome screen flow
When the page loads, the browser renders a#welcome-container — a frosted-glass card centered on screen. It holds a heading, a short description, two tip paragraphs, a Controls checkbox, and an Enter Zen button. The card sits at z-index: 1000, floating above the island scene that is already rendered behind it.
Two event listeners drive all of the welcome screen’s interactive behavior:
User checks the Controls toggle
The
change event fires on #w-controls-toggle. The handler reads event.target.checked and writes it directly to blackNoise.controls — the boolean property of the <audio> element that shows or hides the browser’s native playback bar.User clicks Enter Zen
The
click event fires on #w-enter. The handler adds the .fade-out class to #welcome-container. CSS takes over from this point — no further JavaScript is involved.All DOM queries and event bindings are wrapped in a
DOMContentLoaded listener, so the script is safe to place at the end of <body> without a defer attribute.Fade animation
The entire welcome screen dismissal is handled by a single CSS keyframe declared at the top ofstyle.css:
forwardsfill mode — without it, the element would snap back toopacity: 1the moment the animation finished. Theforwardskeyword tells the browser to keep the computed style from the final (100%) keyframe in place indefinitely, effectively hiding the element without removing it from the DOM.pointer-events: none— this is applied at the same time as the animation begins, not after it ends. That means clicks and touches pass straight through the (still technically present) container to the scene underneath from the very first frame of the fade. There is no window during the 120 ms animation where a mis-click could re-trigger a button.
Scene composition
Behind the welcome card, three visual layers build the island scene. They are rendered in document order inside#main-container and positioned with CSS:
| Element | CSS strategy | Role |
|---|---|---|
#sand | position: fixed; bottom: 0; width: 100dvw | Full-width SVG anchored to the bottom edge of the viewport |
#group-tree | position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); z-index: 5 | Palm tree group centered horizontally, sitting just above the sand |
#moon | position: absolute; top: 200px; right: 100px | CSS-drawn circle with a yellow glow, placed in the upper-right area |
<div> styled entirely with CSS:
100dvw and 100dvh (dynamic viewport units) are used instead of 100vw / 100vh so the layout accounts for retractable browser toolbars on iOS and Android. This prevents the sand strip from appearing to float above the bottom of the screen on mobile devices.Audio element
The black noise track is declared as a plain HTML<audio> element at the very top of <body>, before any visual content:
src— points to a local.oggfile in theassets/folder. Using.ogg(Vorbis) keeps the file size small while maintaining broad browser support across Chrome, Firefox, Safari, and mobile browsers.autoplay— asks the browser to begin playback as soon as the audio is ready, without waiting for a user gesture.loop— restarts the track the instant it finishes, creating an uninterrupted ambient backdrop with no audible gap.
#black-noise audio element is also positioned on screen (top: 20px, max-width: 90vw) so that when controls is true, the native browser audio bar appears neatly at the top of the page rather than in an unexpected location.