DESIGN.md · git:20261105.afbdea7 · 2026-11-05 · sha256 c7d137e9d847e1d1

DESIGN.md git:20261105.afbdea7A

Immutable. This exact content never changes and is served at /api/v1/blob/c7d137e9d847e1d1.

## Overview

This is the Alook design system. It is organized in layers: the **why** (context, principles), the **what** (foundations — color, type, spacing, elevation, shape, motion), the **how** (components, patterns), and the **words** (voice, do's & don'ts).

Light and dark are both first-class, and the app adapts across two breakpoints — **desktop** and **mobile**. Every token below resolves through CSS variables in `src/web/src/app/globals.css` — read values from there, never hard-code a hex or oklch in a component.

## Design Context

### Users
Power users and tasteful hackers who want Your Personal Company with a minimalist, collaborative approach. They value control over their infrastructure, appreciate good tooling, and have strong aesthetic sensibilities. They use Alook in focused work sessions — managing agents, reviewing task output, and iterating on instructions.

### Brand Personality
**Warm, precise, and utilitarian.** Alook feels like a well-crafted tool made by someone who cares — not cold and corporate, not flashy and consumer. It earns trust through restraint and clarity. Every element has a reason.

3-word personality: **Warm. Sharp. Purposeful.**

Emotional goals: confidence, calm focus, quiet delight in small details.

### Aesthetic Direction
**Visual tone**: Notion-inspired warmth meets developer-tool precision. Soft neutral palette (warm grays, cream tints) with crisp typography and intentional micro-interactions. Light and airy in light mode, cozy and focused in dark mode.

**References**: Notion (polished, warm, delightful micro-interactions), vintage Macintosh product photography (warm object on cool ground, generous negative space, matte textures)

**Anti-references**:
- Generic SaaS dashboards (blue buttons, card grids, cookie-cutter layouts)
- AI chatbot UIs (ChatGPT-style centered chat with big rounded bubbles and gradients)
- Playful/consumer apps (bright colors, illustrations, emoji-heavy, gamification)

**Theme**: Both light and dark as first-class citizens. Warm-tinted neutrals in both modes — never pure gray.

## Design Principles

1. **Every pixel earns its place** — No decorative filler. If an element doesn't help the user accomplish their goal, remove it. Whitespace is a feature, not wasted space.

2. **Warm precision** — Technical doesn't mean cold. Use warm color tints, generous spacing, and thoughtful transitions to make the tool feel human without being cute.

3. **Progressive disclosure** — Start simple, reveal depth through interaction. The interface should feel approachable on first use and powerful on the hundredth.

4. **Motion with meaning** — Animate state changes to orient the user, not to impress. A well-timed 200ms transition beats a flashy 2-second animation.

5. **Respect the craft** — This is a tool for people who appreciate good tools. Match the quality they expect from their best CLI utilities — fast, predictable, and delightful in the details.

## Foundations

The token values below are the source of truth recorded in prose. The live definitions live in `globals.css` (`:root` for light, `.dark` for dark). When they disagree, `globals.css` wins — update this doc to match, don't fork the values.

### Color

Inspired by vintage Macintosh product photography — a warm cream object on a dusty periwinkle ground, matte textures, even lighting, and nothing competing for attention.

**Lessons**

- **Temperature contrast over color variety** — One warm tone (cream/beige) against one cool tone (muted blue) creates more visual interest than five harmonious colors. Limit the palette, let temperature do the work.
- **Desaturated > saturated** — Dusty, powdery, slightly muted tones feel confident and timeless. Fully saturated colors feel loud and cheap. When picking any accent, pull it 20-30% toward gray.
- **Matte everything** — Avoid glossy effects, specular highlights, and glass-morphism. Matte surfaces feel tactile, calm, and honest. Shadows should be soft and diffuse, never sharp or dramatic.
- **Generous negative space is the luxury** — One element with room to breathe feels more expensive than ten elements packed together. When in doubt, add space, not content.
- **Nostalgia as warmth, not kitsch** — Reference the feeling of early personal computing (optimism, simplicity, human scale) without literal retro styling. Warm tints and rounded-but-not-bubbly shapes evoke this without cosplaying the past.

**The system in practice** — all neutrals sit in the warm hue band (oklch hue **60–80**). There is no neutral gray; "gray" is always tinted warm. Color carries meaning, not decoration: use a semantic token for what an element *is*, never a raw color value.

