# Relmio design system This file is the design contract for every Relmio interface: the local browser wizard in `src/ui` and the hosted web app in `web/`. Read it with [BRANDKIT.md](BRANDKIT.md), which holds the logo, colors, type and voice. Agents and frontend skills should treat both files as the project brief and the existing design tokens. The two apps share one component kit, `src/ui/relmio-ui.css`. The wizard links it directly. The web app imports a generated copy, `web/app/relmio-ui.css`, which `npm run ui:sync` in `web/` refreshes and `npm run ui:check` verifies in CI. Edit only the source file. ## Principles 1. One screen, one job in the wizard. Each wizard and dashboard view answers one question or completes one step, and it fits the window at laptop size. The next action is always visible. The hosted site is a scrolling page; see [The hosted site](#the-hosted-site). 2. Safety stays in sight. Warnings that change a decision are visible without a click. Background and technical detail sits behind a labelled disclosure. 3. Same parts everywhere. A button, field, notice or top bar looks and behaves the same in the wizard and on the website. 4. Two themes, one accent. Light is pastel green, dark is black. The accent (black in light, pastel green in dark) marks the primary action, the current place and selection. 5. Plain words. Short sentences, sentence case, no jargon without a hint. See the voice rules in BRANDKIT.md. ## Surfaces | Surface | Where | Job | | --- | --- | --- | | Setup wizard | `src/ui/index.html` (`/`) | Choose a route, check the server, choose n8n, review, finish | | Local dashboard | `src/ui/local.html` (`/local`) | See and manage connections on this computer | | Route wizards | `/supergrok-vps`, `/local-model-vps`, `/assistant` | Provider or companion setup on a server | | Hosting options | `/hosting` | Compare hosts and build a plan without remote changes | | Home | `web/app/page.tsx` (`/`) | Explain Relmio, show the routes and start the install | | Install | `/install` | Pick a terminal and copy the command | | Hosted chat notice | `/#chat`, a section of the home page (`/chat` redirects there) | Say hosted chat is off and remove an old saved sign-in | | Docs | `/docs`, `/docs/[slug]` | Find and read a guide | | Changelog | `/changelog` | Read release notes | The wizard runs on the user's computer with a strict Content Security Policy: same-origin scripts, styles, fonts and images only, no inline styles or scripts, and `data:` images allowed. The web app runs on Vercel with a per-request nonce policy; see the web implementation rules. ## The one-screen rule This rule covers the local wizard and dashboard (`src/ui`) only. The hosted web app does not use it; see [The hosted site](#the-hosted-site). Every wizard step and dashboard view must show all of its controls and content without a page scrollbar or a panel scrollbar at these window sizes: - 1280 x 720, 1366 x 768, 1440 x 900 and 1920 x 1080 - 1024 x 768 The rule covers every default, busy and error state. When a person opens an optional disclosure, the panel body or the rail notes may scroll; the page and the main area never scroll, and the footer actions stay visible. Owner decision, 2026-10-03: optional explanations may stay in disclosures that scroll this way, so they do not have to move to separate help views. A chat transcript and an activity log may scroll inside their own region. The shell makes this possible: put `rm-app rm-app--fit` on `
`. From 1024 x 600 the shell is exactly one window tall and `.rm-app__main` is the only scroll container. Views are designed to fit, so that container never scrolls at the target sizes. If a view still overflows, for example at 200% zoom, the main area scrolls instead of clipping. Below 1024 pixels wide the page scrolls normally. Never hide overflow to pass the rule. Ways to fit a view, in order of preference: 1. Remove repetition. Say a safety fact once, in the place it matters. 2. Split a long step into two steps, or move secondary tasks to their own view or route. 3. Put optional explanation in an `rm-disclosure` and long warnings in an `rm-notice`. Keep the warning's first sentence visible. 4. Use the width: two-column forms, a `rm-grid` of choices, a definition list for review facts. 5. Keep actions in the panel footer, which stays visible. Narrow screens (390 x 844 and 320 wide) must never scroll sideways. The first screen of every view shows its title and its primary action or first choice. Verify the rule by measuring, not by eye: at each target size, `document.documentElement.scrollHeight` must equal `innerHeight`, and no element with `overflow: auto` or `scroll` may have `scrollHeight` above its `clientHeight`, except a chat transcript or an activity log. ## The hosted site The web app in `web/` is a marketing and documentation site. It scrolls as a normal page and may be expressive, as long as it stays in the brand: the same tokens, kit components, top bar and themes as the wizard. - The root layout renders `rm-app` without `rm-app--fit`, then the top bar, the page's `main` and the shared `SiteFooter`. Never lock a page to the window height. - Home runs top to bottom: the hero with the Doorway scene, How it works (`#how-it-works`), the hosted chat notice (`#chat`), the safety boundary (`#security`), then the footer. Hosted chat and its ChatGPT sign-in stay off until OpenAI approves access; see [issue #95](https://github.com/Demonbane18/relmio/issues/95). The notice links to the local wizard and offers to remove an old saved sign-in from the browser. Install, docs, changelog and the 404 page follow the same rhythm: a large title, generous sections, the footer. Docs and changelog keep their sidebar in view while the page scrolls. - Full-width bands carry the sections. A soft hill edge joins one band to the next. The safety boundary is a night band that re-points the ink, accent and focus tokens to the terminal values, which stay dark in both themes. - Kit shadows and tilted `--rm-accent-soft` sheets add depth to cards such as the notice's cleanup card and the install toolbox. The home illustration stays unframed on the page canvas. - Brand teal and cream are illustration accents only: the doorway and mascot, and the teal wavy underline in the home headline. They never mark state. - Sections may rise into view with scroll-driven animation (`animation-timeline: view()`). Content stays visible without support and with reduced motion. Animate transform and opacity only. - Every page ends with the footer: brand and one-line description, product links (Install, Docs, Changelog, npm, GitHub), the creator's profiles with icon and visible handle, and the line `©