DESIGN.md@.claude/skills/worca-changelog · git:20261007.b1bf578 · 2026-10-07 · sha256 1e0e4224e5e43c05

DESIGN.md@.claude/skills/worca-changelog git:20261007.b1bf578A

Immutable. This exact content never changes and is served at /api/v1/blob/1e0e4224e5e43c05.

# Ship-log design reference

The changelog page is the "Worca — 3-Day Ship Log" design: a warm off-white
canvas, big rounded white cards, one accent ribbon, screenshots in browser
frames, and a small animated demo beside every feature. It reads like a
product launch page, not a release note. Everything here is already encoded
in `template.html`; this document says what each part is for so the copy
and the demos land in the right shape.

## Principles

1. **One capability per section.** A section has one headline, one
   screenshot, one demo. If a theme needs two headlines it is two sections.
2. **Show the mechanism, not the menu.** The demo animates the thing the
   feature *does* — a flag appearing, a value being masked, a precedence
   resolving — in a 2–3 second loop. It is never a second screenshot.
3. **Obvious headlines, problem-first subs.** The h2 names the feature so
   plainly a first-time user knows what it is (*New to Worca? Follow the
   checklist.*); the sub opens with the reader's problem in bold, then
   *Now …* and what Worca does about it.
4. **Plain chips, few of them.** Only facts a reader understands at a
   glance and actually cares about, numbers in `<b>`. No internal names.
5. **Motion is progressive.** Content reveals on scroll, ribbons drift with
   scroll position, demos loop on timers. With `prefers-reduced-motion`
   everything is visible immediately in its final state — the page must be
   complete with no motion at all.
6. **Real pixels.** Screenshots come from a seeded, sandboxed Worca — never
   mocked-up UI, never a private catalog.
7. **One file.** Logo and screenshots are inlined as data URIs; the page has
   no external requests and survives being saved, mailed, or published.

## Tokens

Defined on `:root` in the template. Do not add colours; pick from these.

| Token | Value | Use |
| --- | --- | --- |
| `--bg` | `#ECEAE4` | page canvas |
| `--card` / `--card-2` | `#FFFFFF` / `#F6F4EF` | section cards / demo cards, shot toolbar |
| `--ink` / `--ink-2` / `--ink-3` | `#14151A` / `#56534C` / `#8B8780` | text / secondary / labels |
| `--line` | `#E2DFD7` | every border |
| `--ocean` / `--ocean-deep` | `#4B5ED2` / `#3A49AC` | accent: hero ribbon, kicker dot, rail, focus |
| `--wash` / `--wash-2` | `#DDE3F7` / `#EBEEFA` | hero gradient |
| `--coral` / `--coral-soft` | `#EEA47D` / `#F8E3D5` | receipts ribbon |
| `--lime` / `--lime-2` | `#DEEFC4` / `#EDF6DC` | positive notes |
| `--ok` / `--warn` / `--bad` / `--info` | `#38854F` / `#DFA23F` / `#C9524A` / `#5B94C8` | kicker dots by area, pills |
| `--r-lg` / `--r-md` / `--r-sm` | 28 / 18 / 12 px | section / demo & shot / rows |
| `--shadow` | `0 18px 50px -22px rgba(20,21,26,.28)` | shots, winning rows, float chips |

Type: system sans (`--sans`), 16px/1.5 body; `--mono` for anything that is
a value — dates, ids, env keys, counts in chips. Headlines are weight 800,
tracking −0.035em, `text-wrap:balance`. `h1` clamps 44–92px, `h2` 34–58px.

**Kicker dot colour by area** (keep the mapping stable across entries so
readers learn it):

| Area | Dot |
| --- | --- |
| New view / composer / UI | `--ocean` (default) |
| Routing, models, connectivity | `--info` |
| Budget, cost, limits | `--warn` |
| Team, plugins, sharing-in | `--bad` |
| Sharing-out, export, docs | `--ok` |
| Receipts | `--coral` |

## Page anatomy

```
.wrap (max 1280)
├── .top            brand logo · mono chip "changelog · v1.1.1 → v1.2.0"
├── section.sec.hero #s0
│   ├── svg.ribbon  ocean band, mono uppercase feature names on a textPath
│   ├── .sec-head   kicker · h1 (2 lines) · sub · chips (first one .acc)
│   └── .shot       hero screenshot, rotated 1.6°, two .float-chip "NEW · X"
├── section.sec #s1 … #sN-1      one per feature
│   ├── .sec-head   kicker(dot) · h2 · sub · chips
│   └── .grid2[.flip]   .demo + .shot   (or .demo + .demo when there is no UI)
├── section.sec.polish #sN       receipts
│   ├── svg.p-ribbon  coral band "TESTS · NUMBERS · PROOF"
│   ├── .sec-head   kicker(coral) · h2 "Shipped, tested, verified live."
│   └── .bubs       six .bub — a circle (number or cropped image) + two lines
├── .foot           "WORCA · changelog · <range>"  ·  mono date
└── nav.rail        fixed dots, one per section, built from the ids
```

Alternate `.grid2` and `.grid2.flip` from section to section so the
screenshot swaps sides; the eye keeps moving.

## Components