| Token | Role |
| --- | --- |
| `background` / `foreground` | Main reading canvas and primary text. Light paper is brighter than the navigation paper; dark reading is black. |
| `sidebar` / `sidebar-foreground` | Navigation surface and labels. It must remain distinct from the reading canvas in both modes. |
| `app-frame` | Outer application chassis, including the server rail. |
| `app-bg` | Existing alias of `background` for reading-canvas consumers. |
| `card` / `popover` | Raised surfaces — slightly lighter (light) / lighter (dark) than `background`. |
| `primary` / `primary-foreground` | The single most important action or the strongest text. Solid warm fill. |
| `secondary` / `secondary-foreground` | Secondary surfaces and controls. |
| `muted` / `muted-foreground` | De-emphasized surfaces and supporting text. `muted-foreground` is the metadata/caption color. |
| `accent` / `accent-foreground` | Hover tint and gentle emphasis. |
| `border` / `input` / `ring` | Dividers, field outlines, and the focus ring. |
| `destructive` | Errors and irreversible actions only. Warm red — never repurpose it for emphasis. |
| `status-online` / `status-offline` | Presence dots only (green online / deep gray offline). Reserved — do not use as UI accents. |
| `warning` | Recoverable degraded states that need attention without implying failure. Muted amber. |
| `sidebar-*` | Sidebar-scoped variants of the above, so the rail can read distinctly from content. |

The application frame, navigation, and reading canvas are separate semantic surfaces. Keep their assignments in the theme, not in individual channel, DM, Me, or message-row fixes. AppSurface uses the reading canvas; AppBackground uses the outer frame. On mobile community pages, native chrome follows the active list or detail surface after navigation and theme changes, including while the keyboard is open. Desktop and non-community pages follow the painted document surface. Landing and authentication keep their own paper backgrounds; their embedded application uses the same application surface tokens.

Rules:
- **Pick tokens by intent, not by lightness.** Don't reach for `muted` because it "looks the right gray" — reach for it because the content is genuinely secondary.
- **Don't signal state by color alone.** Pair color with an icon, label, or weight change so colorblind users and high-contrast modes still read the state.
- **Accents stay desaturated.** Any new accent must be pulled 20–30% toward gray before it ships. Saturated leftovers from templates are bugs (see Do's & Don'ts).
- **External identity buttons keep their mandated brand treatment.** Sign in with Apple is the narrow exception: use the semantic `apple-signin*` tokens, which resolve to Apple's required black-on-light and white-on-dark appearances. Never reuse those tokens elsewhere.

### Typography

| Family | Token | Use |
| --- | --- | --- |
| DM Sans | `font-sans`, `font-heading`, `font-display` | UI, body, and headings — the default for nearly everything. |
| DM Mono | `font-mono` | Code, IDs, tabular data, terminal/CLI surfaces. |
| Literata | `font-news` | Long-form editorial / blog reading. |
| Caveat | `font-brand` | Sparingly — handwritten brand moments only. |
| VT323 | `font-crt` | Landing-page CRT nostalgia only. Never in the app. |

- **Base body** is `--text-base` (15px) at line-height 1.6. Body copy caps at ~65ch for readability.
- **Headings** tighten letter-spacing to -0.015em and ride shorter line-heights (h1 1.15 → h4 1.3). Size builds hierarchy; weight stays restrained (600, not 800).
- Apply families through the font tokens — don't hand-set `font-family`. Reach for size/weight changes only when hierarchy genuinely demands it; default to the base style.

### Layout & Spacing

Use a consistent three-step rhythm so spacing reads as intentional, not arbitrary:

- **8px within a group** (`gap-2` / `space-y-2`) — between tightly related elements (label and its input, icon and its text).
- **16px between groups** (`gap-4` / `space-y-4`) — between distinct clusters inside a section.
- **32–40px between sections** (`gap-8` / `space-y-8`) — between major regions of a page.

Whitespace is a feature, not wasted space (Principle 1). When a layout feels cramped, add space before you add structure. Reserve color and borders for when spacing alone can't carry the hierarchy.

**No half-step exceptions.** If a control feels wrong at 8/16/32, adjust the *control's* internal padding or the *container's* structure — don't reach for `px-5` (20px) or `py-2.5` (10px) as a middle-ground escape hatch. The only axis of variation is the breakpoint (`desktop` / `mobile`).

### Breakpoints

