Merge main into fix/plugin-path-structure

Brings in the jet-black + atomic-tangerine palette repaint
(ba3062c), the consultant-special 2×2 variant, the Jobs-minimal
axis simplification (e13c993), the type-quadrant.md rule
codification (4feb760), and the Codex plugin wrapper from
PR #3 (7326c4e).

Conflict resolutions:

- skills/diagram-design/SKILL.md (add/add): keep the full 400-line
  SKILL.md from this PR. PR #3's 13-line Codex wrapper becomes
  unnecessary — with the real SKILL.md at skills/diagram-design/,
  the Codex plugin's "skills": "./skills/" finds the full file
  directly, no redirect needed.

- README.md (content): keep the new skills/diagram-design/... link
  targets from this PR, combined with the "14 diagrams" count and
  #eb6c36 accent from the repaint work on main.

- example-quadrant-consultant.html: moved to the new
  skills/diagram-design/assets/ location with its Jobs-minimal
  axis labels intact.

Also fixed the clone-install instructions to match the new
layout: clone the repo, then symlink the inner skills/diagram-design/
directory into ~/.claude/skills/diagram-design. The old instructions
(clone the repo root directly into the skills dir) would break with
this structure.
This commit is contained in:
Cathryn Lavery
2026-04-22 11:51:20 -05:00
67 changed files with 2640 additions and 2359 deletions
@@ -30,7 +30,7 @@ future diagrams use your tokens
Ask the skill:
> *"Onboard diagram-design to my site — `https://example.com`"*
> *"Onboard Schematic to my site — `https://example.com`"*
Or run it with an explicit URL and the skill reads this file and executes the steps below.
@@ -68,7 +68,7 @@ Read the rendered `font-family` stack of:
- `<body>` → `node-name` family
- `<code>`, `<pre>`, or any mono-styled element → `sublabel` family
If the site has only one family, keep the diagram-design defaults for the missing roles (Instrument Serif for title, Geist Mono for mono). Don't force-pick a mono font that isn't on the site.
If the site has only one family, keep the schematic defaults for the missing roles (Instrument Serif for title, Geist Mono for mono). Don't force-pick a mono font that isn't on the site.
---
@@ -92,7 +92,7 @@ Before writing, validate:
- **AA contrast**: `ink` on `paper` ≥ 4.5:1. `muted` on `paper` ≥ 4.5:1 for body text.
- **Accent is the most saturated color**: not muted-ish, not near-grey.
- **paper ≠ pure white**: if the site uses `#ffffff`, fall back to `#fafaf7` to preserve diagram-design's warm-neutral feel — or ask the user to confirm pure-white is intentional.
- **paper ≠ pure white**: if the site uses `#ffffff`, fall back to `#fafaf7` to preserve Schematic's warm-neutral feel — or ask the user to confirm pure-white is intentional.
If any check fails, propose an adjusted value and explain why.
@@ -127,8 +127,8 @@ After onboarding, the user should:
## When onboarding fails
- **Site uses webfonts you can't replicate** (custom-hosted, paid): keep the diagram-design defaults for typography and skin only the colors.
- **Brand has 6+ colors** and you can't identify a clear hierarchy: pick one as `accent`, demote the rest to `muted` variants or ignore them. The diagram grammar only uses 5–7 roles.
- **Site uses webfonts you can't replicate** (custom-hosted, paid): keep the schematic defaults for typography and skin only the colors.
- **Brand has 6+ colors** and you can't identify a clear hierarchy: pick one as `accent`, demote the rest to `muted` variants or ignore them. The schematic grammar only uses 5–7 roles.
- **Site is dark-mode first**: flip the inversion — treat their dark paper as the default `paper`, and generate a light variant via inversion.
- **Homepage is all imagery, no text**: ask for a blog or docs URL instead — text-heavy pages expose the type hierarchy.
@@ -136,4 +136,4 @@ After onboarding, the user should:
## Future: per-project skins
If the user wants multiple skins (one per project), duplicate `style-guide.md` as `style-guides/<project>.md` and add a header comment pointing the build to the active one. That's a v1.1 feature — for now, one skin per skill install.
If the user wants multiple skins (one per project), duplicate `style-guide.md` as `style-guides/<project>.md` and add a header comment pointing the build to the active one. That's a v5.2 feature — for now, one skin per skill install.
@@ -6,13 +6,13 @@ Use for editorial asides — the "italic pointer" that marks a detail without co
```svg
<!-- 1. Italic Instrument Serif text -->
<text x="904" y="36" fill="#0b0d0b" font-size="14" font-style="italic"
<text x="904" y="36" fill="#2d3142" font-size="14" font-style="italic"
font-family="'Instrument Serif', serif" text-anchor="end">no imports, no configuration</text>
<!-- 2. Dashed Bézier leader -->
<path d="M 820 44 Q 700 84 520 216" fill="none"
stroke="rgba(11,13,11,0.40)" stroke-width="1" stroke-dasharray="4,3"/>
stroke="rgba(45,49,66,0.40)" stroke-width="1" stroke-dasharray="4,3"/>
<!-- 3. Landing dot -->
<circle cx="520" cy="216" r="2" fill="#0b0d0b"/>
<circle cx="520" cy="216" r="2" fill="#2d3142"/>
```
## Rules
@@ -25,9 +25,9 @@ Use for editorial asides — the "italic pointer" that marks a detail without co
| Intent | Text | Leader |
|---|---|---|
| Neutral aside | ink `#0b0d0b` | `rgba(11,13,11,0.40)` |
| Focal / accent | coral `#f7591f` | `rgba(247,89,31,0.50)` |
| Tertiary (muted) | muted `#52534e` | `rgba(11,13,11,0.30)` |
| Neutral aside | ink `#2d3142` | `rgba(45,49,66,0.40)` |
| Focal / accent | coral `#eb6c36` | `rgba(235,108,54,0.50)` |
| Tertiary (muted) | muted `#4f5d75` | `rgba(45,49,66,0.30)` |
## Anti-patterns
- Solid arrow leader (reads as a flow arrow).
+17 -14
View File
@@ -1,8 +1,8 @@
# Style Guide
**The single source of truth for colors, typography, and tokens.** Every diagram draws from this — not from hex values inlined in other reference files. If you want to change the visual skin of diagram-design, change this file.
**The single source of truth for colors, typography, and tokens.** Every diagram draws from this — not from hex values inlined in other reference files. If you want to change the visual skin of Schematic, change this file.
Default skin is a neutral editorial palette — warm stone paper, deep charcoal ink, rust accent. It's designed to look good out of the box for any open-source user without matching any specific brand. Swap these values (or run [`onboarding.md`](onboarding.md)) and every new diagram inherits the new skin without touching any type-specific logic.
Default skin is a cool editorial palette — white-smoke paper, jet-black ink, atomic-tangerine accent, blue-slate muted. It's designed to look good out of the box; swap these values (or run [`onboarding.md`](onboarding.md)) and every new diagram inherits the new skin without touching any type-specific logic.
To generate your own from a website URL, see [`onboarding.md`](onboarding.md).
@@ -16,18 +16,20 @@ Every token is referred to by **semantic role**, not by its hex value. Type refe
| Role | Purpose | Default (light) | Default (dark) |
|---|---|---|---|
| `paper` | Page background, default node fill | `#faf7f2` | `#1c1917` |
| `paper-2` | Diagram container bg, secondary fill | `#f2ede4` | `#292524` |
| `ink` | Primary text, primary stroke | `#1c1917` | `#faf7f2` |
| `muted` | Secondary text, default arrow stroke | `#57534e` | `#a8a29e` |
| `soft` | Sublabels, boundary labels | `#78716c` | `#8e8680` |
| `rule` | Hairline borders | `rgba(28,25,23,0.12)` | `rgba(250,247,242,0.12)` |
| `rule-solid` | Stronger borders, baselines | `rgba(120,113,108,0.25)` | `rgba(168,162,158,0.25)` |
| `accent` | Focal / 1–2 max per diagram | `#b5523a` | `#d6724a` |
| `accent-tint` | Fill for accent-bordered boxes | `rgba(181,82,58,0.08)` | `rgba(214,114,74,0.10)` |
| `link` | HTTP/API calls, external arrows | `#2563eb` | `#60a5fa` |
| `paper` | Page background, default node fill | `#f5f5f5` (white-smoke) | `#2d3142` (jet-black) |
| `paper-2` | Diagram container bg, secondary fill | `#ececec` | `#393e53` |
| `ink` | Primary text, primary stroke | `#2d3142` (jet-black) | `#f5f5f5` (white-smoke) |
| `muted` | Secondary text, default arrow stroke | `#4f5d75` (blue-slate) | `#bfc0c0` (silver) |
| `soft` | Sublabels, boundary labels | `#7a8399` | `#8e98ac` |
| `rule` | Hairline borders | `rgba(45,49,66,0.12)` | `rgba(245,245,245,0.12)` |
| `rule-solid` | Stronger borders, baselines | `#bfc0c0` (silver) | `rgba(191,192,192,0.25)` |
| `accent` | Focal / 1–2 max per diagram | `#eb6c36` (atomic-tangerine) | `#f08a59` |
| `accent-tint` | Fill for accent-bordered boxes | `rgba(235,108,54,0.08)` | `rgba(240,138,89,0.10)` |
| `link` | HTTP/API calls, external arrows | `#2e5aa8` | `#6a95d8` |
> **Note:** The pre-baked example HTML files in `assets/` were built under an earlier skin. Regenerating them against the current `style-guide.md` is a v1.1 task. New diagrams the skill produces will use the tokens above.
> **Brand palette source:** this skin maps to a five-color brand palette — `jet-black #2d3142`, `silver #bfc0c0`, `white-smoke #f5f5f5`, `atomic-tangerine #eb6c36`, `blue-slate #4f5d75`. The `soft`, `rule`, and `link` tokens are derived (lighter slate, ink-at-opacity, and a saturated variant in the blue-slate hue family) to cover roles the brand palette doesn't name directly.
> **Note:** The pre-baked example HTML files in `assets/` were built under an earlier skin. Regenerating them against the current `style-guide.md` is a v5.1 task. New diagrams the skill produces will use the tokens above.
### Inversion rule (light → dark)
@@ -101,4 +103,5 @@ Three options:
- **No rainbow palette**: if your brand ships 8 colors, pick 3 (paper, ink, accent). The rest become `muted` variants.
- **Serif + sans + mono**: three families, not more. If brand typography is all sans, keep Instrument Serif for `title` and `callout` anyway — the contrast is load-bearing.
- **Paper is warm-neutral, not pure white**: pure white turns the design sterile. Pick a cream, bone, or light grey with a hint of warmth.
- **Dot pattern survives**: the 22×22 dot pattern on the diagram background needs to sit at ~10% opacity of `ink` on `paper` — verify it's visible but quiet after a skin change.
- **Dot pattern is optional, not default**: the 22×22 dot pattern is an opt-in "dotted paper" variant (good for long-form editorial hero diagrams). The default background is a clean `paper` fill, no pattern. When the pattern is enabled, it should sit at ~10% opacity of `ink` on `paper` — visible but quiet.
- **Container is clean by default**: the diagram sits directly on the page paper, no secondary container background or border. A framed variant (`paper-2` bg + `rule` border + 8px radius + padding) is available as an opt-in for card-heavy layouts, but don't reach for it by default — the extra chrome fights the figure.
@@ -9,7 +9,7 @@
1. **Index tag** on the far left (`L3`, `07`, `APPLICATION`) — Geist Mono 8–9px eyebrow.
2. **Layer name** slightly right of center-left — Geist 14–16px 600.
3. **Sublabel / note** on the far right — Geist Mono 9–10px muted.
- Border between layers: 1px hairline `rgba(11,13,11,0.12)`. Outer silhouette 1px ink or muted.
- Border between layers: 1px hairline `rgba(45,49,66,0.12)`. Outer silhouette 1px ink or muted.
- Fills: either alternating subtle shades (paper / paper-2) OR all paper with hairline dividers. Pick one and hold it.
- Direction indicator on the LEFT margin (outside the stack): small up/down arrow + Geist Mono label (`abstraction ↑`, `packets ↓`).
- Coral on **one** focal layer (stroke + subtle tint fill) — the bottleneck, the pay-rent layer, the one under discussion.
@@ -4,7 +4,8 @@
## Layout conventions
- 2×2 grid. Axis lines: 1px ink cross through the center.
- Axis labels at the *ends* of each axis (e.g., `HIGH IMPACT →` on the right, `LOW IMPACT ←` on the left — Geist Mono eyebrow). Never label at the midpoint.
- **Axis labels: Jobs-minimal.** One single word at each arrow tip — no glyphs baked into the label (no `↑` / `→` / `←` / `↓`), no parentheticals, no "HIGH / LOW" modifiers. Geist Mono 9px regular weight, tracked 0.18em, uppercase. Flank the arrow tips — never sit labels on top of the axis line. Shorten the arrow enough (~60–80px inside the viewBox edge) to leave breathing room for the labels beyond the tips.
- Never label at the midpoint.
- Items: small labeled dots (`r=4`) positioned in the quadrants. Labels 8–10px away; don't let labels cross axis lines.
- Coral on the "do first" item (typically top-right).
- Limit to ~12 items; cluster or split beyond that.
@@ -18,3 +19,63 @@
- `assets/example-quadrant.html` — minimal light
- `assets/example-quadrant-dark.html` — minimal dark
- `assets/example-quadrant-full.html` — full editorial
- `assets/example-quadrant-consultant.html` — consultant special (see below)
---
## Consultant special (2×2 scenario matrix)
A **layout variant** of the standard quadrant — same house skin (warm paper, dot pattern, Instrument Serif title, Geist mono eyebrows, coral focal rule). The grammar shifts: axes hold a **range** rather than a measurement; cells hold **named scenarios** rather than positioned items.
**Use when:** you're framing four futures, archetypes, or strategic options across two independent drivers — classic scenario planning, positioning frames, or 2×2 strategy decks (BCG/McKinsey territory). The reader should come away with four named bets, not a point cloud.
**Do not use** for prioritization, density maps, or anything where the *position inside* a cell carries meaning — that's the standard quadrant above.
### What makes it the consultant variant
| Move | Standard quadrant | Consultant special |
|---|---|---|
| Axis arrows | single-ended | **double-ended** — both axes have `marker-start` + `marker-end` |
| Cell content | small dots with labels | **named scenario + 1–3 line description** |
| Quadrant corner | short tag (e.g. DO FIRST) | **numbered tag + axis combination** (`01 · DIMENSION-A / DIMENSION-B`) |
| Focal accent | coral on one *item* | coral on one *quadrant* — tinted bg + coral stroke + coral corner tag |
| Axes | 1px muted ink | **1.2px ink** (slightly heavier — the axes carry more of the figure) |
Both variants use the same Jobs-minimal axis labels: one word at each arrow tip, no glyphs, no parentheticals. The only axis difference is that the consultant variant uses double-ended arrows instead of single-ended.
Everything else — paper, dot pattern, typography, legend strip, 4px grid, complexity budget — is the house default. Don't invent new colors or fonts for this variant.
### Style tokens (in-house)
- **Paper / bg / pattern**: defaults from `style-guide.md` (`paper`, 22×22 dot pattern at 10% ink).
- **Axis lines**: `ink` (`#2d3142`), `stroke-width: 1.2`, `marker-start` + `marker-end` both pointing outward.
- **Focal quadrant tint**: `rgba(235,108,54,0.04)` full rect behind the focal cell.
- **Focal cell**: `accent-tint` fill, `accent` stroke at 1.2px. Corner tag in `accent`, weight 600.
- **Non-focal cells**: `store` treatment (`ink @ 0.04` fill, `muted @ 0.28` stroke).
- **Cell title**: Geist sans, 16px, weight 600, `ink`.
- **Cell description**: Geist sans, 11px, `muted`, 1–3 lines, left-aligned inside the cell.
- **Corner tag**: Geist Mono, 8px, uppercase, tracked `0.18em`, `muted` (or `accent` on focal). Format: `NN · DIMENSION-A / DIMENSION-B` — the two axis-dimension words must match the axis labels exactly.
- **Axis labels**: Geist Mono 9px **regular weight** (not bold), tracked `0.18em`, uppercase, `ink`. **One word per tip.** No arrow glyphs in the label, no `HIGH / LOW` parentheticals, no multi-line sublabels. The word itself *is* the label. Position labels *beyond* the arrow tips (not on the axis line):
- Top tip: `text-anchor="middle"`, ~12px above the arrow tip
- Bottom tip: `text-anchor="middle"`, ~20px below the arrow tip
- Left tip: `text-anchor="end"`, ~12px left of the arrow tip, `dominant-baseline="middle"`
- Right tip: `text-anchor="start"`, ~12px right of the arrow tip, `dominant-baseline="middle"`
### Layout conventions
- Four cells, equal size (240×160 or 280×180 are good defaults), arranged with a 40–60px gap from the axis cross.
- Axis cross passes *between* the cells, not through them.
- Arrow tips live ~20–40px outside the outermost cell edge; single-word axis labels sit ~12px beyond each tip (see Axis labels above).
- Exactly one focal cell. Picking none makes it a placeholder template; picking two erases the signal.
- Keep the legend strip + horizontal rule at the bottom — same as the standard quadrant. Legend swatches should show both "headline bet" (coral) and "candidate future" (neutral).
### Anti-patterns (variant-specific)
- Plain white background — the warm paper + dot pattern is load-bearing across the skill; dropping it to "look consultant" turns the diagram generic.
- Sans-serif H1 — keep Instrument Serif for the page title. The title/diagram contrast is the house signature.
- Unnamed cells ("Scenario 1/2/3/4") in a shipped diagram — OK as a blank template; not OK as a finished artifact.
- Coral on more than one cell — same focal rule as everywhere else in the skill.
- 3×3 or 2×3 grids — those are different diagrams, not this variant.
- Positioning dots *inside* the cells — if position matters, use the standard quadrant.
- Bolded axis labels, arrow glyphs in the text (`↑ DRIVER`), or "HIGH / LOW" parentheticals — all forbidden. Jobs-minimal is non-negotiable on this variant.
- Corner tags that disagree with the axis labels (e.g. axis says `REMOTE / IN-PERSON` but the tag reads `HIGH REMOTE / LOW AI`). Reader parses this as a bug in three seconds.
@@ -20,13 +20,13 @@
## Lifeline primitive
```svg
<line x1="CX" y1="TOP" x2="CX" y2="BOTTOM"
stroke="rgba(11,13,11,0.20)" stroke-width="1" stroke-dasharray="3,3"/>
stroke="rgba(45,49,66,0.20)" stroke-width="1" stroke-dasharray="3,3"/>
```
## Activation bar primitive
```svg
<rect x="CX-4" y="TOP" width="8" height="H"
fill="rgba(11,13,11,0.06)" stroke="#52534e" stroke-width="0.8"/>
fill="rgba(45,49,66,0.06)" stroke="#4f5d75" stroke-width="0.8"/>
```
## Examples
@@ -5,11 +5,11 @@
## Layout conventions
- **Prefer 2 or 3 circles.** Avoid 4+ (unreadable — use a matrix instead).
- Circle stroke: 1px hairline, color per-set (ink, muted, soft).
- Circle fill: very low-opacity tint — `rgba(11,13,11,0.04)` for ink set, `rgba(82,83,78,0.05)` for muted. Tints compound naturally in overlap regions.
- Circle fill: very low-opacity tint — `rgba(45,49,66,0.04)` for ink set, `rgba(79,93,117,0.05)` for muted. Tints compound naturally in overlap regions.
- Radii: equal when sets are comparable in size; proportional when sets are meaningfully different. Don't fake equal sizes for aesthetics.
- **Set labels** placed outside the circle, NEVER crossing the stroke. Geist 12–14px 600 for the set name, optional Geist Mono 9px sublabel.
- **Intersection labels** placed inside the overlap region, Geist 12px 600, centered. For small overlaps, use a leader line to a label in clear space.
- **Coral accent** on the ONE focal intersection — the "sweet spot". Either coral label stroke OR clipPath-bounded coral fill tint (`rgba(247,89,31,0.10)`).
- **Coral accent** on the ONE focal intersection — the "sweet spot". Either coral label stroke OR clipPath-bounded coral fill tint (`rgba(235,108,54,0.10)`).
- Circle centers and radii divisible by 4.
## Anti-patterns