diff --git a/docs/brand/brand-guide.md b/docs/brand/brand-guide.md index 2fbade6..b7d9080 100644 --- a/docs/brand/brand-guide.md +++ b/docs/brand/brand-guide.md @@ -9,79 +9,122 @@ > Companion file: [`tokens.css`](tokens.css) holds the same values as CSS custom > properties, so a page can consume them instead of transcribing hex codes. -The design lives in four hand-authored surfaces, none of which shares a +The design lives in five hand-authored surfaces, none of which shares a stylesheet with the others: - **offworldlabs.com** ([`landing-page-owl`](https://github.com/offworldlabs/landing-page-owl)) — the lab - **retina.fm** ([`landing-page-retina`](https://github.com/offworldlabs/landing-page-retina)) — the product - **dash.retina.fm** (`retina-server/dashboard`) — the admin console - **map.retina.fm** (`retina-server/frontend`) — the live radar map - -They read as one family, but each has its own voice. The map is the odd one out: -it is the only dark surface, a Flightradar24-style operational console. +- **owl.local** ([`retina-gui`](https://github.com/offworldlabs/retina-gui)) — the node's own UI + +They read as one family, but each has its own voice. Two sit apart: the map is +the only dark surface, a Flightradar24-style operational console, and owl-os is +the only one that runs on hardware in someone's house rather than on a server. + +owl-os is the odd repository as well as the odd surface. The UI is authored in +[`retina-gui`](https://github.com/offworldlabs/retina-gui) but shipped by +[`owl-os`](https://github.com/offworldlabs/owl-os), which clones it at a pinned +tag into the SD-card image, brands it `OWL-OS` in the page title and the nav, +and serves it from the node on port 80. Its style is therefore read from +retina-gui `main`; what a node in the field is running is whatever tag the image +pinned (see §10). + +**`retnode.com` is this same surface, not another one.** One Flask app on one +port answers to every name a node has: `owl.local` and `ret.local` on +the LAN, and `ret.retnode.com` over the Cloudflare tunnel from +anywhere. Same templates, same `common.css`, so there is nothing separate to +capture. What differs is the *pathway*, which is decided by hostname alone: the +LAN is unauthenticated (being on the network is the credential), while the +tunnel hostname is challenged for a password and refuses the operations that +need physical presence. Visually that costs a login page, a refusal page, and +greyed-out cards for the services whose ports the tunnel does not route. + +One name under that domain is genuinely a different page. The delay-Doppler +display embedded on offworldlabs.com, +`radar3.retnode.com/display/detection/delay-doppler/`, is **blah2's** own web +output, not this UI: there is no `/display` route in retina-gui. It is a +hand-built tunnel that predates the per-node ones, and its look belongs to +blah2 rather than to any surface described here. --- -## 1. Brand architecture: one family, four voices - -The surfaces share a spine (a blue accent, green/amber status colours, a mono -micro-label, hairline rules) and then diverge in personality. The split maps -onto audience. Three are light; the map is dark. - -| | **owl** — offworldlabs.com | **retina** — retina.fm | **dash** — dash.retina.fm | **map** — map.retina.fm | -|---|---|---|---|---| -| **Role** | The lab / parent org | The product you buy | The console you operate | The live picture | -| **Audience** | Researchers, funders, press | Prospective node owners | Logged-in operators | Anyone watching the map | -| **Feel** | Editorial, institutional | Commercial, confident | Utilitarian, dense | Dark ops console (FR24-style) | -| **Serif** | Source Serif 4, wt 400 | Fraunces, wt 600 | none | none | -| **Sans** | Inter | DM Sans | system stack | Inter (only font) | -| **Mono** | IBM Plex Mono | JetBrains Mono | SF Mono | none (generic) | -| **Canvas** | warm paper `#f7f6f2` | warm paper `#fafaf9` | cool slate `#f1f5f9` | **navy `#0d1b2a`** | -| **Blue** | muted `#5b8dd9` | punchy `#2563eb` | `#3b82f6` → `#2563eb` | sky `#38bdf8` | -| **Radius** | 4–6px | 8–20px | 4–8px | 3–10px | -| **Buttons** | flat | lift + shadow | flat | flat | -| **Dark UI** | none | one dark section | none | **fully dark** | +## 1. Brand architecture: one family, five voices + +The surfaces share a spine (a blue accent, green/amber status colours, a small +uppercase micro-label, hairline rules) and then diverge in personality. The split +maps onto audience. Four are light; the map is dark. + +| | **owl** — offworldlabs.com | **retina** — retina.fm | **dash** — dash.retina.fm | **map** — map.retina.fm | **owl-os** — owl.local | +|---|---|---|---|---|---| +| **Role** | The lab / parent org | The product you buy | The console you operate | The live picture | The node you own | +| **Audience** | Researchers, funders, press | Prospective node owners | Logged-in operators | Anyone watching the map | Whoever has the box | +| **Feel** | Editorial, institutional | Commercial, confident | Utilitarian, dense | Dark ops console (FR24-style) | Appliance settings, unhurried | +| **Serif** | Source Serif 4, wt 400 | Fraunces, wt 600 | none | none | none | +| **Sans** | Inter | DM Sans | system stack | Inter (only font) | Inter | +| **Mono** | IBM Plex Mono | JetBrains Mono | SF Mono | none (generic) | JetBrains Mono | +| **Canvas** | warm paper `#f7f6f2` | warm paper `#fafaf9` | cool slate `#f1f5f9` | **navy `#0d1b2a`** | near-white warm `#fffdfb` | +| **Blue** | muted `#5b8dd9` | punchy `#2563eb` | `#3b82f6` → `#2563eb` | sky `#38bdf8` | `#2f8adc`, accents only | +| **Radius** | 4–6px | 8–20px | 4–8px | 3–10px | 6–14px | +| **Buttons** | flat | lift + shadow | flat | flat | flat, primary is ink | +| **Dark UI** | none | one dark section | none | **fully dark** | none | A rough rule of thumb for a new page: **who is it for?** Reaching outward to the scientific or funding world reads as owl. Selling or explaining the kit reads as retina. Anything behind a login reads as dash. Anything that _is_ the live radar -picture (a map, a track view, an operational overlay) reads as map. +picture (a map, a track view, an operational overlay) reads as map. Anything a +node owner does to their own hardware reads as owl-os. + +dash and owl-os are worth telling apart, since both are settings pages for the +same hardware. dash is an operator holding a fleet at arm's length: dense, +tabular, many rows on one screen, always behind a login. owl-os is one person and +one box on their own network, reached without a password, so it runs a 720px +column, one decision per row, and explains each in a sentence underneath. --- ## 2. Foundations -The parts that stay roughly constant across all four, and are the safest thing +The parts that stay roughly constant across all five, and are the safest thing to carry into new work. -- **A paper-like canvas.** The three outward surfaces use a near-white - background (warm on the marketing sites, cool slate on the console) with - near-black text. The **map is the exception**: it is fully dark navy with light - slate text. So "light paper" is the norm for anything that explains or sells, - and dark is reserved for the live operational view. +- **A paper-like canvas.** Four of the five use a near-white background (warm on + the marketing sites and owl-os, cool slate on the console) with near-black + text; owl-os pushes furthest toward white at `#fffdfb`. The **map is the + exception**: it is fully dark navy with light slate text. So "light paper" is + the norm for anything that explains, sells or configures, and dark is reserved + for the live operational view. - **A blue accent.** owl sits soft and desaturated, retina and dash land on the - brighter `#2563eb`/`#3b82f6`, and the map goes brighter still (sky `#38bdf8`) - to carry on dark. Blue is the only chromatic accent in the UI chrome; - everything else is ink on canvas. (The map adds an amber `#fbbf24` as a - selection/focus highlight.) + brighter `#2563eb`/`#3b82f6`, owl-os lands between them at `#2f8adc`, and the + map goes brighter still (sky `#38bdf8`) to carry on dark. Blue is the only + chromatic accent in the UI chrome; everything else is ink on canvas. (The map + adds an amber `#fbbf24` as a selection/focus highlight.) owl-os spends its blue + the most sparingly: the primary button is ink, and the accent is kept for focus + rings, hover borders, selection washes and the one card that is _this_ node. - **Green and amber as status colours.** Green marks "live" / validated / ADS-B truth; amber marks the radar echo, anomalies, and attention. The console adds red for outright errors. (The exact shades drift between surfaces; see §10.) - **A small uppercase micro-label.** Small, uppercase, letter-spaced, muted. Used for section eyebrows, stat labels, table headers, nav-section titles, and diagram annotations. This is the single most reused idiom and the quickest way - to make a new page read as "ours". The marketing sites and console set it in - their mono; the map keeps the uppercase-and-tracked treatment for panel and - list headers even though it has no mono font. + to make a new page read as "ours". All five surfaces have it. The marketing + sites and console set it in their mono; the map and owl-os keep the + uppercase-and-tracked treatment for section and panel headers in their sans, + the map because it has no mono and owl-os by choice (it has JetBrains Mono and + spends it on data instead). - **Hairline rules and grid dividers.** 1px borders at low contrast separate sections, table rows, fact lists, and card grids. Structure comes from lines, not shadows or fills. - **Flat and quiet.** Minimal ornamentation, few shadows (retina uses a subtle button lift; dash reserves shadow for one dropdown), small status dots for - liveness. + liveness. owl-os is the one partial exception: its cards carry a hairline + shadow at rest and brighten their border plus deepen the shadow on hover, which + is how a whole card reads as clickable without a border change alone carrying + it. - **The radar diagram.** owl and retina both open with a hand-built SVG of the passive-radar geometry (transmitter → target → node) with animated signal - paths. It is the strongest single motif the two marketing sites share. See §8. + paths. It is the strongest single motif the two marketing sites share. owl-os + has a working relative of it, a draggable flight-path simulator. See §8. --- @@ -92,47 +135,67 @@ roles (semantics) are shared unless a surface overrides them. ### Canvas and ink -| Role | owl | retina | dash | map | -|---|---|---|---|---| -| Canvas | `#f7f6f2` | `#fafaf9` | `#f1f5f9` | `#0d1b2a` | -| Sunk surface | `#edecea` | `#f5f4f0` | `#f8fafc` | `#0f2035` | -| Card / panel | `#ffffff` | `#ffffff` | `#ffffff` | `#132240` | -| Dark section | — | `#090904` / `#242422` | — | (all dark) | -| Ink (primary) | `#0e0e0c` | `#1a1a18` | `#0f172a` | `#e2e8f0` | -| Ink (muted) | `#444440` | `#6b6b63` | `#475569` | `#94a3b8` | -| Ink (subtle) | `#888882` | `#9c9c93` | `#94a3b8` | `#64748b` | -| Border | `rgba(14,14,12,.1)` | `#e8e8e3` | `#e2e8f0` | `rgba(100,180,255,.12)` | +| Role | owl | retina | dash | map | owl-os | +|---|---|---|---|---|---| +| Canvas | `#f7f6f2` | `#fafaf9` | `#f1f5f9` | `#0d1b2a` | `#fffdfb` | +| Sunk surface | `#edecea` | `#f5f4f0` | `#f8fafc` | `#0f2035` | `#fbfaf8` | +| Card / panel | `#ffffff` | `#ffffff` | `#ffffff` | `#132240` | `#ffffff` | +| Dark section | — | `#090904` / `#242422` | — | (all dark) | — | +| Ink (primary) | `#0e0e0c` | `#1a1a18` | `#0f172a` | `#e2e8f0` | `#13161c` | +| Ink (muted) | `#444440` | `#6b6b63` | `#475569` | `#94a3b8` | `#494d54` | +| Ink (subtle) | `#888882` | `#9c9c93` | `#94a3b8` | `#64748b` | `#83868c` | +| Border | `rgba(14,14,12,.1)` | `#e8e8e3` | `#e2e8f0` | `rgba(100,180,255,.12)` | `#eae7e4` | The marketing canvases are warm (a hint of yellow); the console is cool slate; the map inverts to dark navy. The map's ink ramp is the dark mirror of the console's slate ramp (`#94a3b8` / `#64748b` recur), and its hairlines are a blue-tinted translucent white rather than a solid grey. +owl-os crosses the two: a warm canvas like the marketing sites, over a **cool** +ink ramp like the console. It is also the only surface authored in **OKLCH** +rather than hex (`oklch(0.20 0.012 260)` and so on), so its ramps are even +perceptual steps by construction. The hex column above is the sRGB equivalent, +for comparison only; the values in the stylesheet are the OKLCH ones. + +owl-os is the only surface whose second border token goes **lighter** rather than +darker: `#eae7e4` bounds a card, `#f3f1ef` divides rows inside one. Structure +therefore gets quieter as you go inward, which is what keeps a config page of +thirty stacked rows from reading as a grid. + ### Accent -| | owl | retina | dash | map | -|---|---|---|---|---| -| Accent | `#5b8dd9` | `#2563eb` | `#3b82f6` | `#38bdf8` | -| Hover / strong | `#4a7cc8` | `#3b82f6` | `#2563eb` | `#7dd3fc` | -| Wash | `rgba(91,141,217,.15)` | `rgba(37,99,235,.06)` | `rgba(59,130,246,.10)` | `rgba(56,189,248,.15)` | +| | owl | retina | dash | map | owl-os | +|---|---|---|---|---|---| +| Accent | `#5b8dd9` | `#2563eb` | `#3b82f6` | `#38bdf8` | `#2f8adc` | +| Hover / strong | `#4a7cc8` | `#3b82f6` | `#2563eb` | `#7dd3fc` | `#1a7acb` | +| Wash | `rgba(91,141,217,.15)` | `rgba(37,99,235,.06)` | `rgba(59,130,246,.10)` | `rgba(56,189,248,.15)` | `#e3f4ff` (opaque) | +| Wash edge | — | `rgba(37,99,235,.15)` | — | — | `#c4daf2` | owl's blue is deliberately soft and low-contrast (an editorial choice, though it costs link legibility, see §10). retina and dash share the saturated blue, with dash resting one step lighter and hovering to retina's resting value. The map -pushes to a brighter sky-blue so the accent reads on navy, and adds an amber -`#fbbf24` for the selection/focus highlight the others do not have. Four distinct -blues in all. +pushes to a brighter sky-blue so the accent reads on navy. owl-os sits between +dash and the map, a shade cyan-ward of both. Five distinct blues in all. + +Two things owl-os does differently with it. Its washes are **opaque tints**, not +alpha overlays, so a wash keeps its colour over any ground it lands on rather +than picking up whatever is behind it. And every wash carries a matching **edge** +one step darker (`#c4daf2` for the accent, `#bee2c9` for success), so a tinted +region is bounded rather than bleeding into the page. The map adds an amber +`#fbbf24` for a selection/focus highlight; owl-os uses the accent wash plus a +3px inset rail for the same job. ### Semantics -| Role | Marketing (owl, retina) | Console (dash) | Map (map) | -|---|---|---|---| -| Success / good | `#16a34a` | `#10b981` (emerald) | `#4ade80` | -| Warning / attention | `#d97706` | `#f59e0b` (amber-500) | `#fbbf24` | -| Error | (unused) | `#ef4444` (red-500) | `#f43f5e` | +| Role | Marketing (owl, retina) | Console (dash) | Map (map) | Node (owl-os) | +|---|---|---|---|---| +| Success / good | `#16a34a` | `#10b981` (emerald) | `#4ade80` | `#33a868` | +| Warning / attention | `#d97706` | `#f59e0b` (amber-500) | `#fbbf24` | `#e1a035` | +| Error | (unused) | `#ef4444` (red-500) | `#f43f5e` | `#e64343` | -Same three roles, brightened a step on the dark map so they carry on navy. Each -pairs with a wash (~10% on light, ~15% on dark) for tinted pill backgrounds. The +Same three roles, brightened a step on the dark map so they carry on navy, and +landing between the marketing and console sets on owl-os. Each pairs with a wash +(~10% on light, ~15% on dark; opaque on owl-os) for tinted pill backgrounds. The console's charts extend the accent into a categorical palette (`#3b82f6, #10b981, #f59e0b, #ef4444, #8b5cf6, #ec4899, #06b6d4, #84cc16, #f97316, #14b8a6`, with `#94a3b8` for an "others" slice); reuse that ordering for any new @@ -145,6 +208,15 @@ gradient** from dark-blue approaching (`#1e3a8a`) through cyan at zero (`#22d3ee to dark-red receding (`#991b1b`). Green there means coverage polygons, not truth. See §8. +owl-os carries a domain palette of its own that no other surface has, because no +other surface asks a person to pick a transmitter. **Broadcast band** is a +categorical hue (FM `#3b82f6`, VHF `#8b5cf6`, UHF `#ec4899`, each on an 8% wash), +and **suitability** reuses the status ramp as a judgement: ideal is the success +green, good is the warning amber, too far is a neutral grey `#9b9fa5`, and too +close is the danger red. Amber and red there are not faults, only "workable" and +"pick another one", which is the one place the status colours are spent on +something other than health. + --- ## 4. Typography @@ -154,21 +226,33 @@ face for running text and UI, and a **mono** face for labels and data. The console collapses everything into the system stack; the map collapses everything into Inter. -| Register | owl | retina | dash | map | -|---|---|---|---|---| -| Display | Source Serif 4 | Fraunces | system sans | Inter | -| Body | Inter | DM Sans | system sans | Inter | -| Mono | IBM Plex Mono | JetBrains Mono | SF Mono | generic `monospace` | +| Register | owl | retina | dash | map | owl-os | +|---|---|---|---|---|---| +| Display | Source Serif 4 | Fraunces | system sans | Inter | Inter | +| Body | Inter | DM Sans | system sans | Inter | Inter | +| Mono | IBM Plex Mono | JetBrains Mono | SF Mono | generic `monospace` | JetBrains Mono | + +Loaded from Google Fonts on the marketing sites, the map (Inter) and owl-os; the +console loads no web fonts at all (its CSP restricts `font-src`). Only the two +marketing sites use a serif; the three operational surfaces (dash, map, owl-os) +are sans-only. -Loaded from Google Fonts on the marketing sites and the map (Inter); the console -loads no web fonts at all (its CSP restricts `font-src`). Only the two marketing -sites use a serif; the two operational surfaces (dash, map) are sans-only. +owl-os is the only surface that borrows both its faces from siblings rather than +choosing new ones (Inter from owl and the map, JetBrains Mono from retina), and +so is the least type-divergent of the five. It also asks Inter for +`font-feature-settings: 'ss01', 'cv11'` (the single-storey `g` and the +straight-tailed `l`), which is what stops a screen full of node IDs and +frequencies from reading as body copy. **Heading weight is the other big tell.** owl sets headings at 400 (light, -serious, editorial); retina at 600 (present, product-confident); dash and map at -700 (compact, functional). Marketing headings carry a tight `letter-spacing` -around `-0.02em` and line-height near 1.1; the operational surfaces run text -small (down to ~0.62rem) and dense. +serious, editorial); retina and owl-os at 600 (present, product-confident); dash +and map at 700 (compact, functional). Marketing headings carry a tight +`letter-spacing` around `-0.02em` and line-height near 1.1; the operational +surfaces run text small (down to ~0.62rem) and dense. + +owl-os keeps the marketing surfaces' `-0.02em` on page titles while sitting at +console sizes, and runs a 14px base rather than 16px: small enough for a page of +settings, large enough not to read as a table. **Scale, as used:** @@ -176,10 +260,17 @@ small (down to ~0.62rem) and dense. retina. Fluid, serif, tight leading. - Section H2 / titles: `clamp(1.6rem, 3vw, 2.4rem)` (owl), `clamp(1.75rem, 3vw, 2.25rem)` (retina). Console page titles are a flat 24px. -- Body: 16px base, line-height ~1.6–1.7, colour = ink-muted for prose. +- Body: 16px base, line-height ~1.6–1.7, colour = ink-muted for prose. owl-os + runs 14px / 1.5, and drops to 12–12.5px for the help line under a field. +- Page title (owl-os): a flat 26px / 600 / `-0.02em`, on Home, Config and every + wizard step alike. Console page titles are a flat 24px. - Micro-label: ~0.65–0.75rem, mono, uppercase, `letter-spacing` 0.04–0.14em, colour = ink-subtle. The `.label` class in `tokens.css` captures the common - case. + case. owl-os sets its own at 11–11.5px, weight 500–600, tracking 0.04–0.08em, + in Inter rather than mono. +- Numbers (owl-os): anything that changes in place (a dBFS reading, a countdown, + a step counter) is mono with `font-variant-numeric: tabular-nums`, so it does + not jitter as it updates. Worth copying anywhere a value refreshes live. --- @@ -187,16 +278,27 @@ small (down to ~0.62rem) and dense. ### Shape -| | owl | retina | dash | map | -|---|---|---|---|---| -| Radius (default) | 4px | 12px | 8px | 6px | -| Radius (small) | 3px | 8px | 4px | 3px | -| Radius (large) | 6px | 20px | 12px | 10px | +| | owl | retina | dash | map | owl-os | +|---|---|---|---|---|---| +| Radius (default) | 4px | 12px | 8px | 6px | 10px | +| Radius (small) | 3px | 8px | 4px | 3px | 6px | +| Radius (large) | 6px | 20px | 12px | 10px | 14px | + +Crisp on owl, soft on retina, moderate on dash, tight on the map, second-softest +on owl-os. Borders are always 1px hairlines; nothing uses a heavy stroke. The map +builds elevation from backdrop-blur (20px on the detail panel, 14px on the +playback bar) and subtle shadow rather than cards, since its panels float over +the map. + +The three-step scale is a fair summary for four of the surfaces and a +simplification for two. The map actually spends 2, 3, 4, 5, 6 and 10px in its +stylesheet plus 8 and 12px inline, and retina spends 5, 6, 8, 10, 12 and 20px, +with neither of its two button radii matching the 12px recorded as its default. -Crisp on owl, soft on retina, moderate on dash, tight on the map. Borders are -always 1px hairlines; nothing uses a heavy stroke. The map builds elevation from -backdrop-blur (14–20px) and subtle shadow rather than cards, since its panels -float over the map. +owl-os is the only surface with a real elevation scale: a hairline `shadow-sm` at +rest, a 24px-blur `shadow-md` on hover and for the sticky save bar, and a +`shadow-pop` for modals. All three are tinted with the ink colour rather than +black, so a raised card warms rather than greys. ### Space @@ -204,7 +306,12 @@ float over the map. 1120–1200px for wide/hero rows. The console is full-width and fluid with a 250px sidebar. The map is full-bleed: a 280px left aircraft list (collapsing to 36px), a 280px right detail panel, and a full-width bottom playback bar. -- Nav / header height: 56px (owl), 64px (retina), 56px (dash). +- owl-os runs a 720px column on Home, a 200px + fluid two-column shell on Config + (max 1100px), and a fixed 560px column for every wizard step. One decision per + row, with its explanation directly underneath. +- Nav / header height: 56px (owl), 64px (retina), 56px (dash). owl-os stacks two + rows instead, a fleet bar over the page tabs, and its config side-nav sticks + below both at 58px. - Section padding: ~5–6rem vertical on the marketing sites, 24px content padding in the console. - Cards/panels: ~20px body padding, 16px header; grids gap ~16px. @@ -220,35 +327,284 @@ Three patterns recur: signal paths flow from transmitter to target to node. owl and dash animate in CSS; retina's hero mixes in inline SVG SMIL (``). -None of the surfaces currently honour `prefers-reduced-motion`; the `tokens.css` -`.reveal` helper adds the guard, and new work should keep it. + +owl-os runs none of the three. It defines no `@keyframes` at all: motion is +limited to 120ms colour, border and shadow transitions on hover, a 150ms switch +throw, and a 2px nudge on a card's arrow. Nothing on the page moves unless it was +touched, which is reasonable for a settings surface someone reaches when +something needs fixing, and the reason its one animated component, the simulator, +is also the only place on any surface that checks `prefers-reduced-motion` before +starting. Everything else across all five surfaces still runs its loops +unguarded; the `tokens.css` `.reveal` helper adds the guard, and new work should +keep it. --- ## 6. Components -- **Nav.** Fixed top bar, `backdrop-filter: blur(...)` over a translucent - canvas, a hairline bottom border. Logo left (mono wordmark, or logo + mono - text on owl), links centre/left, a primary CTA right. Collapses to a hamburger - under ~860–960px. -- **Buttons.** Primary = solid ink (marketing) or solid accent (console), - inverse text, small radius. owl and dash keep them flat; retina lifts them - (`translateY(-1px)` + soft shadow) on hover. Secondary = text link with a - hairline underline (owl), or an outline button (retina/dash). -- **Section eyebrow.** A `.label` micro-label above each H2 naming the section - ("About", "Flagship project", "Capabilities"). The consistent opener for a - marketing section. -- **Fact rows / metrics.** Label-value pairs on hairline-divided rows (owl's - RETINA facts), or a bordered 4-up metrics bar (retina). Values in the display - face, labels muted. A tidy way to present specs. -- **Cards.** White, 1px border, surface radius, no shadow. Grids of cards use a - 1px gap over a border-coloured background so the dividers read as shared lines - (retina's steps/features, dash's panels). -- **Badges / pills.** Rounded (12px), tinted `-wash` background with matching - text colour, often a leading status dot. Success/warning/error on the console; - "live" on the marketing sites. +The five surfaces do not have the same component set, and the differences are +larger than the colour and type differences in §3 and §4. Before reaching for a +pattern, check it exists on the surface you are building for. + +| | owl | retina | dash | map | owl-os | +|---|---|---|---|---|---| +| Form controls | **none** | **none** | inline, ad hoc | a few, ad hoc | a real set | +| Tables | none | none | yes | none | one | +| Modal / dialog | none | none | **native `confirm()`** | one | three | +| Toasts | none | none | none | yes | none | +| Tabs | none | none | one page | app shell only | yes | +| Icons | 36px, part-filled | Unicode glyphs | 24px, stroke 2 | inline SVG | 24px, stroke 1.6 | +| Framework | none | none | none | none | Bootstrap 5.3 | +| Custom properties | yes | yes | yes | **none** | yes | +| `:focus` styling | none | none | **none** | one rule | inputs only | + +The two marketing sites have no `
`, ``, `