Two stages, not three. The split lives at **`640px`** — Tailwind's default `sm` breakpoint. Everything `<640` is **mobile**, everything `≥640` is **desktop**. This maps directly to `useBreakpoint()` in `src/web/src/hooks/use-mobile.ts` — pages read the resolved value and switch layout, they don't rewrite the query. `useIsMobile()` is a boolean shortcut for the common case.

| Stage | Range | Layout shape |
| --- | --- | --- |
| **Mobile** | `< 640px` | Single column with pathname-owned list/detail routing. Back button in detail headers. Popovers may promote to sheets when they'd overflow. |
| **Desktop** | `≥ 640px` | Multi-column shells — server rail + channel/DM sidebar + main (in community), or app sidebar + workspace (elsewhere). No back button in headers. |

Forum post actions use the client platform independently of these layout checkpoints. Mobile native and mobile Web, including tablet browsers, keep actions visible at every width. Desktop native and desktop Web reveal actions on row hover, row focus or while the corresponding popup is open, including in narrow windows. Unknown/initial hydration keeps actions visible. Actions retain their 32px buttons and layout space; permissions determine which buttons and columns exist. This is the Forum-specific exception to the general touch-target sizing rule below. The first title row is at least 32px even without actions, and grows with content; summaries start immediately below it. Forum lists have zero padding; posts retain 16px horizontal and zero vertical padding. An independent 1px separator spans the original row width with the original half-opacity border color, 6.6px above and below; omit it before the first post and after the last, and give the first item 6.6px of top space. Author names stay on one line with ellipsis, capped at the smaller of 12rem or 40% of the metadata width; retain their full text and hover title. Preview-to-author spacing and metadata/tag gaps remain 8px. Both skeletons and measured virtual items share the same composition, including fractional separator spacing. A loaded post's full measured item owns continuous hover background and desktop action visibility across its separator and spacing; pointer activation covers the same item and assigns its separator/prefix to the following post. Original content keyboard and action-event guards remain, and placeholders have no interactive hover or activation. Preserve the narrow tag row's 28px author-name alignment and the existing footer order. Selected ordinary filter chips use an inset ring without enlarging the horizontal rail.

For Community server routes, the URL owns selection and the checkpoint owns composition:

| Route | Meaning | Mobile `< 640px` | Desktop `≥ 640px` |
| --- | --- | --- | --- |
| `/c/channels/{serverId}` | Server list/landing | Server rail + that server's channel list; no channel detail. | Server rail + channel sidebar + main landing. Replace to the remembered channel, otherwise the first top-level channel; an empty server stays on the root. |
| `/c/channels/{serverId}/{channelId}` | Exact channel detail | Channel detail only. The leading server icon replaces directly to the server root; a visible parent breadcrumb replaces directly to that parent channel. | Server rail + channel sidebar + channel detail in one frame. |

Both checkpoints share the same server-scoped data model. A detail route adds channel-scoped content queries; changing checkpoint never changes the route's business meaning or creates a device-specific query contract. Mobile server hierarchy controls use replace-style navigation to their explicit canonical URLs, while browser Back/Forward remains browser-history owned. DM/Me keeps its separate Back contract.

Rules:
- **Read the breakpoint, don't guess.** Use `useBreakpoint()` (string) or `useIsMobile()` (boolean) for any behavior that must branch by stage. Don't sprinkle raw `window.innerWidth` checks or ad-hoc `matchMedia` calls — they drift away from the shared boundary and re-mount without SSR safety.
- **JS and CSS boundaries are the same 640px.** Use the hook for behavior (which zone to render, whether to show a back button); use Tailwind's `sm:` prefix for pure layout fit at the mobile ↔ desktop split. Both share the same 640px pivot so a mobile page never renders desktop CSS at the same width.
- **`md:` is banned. `lg:` is allowed only for desktop-internal fit** — e.g. an issue sheet that can float a timeline panel beside its body once the viewport clears ~1024px, or a stats grid that reflows from 1 col to 2 cols when there's room. This is not a third tier; it's a content-fit fallback that happens *within* desktop. If the switch changes navigation or a user-visible zone, it belongs in the JS hook, not in `lg:`.
- **Touch targets on mobile are non-negotiable.** Interactive elements ≥ 44×44px (`h-11`). On desktop the same control may collapse to `h-9`/`h-10`.
- **UserBar keeps compact visuals inside its touch targets.** Below 640px, square buttons use fixed 44×44px targets and centered 28×28px visual surfaces; at 640px and above both are 28×28px. The name trigger is 44px high below the checkpoint and 28px high above it. Background, hover and expanded tint belong to the visual surface, while focus belongs to the native button. Preserve icon, avatar, unread and running-ring sizes. Keep the bar 48px high and reserve matching slots in both skeletons, including the homepage document with its 14px root font.
- **Don't introduce a third stage.** If a design "needs a tablet mode," either the mobile layout should stretch gracefully or the desktop layout should reflow inside — not a new tier.

