# Sleep timer implementation

Built from the complete `17-scenes` source only. This app owns its copied files, new timer interface and timer engine changes. City, Forest and Water, example scenes, browser scene storage, recording imports, per-event timing and previews, noise/filter/envelope/motion controls, musical layers, reverb and lo-fi controls remain available.

## Listening flow

The sleep panel sits near Start listening. Choose the total listening duration in minutes and the final fade length. The fade is included in the total duration. Zero fade is allowed. Invalid durations or a fade longer than the duration show an explanation beside the timer.

Start listening & timer starts audio from the click and arms the timer after recordings are ready. Set sleep timer arms it during playback. Apply new timer uses the current form values. Restart uses the last armed duration, including the ten-second demo. The demo lasts ten seconds with a six-second fade and does not overwrite the minute inputs.

The countdown and progress line show remaining time. Phase text distinguishes waiting, fading and finished. Cancel leaves the mix playing and ramps the final gate back to the selected listening level over 1.2 seconds. Starting or restarting a timer during a fade also recovers gradually. Master and layer settings are never overwritten by the sleep fade.

Changing the environment or background recording preserves the running timer across the engine's internal restart. Loading an example or saved scene stops playback and clears the timer, as the page explains. Stop all clears the timer. A finished timer requires a new click before anything can play again.

## Audio and cleanup

A dedicated gain node follows the master volume and all effects. Native Web Audio automation schedules the final fade and holds the final gain at zero. Changes to output, intensity or other controls cannot undo that automation. A silent scheduled audio source signals the end. A separate deadline check catches delayed JavaScript callbacks, checks the deadline before scheduling events, and checks again when the page becomes visible.

At completion the existing global stop shuts down and disconnects every tracked source and node, including loop recordings, imported audio, drone oscillators, notes, LFOs and the reverb path. It clears the event scheduler, invalidates pending loads, clears waiting event states and closes the AudioContext. The running CSS state also ends. No restart is scheduled.

The timer is transient and is not saved in scene snapshots. App 18 uses its own browser storage names so saving or deleting a scene here does not change App 17's library.

## Checks

- JavaScript syntax checks passed for engine.js, app.js, scenes.js and sleep.js.
- `node checks/sleep-state.cjs` passed with a fake Web Audio context and clock. It checks native fade scheduling, cancellation recovery, restart, terminal cleanup, zero fade, manual stop and preservation across an internal engine restart.
- All 69 catalog recording paths exist in the supplied local audio folder.
- No browser, browser automation or server was opened by this implementation worker. The coordinator owns browser verification and listening checks. Audible balance and browser rendering have not been verified by this worker.

The first complete implementation is preserved under `attempts/001/`, with recording and observer paths adjusted so that copy is usable at its deeper URL. The working version adds a small follow-up fix: starting playback after completion resets the finished-timer label.

## Limits

A browser or operating system can suspend a page or its audio device. The native scheduled fade reaches and holds zero while the audio clock runs, even when JavaScript timers are delayed. JavaScript performs source cleanup when callbacks can run again, and the wall-clock deadline check prevents sound from returning after an overdue timer. This page cannot act as a system alarm while the browser is closed. Keep the page open while listening.

As in the predecessor, audio imports and saved scenes depend on storage permitted by the browser and this local address. The app reports unavailable recording storage and missing imported files. No external library or internet service was added.
