# Turbo IT brand
# Rules of record. The source is the Demo Builder (generate.turboit.uk), whose one
# shared stylesheet is turbo-it-generate/src/ui-css.js. Every value quoted here is
# that file's, and where it documents its own reasoning (an AA measurement, a
# contrast trap) that reasoning is kept: it is why the value is what it is.
# Tokens: tokens/turbo-it-tokens.css. Visual reference: index.html.

## 1. The mark

- The mark is the bolt. Never redraw it by hand, never recolour it outside the approved
  variants, never rotate it, never add a shadow or an outline.
- **As the builder actually ships it: the bare gradient bolt**, inlined as a data URI
  (`TURBO_LOGO` in `turbo-it-generate/src/index.js`), used for the favicon and the login
  lockup. That is the primary form. `logos/bolt-mark.svg` is the same shape as a clean
  vector.
- Files: `bolt-mark.svg` (gradient, primary), `bolt-mark-mono-*.svg` (electric, white, ink,
  cream), `favicon.svg` (bare bolt), `icon-tile.svg` (optional opaque app icon),
  `lockup-login-*.svg` and `lockup-topbar-*.svg`.
- Clear space: a quarter of the mark's height on every side. Minimums: 14px for the gradient
  mark, 12px for mono, 20px for the tile.
- The mark is 350 x 512 (0.684 aspect), taller than wide. Never squash it to a square.
- The tile (near-black rounded square) is NOT what the builder uses. Keep it for a favicon
  that needs an opaque square, an app icon or an avatar, never as the mark inside a
  product's own topbar.

## 2. Lockups

Two patterns, both the builder's, both using live text plus the bolt image:

- **Login (stacked)**: bolt 38px tall, "Turbo IT" at 15px/600 with `-0.01em`, product name
  at 12px in `--ti-muted-foreground` underneath. Use it for a centred sign-in or an
  interstitial page.
- **Topbar (inline)**: bolt 24px tall, "Turbo IT" at 14px/600, a 1px divider 18px tall, then
  the product name at 400 weight in muted. Use it in an app shell (`ui-css.js` `.ti-brand`).

The wordmark is monochrome. There is no two-tone "Turbo IT" in the builder, so do not invent
one. Never letter-space it, never set it in a serif, never stretch it.

## 3. Type

- Family: the system sans stack in the tokens (`ui-sans-serif, system-ui, -apple-system,
  "Segoe UI", Roboto`). Mono only for code, keys and tabular values.
- **The scale is 11 / 12 / 13 / 14 / 15 / 16 / 17 / 18 / 22 / 24 px, and it stops there.** A
  28px or 40px headline step does not exist in the builder. Do not add one to a product UI:
  a 40px headline in a dashboard reads as a marketing page.
- Weights: 400 body, 500 controls and pills, 600 headings and labels, 700 only for h1, the
  wordmark and a stat tile's number.
- Tracking: `-0.02em` on h1, `.ti-h1` and `.tile .v`; `-0.01em` on h2 and the brand name.
  Uppercase micro-labels take `+0.12em` at 11px, and that is the only uppercase in the kit.
- Line height 1.5 for prose, 1.2-1.45 for controls and dense rows.

## 4. Colour

Source: `ui-css.js` `:root`. Neutrals plus four status hues, each with a fill AND a text
variant, because the bright fill is not legible as small text.

| Token | Value | Use |
|---|---|---|
| `--ti-background` | `#f6f3ed` | page: warm off-white, never stark white |
| `--ti-surface` | `#f2eee6` | table heads, recessed panels, `.dotted` |
| `--ti-card` | `#fefcf8` | cards, topbar, rows |
| `--ti-input-bg` | `#ffffff` | form fields: the one true white |
| `--ti-foreground` | `#231f19` | body, headings |
| `--ti-muted-foreground` | `#605a52` | secondary text |
| `--ti-muted` | `#eee9e0` | hover fills, chips, skeletons |
| `--ti-border` | `#dfdad1` | hairline borders (hover: `#cfc8bb`) |
| `--ti-primary` | `#1276ce` | fills, focus, links |
| `--ti-primary-hover` | `#0064b5` | hover |
| `--ti-primary-foreground` | `#fcfcfc` | text ON the primary fill |
| `--ti-destructive` | `#c1000f` | destructive fill |
| `--ti-success` | `#0f6a2e` | success fill |
| `--ti-warning` | `#8a5400` | warning fill |

Status text variants, which are the ones you put words in: `--ti-info-fg #0064b5`,
`--ti-success-fg #0f6a2e`, `--ti-destructive-fg #c1000f`, `--ti-warning-fg #8a5400`. Each has
a tint pair (`--ti-info-bg/-bd` and friends) for the pill background and border.

Measured contrast (WCAG, sRGB, 2026-09-24):

| Pair | Ratio | Verdict |
|---|---|---|
| foreground on background | 14.80 | AAA |
| muted-foreground on background | 6.15 | AA |
| primary-foreground on primary | 4.66 | AA |
| info-fg on its tint over card | 6.10 | AA |
| success-fg on its tint over card | 6.20 | AA |
| destructive-fg on its tint over card | 6.10 | AA |
| warning-fg on its tint over card | 6.60 | AA |
| bright warning fill as 12px text on its tint | 1.94 | fails: this is why the -fg set exists |
| white on the gradient's teal end | 3.50 | fails: never put white text on the gradient |