### Dots & Indicators

Three status-dot sizes, each for a distinct role. Don't mix them.

| Size | Token | Role |
| --- | --- | --- |
| **6px** | `size-1.5` | Inline compact — inside a status pill, next to a tab label, or in a typing-dot animation. Small enough not to compete with adjacent text at `text-xs` / `text-[11px]`. |
| **8px** | `size-2` | Standalone unread / selection dot — sits at the end of a row or inside a radio-like control. Reads clearly at `text-sm` line height. |
| **10px** | `size-2.5` | Avatar presence badge — overlays the avatar corner and needs a `ring-background` halo to stay legible on any tint. |

Pair every dot with an icon or label change too — never signal state by color alone (see Do's & Don'ts).

### Elevation & Depth

Two matte shadow tokens, no more:

- `--e1` — resting lift (cards, raised surfaces). A barely-there 1px shadow.
- `--e2` — floating lift (popovers, menus, dialogs). A soft, diffuse drop.

Shadows are soft and diffuse, never sharp or dramatic (no hard offsets, no glow). Pair elevation with the matching radius family below. Prefer a tonal surface shift (`card` over `background`) to separate layers; use shadow only when an element genuinely floats.

### Shape

One radius family, scaled from `--radius`. Keep a single radius scale per view — don't mix a 6px control with an 18px sibling card.

- Controls and inputs → `radius-sm` / `radius-md`
- Cards and surfaces → `radius-lg`
- Menus, dialogs, large panels → `radius-xl` / `radius-2xl`
- Pills and avatars → fully round

Rounded-but-not-bubbly. The radius should soften an edge, not turn a button into a lozenge.

### Motion

**Motion with meaning** (Principle 4) — animate to orient the user, not to impress.

- **Duration**: 150ms for state changes (hover, color, opacity), ~200ms for popovers/disclosure, ~300ms for full overlays. If in doubt, shorter wins. Sometimes the snappiest choice is no animation at all.
- **Easing**: ease-out for entrances; the house curve is `cubic-bezier(0.2, 0.8, 0.2, 1)`.
- **Reduced motion is mandatory.** Every animation must degrade gracefully under `prefers-reduced-motion: reduce` — this is already wired across `globals.css`; new animations must follow suit.

## Components

### Interaction states

State must be *visible*, and it must come from tokens — not ad-hoc tweaks. Every interactive element moves through:

- **Default** → base surface/border token.
- **Hover** → `accent` tint (or one step lighter/darker surface). 150ms transition.
- **Active / pressed** → one step beyond hover, so a click feels like it landed.
- **Disabled** → muted surface + `muted-foreground` text + `not-allowed` cursor. Never just lowered opacity on the whole control.
- **Focus** → a visible focus ring on `:focus-visible` using `ring`. Never remove an outline without a visible replacement — this is an accessibility requirement, not a style choice.

### Buttons & inputs

- **Primary** — solid `primary` fill, `primary-foreground` label. One per view, for the single most important action.
- **Secondary** — `background`/`secondary` surface with a `border`. The default workhorse.
- **Tertiary / ghost** — transparent, tints to `accent` on hover. For low-emphasis and inline actions.
- **Destructive** — `destructive` fill, reserved for irreversible actions; confirm before firing.
- Inputs use `input` for the border and `ring` for focus. Match the control's radius to the Shape scale.

### Landing testimonials

A landing-only extension of the inherited green/CRT world, immediately after the Hero and before the interactive workspace. This record describes `landing-testimonials.tsx`, its CSS module, and the shared MessageAuthorLine and Avatar primitives; it does not establish a new global direction.

**Palette and type.** Transparent message rows sit on the alternate landing section background between the pale Hero and workspace, and use landing text tokens; handles, source icons and avatar fallback initials use landing muted text. Hover and keyboard focus add the landing surface tint. The CRT heading keeps its regular weight, fluid display size (`clamp(3rem, 4.6vw, 5rem)`), tight leading (0.98) and tracking (-0.025em). Native author names are semibold (15px); handles are subordinate (12px). Quotes use the inherited sans family (15px, line-height 1.375), preserve line breaks and wrap long words.

