# stillPUB brand identity

This revision uses a corrected lowercase ribbon **s**, a saturated signal-orange palette, and explicit light/dark wordmarks. The artwork is original and avoids letter tiles, Office-app silhouettes, Fluent geometry, and competitor brand colors. It intentionally replaces the rejected golden-umber kit and the older emerald UI ramp; no file outside this directory has been edited.

## Mark decision

The retained concept is now a genuine **continuous ribbon s** rather than the prior squared galley that read as `2`. The path starts at the upper-right terminal, travels left around the top bowl, crosses through the waist toward the right, wraps the bottom bowl, and finishes at the lower-left terminal. That gives the defining lowercase-s apertures: the **top bowl opens right** and the **bottom bowl opens left**. Its centerline stays between x=12–52 and y=8–56; the 10-unit protective stroke makes the exact stroke-inclusive bounds x=7–57 and y=3–61, centered at (32,32) in the 64-unit viewBox. At 16px those bounds scale to x=1.75–14.25 and y=0.75–15.25, still centered at (8,8), with the same opposing openings clearly present.

## Chosen palette

**Signal orange** was selected because its high chroma and pale, clean fills feel current rather than earthy, while orange occupies clear space away from Publisher teal, Word/Affinity blue, Excel green, Canva teal-purple, and Adobe red. The accessible primary is necessarily deeper than the decorative border and dark-mode accent, but it remains a saturated orange rather than brown or ochre.

| Role | Hex | Verified use |
|---|---|---|
| Dark / hover / light-theme text | `#711F00` | **11.06:1 on white** |
| Primary | `#AC3900` | **white text is 6.29:1** |
| Border | `#D85A17` | **3.89:1 on white**, passing the 3:1 non-text UI threshold |
| Light fill | `#FFE0D2` | selected controls |
| Subtle fill | `#FFF3ED` | quiet hover surfaces |
| Dark-theme accent | `#FF8A4C` | **6.34:1 on `#24282E`** |
| On accent | `#FFFFFF` | text and simple icon strokes on primary |

All ratios were computed from the exact sRGB hex values above using the WCAG relative-luminance formula. `palette-options.svg` also shows three viable alternatives. Their checked ratios are:

| Ramp | Dark | Primary | Border | Light fill | Dark accent | White/primary | Dark/white | Accent/`#24282E` |
|---|---|---|---|---|---|---:|---:|---:|
| Signal orange — selected | `#711F00` | `#AC3900` | `#D85A17` | `#FFE0D2` | `#FF8A4C` | 6.29:1 | 11.06:1 | 6.34:1 |
| Electric rose | `#720032` | `#A91555` | `#D33E78` | `#FBD9E8` | `#FF75AD` | 7.18:1 | 11.92:1 | 5.92:1 |
| Cool graphite | `#242A33` | `#414B59` | `#718094` | `#E2E8F0` | `#B8C5D5` | 8.84:1 | 14.44:1 | 8.45:1 |
| Laser lime | `#245000` | `#3F7300` | `#609B16` | `#E1F5C8` | `#9BEA4D` | 5.73:1 | 9.45:1 | 10.06:1 |

## Mark and wordmark: Carlito-Bold outlines (round 3, 2026-08-15)

Rounds 1-2 hand-drew the s and both were rejected (read as a 2, then as a
wobbly cut-off stroke). Round 3 stops drawing letterforms: the mark and the
wordmark are the actual 's' / 'stillPUB' glyph outlines extracted from the
bundled Carlito-Bold (OFL - outlines of rendered text are free to use; the
build script lives in the project scratchpad and any session can regenerate
with fontTools). Identity comes from the color, the tile, and the keyline,
not from a novelty letterform.

- `mark.svg` - primary-orange s with a white keyline ring so it survives
  dark or unknown surfaces.
