# Magogi brand-web kit

A **self-contained, drop-in** brand layer for any Magogi Foundation web surface —
the CSS implementation of the [Magogi Brand Book][bb] (Part V Colour, Part VI
Typography, Part VII/VIII components) that `mgf-brand` itself ships only as prose
+ tokens. Everything here is plain CSS + assets: no build step, no framework.

> **Status:** shipped as the installable **`mgf-brand-web`** package (this
> directory is its package data; consumers mount `mgf.brand_web.static_dir()`).
> Consumed today by `mgf-fed-web`, `mgf-cloud-web`, and `mgf-test-web`. Since
> 0.3.0 the token layer is **generated upstream** — `global-tokens.css` is a
> verbatim copy of `mgf-brand/brand/assets/system/global-tokens.css` (single
> source: `design-tokens.json`); never hand-edit it here, re-vendor it. Keep
> this folder free of app-specific CSS (that lives in each app's `app.css`).

## Contents

| File | Role |
|------|------|
| `global-tokens.css` | **The canonical token layer** (`--mgf-*`, light + dark at parity). A VERBATIM copy of the GENERATED `mgf-brand/brand/assets/system/global-tokens.css` (single source: `design-tokens.json`; verify upstream with `python3 brand/build/gen_tokens.py --check`). Never hand-edit; never hardcode hex. |
| `tokens.css` | The kit's linked **entry point**: imports `global-tokens.css`, then declares the **deprecated** legacy aliases (`--color-*`, `--state-*`, `--space-*`, …) so pre-0.3 consumers keep working. New code consumes `--mgf-*` directly; alias removal is retargeted to 0.5 (the P4.2 adoption wave's app CSS still consumes them). |
| `base.css` | Element defaults, type scale, links, focus rings, buttons, a11y utilities. |
| `components.css` | Reusable components: nav, cards, stat tiles, tables, status badges, forms, empty state, Evidence Ledger. |
| `instruments.css` | **Operator-instrument layer** (optional, additive): control-surface components for federation/console/testing tools — state chips (with 0.4.0 icon slots), live indicators, progress, tabs, the dark streaming console, authority markers, ribbons, the telemetry live-pane, the config panel, level badges, reference pills, detail/evidence blocks, empty-state variants + the honest-absence composition, workflow chips (`.tstate`), origin badges (`.origin-badge`), the derived tag. |
| `console.css` | **The `.mgf-console` operator shell** (0.4.0; optional, LAYOUT layer): the dark instrument top bar + mark + status pill, the dark nav rail + legend, the light printable readout, the skip link, and the print reset — extracted from the near-identical fed-web/test-web app shells (M1 P4.1). Consoles only; content sites must not load it. Markup ships as the `mgf/console.html` Jinja template (see `templates_dir()`). |
| `icons/icons-sprite.svg` | **The 42-icon vocabulary** (Brand Book Part VIb; F3 founder-approved 2026-07-04). A **VERBATIM copy** of the GENERATED `mgf-brand/brand/assets/icons/icons-sprite.svg` @ `865477b` (single source: the per-icon SVGs, assembled by `brand/build/gen_icons.py`; sha256 `392322edc7a3ec2ed6ca9dbac8b6a6cc55d359a162ef752920949c04f6dfd774`). Never hand-edit; re-vendor it. 24×24 grid, stroke 1.25, `currentColor`. |
| `fonts.css` + `fonts/` | Self-hosted OFL families: Inter (body), Space Grotesk (display), JetBrains Mono (code/labels). |
| `logo/` | Cornerstone Orbit marks (icon, lockup, on-dark, mono) + favicon. |
| `pattern/` | Federation Lattice tiles (fine/medium, light/dark). |

Load order matters: **tokens → fonts → base → components → instruments →
console**, then your app CSS (`tokens.css` pulls in `global-tokens.css` itself
via `@import`). `instruments.css` and `console.css` are optional — load them
only on operator/console surfaces; pure content surfaces skip both. Or skip the
hand-written `<head>` entirely: `{% extends "mgf/console.html" %}` from the
kit's template pack (`mgf.brand_web.templates_dir()`) links everything in
canonical order and renders the shell.

## Icons (`icons/icons-sprite.svg`)

One sprite, 42 `<symbol>`s, ids `mgf-icon-<kebab-name>`, every glyph
`viewBox="0 0 24 24"` and `stroke="currentColor"` — monochrome by law, themed
by the surrounding text colour. Reference it externally (same-origin) with
`aria-hidden` by default; name the meaningful ones:

```html
<!-- decorative (the default) -->
<svg class="mgf-icon" aria-hidden="true">
  <use href="/static/brand/icons/icons-sprite.svg#mgf-icon-proof"/>
</svg>

<!-- meaningful: name it, drop aria-hidden -->
<svg class="mgf-icon" role="img" aria-label="Verified">
  <use href="/static/brand/icons/icons-sprite.svg#mgf-icon-success"/>
</svg>
```

`.mgf-icon` (base.css) sizes the glyph at `1em` in text flow; fix a size with
inline width/height styles — or let the template pack's `icon()` macro emit
all of this for you. Status icons never replace the dot + text label (colour
is never the only signal); gold only when the icon itself is the view's one
proof emphasis.

## Drop-in usage

1. `pip install mgf-brand-web`, then mount the package data (FastAPI:
   `from mgf.brand_web import static_dir` →
   `app.mount("/static/brand", StaticFiles(directory=static_dir()), name="brand")`).
2. Put this in your base template `<head>` (adjust the `/static` prefix to your
   mount point):