**Layout and shape.** The introduction follows the inherited content width and page gutter. Two full-width clipped lanes carry unboxed rows with round large avatars (40px), an avatar-to-body gap (8px), and no fixed post height. Rows are 360px wide with 40px spacing; below 640px, widths fit within the viewport with 48px clearance and spacing becomes 24px. Lane spacing changes from 32px to 24px at the same boundary. The whole row is a source anchor with 8px interaction padding, a small corner radius (4px) and a minimum target height (44px). There are no resting card surfaces, card borders or shadows.

**The Native Attribution Rule.** Keep the source arrow beside the name, with both vertically centered in the author row and an 8px gap. The handle sits below; quote text follows with 8px separation and a maximum of three visible lines with CSS ellipsis. Preserve the full exact quotation in the document. The entire row opens the original in a new tab and includes an accessible source notice; the icon is decorative. There is no visible source label or separate source control.

**The Readable Motion Rule.** Preserve both opposing lanes (100s forward and 110s reverse, linear and continuous). Hover or an active press on the wall pauses the current transform; it does not replace the pressed link. Keyboard-visible focus removes animation, hides loop copies and enables manual horizontal lane scrolling with the shared thin scrollbar. Reduced motion uses the same static manual-reading layout. Focused rows retain a visible landing-text outline (2px, offset 4px). No Pause/Resume control or reading disclosure is present.

**The Single Reading Copy Rule.** Expose the 20 original source links once to assistive technology and keyboard navigation. Repeated loop groups are `aria-hidden`, with their links outside the tab order; originals remain accessible in the moving lanes. These are attributed community comments, not a new claim of verified customers.

Component-only extension metadata and a self-contained source-row preview are recorded in `.impeccable/design.json`. Existing global documentation and token ownership remain unchanged.

## Patterns

### Public download and contact pages

Download and Contact share the Contact-style header and existing landing footer. Their public links have one owner, including Download, Pricing, Blog and Contact. Preserve the current landing green/CRT tokens and responsive gutter. The download page uses a lead action followed by desktop and mobile sections, with actual existing Alook product preview modules. Platform, architecture and installer format are explicit; all available links exist in server HTML. App Store and Google Play show noninteractive Coming soon states, while Android offers the actual APK. Keep the browser entrance visible and do not infer a Mac chip or automatically start a download.

### Progressive disclosure

Never show all options at once. Complexity exists but stays one interaction away.

- **Hover to preview** — hovering a linked page shows a preview without navigating. Tooltips appear contextually, not eagerly.
- **Click to expand** — sidebar tree nodes, dropdown menus, and kanban column options are collapsed by default. Expanded state is driven by user action, not by default.
- **Scrolling reveals depth** — additional features and settings appear as the user scrolls or explores. The first screen is always clean.

### Visual Harmony

Every pixel should reduce mental load, not add it. Whitespace, typography, and hierarchy aren't cosmetic — they're how brains process information.

- The UI should fade into the background. If a user notices the tool instead of their content, something is wrong.
- Aim for visual calm: Japanese minimalism, Bauhaus clarity. No decoration that doesn't serve comprehension.
- If a feature makes the interface more complicated without making it more powerful, cut it.

### Loading to Loaded Stability

The transition from loading to loaded must feel like a *reveal*, not a *rearrangement*. The user's eye should never lose its place.

**Core rule**: The loading skeleton and the loaded content must occupy the **same dimensions, position, and layout flow**. Nothing should jump, shift, or reflow when data arrives.

**Guidelines**

- **Reserve exact space** — Skeleton placeholders must match the height, width, and margin of the real content they replace. A skeleton card that is 20px shorter than the loaded card causes a visible pop.
- **Anchor scroll position** — If content loads above the viewport (e.g. prepending items), compensate scroll offset so the user's visible content stays pinned.
- **Fade, don't swap** — Use a short crossfade (150–200ms, ease-out) to transition from skeleton to content. Avoid hard cuts where a gray block snaps to text in a single frame.
- **Match structure, not just size** — Skeleton shapes should echo the content layout (e.g. a line for a title, a shorter line for metadata, a block for an avatar). Generic identical bars feel lazy and make the transition more jarring, not less.
- **No Cumulative Layout Shift (CLS)** — Treat any visible layout shift during load as a bug. Images must have explicit dimensions or aspect-ratio containers. Dynamic lists should use fixed-height rows or virtualized containers.
- **Empty states hold the frame** — When a section loads but has zero items, the empty state placeholder must fill the same region the skeleton occupied. Don't collapse the container.
- **Stagger gracefully** — If multiple sections load independently, each section transitions on its own timeline. One section loading should never cause another to reflow.
- **Avoid spinners as primary indicators** — Prefer inline skeletons over centered spinners. Spinners displace content and create a jarring before/after. Use spinners only for actions (button presses, form submissions) where there is no content to skeleton.