- `favicon.svg` - white s on a deep-umber (#711F00) circle; self-contained
  on any tab chrome.
- `icon-maskable.svg` - white s on a primary tile, inside the maskable safe
  zone (regenerate the 192/512 PNGs from it after any change).
- `wordmark.svg` - mark + "stillPUB" in Carlito Bold; embedded
  prefers-color-scheme styles swap to the dark accent (#FF8A4C) on dark.
- `wordmark-dark.svg` - static dark-surface version for app-controlled
  themes and renderers that ignore SVG media queries. Never on white.
- `wordmark-mask.svg` - black silhouette of the word (aspect 3.612:1,
  retaining the original Carlito baseline and descender space) for CSS mask
  usage; the app's title bar renders it filled with --titlebar-brand so the
  ink follows the theme.

## Regenerating the PNG icons

`icon-192.png` and `icon-512.png` (in `app/public/`, referenced by
`app/public/manifest.webmanifest`) are rasterized from `icon-maskable.svg` in
this directory. They used to be produced by throwaway scratchpad Playwright
scripts that no longer exist, so there was no way to regenerate them if the
mark changed. That is fixed: `scripts/build-brand-icons.mjs` at the repo root
does this now and is checked in.

There is no root-level `package.json` in this repo (only `app/package.json`
and `cli/package.json`), so this command is documented here instead of as an
npm script:

```sh
node scripts/build-brand-icons.mjs
```

Run it from the repo root with `app/` dependencies installed (it resolves
Playwright from `app/node_modules`, same as `scripts/capture-marketing-shots.mjs`).
It overwrites `app/public/icon-192.png` and `app/public/icon-512.png` in
place and is idempotent: with an unchanged `icon-maskable.svg` it reproduces
byte-identical output.

`site/assets/og.png` is a different thing and is out of scope for this
script: it is a screenshot composite of the live running app plus a text/CTA
overlay, not a rasterization of a brand-kit SVG. Its own pipeline is
`scripts/capture-marketing-shots.mjs`.

## UI token remap — guidance only

To adopt this palette, Matt would change the light values in `app/src/editor/ui/ribbon/tokens.css` as follows. This kit does **not** edit that file.

```css
--pub-accent-700: #711f00; /* hover / pressed */
--pub-accent-600: #ac3900; /* primary background */
--pub-accent-500: #d85a17; /* active border */
--pub-accent-100: #ffe0d2; /* selected control fill */
--pub-accent-050: #fff3ed; /* subtle hover fill */
--accent-text: #711f00;
--on-accent: #ffffff;
```

Map the light title-bar background to `#AC3900` and hover to `#711F00`. In **both duplicated dark-theme blocks**, map active borders, `--accent-text`, and `--titlebar-brand` to `#FF8A4C`; use `#47291F` and `#302824` for the two dark accent fills. Keep `--on-accent: #FFFFFF`. Variable renaming is optional; replacing the values is sufficient.

## Wiring

```html
<link rel="icon" href="/brand/favicon.svg" type="image/svg+xml" sizes="any">
<link rel="manifest" href="/manifest.webmanifest">

<img src="/brand/wordmark.svg" alt="stillPUB" width="420" height="96">
<img src="/brand/wordmark-dark.svg" alt="stillPUB" width="420" height="96">
<img src="/brand/mark.svg" alt="" width="64" height="64">
```

Add the following entries to the existing manifest's `icons` array:

```json
{
  "icons": [
    { "src": "/brand/mark.svg", "sizes": "any", "type": "image/svg+xml", "purpose": "any" },
    { "src": "/brand/icon-maskable.svg", "sizes": "any", "type": "image/svg+xml", "purpose": "maskable" }
  ]
}
```

## Files

- `/Users/matthew/parallax-private/Projects/pubworks/app/public/brand/wordmark.svg`
- `/Users/matthew/parallax-private/Projects/pubworks/app/public/brand/wordmark-dark.svg`
- `/Users/matthew/parallax-private/Projects/pubworks/app/public/brand/mark.svg`
- `/Users/matthew/parallax-private/Projects/pubworks/app/public/brand/favicon.svg`
- `/Users/matthew/parallax-private/Projects/pubworks/app/public/brand/icon-maskable.svg`
- `/Users/matthew/parallax-private/Projects/pubworks/app/public/brand/palette-options.svg`
- `/Users/matthew/parallax-private/Projects/pubworks/app/public/brand/README.md`