```html
<link rel="icon" href="/static/brand/logo/magogi-favicon.svg" />
<link rel="preload" as="font" type="font/woff2" crossorigin
      href="/static/brand/fonts/inter-latin.woff2" />
<link rel="preload" as="font" type="font/woff2" crossorigin
      href="/static/brand/fonts/space-grotesk-latin.woff2" />
<link rel="stylesheet" href="/static/brand/tokens.css" />
<link rel="stylesheet" href="/static/brand/fonts.css" />
<link rel="stylesheet" href="/static/brand/base.css" />
<link rel="stylesheet" href="/static/brand/components.css" />
<link rel="stylesheet" href="/static/app.css" />  <!-- your app-specific layer -->
```

3. Use the classes: `.button`/`.button-primary`/`.button-accent`, `.card`,
   `.stat`/`.stat-grid`, `.table`/`.table-wrap`, `.badge`/`.badge-success`…,
   `.form`/`.field`/`.input`, `.app-nav`, `.eyebrow`, `.empty`, `.ledger`.

## Operator-instrument layer (`instruments.css`)

The control-surface vocabulary for operator tools, on the same tokens. ~14
families:

| Family | Classes |
|--------|---------|
| **State chips** (SYNC + TEST language) | `.status-chip` + `--in-sync/--stale/--tampered/--unknown/--unreadable/--checking/--syncing/--error` and `--pass/--fail/--error/--skipped/--running`; `.status-chip__dot`, `.spinner`. Map a state with `state.toLowerCase().replaceAll('_','-')`. |
| **Live indicator dots** | `.status-indicator` + `--running/--queued/--down` (pulsing). |
| **Progress bars** | `.progress`, `.progress__fill` (+ `--done`), `.progress--indeterminate`. |
| **Tabs / lens-tabs** | `.tabs`/`.tab`/`.tab--active` (gold underline); `.lens-tabs`/`.lens-tab`/`.lens-tab--active` (pill). |
| **Dark streaming console** | `.console`, `.console__line/__seq/__ts/__kind/__text`; per-kind colours via shared `.kind--<event>` (e.g. `--session-start`, `--step`, `--gate`, `--artifact`, `--error`). Light text on dark ink — stays dark in both themes. |
| **Authority / broker** | `.authority-badge` (violet dashed), `.service-status--up/--down`. |
| **Ribbons** | `.ribbon--warning/--danger/--info`. |
| **Live-pane** (telemetry) | `.live-pane`, `__head/__op/__body/__step/__meta/__latest/__timeline/__events/__event` + `.live-pane__kind` (reuses `.kind--*`). |
| **Config-panel** | `.config-toggle`, `.config-panel`, `__head/__row/__foot/__note`. |
| **Level badges** | `.level-badge--low/--medium/--high` (+ `--effort`). |
| **Telemetry marker** | `.telemetry-marker`, `.live-dot` (+ `--ended`), `.live-chip` (+ `--ended`). |
| **Reference pills** | `.pill` + `--age/--priority`. |
| **Detail / evidence** | `.detail` (+ `.detail__key`), `.detail-block` (+ `--warning/--derived`), `.evidence`. |
| **Empty-state variants** | `.empty--unknown/--unreadable/--no-data`, `.empty__icon`, `.empty__desc` (extend the existing `.empty`); `.absence` (+ `__state/__errs`) — the honest-absence composition behind the `absence()` macro. |
| **Workflow chips** (0.4.0) | `.tstate` + `--done/--in-progress/--next/--postponed/--blocked` (+ neutral), `.tstate__dot` — task/stage workflow language (lifted from fed-web). |
| **Origin badges** (0.4.0) | `.origin-badge` + `--web/--agent/--ci` (cli/other = neutral) — who submitted the run (lifted from test-web's `.pw-origin`). |
| **Derived tag** (0.4.0) | `.derived-tag` — the violet dashed "inferred by the web layer" marker (lifted from fed-web). |

## Jinja template pack (`../templates/mgf/`, 0.4.0)

Shipped as plain package data (`templates_dir()` accessor; the kit still
imports no web framework): `mgf/console.html` — the `.mgf-console` shell as an
extendable base (blocks: `title · mark_title · mark_sub · topbar · rail ·
main · scripts · head_extra · body_attrs …`); `mgf/macros.html` — `icon()`,
`sync_chip()`, `status_chip()` (both with optional sprite-icon slots),
`tstate()`, `origin_badge()`, `derived_tag()`, `absence()`, `empty_state()`;
`mgf/styleguide.html` — the living styleguide.

**The living styleguide** renders the shell + every family above on one page,
from the shipped templates and assets: `python demo/app.py` in the kit repo →
`http://127.0.0.1:8791/`.

## Brand rules baked in

- **One gold accent per view** ("one flame per room") — Keystone Gold
  (`--color-accent`) is for the single primary action / active marker, never
  body text. The active tab/lens marker uses gold only as the underline; text
  stays dark for contrast.
- **Colour policy (D-BRAND-ACCENT — ratified as brand canon by Decision 24,
  founder-enacted 2026-07-04)** for the instrument layer: **gold** =
  affirmative action (use `.button-accent`; blue is *never* a CTA), **blue**
  (`--mgf-busy` / `--mgf-color-state-busy`) = functional "busy / running"
  only, **violet** (`--mgf-derived` / `--mgf-color-state-derived`) =
  "derived / authority / telemetry" — both now defined by the generated
  canon layer, no longer kit-invented. The success/warning/error/info tokens
  carry the rest of the state language.
- Status is **colour + dot + label**, never colour alone (a11y).
- Dark mode is automatic via `prefers-color-scheme` — tokens remap, no JS.
- Motion is restrained and honours `prefers-reduced-motion`.

[bb]: https://codeberg.org/magogi-admin/mgf-brand — `brand/MAGOGI_BRAND_BOOK.md`