## Voice & Content

Words are part of the interface. They should sound like the brand: **warm, sharp, purposeful** — a capable peer, never a corporate assistant or a chirpy mascot.

- **Name actions by what they do** — verb + noun (`Send invite`, `Delete workspace`), never a bare `OK` / `Confirm` / `Submit`.
- **Errors say what happened and what to do next.** "Couldn't reach the agent — check it's running and retry." Not "An error occurred."
- **Confirmations are specific and quiet.** Name the thing that changed (`Workspace deleted`), drop the trailing period, and never say "successfully."
- **Write like a person, skip the filler.** No "please," no superlatives, no exclamation marks by default. Use real numerals, curly quotes, and the ellipsis character.
- **Empty states teach, not apologize.** Say what goes here and how to add the first one.
- **Match the surface.** Plain language in the UI; precise, literal language in anything CLI- or developer-facing.

## Do's & Don'ts

- **Do** pick tokens by intent (`muted` because it's secondary), not by how the color looks.
- **Do** keep WCAG AA contrast (4.5:1 for body text) in both light and dark.
- **Do** show a visible focus ring on every interactive element at `:focus-visible`.
- **Do** desaturate any new accent 20–30% toward gray before shipping.
- **Do** pair `overflow-y-auto` / `overflow-x-auto` with `thin-scrollbar` — always.
- **Don't** introduce a saturated or off-palette color. Template leftovers (e.g. a blue-violet sidebar token) are bugs to fix, not values to keep.
- **Don't** signal state by color alone — add an icon, label, or weight.
- **Don't** use glass-morphism, glossy highlights, or hard/dramatic shadows.
- **Don't** animate to impress, run animations over ~300ms, or skip the `prefers-reduced-motion` fallback.
- **Don't** hard-code colors, fonts, or radii in components — go through the tokens.
- **Don't** add a feature that makes the interface more complicated without making it more powerful.

## Interactive landing workspace

- Keep the interactive second screen separate from the existing product story. Use native community views with local data; preview navigation and actions must not mutate a real account.
- Reserve the workspace frame before loading. Mount its isolated document immediately after the hero mounts, its paper font/canvas settles, and its own images settle, without waiting for the full homepage load event; show a responsive workspace skeleton until that document reports readiness. Readiness must not depend on animation callbacks in the hidden iframe.
- Compact preview typography must preserve fixed-pixel rail, avatar, and Inbox geometry. Grouped messages and reply previews align with the first message's avatar column.
- Mobile landing bot profiles retain the Bot log companion but hide its footer row to give the notebook body more space. Desktop retains the full notebook.
- Bot logs use local fixed Thoughts and Marks. Preview Thoughts are static. Scroll-to-tail affects only the notebook scroller, never the surrounding landing page.
- Production loading has no QA hold switch or test-only URL controls.

- The mobile landing Bot log retains 8px of visible paper below its content: 16px content padding minus its 8px paper inset.

### Landing feature gallery

The public landing keeps Hero → testimonials → interactive workspace → feature gallery → FAQ → closing CTA. The workspace invitation uses the existing VT323 display scale: “Try it. Imagine your team and friends here.”

The gallery preserves the green landing tokens, DM Sans tabs, VT323 short titles and original feature animations. Five single-line text tabs that support native touch/trackpad scrolling, mouse drag and wheel scrolling have a 44px minimum target, an active underline and edge fades when more options exist. Each panel shows one short title, one or two sentences about a user scenario, one CTA and one complete scene; mobile keeps these within one screen. Original camera, cursor and timelines scale together as a complete canvas. Remote control scales the laptop and phone together, with content filling both screens. Identity shows only the profile card; setup retains its dark surface. The selected scene loads on entering view and remains mounted offscreen. Rotation waits at least 15 seconds and a complete scene cycle; hover, focus, manual selection, hidden document and reduced motion pause it. There is no playback button. Arrow keys, Home and End navigate and reveal the selected tab. Tabs and copy stack below 640px.