diff --git a/.gitignore b/.gitignore
index e4587c7..61557c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,6 @@ deploy.env
# Screenshot tooling: bytecode, and database dumps that hold production data
__pycache__/
*.dump
+
+# Output of scripts/check/site.py
+.check/
diff --git a/CLAUDE.md b/CLAUDE.md
index 50b1c70..f924eb2 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -10,9 +10,12 @@ get started.
## Project Purpose
Potential users land here and need to answer three questions in under 10 seconds:
-1. What is this?
-2. Is it for me?
-3. How do I try it?
+1. What is this? — Control instead of drift: define the desired state once,
+ netOrk finds every deviation and puts it back.
+2. Is it for me? — IT departments in small and mid-sized companies with mixed
+ hardware (service providers and IT support are secondary).
+3. What does it cost? — netOrk is free; a licence adds vulnerability data and
+ updates (`/pricing`).
Everything on the site should serve those three questions.
@@ -74,13 +77,19 @@ exactly as netOrk's `ui/src/components/ui.tsx` does.
## Design Rules (summary — full detail in docs/DESIGN.md)
-- **Dark theme only.** Background `bg-slate-950`. Cards `bg-slate-900`.
-- **Accent color:** `sky-500` / `sky-600` for CTAs, links, highlights.
-- **No light mode toggle.** Ever.
-- Font stack: system default (Tailwind sans). No Google Fonts.
-- All interactive elements use `transition-colors` — no layout shifts.
-- Screenshots/mockups of the actual app use a `border border-slate-700 rounded-xl
- overflow-hidden` wrapper to frame them against the dark background.
+- **Light pages, dark product.** Pages are `paper` with `ink`; the only dark
+ surfaces are real netOrk screenshots and code, on the `night` stage.
+- One accent, `accent` (sky-700), for links, eyebrows and focus. Buttons are ink.
+- Font: Inter Variable, self-hosted via `@fontsource-variable/inter`. No Google
+ Fonts, no request to any other origin.
+- Layout from `src/components/ui.tsx`: split sections, ruled lists, numbered
+ steps, bands. No card grids, no icon tiles, no centred text blocks.
+- Motion: `transition-colors` only — no layout shifts.
+- **Screenshots are real.** Taken from the anonymised demo copy with
+ `scripts/screenshots/capture.py`, cropped to what the text talks about, at most
+ four on the site. No mockups, no edited data, no clicks that fake a state.
+- **Less text.** Word budgets per page are in docs/PAGES.md and checked by
+ `scripts/check/site.py`.
---
@@ -108,7 +117,9 @@ netork-website/
## Tone of Voice
-- Direct and technical — audience is engineers, not executives.
+- Direct and technical — audience is the admins of an IT department, not executives.
+- One message: control instead of drift. Everything else supports it.
- No marketing fluff ("revolutionize", "empower", "seamless").
-- Show, don't tell — a screenshot or code block beats three sentences of prose.
-- German is fine for internal docs; the website copy is in **English**.
+- Show, don't tell — a real screenshot beats three sentences of prose.
+- Website copy exists in **English and German** (German addresses readers with
+ "ihr"); the language follows the browser until the visitor chooses.
diff --git a/docs/DESIGN.md b/docs/DESIGN.md
index 4a1d578..16970d2 100644
--- a/docs/DESIGN.md
+++ b/docs/DESIGN.md
@@ -1,304 +1,78 @@
-# netOrk — Visual Identity & Design System
+# netOrk website — design system
-This document defines the visual identity of netOrk and must be followed
-exactly when building the website. The goal is zero visual discontinuity
-between the product UI and the marketing site.
+**Light pages, dark product.** The site is calm paper with ink; the only dark
+surfaces are real screenshots of netOrk and code, set on a "stage". References:
+Linear/Vercel for precision, Tailscale/Netbird for friendliness.
----
+Tokens live in `tailwind.config.js`, building blocks in `src/components/ui.tsx`.
+If a page needs something that is not there, it probably needs less instead.
-## Logo Assets
+## Colour
-The logo file is in `public/` — use it directly, do not recreate.
-
-| File | Format | Size | Use |
-|---|---|---|---|
-| `public/logo.png` | PNG | 1024×1024, RGBA | Nav logo, OG image, hero, press kit, favicon fallback |
-
-### Usage in `` (nav, hero)
-
-```tsx
-
-```
-
-For the nav, pair it with the wordmark:
-
-```tsx
-
-
-
- netOrk
-
-
-```
-
-Use `netOrk` consistently — the `Ork` part
-in sky-400 ties the wordmark to the accent color.
-
-### `
` references
-
-```html
-
-
-```
-
----
-
-## Core Principle
-
-**The website looks like a dark-mode dev tool, not a SaaS landing page.**
-No gradients, no floating orbs, no animated hero blobs. The aesthetic is
-deliberate, minimal, and technical — consistent with the product itself.
-
----
-
-## Color Palette
-
-All colors are Tailwind CSS v3 classes. Do not use hex values directly —
-always use Tailwind class names to stay consistent.
-
-### Backgrounds
-
-| Layer | Class | Usage |
+| Token | Value | Use |
|---|---|---|
-| Page / outermost | `bg-slate-950` | Body, full-bleed sections |
-| Card / panel | `bg-slate-900` | Content cards, code blocks, feature boxes |
-| Elevated element | `bg-slate-800` | Hover states, dropdowns, table rows on hover |
-| Border | `border-slate-700` | Between sections, card outlines |
-| Subtle border | `border-slate-800` | Inside cards, dividers |
+| `paper` / `paper-2` | `#FAFAF9` / `#F3F3F0` | page / band |
+| `line` / `line-strong` | `#E6E6E3` / `#D4D4D0` | hairlines |
+| `ink` / `ink-soft` / `ink-muted` / `ink-faint` | `#0E1116` … `#9AA0A8` | headings / body / secondary / quiet |
+| `night` | `#020617` | screenshot and code stage — the netOrk UI's own background |
+| `accent` (`hover`, `soft`) | `#0369A1` | links, eyebrows, numbers, focus ring (5.7:1 on paper) |
+| `drift` / `sync` | `#B45309` / `#15803D` | status: deviates / matches; never the only signal |
-### Text
+No gradients, no glow, no second accent. Buttons are ink, not accent.
-| Role | Class |
+## Type
+
+Inter Variable, self-hosted through `@fontsource-variable/inter` (bundled by
+Vite; the site makes no request to anyone else). Scale:
+
+| Class | Use |
|---|---|
-| Primary | `text-slate-100` |
-| Secondary / muted | `text-slate-400` |
-| Tertiary / placeholder | `text-slate-500` |
-| Accent (interactive) | `text-sky-400` |
-| Danger | `text-red-400` |
+| `text-display` | the home headline only |
+| `text-h1` | one per page, in `PageHeader` |
+| `text-h2` | section headings |
+| `text-h3` | row terms, plan names |
+| `text-lead` | the paragraph under a heading |
+| `text-eyebrow` + `uppercase text-accent` | the small line above a heading |
-### Accent (Interactive / CTA)
+Everything is left-aligned. Headings balance and hyphenate (`` is
+set per language). Text columns stay within `max-w-measure` (38rem).
-| State | Class |
-|---|---|
-| Default button | `bg-sky-600 text-white` |
-| Hover | `hover:bg-sky-500` |
-| Link / inline | `text-sky-400 hover:text-sky-300` |
-| Active indicator | `text-sky-400` |
-| Focus ring | `focus:ring-sky-500` |
+## Layout
-### Semantic Colors
+- Container `max-w-page` (72rem), `px-5 sm:px-8`. Sections `py-20 md:py-28`.
+- **Split**: heading on the left five columns, content on the right. The
+ default section.
+- **RuleList**: rows divided by hairlines, term and body; one or two columns.
+ This replaces every card grid.
+- **Steps**: numbered rows (`01`, `02`, `03`) in mono accent.
+- **Band**: `bg-paper-2` with hairlines, for the hardware strip and the closing
+ call to action (`CtaBand`).
+- **Stage**: `bg-night`, `rounded-2xl`, `shadow-stage` — screenshots (`Shot`)
+ and code (`CodeBlock`).
-| Meaning | Color |
-|---|---|
-| Success / active | `text-green-400`, `bg-green-500/20` |
-| Warning / caution | `text-yellow-400`, `bg-yellow-500/20` |
-| Danger / error | `text-red-400`, `bg-red-500/20` |
-| Info / neutral | `text-blue-400`, `bg-blue-500/20` |
+Not used: icon tiles, pills for names, cards, centred text blocks, fake browser
+windows, emoji. Motion is `transition-colors` only.
-### Status Badge Pattern
+## Screenshots
-```tsx
-// Active / online
-
- active
-
+Only real screenshots of netOrk, from the anonymised demo copy
+(`scripts/demo`), taken by `scripts/screenshots/capture.py` and published as
+WebP in `public/screenshots/`. Their sizes are written to
+`src/data/screenshots.json`, which `Shot` reads.
-// Offline
-
- offline
-
+- At most four different images on the site. Each is cropped to the one thing
+ the text next to it talks about (`clip` or `element` in `shots.py`).
+- Cropping shows less of a real screen; it never changes what is on it. No
+ edited data, no clicks that fake a state, no mockups.
+- A crop that does not read on a phone gets a `-narrow` variant (`Shot narrow=`).
+- Every image has an alt text and a caption that says what is true in it.
-// Warning
-
- warning
-
-```
+## Wordmark
----
+Text only: `netOrk` in ink. `public/logo.png`
+is the favicon and OG image; it does not sit well on a light background.
-## Typography
+## Glossary marks
-Font stack: Tailwind default sans-serif (`font-sans`). **No Google Fonts.**
-The product uses system fonts; the website must match.
-
-| Element | Classes |
-|---|---|
-| Hero heading | `text-4xl md:text-6xl font-bold text-slate-100 leading-tight` |
-| Section heading | `text-2xl md:text-3xl font-bold text-slate-100` |
-| Subsection heading | `text-xl font-semibold text-slate-200` |
-| Body text | `text-base text-slate-400 leading-relaxed` |
-| Small / label | `text-sm text-slate-400` |
-| Tiny / tag | `text-xs font-medium text-slate-500` |
-| Code / monospace | `font-mono text-sky-400` |
-| Accent text | `text-sky-400` |
-
----
-
-## Spacing & Layout
-
-- Max content width: `max-w-7xl mx-auto px-6`
-- Section padding: `py-24` (desktop), `py-16` (mobile)
-- Card padding: `p-6`
-- Gap between grid items: `gap-6` or `gap-8`
-- All layouts are mobile-first; use `md:` and `lg:` breakpoints.
-
----
-
-## Components
-
-### Primary CTA Button
-
-```tsx
-
- Get started
-
-```
-
-### Secondary / Ghost Button
-
-```tsx
-
- See all features
-
-```
-
-### Feature Card
-
-```tsx
-
- Description of the feature in one to three sentences.
-
-
-```
-
-### Screenshot Frame
-
-App screenshots must be wrapped in this frame to integrate naturally
-against the dark background:
-
-```tsx
-
-
-
-```
-
-**Only real screenshots of the running application.** No JSX mockups or
-drawn imitations of the UI. They come from an anonymized demo copy of a real
-installation and are taken with `scripts/screenshots/capture.py` (see
-`scripts/demo/README.md`), published as WebP in `public/screenshots/`.
-`Screenshot` in `src/pages/Home.tsx` is the frame.
-
-Optionally add a browser chrome header above the image:
-
-```tsx
-