Files
kontra/DESIGN.md

183 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
type: design-system
name: Kontra — Broadsheet Editorial
version: 1.0.0
status: approved 2026-09-08
source:
stitch-panel: "The Gazette — Tides of the Outer Reach"
stitch-export-html: "Image 2.html"
stitch-export-design-md: "Image 3.markdown"
audience: desktop + mobile news-opinion site (Kontra)
---
# Kontra — DESIGN.md (Broadsheet Editorial)
> Adopted 2026-09-08 from Google Stitch "Broadsheet Editorial" panel.
> **Finalized 2026-09-08:** brand is **Kontra** (not "Kontra Day"); centered masthead;
> "Topics" heading; responsive (≥1024 / 641–1023 / ≤640) with dropdown topic nav
> + mobile sections drawer. Clickable prototype: `prototype/index.html`,
> `prototype/article.html`, tokens in `prototype/assets/kontra.css`.
> Palette + typography reconciled to the *rendered* Stitch export (Image 2.html) —
> the DESIGN.md export used slightly different hexes (e.g. `#F8F6F0` vs `#fbf9f3`);
> the rendered HTML is what you actually saw, so it wins. Differences noted inline.
## Identity
A tactile, deliberate reading environment inspired by physical print journalism
and high-grade editorial typography. Intellectual, trustworthy, measured, authorial.
Ultra-clean editorial minimalism: structure from hairline rules, typographic scale,
and whitespace — **not** shadows, rounded containers, or neon accents.
Rejects app-clutter (FABs, heavy shadows, dense cards).
**Kontra adaptation:** from a mobile-first Stitch panel, we built a **desktop-first**
site: front page with lead stack + Topics grid + Latest feed, subject indexes,
wider measures. Tokens carry over; the desktop layout is finalized in §Layout.
## Palette
Base is **warm newsprint**, ink is **soft charcoal**, accent is **editorial vermilion**.
No pure black-on-white (optical glare).
| Token | Value (rendered) | Role |
|---|---|---|
| `--canvas` | `#fbf9f3` | Base page background (newsprint) |
| `--canvas-bright` | `#ffffff` | Cards/forms on dark wells; bright surfaces |
| `--surface` | `#f0eee8` | Secondary canvas: section wells, meta blocks |
| `--surface-hi` | `#eae8e2` | Tertiary wells, footer sections |
| `--surface-highest` | `#e4e2dd` | Hairline borders, dividers (also `#e4e2dd`) |
| `--ink` | `#1b1c18` | Primary text (soft charcoal, not black) |
| `--ink-muted` | `#444748` | Byline, captions, secondary metadata |
| `--ink-faint` | `#747878` | Timestamps, reading time, tertiary |
| `--accent` | `#ad3222` | **Editorial vermilion**: breaking tags, section headers, links, active states, numerals |
| `--accent-deep` | `#8b190d` | Accent hover/pressed states (from secondary-fixed-variant) |
| `--accent-soft` | `#ffdad4` | Accent tint wells, selection bg |
| `--on-accent-soft` | `#400100` | Text on accent-soft (selection) |
| `--ink-inverse` | `#1c1b1b` | Dark solid: primary buttons, masthead icon well |
| `--on-ink-inverse` | `#ffffff` | Text/icon on ink-inverse |
| `--outline` | `#c4c7c7` | Subtle separators, placeholder |
| `--hairline` | `#e4e2dd` | 1px rules (same as surface-highest) |
| `--scrim` | `rgba(26,26,26,0.4)` | Warm charcoal scrim for modals/drawers |
### Notes
- Default button: `--ink-inverse` bg, `--on-ink-inverse` text; hover → `--accent`.
- Focus: hairline transitions `--hairline` → `--ink`, **no glow/shadow**.
- Selection: `bg #ffdad4`, text `#400100`.
## Typography
| Token | Family | Size | Weight | Line | Track |
|---|---|---|---|---|---|
| `--font-display` | **Newsreader** (serif) | — | — | — | — |
| `--font-body` | **Literata** (serif, print) | — | — | — | — |
| `--font-ui` | **Work Sans** (sans) | — | — | — | — |
| `masthead` | Newsreader | 38px (mob 30px) | 700 | 1.16 (44px) | -3% |
| `headline-xl` | Newsreader | 32px (mob 28px) | 600 | 1.19 (38px) | -2% |
| `headline-lg` | Newsreader | 24px | 600 | 1.25 | -1% |
| `headline-md` | Newsreader | 20px | 500 | 1.3 | 0 |
| `headline-sm` | Newsreader | 18px | 600 | 1.33 | 0 |
| `body-lead` | Literata | 19px | 400 | 1.58 (30px) | -0.5% |
| `body-md` | Literata | 17px | 400 | 1.65 (28px) | 0 |
| `body-sm` | Literata | 14px | 400 | 1.57 (22px) | 0 |
| `quote` | Newsreader *italic* | 21–22px | 400 | 1.45 | -1% |
| `label-caps` | Work Sans | 11px | 600 | 16px | +12% (uppercase) |
| `label-meta` | Work Sans | 12px | 500 | 18px | +2% |
| `label-ui` | Work Sans | 14px | 500 | 20px | +1% |
### Rules
- **Body measure ≤ 68ch** (`max-width: 65ch`); content column `42rem` max.
- **Italic serif reserved**: book titles, direct quotes, editorial side notes only.
- Section lead-ins: `label-caps` in `--accent` above headline.
- Headlines: Newsreader, tight tracking, no hyphenation; keep 2-line constraint on feeds.
- **Hierarchy (approved tweak)**: sub-headings in feeds/subject boxes render **one step smaller** than the box's primary headline, and decks one step smaller again — so the leading story reads clearly above the secondary tiers.
- Fonts self-hosted (woff2) — not Google CDN at runtime (page 3 of plan).
## Spacing / Grid
- Baseline: **8px** grid. Vertical rhythm via `--space-md` (16px) / `--space-lg` (24px) / `--space-xl` (32px).
- Gutter: mobile `20px` (1.25rem); tablet/desktop scales to `24–32px`.
- **Content column**: centered `max-width: 42rem` (672px) for article body.
- Front page: two/three-tier column grid (12-col on ≥1024px) — see Desktop Extension.
- Line length hard cap: `65ch` body.
## Shape / Elevation
- **0px radius everywhere** (buttons, cards, inputs, chips, image frames). Sharp right angles only.
- Circular allowed **only** for: author avatars, audio scrubbers.
- **No drop shadows, no blur-layered elevation.** Depth is planar + hairlines.
- Modals/drawers: solid sheet, 1px `--ink` border, `--scrim` backup. Sticky masthead: hairline bottom border only.
## Components
### Masthead (sticky top)
- Meta line: date • edition (label-caps, `--ink-muted`), edition flag (label-caps, `--accent`).
- Brand row: masthead title (Newsreader, `--ink`) + search icon + avatar circle (`--ink-inverse`).
- Section ribbon: horizontal scroll, label-caps `--ink-muted`; active = `--ink` + 2px bottom rule; accent section (`--accent`).
- Border-bottom hairline; `bg --canvas/95` + `backdrop-blur-md` (only blur allowed).
### Bottom nav (mobile)
- Fixed bar, 4 items (Edition / Sections / Reader Mode / Saved), icon + 11px label, hairline top border. (Desktop: replaced by persistent top nav.)
### Article header
- Section tag chip (`--accent` label-caps + 4px dot) → `headline-xl` → byline (`--ink` label-meta) → desk • dateline • read time (`--ink-faint`). Hairline under meta.
### Hero plate / figure
- Full-bleed image, max-h 72vh; **grayscale + slightly boosted contrast** (Stitch used `contrast-108`, true B&W look).
- Figcaption: `Fig. N` label-caps `--ink` + plate/credit `--ink-faint`; 1-2 line description `body-sm` `--ink-muted`. Hairline frame.
### Pull quote
- `--surface` well, `4px` left rule `--accent`, giant serif opening quote (`--accent`, 38px, opacity-80), Newsreader italic `quote` text, cite in `--accent` label-caps with hairline above. Sharp corners.
### Photo strip / field notes
- Section header: `label-caps` `--ink` + small icon; "X of Y" `--ink-faint`.
- Grid (1-col mobile, 2-col tablet+). Figures: `--surface` well, 1px hairline frame, 3:2 image, `--accent` label-caps fig caption + body-sm description.
### Feed list (related / subject index)
- Stacked rows divided by hairlines. Each: section tag (`--accent` label-caps), **primary headline (`headline-sm`, 17–18px)**, **sub-headline one step smaller (`headline-sm` 16px)**, deck `body-sm` 13px `--ink-muted`, byline+read time `label-meta` `--ink-faint`. Thumb 3:2 or 16:9 with hairline frame. Hover: row/hairline shifts `--ink-faint`; headline → `--accent`.
- Rows are touch-friendly (min 44px).
### Subject grid boxes (front page)
- Approved: lower boxes titled **World / Politics / Culture / Tech etc.** (subject names). Each box: subject title (`label-caps` `--accent`), latest story **headline 17px** (`headline-sm`), sub-headline 16px, deck 13px, byline. Subject titles stay full strength; story sub-headings step down in size to differentiate tiers.
### Buttons
- Primary: solid `--ink-inverse`, `label-ui` `--on-ink-inverse`, 0px, min-h 42–44px, hover → `--accent`. Include uppercase `label-caps` style for action labels.
- Secondary: 1px `--ink` border, `--ink` label; press = 10% `--ink` tint.
- Text links: 1px underline 3px below baseline, `--accent` or `--ink-faint`.
### Forms
- Underline or 1px bordered box (`--hairline`); focus border → `--ink` (no glow). Placeholder `--ink-faint` in Literata. Sharp corners.
### Newsletter / save modules
- `--surface` or white card, hairline border, `label-caps` `--accent` title, icon, body-sm copy, inline form (input + primary button). HTMX `hx-post` swap-outerHTML.
## Layout (finalized 2026-09-08)
Brand: **Kontra** (centered masthead). Home section heading: **Topics** (not "By Subject").
1. **Front page** (home template):
- **Lead stack**: featured article (hero plate + headline-xl + deck) 2fr + right rail of `headline-md` secondary stories 1fr.
- **Topics grid**: 4 subject boxes (World / Politics / Culture / Tech) — kicker `--accent` label-caps, 17px s-head, 16px s-sub, byline, "More X →". 4-col desktop → 2-col tablet → 1-col mobile. **Approved.**
- **Latest feed**: 2-col article rows (kicker + headline + sub + meta) → 1-col mobile.
2. **Subject index page**: section masthead (`--accent` label-caps + Newsreader title) + lead featured + feed.
3. **Article**: centered 42rem column; hero plate full-bleed to column edge; pull quotes and photo strips within measure; sticky masthead.
4. **Nav**: desktop/tablet persistent top ribbon with **hover dropdowns** per topic (2–3 active stories + "All X →"); mobile ≤640 fixed bottom nav (Edition / Sections / Reader / Saved) where Sections opens a **full-screen drawer** (`<details>`-based, no JS).
5. **Responsive breakpoints**: **≥1024px** 12-col grid / lead+rail; **641–1023px** single-column, 42rem, ribbon scrolls, topics 2-col; **≤640px** single column, topics 1-col, bottom nav replaces ribbon.
Reference implementation: `prototype/` (index.html, article.html, assets/kontra.css).
## Media (implementation note)
- Images are **git files beside their article**: `content/subjects/<s>/<slug>/<file>`.
Reference via `{{media:<slug>/<file>}}` (front-matter `image:` MUST be quoted —
`image: "{{media:slug/file.jpg}}"`). The app serves `/media/<path>` by searching
article folders (safe-path guarded). No S3/object store (Garage dropped 2026-09-10).
- Hero image: grayscale plate per §Hero plate; leave `image: ""` for text-only pieces.
## Token wiring (for the theme)
- Implement as CSS custom properties on `:root` (the design-token layer).
- Subject accent overrides: each subject sets `--accent`-derived token(s) via a data attribute /
config (per plan: `subjects/<x>/_subject.yaml` → design tokens, admin-editable values, not code).
---
*Source: Stitch panel "The Gazette — Tides of the Outer Reach" (design.png), export Image 2.html, Image 3.markdown.*