- **`.ribbon`** (hero) — the band sits *behind* everything in the hero:
  ribbon `z-index:1`, shot wrapper `2`, `.sec-head` `4`. `.hero-grid` takes
  no `z-index`: a stacking context there would lift the ribbon over the
  headline, sub and chips. The path runs low under the text column and only
  climbs behind the screenshot; keep it that way when editing it, and check
  the hero at 1440, 1100 and 960 px wide (it hides below 920).

- **`.kicker`** — pill with a dot. Text is 1–2 words, uppercase by CSS.
- **`.chip`** — pill fact. `.chip.acc` is the dark one; only the hero's first
  chip uses it. `<b>` inside a chip is mono and dark — for numbers.
- **`.shot`** — browser frame: three-dot toolbar + `.crop` + `<img>`. Zoom
  with inline styles on the img (`width:130%;max-width:none;margin:-6% 0 0 -18%`)
  and `max-height` on `.crop`. Always follow with `.shot-cap`.
- **`.float-chip`** — absolutely-positioned callout on the hero shot:
  `<small>New</small><span>Feature</span>`. Two per hero, no more.
- **`.demo`** — card-2 background, `.dlabel` uppercase label first, then the
  animation. Ends with `.env-note` when a one-line takeaway helps.
- **`.rv`** — reveal-on-scroll. Put it on `.sec-head`, each `.grid2` child,
  each `.bub`. `.d1`/`.d2` stagger siblings by 80ms steps.
- **`.bub`** — receipts item. `.im` is an 86px circle holding either
  `<span class="big">2,273</span>` or a cropped `<img>` (`width:300%` and a
  negative `left`/`top` to aim at the interesting part).

## Demo recipes

Every demo is markup + a class toggle on a `setInterval`. The template ships
these six; reuse before inventing:

| Recipe | Shows | Mechanism |
| --- | --- | --- |
| **Precedence** (`.cat-demo`) | layers resolving to one winner | rows with `.win` / `.dim`; static, no loop needed |
| **Mask / reveal** (`.env-demo`) | a secret shown only on demand | toggle `.reveal` every 2.6s, button text flips |
| **Meter + flag** (`.meter-run`, `.cost-banner`, `.cap-steps`) | a run crossing a threshold | 4-phase loop: fill width, pill text, banner `.show`, numbered steps `.on` |
| **Grouped picker** (`.dd-demo`) | grouping + a collision suffix | toggle `.collide` to fade `.sfx` in |
| **Review rows** (`.con-demo`) | red-flagged changes + a green guarantee | static `.red-chip` rows + `.con-note` |
| **Policy flip** (`.pol-demo`) | a heuristic changing a default | toggle `.flip` on one `.prow`; the `.warn-note` sibling fades in |

Inventing a new one: keep it to one toggled class, one interval of 2–3s,
≤ 20 lines of CSS, and add its final state to the reduced-motion block in
the script (`if (reduced) { … add the class …; return; }`).

## Voice

- **Headlines** are obvious before they are clever: a reader must know
  what the feature is from the headline alone — *New to Worca? Follow the
  checklist.* *Team metrics & spend dashboard.* — never a riddle the sub
  has to decode. ≤ 7 words, ending in a period.
- **Subs** state the problem first, then the answer. Line 1 is one plain
  question or pain the reader recognises, in bold (`<b>…</b><br>`): *Ever
  wondered which workflow to pick for a task?* Line 2 begins *Now …* and
  says what Worca does and how, in words a first-time user understands:
  *Now Worca can pick one for you. Start a run on Auto: …* Never "we've
  added", "now supports", "improved"; no internal terms.
- **Chips** are plain phrases anyone understands at a glance, and only
  the ones that matter: `highlights the real button`, `stored in your git
  remote`, `<b>8</b> steps, in order`. Two to four per section. No tool
  names, flags, schema versions, internal terms, or shorthand that needs
  decoding (`Esc · scrim · Skip`, `ticks derived, never stored` are the
  kind to cut). A chip can carry one glyph (`⚠cost`) when the product
  shows it that way. Demo labels, steps and notes follow the same rule.
- **Captions** (`.shot-cap`) tell the reader where they are looking: *The
  editor: efforts, label, and the full routing env per model.*
- **Receipts** are two lines: a bold claim (`Tests green`) and the number
  behind it (`8 new suites · +1,703 test lines`). Middle dots separate
  facts, never commas.
- Use `·` between facts, `—` for an aside inside a sub, `→` only inside
  mono text. No exclamation marks anywhere on the page.

## Screenshots

- 1440 × 900, light theme, seeded demo data per `docs/screenshots.md`.
- Hero: the one view that carries the release. Sections: the surface the
  feature lives on, zoomed so the feature is the largest thing in frame.
- JPEG at quality ~82 for full views; PNG only for crops that are mostly
  text and under 150 KB.
- Alt text names the view and the state: *Model editor — routing env with
  masked values, copy and reveal.*

## Index

`docs/changelog/entries.json` holds one record per entry, newest first:

```json
[
  { "version": "1.6.0", "since": "1.5.0", "date": "2026-09-27", "artifact": "https://claude.ai/artifact/…" }
]
```

`docs-site/build.mjs` builds the list at docs.worca.dev/changelog/ from it,
taking each release's summary from the hero's `.sub` and its headlines from
the `<h2>` of every `<section class="sec">` (the hero and the `polish`
receipts are left out). So the hero sub must read on its own, and every
feature section keeps the `class="sec"` + `id="sN"` shape of `template.html`.
The build fails on a page without a record, a record without a page, or a
missing image.