# Homepage implementation

The homepage presents one content tree through two layouts. Its scene, dock, preferences, and content remain mounted when the presentation changes.



The homepage presents one content tree through two layouts. Its scene, dock,
preferences, and content remain mounted when the presentation changes.

## Layout responsibilities [#layout-responsibilities]

`src/components/home/HomePage.tsx` owns the section order: introduction, projects,
client work, notes, photos, and contact. The CSS module applies the selected
layout through `data-home-layout` on the page root.

| Layout      | Desktop presentation                                                      | Small screens                         |
| ----------- | ------------------------------------------------------------------------- | ------------------------------------- |
| Two columns | Sticky introduction on the left, sections on the right, scene behind both | Stacked arrangement                   |
| Hero        | Introduction inside a centered scene card, sections beneath               | Centered card with responsive spacing |

Two columns is the default when no saved preference exists. A valid saved Hero
preference still takes precedence. The top navigation and bottom dock remain
centered. Layout variants reuse the content tree so switching does not duplicate
sections, restart the artwork, or create independent copies of page state.

## Preference storage [#preference-storage]

`src/hooks/use-home-layout.ts` exposes the current layout and whether the picker
is open through `useSyncExternalStore`. It restores a validated layout from the
`home-layout` storage key and synchronizes changes from other browser tabs.
Only the layout choice is persisted; panel visibility is temporary UI state.

If storage is unavailable, the selection continues to work in memory and the
store reports the failure. Invalid or removed values fall back to the default.

```mermaid
"sequenceDiagram\n    actor Visitor\n    participant Picker as Layout picker\n    participant Store as Layout store\n    participant Browser as Browser storage\n    participant Page as Homepage CSS\n    Visitor->>Picker: Open Homepage layout\n    Visitor->>Picker: Move focus with arrow keys\n    Note over Picker,Store: Focus movement does not change the layout\n    Visitor->>Picker: Press Enter\n    Picker->>Store: Apply selected layout\n    Store->>Browser: Save home-layout\n    Store->>Page: Publish new layout\n    Picker->>Visitor: Close and restore trigger focus"
```

## Keyboard and panel behavior [#keyboard-and-panel-behavior]

`LayoutDockButton` uses native radio inputs with explicit arrow-key handling.
Arrow keys move focus between options; Enter applies the focused option. Mouse
and touch selection apply immediately. Selecting the current option also closes
the panel. Escape closes without changing the preference.

The scene and layout panels coordinate their open state so opening one dismisses
the other. `DockPanel` retains an exiting panel long enough to fade and move
it toward the dock, while making that surface inert and hidden from assistive
technology. `restoreFocusWithoutTooltip` returns keyboard focus without leaving
an unrelated tooltip over the page.

The command palette exposes the picker and direct layout actions. The desktop
shortcut is Cmd/Ctrl+Shift+L. The visible picker button is specific to the homepage;
commands can navigate home before applying a layout.

## Scene rendering [#scene-rendering]

`SceneBackground` positions the scene and applies the background fades needed
for readable text. In Two columns, the artwork fills the viewport behind the
columns. The eased gradient protects the text areas while leaving the open center
visible in both themes.

`SceneSurface` loads the selected native scene and waits until it has produced a
frame before crossfading. Keeping the previous surface during loading avoids
flashing an empty background. A layout change keeps the existing canvas and
changes its presentation instead of remounting the renderer.

Scene settings live in `src/lib/home/scene-settings.ts` and are managed by
`use-scene-store.ts`. Defaults include 24 FPS, normal speed, automatic rotation,
and a visible glyph trail. The controls expose character density, frame rate,
color treatment, positioning, zoom, pause, and visibility.

## Glyph trail [#glyph-trail]

`GlyphTrail` adapts the native pointer-driven effect. It uses accent and shadow
colors selected for the active scene, with deeper pigment on light backgrounds.
The trail is enabled only for a fine desktop pointer without a reduced-motion
preference. It does not add an idle animation or intercept pointer input.

## Motion timing [#motion-timing]

When entering Two columns, both content columns use the same fade-and-rise timing.
The scene fades in as it expands, while the navigation and dock enter in their
established directions. Motion applies to the content surface rather than the
scene's containing layout, preserving the full-viewport artwork.

Reduced-motion preferences disable entrance animation and smooth scrolling.
Do not use motion as the only indication of a selected layout: checked state,
labels, keyboard focus, and the visible content arrangement remain available.

## Source map [#source-map]

| File                                             | Responsibility                                     |
| ------------------------------------------------ | -------------------------------------------------- |
| `src/lib/home/home-layouts.ts`                   | Typed layout options and descriptions              |
| `src/hooks/use-home-layout.ts`                   | Preference validation, persistence and panel state |
| `src/components/home/HomePage.module.css`        | Layout widths, stacking and column entrances       |
| `src/components/home/SceneBackground.module.css` | Scene placement and theme-aware edge blending      |
| `src/components/home/SceneSurface.tsx`           | Ready-frame scene loading and crossfades           |
| `src/components/ui/DockPanel.tsx`                | Shared panel entrance and exit motion              |
| `src/lib/home/scene-trail-colors.ts`             | Scene-specific glyph-trail palettes                |

## Verify a change [#verify-a-change]

Test a fresh browser and one with a saved preference. Check Hero and Two columns,
a narrow mobile viewport, a wide desktop viewport, and reduced motion. Use the
keyboard to move focus without selecting, apply with Enter, dismiss with Escape,
and reopen from the dock and command palette. Confirm the scene stays visible
and the canvas is not recreated merely because the layout changed.

- [Visitor controls](/docs/using-the-site/layouts-and-scenes): The layouts and artwork settings as a visitor experiences them.
- [Brand resources](/docs/using-the-site/brand): Shared typography, spacing, colors and action-button rules.