Rules that follow, and are not negotiable:

1. Status words use the `-fg` variant. The plain hue is for the fill only.
2. Never put white text on the gradient (`--ti-avatar` in `ui-css.js` is solid primary for
   exactly this reason).
3. `--ti-muted-foreground` is the floor for secondary text. There is no third grey for text.
4. If you need a colour that is not here, add it to the token file first, with its measured
   contrast, then use it.

## 5. The brand gradient

`--ti-grad`: `linear-gradient(100deg, #8a4af5 0%, #1276ce 46%, #0093cb 74%, #00b5bc 100%)`.
Three sanctioned uses, all from the builder: the topbar's 2px accent line at 50% opacity, the
wordmark lockups, and the progress fill. Never a button fill, never behind text, never under
the mark.

## 6. Shape, depth, motion, density

- Radii: 6 (kbd, skeletons) / 8 (buttons, fields, alerts) / 10 (the base `--radius`: segs,
  panels, dropzones) / 12 (cards, tiles, menus) / 14 (modals) / 999 (pills, chips, badges,
  switch, avatar). Nothing square, nothing at 4px.
- Depth: hairline borders plus warm low-contrast shadows (`--ti-shadow-sm`,
  `--ti-shadow-card`). The primary button additionally carries the electric glow
  (`0 0 40px -8px`, widening to `60px -5px` on hover). One border and one shadow per surface.
- Motion: 150ms ease (`--ti-tt`) on colour, border, shadow and background only. Skeleton
  shimmer and the 0.7s button spinner are the only loops. Honour
  `prefers-reduced-motion`: the builder collapses all animation to 0.001ms there.
- Density: controls are 40px (32px small, 48px large), fields 40px, table rows 48px, the
  topbar 60px (`--ti-nav-h`). On a coarse pointer every 32px and 36px control lifts to 44px.
- Focus: border to primary plus `0 0 0 3px rgba(18,118,206,.18)`. Never remove a focus ring.

## 7. The link row (extension)

Not in the Demo Builder. This is the hub's destination row, assembled out of the components
above (a card row, a pill and `.btn-sm`). It exists because a product needs one obvious
action per destination, always visible, in the same place on every row.

```
.row          min-height 56px; padding 9px 12px 9px 14px; gap 12px; radius 10;
              1px --ti-border; background --ti-card
.row:hover    background --ti-muted          (the builder's table hover)
.ti-icon      36x36; radius 8; white tile; 1px --ti-border; image inset 5px
.ti-title     14px / 600 / --ti-foreground, truncated
.ti-desc      13px / 400 / --ti-muted-foreground, truncated, one line
.ti-host      mono 11.5px / --ti-muted-foreground; pill: --ti-muted bg, radius 999,
              padding 3px 10px, max-width 30%, truncated
.ti-badge     the builder's .pill-info: 12px / 500, --ti-info-bg, 1px --ti-info-bd,
              --ti-info-fg, a 6px dot, radius 999
.ti-open      .btn-sm: 32px tall, min-width 78px, radius 8, 13px / 500; idle = secondary
              (card bg, border, shadow-sm), row hover = primary (electric + glow)
.ti-delslot   a reserved 22px before the button, so a delete button never shifts it
below 640px   hide .ti-host and .ti-desc, .ti-open min-width 64px (76px in practice)
```

Positioning rules: the action is the last element in the row, always visible (never
hover-revealed), its right edge 12px from the row edge on every row, and it keeps its width
whether or not the row has a delete button. Rows are 56px; a two-line body in a single row
is a bug, not a variant.

Two placements, one component: standalone the row is its own bordered card with 8px gaps;
inside a panel it is hairline-separated (`.row + .row`) with no border of its own. The hub
uses the panel placement. On a phone the rows keep identical metrics to each other: what
changes is the row's content, never one row's size. Under 640px `.ti-host` and `.ti-desc` are
hidden, `.ti-open` takes a 64px minimum (75px in practice) with 9px padding, and the badge
collapses to its dot (the words cost the title about 48px; carry the meaning on the badge's
`title` and `aria-label`).

## 8. Dark mode

**The Demo Builder has no dark mode.** Anything dark in a Turbo IT product is an extension,
and the tokens file keeps it in a clearly separated block. If a product ships dark, derive it
from the light palette and keep the relationships: electric is the fill, a lighter electric is
the text on the surface, and text ON an electric fill is dark (white on `#0090ff` is 3.26:1).
Do not let a dark theme become the default for an internal tool that also has to match the
builder's screenshots.

## 9. Voice

Plain English, sentence case, no exclamation marks, no emoji in product UI (the hub's category
icons are the estate's one existing exception). Say what a thing does: "Instant AI client-site
mock-ups for sales calls", not "Supercharge your pipeline!". Status words are the plain ones
the builder already uses: Live, Degraded, Failed, Queued, Locked.

**No em dashes, ever** (owner rule, estate-wide). Use a comma, a colon or a full stop. Watch
the hidden forms: `&mdash;`, `\u2014`, and a lone dash on its own line. En dashes are fine in
genuine ranges.
