Repaint to jet-black + atomic-tangerine skin, add consultant-special 2×2

Why: the default skin was too warm/neutral and the pyramid + venn never
quite read the way they should. Also prepping for public sharing, so the
example diagrams needed to drop the littlemight-specific copy.

Changes:
- New five-color palette: jet-black ink, atomic-tangerine accent,
  white-smoke paper, blue-slate muted, silver hairlines. Replaces
  warm-stone + rust across every variant + dark-mode tokens.
- Default background is clean paper; dot grid + framed container are
  now opt-in variants (uncomment in template to enable).
- New consultant-special quadrant variant (example-quadrant-consultant.html)
  — 2×2 scenario matrix with named cells, double-ended axes, one focal
  quadrant; house skin, not a separate visual language.
- Pyramid redrawn as a true triangular silhouette with shared edges on
  one slope (stacked polygons on a single triangle outline, no kinks).
- Venn redesigned: dark-fill triple-intersection with white text,
  circle labels moved inside non-overlap lobes, pair-overlap labels
  removed, legend dropped.
- Example content genericized (content site / product timeline /
  content platform instead of littlemight-branded copy).
- Screenshots regenerated at 2× DPI; added quadrant-consultant.png
  (14th diagram in the gallery).
- README: hero-first opener, preserved Why-I-built-it section, UTM
  tags on littlemight + bestself links, palette description updated.
This commit is contained in:
Cathryn Lavery
2026-04-22 11:14:08 -05:00
parent 66d0d6ab76
commit ba3062c5ba
66 changed files with 2586 additions and 2353 deletions
+24 -11
View File
@@ -1,10 +1,20 @@
# Diagram Design
**I wanted good-looking diagrams for my blog posts.**
**Editorial diagrams your designer won't hate.**
I write at [littlemight.com](https://littlemight.com). Every time I needed a diagram — an architecture sketch, a flowchart, a pyramid of what matters most — I'd ask Claude and get back a generic rounded-box thing that looked nothing like the rest of the site. I'd either fight with Figma for 30 minutes or just skip the diagram.
![Content site architecture](docs/screenshots/architecture.png)
So I built a Claude Code skill for it. 13 types, editorial quality, matches your brand in 60 seconds by reading your website.
14 types. One Claude Code skill. Your brand in 60 seconds — the skill reads your website and maps colors + fonts to every diagram.
No Figma. No generic rounded boxes. No 30-minute color-picking sessions.
---
## Why I built it
I write at [littlemight.com](https://littlemight.com?utm_source=diagram-design&utm_medium=readme&utm_campaign=github&utm_content=intro) (and run [BestSelf.co](https://bestself.co?utm_source=diagram-design&utm_medium=readme&utm_campaign=github&utm_content=intro) on the side). Every time I needed a diagram — an architecture sketch, a flowchart, a pyramid of what matters most — I'd ask Claude and get back a generic rounded-box thing that looked nothing like the rest of the site. I'd either fight with Figma for 30 minutes or just skip the diagram.
So I built a Claude Code skill for it. Fourteen types, editorial quality, matches your brand in 60 seconds by reading your website.
> *The highest-quality move is usually deletion.* Every node earns its place. The accent color is reserved for the 1–2 things the reader should look at first. Target density: 4/10.
@@ -12,7 +22,7 @@ So I built a Claude Code skill for it. 13 types, editorial quality, matches your
## What it makes
All 13 diagrams ship in three variants: minimal light, minimal dark, and full-editorial. Open any of them directly in a browser — no build step, no JS, no external images.
All 14 diagrams ship in three variants: minimal light, minimal dark, and full-editorial. Open any of them directly in a browser — no build step, no JS, no external images.
<table>
<tr>
@@ -36,11 +46,13 @@ All 13 diagrams ship in three variants: minimal light, minimal dark, and full-ed
<td align="center"><img src="docs/screenshots/venn.png" alt="Venn"><br><b>Venn</b><br><sub>Set overlap</sub></td>
</tr>
<tr>
<td align="center" colspan="3"><img src="docs/screenshots/pyramid.png" alt="Pyramid" width="40%"><br><b>Pyramid / funnel</b><br><sub>Ranked hierarchy or conversion drop-off</sub></td>
<td align="center"><img src="docs/screenshots/pyramid.png" alt="Pyramid"><br><b>Pyramid / funnel</b><br><sub>Ranked hierarchy or drop-off</sub></td>
<td align="center"><img src="docs/screenshots/quadrant-consultant.png" alt="Consultant 2×2"><br><b>Consultant 2×2</b><br><sub>Scenario matrix · named cells</sub></td>
<td align="center">&nbsp;</td>
</tr>
</table>
**Browse the live gallery:** open [`assets/index.html`](assets/index.html) in your browser to flip through all 13 types with light / dark / full-editorial tabs.
**Browse the live gallery:** open [`assets/index.html`](assets/index.html) in your browser to flip through all 14 diagrams with light / dark / full-editorial tabs.
---
@@ -75,7 +87,7 @@ Quicker to install — but the skill lives in the plugin cache, so edits to `ref
The whole point: ship editorial-quality diagrams in **your** colors and typography, not a generic template.
Out of the box, diagrams render in a neutral **stone + rust** palette (warm off-white paper, deep charcoal ink, rust-orange accent). Good enough to screenshot straight away. But 60 seconds of onboarding is better — the skill will pull your brand from your website and apply it across every diagram.
Out of the box, diagrams render in a clean **jet-black + atomic-tangerine** palette (white-smoke paper, jet-black ink, atomic-tangerine accent, blue-slate muted, silver hairlines). Good enough to screenshot straight away. But 60 seconds of onboarding is better — the skill will pull your brand from your website and apply it across every diagram.
### The flow
@@ -111,7 +123,7 @@ Before writing tokens, the skill verifies WCAG AA contrast on `ink` over `paper`
### Manual override
Prefer to set tokens by hand? Open [`references/style-guide.md`](references/style-guide.md) and edit the table. Everything downstream reads from there — the 13 types, the annotation primitive, and the gallery all inherit semantic role names (`accent`, not `#b5523a`).
Prefer to set tokens by hand? Open [`references/style-guide.md`](references/style-guide.md) and edit the table. Everything downstream reads from there — all 14 diagrams, the annotation primitive, and the gallery all inherit semantic role names (`accent`, not `#eb6c36`).
### First-run gate
@@ -126,7 +138,7 @@ See [`references/onboarding.md`](references/onboarding.md) for the full spec.
## Quickstart
```bash
# Open the gallery to see all 13 types
# Open the gallery to see all 14 diagrams
open ~/.claude/skills/diagram-design/assets/index.html
# In Claude Code, just ask:
@@ -172,7 +184,8 @@ diagram-design/
├── assets/
│ ├── index.html — live gallery, tabbed
│ ├── template*.html — scaffolds for new diagrams
│ └── example-<type>.html — 3 variants × 13 types
│ ├── example-<type>.html — 3 variants × 13 types
│ └── example-quadrant-consultant.html — consultant-special 2×2 scenario matrix
└── docs/screenshots/ — the images in this README
```
@@ -189,7 +202,7 @@ The top-level `SKILL.md` is always in context. Everything else is pulled in only
| "Onboard this skill to my site" | `SKILL.md` + `references/onboarding.md` + `references/style-guide.md` |
| "Add an editorial callout to this diagram" | `SKILL.md` + `references/primitive-annotation.md` |
| "Give me a hand-drawn version" | `SKILL.md` + `references/primitive-sketchy.md` |
| Routine diagram-making (any of the 13 types) | Only `SKILL.md` + that one type's reference |
| Routine diagram-making (any of the 14 diagrams) | Only `SKILL.md` + that one type's reference |
No matter how many types exist, Claude only reads the one you need. Add a new type tomorrow and nothing else changes.
+34 -23
View File
@@ -20,7 +20,7 @@ Thirteen diagram types. One shared design system, complexity budget, and taste g
Open [`references/style-guide.md`](references/style-guide.md) and check the default tokens. If they're still the shipped defaults (paper `#faf7f2`, ink `#1c1917`, accent `#b5523a` rust), **pause and ask the user**:
> *"This is your first diagram in this project. The style guide is still at the default (neutral stone + rust). Do you want to customize it to match your brand first? Options: (a) run onboarding — I'll pull colors and fonts from your website, (b) paste your tokens manually, (c) proceed with the default for now."*
> *"This is your first Schematic in this project. The style guide is still at the default (neutral stone + rust). Do you want to customize it to match your brand first? Options: (a) run onboarding — I'll pull colors and fonts from your website, (b) paste your tokens manually, (c) proceed with the default for now."*
Then branch:
- **(a)** → follow [`references/onboarding.md`](references/onboarding.md) to fetch the site, extract palette + fonts, propose a diff, and write `style-guide.md`.
@@ -39,11 +39,11 @@ Don't silently ship default-skinned diagrams into a branded project — that's t
From `.impeccable.md`: *"Confident restraint. Earn every element. One color accent, two families, a small spacing vocabulary. If removing it wouldn't hurt the page, remove it."*
Applied to diagrams:
Applied to schematics:
- Every node represents a distinct idea. Two nodes that always travel together are one node.
- Every connection carries information. If the relationship is obvious from layout, remove the line.
- Coral is **editorial, not a flag.** 1–2 focal nodes per diagram. Using it on 5 nodes erases the signal.
- The diagram isn't done when everything is added. It's done when nothing can be removed.
- The schematic isn't done when everything is added. It's done when nothing can be removed.
**Target density: 4/10.** Enough to be technically complete. Not so dense it needs a guide. Above 9 nodes, it's probably two diagrams.
@@ -94,7 +94,7 @@ Rules of thumb:
## 4. Universal Anti-patterns
These mark "AI slop" diagrams of any type:
These mark "AI slop" schematics of any type:
| Anti-pattern | Why it fails |
|---|---|
@@ -115,7 +115,7 @@ Type-specific anti-patterns live in each `references/type-*.md`.
## 5. Design System
**The design system is skinnable.** All colors, typography, and tokens live in a single source of truth — [`references/style-guide.md`](references/style-guide.md). This file describes semantic roles (`paper`, `ink`, `muted`, `accent`, `link`, …). The default skin is littlemight.com (warm paper, ink, coral); to apply your own brand, either edit `style-guide.md` directly or run the URL-based flow described in [`references/onboarding.md`](references/onboarding.md).
**The design system is skinnable.** All colors, typography, and tokens live in a single source of truth — [`references/style-guide.md`](references/style-guide.md). This file describes semantic roles (`paper`, `ink`, `muted`, `accent`, `link`, …). The default skin is a cool editorial palette (white-smoke paper, jet-black ink, atomic-tangerine accent, blue-slate muted, silver hairlines); to apply your own brand, either edit `style-guide.md` directly or run the URL-based flow described in [`references/onboarding.md`](references/onboarding.md).
> When specs below or in type references mention "ink", "accent", "muted", etc., look up the current hex value in `style-guide.md`.
@@ -169,35 +169,45 @@ Universal building blocks. Type-specialized primitives (lifeline, activation bar
### Background
**Default: clean paper, no dot pattern.** Single `<rect>` filled with `paper`. Don't wrap the diagram in a secondary container background — the diagram sits directly on the page.
```svg
<rect width="100%" height="100%" fill="#f5f5f5"/>
```
**Optional: dotted paper variant.** When a long-form editorial diagram benefits from textured ground (essays, hero diagrams on a dedicated page), opt in by adding the `dots` pattern and a second rect:
```svg
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.6"/>
```
Don't use the dot pattern when the diagram sits inside a product page, slide, or card — the texture compounds with surrounding chrome and reads as noise.
### Arrow markers (define all three, always)
```svg
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#52534e"/>
<polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/>
</marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#f7591f"/>
<polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/>
</marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#1a70c7"/>
<polygon points="0 0, 8 3, 0 6" fill="#2e5aa8"/>
</marker>
```
| Arrow | Stroke | When |
|---|---|---|
| Default | muted `#52534e` | Internal, generic |
| Accent | coral `#f7591f` | Primary / highlighted / headline |
| Link-blue | `#1a70c7` | HTTP/API calls, external systems |
| Default | muted `#4f5d75` | Internal, generic |
| Accent | coral `#eb6c36` | Primary / highlighted / headline |
| Link-blue | `#2e5aa8` | HTTP/API calls, external systems |
| Dashed | `stroke-dasharray="5,4"` + any color | Optional, passive, return, async |
**Draw arrows before boxes** so z-order puts lines behind nodes.
@@ -206,7 +216,7 @@ Universal building blocks. Type-specialized primitives (lifeline, activation bar
```svg
<!-- 1. Opaque paper mask — prevents arrows bleeding through transparent fills -->
<rect x="X" y="Y" width="W" height="H" rx="6" fill="#f5f4ed"/>
<rect x="X" y="Y" width="W" height="H" rx="6" fill="#f5f5f5"/>
<!-- 2. Styled box -->
<rect x="X" y="Y" width="W" height="H" rx="6" fill="FILL" stroke="STROKE" stroke-width="1"/>
<!-- 3. Rectangular type tag (rx=2, NOT a pill) -->
@@ -214,10 +224,10 @@ Universal building blocks. Type-specialized primitives (lifeline, activation bar
<text x="X+22" y="Y+15" fill="STROKE@0.8" font-size="7" font-family="'Geist Mono', monospace"
text-anchor="middle" letter-spacing="0.08em">API</text>
<!-- 4. Node name (Geist sans — human-readable) -->
<text x="CX" y="CY+2" fill="#0b0d0b" font-size="12" font-weight="600"
<text x="CX" y="CY+2" fill="#2d3142" font-size="12" font-weight="600"
font-family="'Geist', sans-serif" text-anchor="middle">Node Name</text>
<!-- 5. Technical sublabel (Geist Mono) -->
<text x="CX" y="CY+18" fill="#52534e" font-size="9"
<text x="CX" y="CY+18" fill="#4f5d75" font-size="9"
font-family="'Geist Mono', monospace" text-anchor="middle">tech:port</text>
```
@@ -226,8 +236,8 @@ Universal building blocks. Type-specialized primitives (lifeline, activation bar
Every arrow label needs an opaque rect behind it. Without one it bleeds through the line.
```svg
<rect x="MID_X-18" y="ARROW_Y-12" width="36" height="12" rx="2" fill="#f5f4ed"/>
<text x="MID_X" y="ARROW_Y-3" fill="#65655c" font-size="8"
<rect x="MID_X-18" y="ARROW_Y-12" width="36" height="12" rx="2" fill="#f5f5f5"/>
<text x="MID_X" y="ARROW_Y-3" fill="#7a8399" font-size="8"
font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">WRITE</text>
```
@@ -239,8 +249,8 @@ Rules: ≤14 characters, all-caps, centered on segment midpoint, 8–10px above
```svg
<line x1="30" y1="LEGEND_Y-8" x2="VIEWBOX_W-30" y2="LEGEND_Y-8"
stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="30" y="LEGEND_Y+8" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace"
stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="30" y="LEGEND_Y+8" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace"
letter-spacing="0.14em">LEGEND</text>
<!-- Items — horizontal row, ~160px apart -->
```
@@ -291,7 +301,7 @@ If you exceed, split into two diagrams (overview + detail).
### Page layout
1. **Header** — eyebrow (Geist Mono), title (Instrument Serif), optional subtitle (Geist muted).
2. **Diagram container** — `#efeee5` bg, 1px `rgba(11,13,11,0.12)` border, 8px radius, `overflow-x: auto`.
2. **Diagram container** — default: **clean, borderless**, no background — the SVG sits directly on the page paper. Optional *framed* variant (for card-heavy layouts or hero placements): `paper-2` bg + 1px `rule` border + 8px radius + `1.5rem` padding + `overflow-x: auto`.
3. **Summary cards** — 2–3 col grid with *varied* widths (e.g., `1.1fr 1fr 0.9fr`).
4. **Footer** — colophon in Geist Mono, muted, hairline top border.
@@ -314,7 +324,7 @@ Don't use 3 identical generic cards. Vary the treatment:
Rules:
- `background: #ffffff` (not paper — slight lift without shadow)
- `border: 1px solid rgba(11,13,11,0.12)`
- `border: 1px solid rgba(45,49,66,0.12)`
- `border-radius: 6px`, `padding: 1.25rem`
- **No `box-shadow`**
- Card dots: 7px, `border-radius: 50%` — ink / muted / coral / link / soft variants
@@ -343,7 +353,7 @@ Run before producing any diagram.
**Technical:**
- [ ] Arrows drawn before boxes?
- [ ] Every arrow label has an opaque `fill="#f5f4ed"` rect behind it?
- [ ] Every arrow label has an opaque `fill="#f5f5f5"` rect behind it?
- [ ] Legend is a horizontal bottom strip, not floating?
- [ ] No vertical `writing-mode` text?
- [ ] `viewBox` expanded for the legend strip (~60px)?
@@ -367,6 +377,7 @@ Every diagram ships in three variants (see `assets/`):
| **Minimal light** (default) | `template.html`, `example-<type>.html` | Screenshot-ready. Diagram + title. Warm paper. |
| **Minimal dark** | `template-dark.html`, `example-<type>-dark.html` | Dark mode sites, slides, high-contrast posts. |
| **Full editorial** | `template-full.html`, `example-<type>-full.html` | Long-form posts where the diagram is the hero. |
| **Consultant special** (quadrant only) | `example-quadrant-consultant.html` | BCG/McKinsey-style 2×2 scenario matrix. Clinical sans-serif, white bg, bold blue double-ended axes, named scenario cells. See [type-quadrant.md](references/type-quadrant.md#consultant-special-2x2-scenario-matrix). |
**Sketchy variant** (optional, applied to any of the above) — see [primitive-sketchy.md](references/primitive-sketchy.md). SVG turbulence filter wobbles strokes for a hand-drawn feel. Good for essays, not for technical docs.
+70 -70
View File
@@ -3,15 +3,15 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>littlemight.com · Architecture</title>
<title>Content site · Architecture</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -56,106 +56,106 @@
<body>
<div class="frame">
<p class="eyebrow">Architecture · Diagram Design</p>
<h1>littlemight.com in production</h1>
<h1>Content site in production</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#a8a69d"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#ff6a30"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#5ba8eb"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f08a59"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#6a95d8"/></marker>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Arrows first (behind boxes) -->
<line x1="168" y1="272" x2="220" y2="272" stroke="#5ba8eb" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<line x1="364" y1="272" x2="416" y2="272" stroke="#ff6a30" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="576" y1="256" x2="628" y2="212" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="576" y1="288" x2="628" y2="332" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="168" y1="272" x2="220" y2="272" stroke="#6a95d8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<line x1="364" y1="272" x2="416" y2="272" stroke="#f08a59" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="576" y1="256" x2="628" y2="212" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="576" y1="288" x2="628" y2="332" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Arrow labels -->
<rect x="172" y="252" width="48" height="12" rx="2" fill="#1c1a17"/>
<text x="196" y="262" fill="#5ba8eb" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">HTTPS</text>
<rect x="172" y="252" width="48" height="12" rx="2" fill="#2d3142"/>
<text x="196" y="262" fill="#6a95d8" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">HTTPS</text>
<rect x="368" y="252" width="48" height="12" rx="2" fill="#1c1a17"/>
<text x="392" y="262" fill="#ff6a30" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SSR</text>
<rect x="368" y="252" width="48" height="12" rx="2" fill="#2d3142"/>
<text x="392" y="262" fill="#f08a59" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SSR</text>
<rect x="560" y="212" width="56" height="12" rx="2" fill="#1c1a17"/>
<text x="588" y="222" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">READ MDX</text>
<rect x="560" y="212" width="56" height="12" rx="2" fill="#2d3142"/>
<text x="588" y="222" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">READ MDX</text>
<rect x="560" y="320" width="52" height="12" rx="2" fill="#1c1a17"/>
<text x="586" y="330" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text>
<rect x="560" y="320" width="52" height="12" rx="2" fill="#2d3142"/>
<text x="586" y="330" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text>
<!-- Node: Reader -->
<rect x="40" y="240" width="128" height="64" rx="6" fill="#1c1a17"/>
<rect x="40" y="240" width="128" height="64" rx="6" fill="rgba(168,166,157,0.10)" stroke="#8e8c83" stroke-width="1"/>
<rect x="40" y="240" width="128" height="64" rx="6" fill="#2d3142"/>
<rect x="40" y="240" width="128" height="64" rx="6" fill="rgba(191,192,192,0.10)" stroke="#8e98ac" stroke-width="1"/>
<rect x="48" y="248" width="28" height="12" rx="2" fill="transparent" stroke="rgba(142,140,131,0.40)" stroke-width="0.8"/>
<text x="62" y="257" fill="#8e8c83" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="104" y="276" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="104" y="292" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<text x="62" y="257" fill="#8e98ac" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="104" y="276" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="104" y="292" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<!-- Node: Cloudflare -->
<rect x="220" y="240" width="144" height="64" rx="6" fill="#1c1a17"/>
<rect x="220" y="240" width="144" height="64" rx="6" fill="rgba(241,239,231,0.03)" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<rect x="228" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(241,239,231,0.22)" stroke-width="0.8"/>
<text x="244" y="257" fill="#8e8c83" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="356" y="300" fill="rgba(241,239,231,0.06)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">01</text>
<text x="292" y="276" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="292" y="292" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<rect x="220" y="240" width="144" height="64" rx="6" fill="#2d3142"/>
<rect x="220" y="240" width="144" height="64" rx="6" fill="rgba(245,245,245,0.03)" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<rect x="228" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.22)" stroke-width="0.8"/>
<text x="244" y="257" fill="#8e98ac" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="356" y="300" fill="rgba(245,245,245,0.06)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">01</text>
<text x="292" y="276" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="292" y="292" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<!-- Node: Astro (focal coral) -->
<rect x="416" y="240" width="160" height="64" rx="6" fill="#1c1a17"/>
<rect x="416" y="240" width="160" height="64" rx="6" fill="rgba(255,106,48,0.08)" stroke="#ff6a30" stroke-width="1"/>
<rect x="424" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(255,106,48,0.50)" stroke-width="0.8"/>
<text x="440" y="257" fill="#ff6a30" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="568" y="300" fill="rgba(255,106,48,0.10)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">02</text>
<text x="496" y="276" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="496" y="292" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<rect x="416" y="240" width="160" height="64" rx="6" fill="#2d3142"/>
<rect x="416" y="240" width="160" height="64" rx="6" fill="rgba(240,138,89,0.08)" stroke="#f08a59" stroke-width="1"/>
<rect x="424" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(240,138,89,0.50)" stroke-width="0.8"/>
<text x="440" y="257" fill="#f08a59" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="568" y="300" fill="rgba(240,138,89,0.10)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">02</text>
<text x="496" y="276" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="496" y="292" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<!-- Node: MDX Bundle -->
<rect x="628" y="160" width="144" height="64" rx="6" fill="#1c1a17"/>
<rect x="628" y="160" width="144" height="64" rx="6" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<rect x="636" y="168" width="32" height="12" rx="2" fill="transparent" stroke="rgba(241,239,231,0.40)" stroke-width="0.8"/>
<text x="652" y="177" fill="#f1efe7" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BUN</text>
<text x="700" y="196" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MDX Bundle</text>
<text x="700" y="212" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/*.mdx</text>
<rect x="628" y="160" width="144" height="64" rx="6" fill="#2d3142"/>
<rect x="628" y="160" width="144" height="64" rx="6" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<rect x="636" y="168" width="32" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.40)" stroke-width="0.8"/>
<text x="652" y="177" fill="#f5f5f5" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BUN</text>
<text x="700" y="196" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MDX Bundle</text>
<text x="700" y="212" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/*.mdx</text>
<!-- Node: Content CMS -->
<rect x="628" y="320" width="144" height="64" rx="6" fill="#1c1a17"/>
<rect x="628" y="320" width="144" height="64" rx="6" fill="rgba(241,239,231,0.05)" stroke="#a8a69d" stroke-width="1"/>
<rect x="636" y="328" width="28" height="12" rx="2" fill="transparent" stroke="rgba(168,166,157,0.50)" stroke-width="0.8"/>
<text x="650" y="337" fill="#a8a69d" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CMS</text>
<text x="700" y="356" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Content CMS</text>
<text x="700" y="372" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">assets · og images</text>
<rect x="628" y="320" width="144" height="64" rx="6" fill="#2d3142"/>
<rect x="628" y="320" width="144" height="64" rx="6" fill="rgba(245,245,245,0.05)" stroke="#bfc0c0" stroke-width="1"/>
<rect x="636" y="328" width="28" height="12" rx="2" fill="transparent" stroke="rgba(191,192,192,0.50)" stroke-width="0.8"/>
<text x="650" y="337" fill="#bfc0c0" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CMS</text>
<text x="700" y="356" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Content CMS</text>
<text x="700" y="372" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">assets · og images</text>
<!-- Legend strip -->
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(241,239,231,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(255,106,48,0.08)" stroke="#ff6a30" stroke-width="1"/>
<text x="60" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Focal / origin</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(240,138,89,0.08)" stroke="#f08a59" stroke-width="1"/>
<text x="60" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Focal / origin</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="200" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Backend / bundle</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="200" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Backend / bundle</text>
<rect x="340" y="436" width="14" height="10" rx="2" fill="rgba(241,239,231,0.05)" stroke="#a8a69d" stroke-width="1"/>
<text x="360" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Store</text>
<rect x="340" y="436" width="14" height="10" rx="2" fill="rgba(245,245,245,0.05)" stroke="#bfc0c0" stroke-width="1"/>
<text x="360" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Store</text>
<rect x="436" y="436" width="14" height="10" rx="2" fill="rgba(241,239,231,0.03)" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<text x="456" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Cloud</text>
<rect x="436" y="436" width="14" height="10" rx="2" fill="rgba(245,245,245,0.03)" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<text x="456" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Cloud</text>
<rect x="528" y="436" width="14" height="10" rx="2" fill="rgba(168,166,157,0.10)" stroke="#8e8c83" stroke-width="1"/>
<text x="548" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">External</text>
<rect x="528" y="436" width="14" height="10" rx="2" fill="rgba(191,192,192,0.10)" stroke="#8e98ac" stroke-width="1"/>
<text x="548" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">External</text>
<line x1="636" y1="442" x2="664" y2="442" stroke="#5ba8eb" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="672" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<line x1="636" y1="442" x2="664" y2="442" stroke="#6a95d8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="672" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<line x1="784" y1="442" x2="812" y2="442" stroke="#ff6a30" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="820" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Primary flow</text>
<line x1="784" y1="442" x2="812" y2="442" stroke="#f08a59" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="820" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Primary flow</text>
</svg>
</div>
</body>
+77 -77
View File
@@ -3,16 +3,16 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>littlemight.com · Architecture</title>
<title>Content site · Architecture</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed; --color-paper-2: #efeee5;
--color-ink: #0b0d0b; --color-muted: #52534e; --color-soft: #65655c;
--color-rule: rgba(11,13,11,0.12);
--color-accent: #f7591f; --color-accent-tint: rgba(247,89,31,0.08);
--color-link: #1a70c7;
--color-paper: #f5f5f5; --color-paper-2: #ececec;
--color-ink: #2d3142; --color-muted: #4f5d75; --color-soft: #7a8399;
--color-rule: rgba(45,49,66,0.12);
--color-accent: #eb6c36; --color-accent-tint: rgba(235,108,54,0.08);
--color-link: #2e5aa8;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -29,21 +29,21 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; letter-spacing: -0.005em; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<p class="header-eyebrow">Architecture · Diagram Design</p>
<h1>littlemight.com in production</h1>
<h1>Content site in production</h1>
<p class="subtitle">The static-first stack: Cloudflare's edge absorbs most reads, Astro renders MDX on misses, content is checked into the repo.</p>
</div>
@@ -51,101 +51,101 @@
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#52534e"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f7591f"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#1a70c7"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#2e5aa8"/></marker>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Arrows first (behind boxes) -->
<line x1="168" y1="272" x2="220" y2="272" stroke="#1a70c7" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<line x1="364" y1="272" x2="416" y2="272" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="576" y1="256" x2="628" y2="212" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="576" y1="288" x2="628" y2="332" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="168" y1="272" x2="220" y2="272" stroke="#2e5aa8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<line x1="364" y1="272" x2="416" y2="272" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="576" y1="256" x2="628" y2="212" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="576" y1="288" x2="628" y2="332" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Arrow labels -->
<rect x="172" y="252" width="48" height="12" rx="2" fill="#f5f4ed"/>
<text x="196" y="262" fill="#1a70c7" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">HTTPS</text>
<rect x="172" y="252" width="48" height="12" rx="2" fill="#f5f5f5"/>
<text x="196" y="262" fill="#2e5aa8" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">HTTPS</text>
<rect x="368" y="252" width="48" height="12" rx="2" fill="#f5f4ed"/>
<text x="392" y="262" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SSR</text>
<rect x="368" y="252" width="48" height="12" rx="2" fill="#f5f5f5"/>
<text x="392" y="262" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SSR</text>
<rect x="560" y="212" width="56" height="12" rx="2" fill="#f5f4ed"/>
<text x="588" y="222" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">READ MDX</text>
<rect x="560" y="212" width="56" height="12" rx="2" fill="#f5f5f5"/>
<text x="588" y="222" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">READ MDX</text>
<rect x="560" y="320" width="52" height="12" rx="2" fill="#f5f4ed"/>
<text x="586" y="330" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text>
<rect x="560" y="320" width="52" height="12" rx="2" fill="#f5f5f5"/>
<text x="586" y="330" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text>
<!-- Node: Reader -->
<rect x="40" y="240" width="128" height="64" rx="6" fill="#f5f4ed"/>
<rect x="40" y="240" width="128" height="64" rx="6" fill="rgba(82,83,78,0.10)" stroke="#65655c" stroke-width="1"/>
<rect x="48" y="248" width="28" height="12" rx="2" fill="transparent" stroke="rgba(101,101,92,0.40)" stroke-width="0.8"/>
<text x="62" y="257" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="104" y="276" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="104" y="292" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<rect x="40" y="240" width="128" height="64" rx="6" fill="#f5f5f5"/>
<rect x="40" y="240" width="128" height="64" rx="6" fill="rgba(79,93,117,0.10)" stroke="#7a8399" stroke-width="1"/>
<rect x="48" y="248" width="28" height="12" rx="2" fill="transparent" stroke="rgba(122,131,153,0.40)" stroke-width="0.8"/>
<text x="62" y="257" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="104" y="276" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="104" y="292" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<!-- Node: Cloudflare -->
<rect x="220" y="240" width="144" height="64" rx="6" fill="#f5f4ed"/>
<rect x="220" y="240" width="144" height="64" rx="6" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<rect x="228" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.22)" stroke-width="0.8"/>
<text x="244" y="257" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="356" y="300" fill="rgba(11,13,11,0.06)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">01</text>
<text x="292" y="276" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="292" y="292" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<rect x="220" y="240" width="144" height="64" rx="6" fill="#f5f5f5"/>
<rect x="220" y="240" width="144" height="64" rx="6" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<rect x="228" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.22)" stroke-width="0.8"/>
<text x="244" y="257" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="356" y="300" fill="rgba(45,49,66,0.06)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">01</text>
<text x="292" y="276" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="292" y="292" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<!-- Node: Astro (focal coral) -->
<rect x="416" y="240" width="160" height="64" rx="6" fill="#f5f4ed"/>
<rect x="416" y="240" width="160" height="64" rx="6" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<rect x="424" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(247,89,31,0.50)" stroke-width="0.8"/>
<text x="440" y="257" fill="#f7591f" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="568" y="300" fill="rgba(247,89,31,0.10)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">02</text>
<text x="496" y="276" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="496" y="292" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<rect x="416" y="240" width="160" height="64" rx="6" fill="#f5f5f5"/>
<rect x="416" y="240" width="160" height="64" rx="6" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<rect x="424" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="440" y="257" fill="#eb6c36" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="568" y="300" fill="rgba(235,108,54,0.10)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">02</text>
<text x="496" y="276" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="496" y="292" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<!-- Node: MDX Bundle -->
<rect x="628" y="160" width="144" height="64" rx="6" fill="#f5f4ed"/>
<rect x="628" y="160" width="144" height="64" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="636" y="168" width="32" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="652" y="177" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BUN</text>
<text x="700" y="196" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MDX Bundle</text>
<text x="700" y="212" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/*.mdx</text>
<rect x="628" y="160" width="144" height="64" rx="6" fill="#f5f5f5"/>
<rect x="628" y="160" width="144" height="64" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="636" y="168" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="652" y="177" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BUN</text>
<text x="700" y="196" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MDX Bundle</text>
<text x="700" y="212" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/*.mdx</text>
<!-- Node: Content CMS -->
<rect x="628" y="320" width="144" height="64" rx="6" fill="#f5f4ed"/>
<rect x="628" y="320" width="144" height="64" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="1"/>
<rect x="636" y="328" width="28" height="12" rx="2" fill="transparent" stroke="rgba(82,83,78,0.50)" stroke-width="0.8"/>
<text x="650" y="337" fill="#52534e" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CMS</text>
<text x="700" y="356" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Content CMS</text>
<text x="700" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">assets · og images</text>
<rect x="628" y="320" width="144" height="64" rx="6" fill="#f5f5f5"/>
<rect x="628" y="320" width="144" height="64" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="1"/>
<rect x="636" y="328" width="28" height="12" rx="2" fill="transparent" stroke="rgba(79,93,117,0.50)" stroke-width="0.8"/>
<text x="650" y="337" fill="#4f5d75" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CMS</text>
<text x="700" y="356" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Content CMS</text>
<text x="700" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">assets · og images</text>
<!-- Legend strip -->
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="60" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Focal / origin</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="60" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Focal / origin</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="200" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Backend / bundle</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="200" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Backend / bundle</text>
<rect x="340" y="436" width="14" height="10" rx="2" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="1"/>
<text x="360" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Store</text>
<rect x="340" y="436" width="14" height="10" rx="2" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="1"/>
<text x="360" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Store</text>
<rect x="436" y="436" width="14" height="10" rx="2" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="456" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Cloud</text>
<rect x="436" y="436" width="14" height="10" rx="2" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="456" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Cloud</text>
<rect x="528" y="436" width="14" height="10" rx="2" fill="rgba(82,83,78,0.10)" stroke="#65655c" stroke-width="1"/>
<text x="548" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">External</text>
<rect x="528" y="436" width="14" height="10" rx="2" fill="rgba(79,93,117,0.10)" stroke="#7a8399" stroke-width="1"/>
<text x="548" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">External</text>
<line x1="636" y1="442" x2="664" y2="442" stroke="#1a70c7" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="672" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<line x1="636" y1="442" x2="664" y2="442" stroke="#2e5aa8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="672" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<line x1="784" y1="442" x2="812" y2="442" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="820" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Primary flow</text>
<line x1="784" y1="442" x2="812" y2="442" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="820" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Primary flow</text>
</svg>
</div>
@@ -166,8 +166,8 @@
</div>
<div class="footer">
<span>littlemight.com · architecture</span>
<span>example · diagram-design</span>
<span>content site · architecture</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+71 -71
View File
@@ -3,15 +3,15 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>littlemight.com · Architecture</title>
<title>Content site · Architecture</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -56,106 +56,106 @@
<body>
<div class="frame">
<p class="eyebrow">Architecture · Diagram Design</p>
<h1>littlemight.com in production</h1>
<h1>Content site in production</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#52534e"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f7591f"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#1a70c7"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#2e5aa8"/></marker>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Arrows first (behind boxes) -->
<line x1="168" y1="272" x2="220" y2="272" stroke="#1a70c7" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<line x1="364" y1="272" x2="416" y2="272" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="576" y1="256" x2="628" y2="212" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="576" y1="288" x2="628" y2="332" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="168" y1="272" x2="220" y2="272" stroke="#2e5aa8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<line x1="364" y1="272" x2="416" y2="272" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="576" y1="256" x2="628" y2="212" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="576" y1="288" x2="628" y2="332" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Arrow labels -->
<rect x="172" y="252" width="48" height="12" rx="2" fill="#f5f4ed"/>
<text x="196" y="262" fill="#1a70c7" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">HTTPS</text>
<rect x="172" y="252" width="48" height="12" rx="2" fill="#f5f5f5"/>
<text x="196" y="262" fill="#2e5aa8" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">HTTPS</text>
<rect x="368" y="252" width="48" height="12" rx="2" fill="#f5f4ed"/>
<text x="392" y="262" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SSR</text>
<rect x="368" y="252" width="48" height="12" rx="2" fill="#f5f5f5"/>
<text x="392" y="262" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SSR</text>
<rect x="560" y="212" width="56" height="12" rx="2" fill="#f5f4ed"/>
<text x="588" y="222" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">READ MDX</text>
<rect x="560" y="212" width="56" height="12" rx="2" fill="#f5f5f5"/>
<text x="588" y="222" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">READ MDX</text>
<rect x="560" y="320" width="52" height="12" rx="2" fill="#f5f4ed"/>
<text x="586" y="330" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text>
<rect x="560" y="320" width="52" height="12" rx="2" fill="#f5f5f5"/>
<text x="586" y="330" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text>
<!-- Node: Reader -->
<rect x="40" y="240" width="128" height="64" rx="6" fill="#f5f4ed"/>
<rect x="40" y="240" width="128" height="64" rx="6" fill="rgba(82,83,78,0.10)" stroke="#65655c" stroke-width="1"/>
<rect x="48" y="248" width="28" height="12" rx="2" fill="transparent" stroke="rgba(101,101,92,0.40)" stroke-width="0.8"/>
<text x="62" y="257" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="104" y="276" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="104" y="292" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<rect x="40" y="240" width="128" height="64" rx="6" fill="#f5f5f5"/>
<rect x="40" y="240" width="128" height="64" rx="6" fill="rgba(79,93,117,0.10)" stroke="#7a8399" stroke-width="1"/>
<rect x="48" y="248" width="28" height="12" rx="2" fill="transparent" stroke="rgba(122,131,153,0.40)" stroke-width="0.8"/>
<text x="62" y="257" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="104" y="276" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="104" y="292" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<!-- Node: Cloudflare -->
<rect x="220" y="240" width="144" height="64" rx="6" fill="#f5f4ed"/>
<rect x="220" y="240" width="144" height="64" rx="6" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<rect x="228" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.22)" stroke-width="0.8"/>
<text x="244" y="257" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="356" y="300" fill="rgba(11,13,11,0.06)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">01</text>
<text x="292" y="276" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="292" y="292" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<rect x="220" y="240" width="144" height="64" rx="6" fill="#f5f5f5"/>
<rect x="220" y="240" width="144" height="64" rx="6" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<rect x="228" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.22)" stroke-width="0.8"/>
<text x="244" y="257" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="356" y="300" fill="rgba(45,49,66,0.06)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">01</text>
<text x="292" y="276" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="292" y="292" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<!-- Node: Astro (focal coral) -->
<rect x="416" y="240" width="160" height="64" rx="6" fill="#f5f4ed"/>
<rect x="416" y="240" width="160" height="64" rx="6" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<rect x="424" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(247,89,31,0.50)" stroke-width="0.8"/>
<text x="440" y="257" fill="#f7591f" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="568" y="300" fill="rgba(247,89,31,0.10)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">02</text>
<text x="496" y="276" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="496" y="292" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<rect x="416" y="240" width="160" height="64" rx="6" fill="#f5f5f5"/>
<rect x="416" y="240" width="160" height="64" rx="6" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<rect x="424" y="248" width="32" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="440" y="257" fill="#eb6c36" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="568" y="300" fill="rgba(235,108,54,0.10)" font-size="32" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">02</text>
<text x="496" y="276" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="496" y="292" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<!-- Node: MDX Bundle -->
<rect x="628" y="160" width="144" height="64" rx="6" fill="#f5f4ed"/>
<rect x="628" y="160" width="144" height="64" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="636" y="168" width="32" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="652" y="177" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BUN</text>
<text x="700" y="196" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MDX Bundle</text>
<text x="700" y="212" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/*.mdx</text>
<rect x="628" y="160" width="144" height="64" rx="6" fill="#f5f5f5"/>
<rect x="628" y="160" width="144" height="64" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="636" y="168" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="652" y="177" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BUN</text>
<text x="700" y="196" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MDX Bundle</text>
<text x="700" y="212" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/*.mdx</text>
<!-- Node: Content CMS -->
<rect x="628" y="320" width="144" height="64" rx="6" fill="#f5f4ed"/>
<rect x="628" y="320" width="144" height="64" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="1"/>
<rect x="636" y="328" width="28" height="12" rx="2" fill="transparent" stroke="rgba(82,83,78,0.50)" stroke-width="0.8"/>
<text x="650" y="337" fill="#52534e" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CMS</text>
<text x="700" y="356" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Content CMS</text>
<text x="700" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">assets · og images</text>
<rect x="628" y="320" width="144" height="64" rx="6" fill="#f5f5f5"/>
<rect x="628" y="320" width="144" height="64" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="1"/>
<rect x="636" y="328" width="28" height="12" rx="2" fill="transparent" stroke="rgba(79,93,117,0.50)" stroke-width="0.8"/>
<text x="650" y="337" fill="#4f5d75" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CMS</text>
<text x="700" y="356" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Content CMS</text>
<text x="700" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">assets · og images</text>
<!-- Legend strip -->
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="60" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Focal / origin</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="60" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Focal / origin</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="200" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Backend / bundle</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="200" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Backend / bundle</text>
<rect x="340" y="436" width="14" height="10" rx="2" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="1"/>
<text x="360" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Store</text>
<rect x="340" y="436" width="14" height="10" rx="2" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="1"/>
<text x="360" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Store</text>
<rect x="436" y="436" width="14" height="10" rx="2" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="456" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Cloud</text>
<rect x="436" y="436" width="14" height="10" rx="2" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="456" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Cloud</text>
<rect x="528" y="436" width="14" height="10" rx="2" fill="rgba(82,83,78,0.10)" stroke="#65655c" stroke-width="1"/>
<text x="548" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">External</text>
<rect x="528" y="436" width="14" height="10" rx="2" fill="rgba(79,93,117,0.10)" stroke="#7a8399" stroke-width="1"/>
<text x="548" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">External</text>
<line x1="636" y1="442" x2="664" y2="442" stroke="#1a70c7" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="672" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<line x1="636" y1="442" x2="664" y2="442" stroke="#2e5aa8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="672" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<line x1="784" y1="442" x2="812" y2="442" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="820" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Primary flow</text>
<line x1="784" y1="442" x2="812" y2="442" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="820" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Primary flow</text>
</svg>
</div>
</body>
+104 -104
View File
@@ -3,15 +3,15 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>littlemight content model · ER</title>
<title>Content platform · ER model</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -56,144 +56,144 @@
<body>
<div class="frame">
<p class="eyebrow">ER · Diagram Design</p>
<h1>littlemight content model</h1>
<h1>Content platform · data model</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#a8a69d"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Relationship lines (drawn first) -->
<!-- 1. Author — Article (1:N "writes") -->
<line x1="260" y1="240" x2="400" y2="240" stroke="#a8a69d" stroke-width="1" />
<line x1="260" y1="240" x2="400" y2="240" stroke="#bfc0c0" stroke-width="1" />
<!-- 2. Article — ArticleTag (1:N) -->
<line x1="640" y1="320" x2="780" y2="328" stroke="#a8a69d" stroke-width="1" />
<line x1="640" y1="320" x2="780" y2="328" stroke="#bfc0c0" stroke-width="1" />
<!-- 3. Tag — ArticleTag (1:N, vertical) -->
<line x1="880" y1="248" x2="880" y2="280" stroke="#a8a69d" stroke-width="1" />
<line x1="880" y1="248" x2="880" y2="280" stroke="#bfc0c0" stroke-width="1" />
<!-- Cardinality labels -->
<rect x="266" y="232" width="12" height="12" rx="2" fill="#1c1a17"/>
<text x="272" y="242" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="266" y="232" width="12" height="12" rx="2" fill="#2d3142"/>
<text x="272" y="242" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="378" y="232" width="16" height="12" rx="2" fill="#1c1a17"/>
<text x="386" y="242" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="378" y="232" width="16" height="12" rx="2" fill="#2d3142"/>
<text x="386" y="242" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="646" y="316" width="12" height="12" rx="2" fill="#1c1a17"/>
<text x="652" y="326" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="646" y="316" width="12" height="12" rx="2" fill="#2d3142"/>
<text x="652" y="326" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="760" y="324" width="16" height="12" rx="2" fill="#1c1a17"/>
<text x="768" y="334" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="760" y="324" width="16" height="12" rx="2" fill="#2d3142"/>
<text x="768" y="334" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="872" y="252" width="16" height="12" rx="2" fill="#1c1a17"/>
<text x="880" y="262" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="872" y="252" width="16" height="12" rx="2" fill="#2d3142"/>
<text x="880" y="262" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="872" y="268" width="16" height="12" rx="2" fill="#1c1a17"/>
<text x="880" y="278" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="872" y="268" width="16" height="12" rx="2" fill="#2d3142"/>
<text x="880" y="278" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<!-- Relationship labels -->
<rect x="304" y="220" width="56" height="14" rx="2" fill="#1c1a17"/>
<text x="332" y="230" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">WRITES</text>
<rect x="304" y="220" width="56" height="14" rx="2" fill="#2d3142"/>
<text x="332" y="230" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">WRITES</text>
<rect x="688" y="300" width="56" height="14" rx="2" fill="#1c1a17"/>
<text x="716" y="310" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">TAGGED</text>
<rect x="688" y="300" width="56" height="14" rx="2" fill="#2d3142"/>
<text x="716" y="310" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">TAGGED</text>
<!-- Entity: Author -->
<rect x="60" y="160" width="200" height="160" rx="6" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<rect x="60" y="160" width="200" height="40" rx="6" fill="rgba(241,239,231,0.04)" stroke="none"/>
<rect x="60" y="192" width="200" height="8" fill="rgba(241,239,231,0.04)"/>
<line x1="60" y1="200" x2="260" y2="200" stroke="rgba(241,239,231,0.22)" stroke-width="1"/>
<text x="76" y="176" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="76" y="192" fill="#f1efe7" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Author</text>
<text x="76" y="220" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="220" y="220" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="76" y="240" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">handle</text>
<text x="220" y="240" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="260" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="220" y="260" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="280" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">bio</text>
<text x="220" y="280" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="300" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">site_url</text>
<text x="220" y="300" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<rect x="60" y="160" width="200" height="160" rx="6" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<rect x="60" y="160" width="200" height="40" rx="6" fill="rgba(245,245,245,0.04)" stroke="none"/>
<rect x="60" y="192" width="200" height="8" fill="rgba(245,245,245,0.04)"/>
<line x1="60" y1="200" x2="260" y2="200" stroke="rgba(245,245,245,0.22)" stroke-width="1"/>
<text x="76" y="176" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="76" y="192" fill="#f5f5f5" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Author</text>
<text x="76" y="220" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="220" y="220" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="76" y="240" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">handle</text>
<text x="220" y="240" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="260" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="220" y="260" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="280" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">bio</text>
<text x="220" y="280" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="300" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">site_url</text>
<text x="220" y="300" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<!-- Entity: Article (focal coral) -->
<rect x="400" y="120" width="240" height="240" rx="6" fill="rgba(255,106,48,0.04)" stroke="#ff6a30" stroke-width="1"/>
<rect x="400" y="120" width="240" height="40" rx="6" fill="rgba(255,106,48,0.10)" stroke="none"/>
<rect x="400" y="152" width="240" height="8" fill="rgba(255,106,48,0.10)"/>
<line x1="400" y1="160" x2="640" y2="160" stroke="rgba(255,106,48,0.40)" stroke-width="1"/>
<text x="416" y="136" fill="#ff6a30" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY · AGGREGATE ROOT</text>
<text x="416" y="152" fill="#f1efe7" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Article</text>
<text x="416" y="180" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="600" y="180" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="200" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">title</text>
<text x="600" y="200" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="220" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="600" y="220" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="416" y="240" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">body_mdx</text>
<text x="600" y="240" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="260" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">published_at</text>
<text x="600" y="260" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">timestamp</text>
<text x="416" y="280" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">→ author_id</text>
<text x="600" y="280" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="300" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">status</text>
<text x="600" y="300" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">enum</text>
<text x="416" y="320" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">og_image</text>
<text x="600" y="320" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · url</text>
<rect x="400" y="120" width="240" height="240" rx="6" fill="rgba(240,138,89,0.04)" stroke="#f08a59" stroke-width="1"/>
<rect x="400" y="120" width="240" height="40" rx="6" fill="rgba(240,138,89,0.10)" stroke="none"/>
<rect x="400" y="152" width="240" height="8" fill="rgba(240,138,89,0.10)"/>
<line x1="400" y1="160" x2="640" y2="160" stroke="rgba(240,138,89,0.40)" stroke-width="1"/>
<text x="416" y="136" fill="#f08a59" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY · AGGREGATE ROOT</text>
<text x="416" y="152" fill="#f5f5f5" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Article</text>
<text x="416" y="180" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="600" y="180" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="200" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">title</text>
<text x="600" y="200" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="220" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="600" y="220" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="416" y="240" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">body_mdx</text>
<text x="600" y="240" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="260" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">published_at</text>
<text x="600" y="260" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">timestamp</text>
<text x="416" y="280" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">→ author_id</text>
<text x="600" y="280" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="300" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">status</text>
<text x="600" y="300" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">enum</text>
<text x="416" y="320" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">og_image</text>
<text x="600" y="320" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · url</text>
<!-- Entity: Tag -->
<rect x="780" y="120" width="200" height="128" rx="6" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<rect x="780" y="120" width="200" height="40" rx="6" fill="rgba(241,239,231,0.04)" stroke="none"/>
<rect x="780" y="152" width="200" height="8" fill="rgba(241,239,231,0.04)"/>
<line x1="780" y1="160" x2="980" y2="160" stroke="rgba(241,239,231,0.22)" stroke-width="1"/>
<text x="796" y="136" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="796" y="152" fill="#f1efe7" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Tag</text>
<text x="796" y="180" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="940" y="180" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="200" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="940" y="200" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="796" y="220" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="940" y="220" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="796" y="240" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">description</text>
<text x="940" y="240" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<rect x="780" y="120" width="200" height="128" rx="6" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<rect x="780" y="120" width="200" height="40" rx="6" fill="rgba(245,245,245,0.04)" stroke="none"/>
<rect x="780" y="152" width="200" height="8" fill="rgba(245,245,245,0.04)"/>
<line x1="780" y1="160" x2="980" y2="160" stroke="rgba(245,245,245,0.22)" stroke-width="1"/>
<text x="796" y="136" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="796" y="152" fill="#f5f5f5" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Tag</text>
<text x="796" y="180" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="940" y="180" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="200" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="940" y="200" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="796" y="220" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="940" y="220" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="796" y="240" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">description</text>
<text x="940" y="240" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<!-- Entity: ArticleTag (join) -->
<rect x="780" y="280" width="200" height="96" rx="6" fill="rgba(241,239,231,0.04)" stroke="#a8a69d" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="780" y="280" width="200" height="40" rx="6" fill="rgba(241,239,231,0.06)" stroke="none"/>
<rect x="780" y="312" width="200" height="8" fill="rgba(241,239,231,0.06)"/>
<line x1="780" y1="320" x2="980" y2="320" stroke="rgba(241,239,231,0.22)" stroke-width="1"/>
<text x="796" y="296" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">JOIN</text>
<text x="796" y="312" fill="#f1efe7" font-size="14" font-weight="600" font-family="'Geist', sans-serif">ArticleTag</text>
<text x="796" y="340" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">→ article_id</text>
<text x="940" y="340" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="360" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace">→ tag_id</text>
<text x="940" y="360" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<rect x="780" y="280" width="200" height="96" rx="6" fill="rgba(245,245,245,0.04)" stroke="#bfc0c0" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="780" y="280" width="200" height="40" rx="6" fill="rgba(245,245,245,0.06)" stroke="none"/>
<rect x="780" y="312" width="200" height="8" fill="rgba(245,245,245,0.06)"/>
<line x1="780" y1="320" x2="980" y2="320" stroke="rgba(245,245,245,0.22)" stroke-width="1"/>
<text x="796" y="296" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">JOIN</text>
<text x="796" y="312" fill="#f5f5f5" font-size="14" font-weight="600" font-family="'Geist', sans-serif">ArticleTag</text>
<text x="796" y="340" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">→ article_id</text>
<text x="940" y="340" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="360" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace">→ tag_id</text>
<text x="940" y="360" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<!-- Legend -->
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(241,239,231,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(255,106,48,0.04)" stroke="#ff6a30" stroke-width="1"/>
<text x="60" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Aggregate root</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(240,138,89,0.04)" stroke="#f08a59" stroke-width="1"/>
<text x="60" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Aggregate root</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="200" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Entity</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="200" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Entity</text>
<rect x="268" y="436" width="14" height="10" rx="2" fill="rgba(241,239,231,0.04)" stroke="#a8a69d" stroke-width="1" stroke-dasharray="3,2"/>
<text x="288" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Join table</text>
<rect x="268" y="436" width="14" height="10" rx="2" fill="rgba(245,245,245,0.04)" stroke="#bfc0c0" stroke-width="1" stroke-dasharray="3,2"/>
<text x="288" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Join table</text>
<text x="372" y="444" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">#</text>
<text x="388" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Primary key</text>
<text x="372" y="444" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">#</text>
<text x="388" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Primary key</text>
<text x="476" y="444" fill="#f1efe7" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">→</text>
<text x="492" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Foreign key</text>
<text x="476" y="444" fill="#f5f5f5" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">→</text>
<text x="492" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Foreign key</text>
<text x="584" y="444" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">1 / N</text>
<text x="616" y="444" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Cardinality</text>
<text x="584" y="444" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">1 / N</text>
<text x="616" y="444" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Cardinality</text>
</svg>
</div>
</body>
+106 -106
View File
@@ -3,11 +3,11 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>littlemight content model · ER</title>
<title>Content platform · ER model</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root { --color-paper:#f5f4ed; --color-paper-2:#efeee5; --color-ink:#0b0d0b; --color-muted:#52534e; --color-soft:#65655c; --color-rule:rgba(11,13,11,0.12); --color-accent:#f7591f; --color-link:#1a70c7; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --color-link:#2e5aa8; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
@@ -20,21 +20,21 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<p class="header-eyebrow">ER · Diagram Design</p>
<h1>littlemight content model</h1>
<h1>Content platform · data model</h1>
<p class="subtitle">The four entities behind the site. Article is the aggregate root — everything else exists to describe or classify it. `#` marks primary keys, `→` marks foreign keys.</p>
</div>
@@ -42,139 +42,139 @@
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#52534e"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Relationship lines (drawn first) -->
<!-- 1. Author — Article (1:N "writes") -->
<line x1="260" y1="240" x2="400" y2="240" stroke="#52534e" stroke-width="1" />
<line x1="260" y1="240" x2="400" y2="240" stroke="#4f5d75" stroke-width="1" />
<!-- 2. Article — ArticleTag (1:N) -->
<line x1="640" y1="320" x2="780" y2="328" stroke="#52534e" stroke-width="1" />
<line x1="640" y1="320" x2="780" y2="328" stroke="#4f5d75" stroke-width="1" />
<!-- 3. Tag — ArticleTag (1:N, vertical) -->
<line x1="880" y1="248" x2="880" y2="280" stroke="#52534e" stroke-width="1" />
<line x1="880" y1="248" x2="880" y2="280" stroke="#4f5d75" stroke-width="1" />
<!-- Cardinality labels -->
<rect x="266" y="232" width="12" height="12" rx="2" fill="#f5f4ed"/>
<text x="272" y="242" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="266" y="232" width="12" height="12" rx="2" fill="#f5f5f5"/>
<text x="272" y="242" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="378" y="232" width="16" height="12" rx="2" fill="#f5f4ed"/>
<text x="386" y="242" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="378" y="232" width="16" height="12" rx="2" fill="#f5f5f5"/>
<text x="386" y="242" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="646" y="316" width="12" height="12" rx="2" fill="#f5f4ed"/>
<text x="652" y="326" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="646" y="316" width="12" height="12" rx="2" fill="#f5f5f5"/>
<text x="652" y="326" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="760" y="324" width="16" height="12" rx="2" fill="#f5f4ed"/>
<text x="768" y="334" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="760" y="324" width="16" height="12" rx="2" fill="#f5f5f5"/>
<text x="768" y="334" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="872" y="252" width="16" height="12" rx="2" fill="#f5f4ed"/>
<text x="880" y="262" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="872" y="252" width="16" height="12" rx="2" fill="#f5f5f5"/>
<text x="880" y="262" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="872" y="268" width="16" height="12" rx="2" fill="#f5f4ed"/>
<text x="880" y="278" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="872" y="268" width="16" height="12" rx="2" fill="#f5f5f5"/>
<text x="880" y="278" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<!-- Relationship labels -->
<rect x="304" y="220" width="56" height="14" rx="2" fill="#f5f4ed"/>
<text x="332" y="230" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">WRITES</text>
<rect x="304" y="220" width="56" height="14" rx="2" fill="#f5f5f5"/>
<text x="332" y="230" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">WRITES</text>
<rect x="688" y="300" width="56" height="14" rx="2" fill="#f5f4ed"/>
<text x="716" y="310" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">TAGGED</text>
<rect x="688" y="300" width="56" height="14" rx="2" fill="#f5f5f5"/>
<text x="716" y="310" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">TAGGED</text>
<!-- Entity: Author -->
<rect x="60" y="160" width="200" height="160" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="60" y="160" width="200" height="40" rx="6" fill="rgba(11,13,11,0.04)" stroke="none"/>
<rect x="60" y="192" width="200" height="8" fill="rgba(11,13,11,0.04)"/>
<line x1="60" y1="200" x2="260" y2="200" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<text x="76" y="176" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="76" y="192" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Author</text>
<text x="76" y="220" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="220" y="220" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="76" y="240" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">handle</text>
<text x="220" y="240" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="260" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="220" y="260" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="280" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">bio</text>
<text x="220" y="280" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="300" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">site_url</text>
<text x="220" y="300" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<rect x="60" y="160" width="200" height="160" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="60" y="160" width="200" height="40" rx="6" fill="rgba(45,49,66,0.04)" stroke="none"/>
<rect x="60" y="192" width="200" height="8" fill="rgba(45,49,66,0.04)"/>
<line x1="60" y1="200" x2="260" y2="200" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<text x="76" y="176" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="76" y="192" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Author</text>
<text x="76" y="220" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="220" y="220" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="76" y="240" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">handle</text>
<text x="220" y="240" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="260" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="220" y="260" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="280" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">bio</text>
<text x="220" y="280" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="300" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">site_url</text>
<text x="220" y="300" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<!-- Entity: Article (focal coral) -->
<rect x="400" y="120" width="240" height="240" rx="6" fill="rgba(247,89,31,0.04)" stroke="#f7591f" stroke-width="1"/>
<rect x="400" y="120" width="240" height="40" rx="6" fill="rgba(247,89,31,0.10)" stroke="none"/>
<rect x="400" y="152" width="240" height="8" fill="rgba(247,89,31,0.10)"/>
<line x1="400" y1="160" x2="640" y2="160" stroke="rgba(247,89,31,0.40)" stroke-width="1"/>
<text x="416" y="136" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY · AGGREGATE ROOT</text>
<text x="416" y="152" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Article</text>
<text x="416" y="180" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="600" y="180" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="200" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">title</text>
<text x="600" y="200" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="220" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="600" y="220" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="416" y="240" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">body_mdx</text>
<text x="600" y="240" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="260" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">published_at</text>
<text x="600" y="260" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">timestamp</text>
<text x="416" y="280" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">→ author_id</text>
<text x="600" y="280" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="300" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">status</text>
<text x="600" y="300" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">enum</text>
<text x="416" y="320" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">og_image</text>
<text x="600" y="320" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · url</text>
<rect x="400" y="120" width="240" height="240" rx="6" fill="rgba(235,108,54,0.04)" stroke="#eb6c36" stroke-width="1"/>
<rect x="400" y="120" width="240" height="40" rx="6" fill="rgba(235,108,54,0.10)" stroke="none"/>
<rect x="400" y="152" width="240" height="8" fill="rgba(235,108,54,0.10)"/>
<line x1="400" y1="160" x2="640" y2="160" stroke="rgba(235,108,54,0.40)" stroke-width="1"/>
<text x="416" y="136" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY · AGGREGATE ROOT</text>
<text x="416" y="152" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Article</text>
<text x="416" y="180" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="600" y="180" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="200" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">title</text>
<text x="600" y="200" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="220" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="600" y="220" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="416" y="240" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">body_mdx</text>
<text x="600" y="240" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="260" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">published_at</text>
<text x="600" y="260" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">timestamp</text>
<text x="416" y="280" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">→ author_id</text>
<text x="600" y="280" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="300" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">status</text>
<text x="600" y="300" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">enum</text>
<text x="416" y="320" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">og_image</text>
<text x="600" y="320" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · url</text>
<!-- Entity: Tag -->
<rect x="780" y="120" width="200" height="128" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="780" y="120" width="200" height="40" rx="6" fill="rgba(11,13,11,0.04)" stroke="none"/>
<rect x="780" y="152" width="200" height="8" fill="rgba(11,13,11,0.04)"/>
<line x1="780" y1="160" x2="980" y2="160" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<text x="796" y="136" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="796" y="152" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Tag</text>
<text x="796" y="180" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="940" y="180" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="200" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="940" y="200" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="796" y="220" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="940" y="220" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="796" y="240" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">description</text>
<text x="940" y="240" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<rect x="780" y="120" width="200" height="128" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="780" y="120" width="200" height="40" rx="6" fill="rgba(45,49,66,0.04)" stroke="none"/>
<rect x="780" y="152" width="200" height="8" fill="rgba(45,49,66,0.04)"/>
<line x1="780" y1="160" x2="980" y2="160" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<text x="796" y="136" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="796" y="152" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Tag</text>
<text x="796" y="180" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="940" y="180" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="200" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="940" y="200" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="796" y="220" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="940" y="220" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="796" y="240" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">description</text>
<text x="940" y="240" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<!-- Entity: ArticleTag (join) -->
<rect x="780" y="280" width="200" height="96" rx="6" fill="rgba(11,13,11,0.04)" stroke="#52534e" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="780" y="280" width="200" height="40" rx="6" fill="rgba(11,13,11,0.06)" stroke="none"/>
<rect x="780" y="312" width="200" height="8" fill="rgba(11,13,11,0.06)"/>
<line x1="780" y1="320" x2="980" y2="320" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<text x="796" y="296" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">JOIN</text>
<text x="796" y="312" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif">ArticleTag</text>
<text x="796" y="340" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">→ article_id</text>
<text x="940" y="340" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="360" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">→ tag_id</text>
<text x="940" y="360" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<rect x="780" y="280" width="200" height="96" rx="6" fill="rgba(45,49,66,0.04)" stroke="#4f5d75" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="780" y="280" width="200" height="40" rx="6" fill="rgba(45,49,66,0.06)" stroke="none"/>
<rect x="780" y="312" width="200" height="8" fill="rgba(45,49,66,0.06)"/>
<line x1="780" y1="320" x2="980" y2="320" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<text x="796" y="296" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">JOIN</text>
<text x="796" y="312" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif">ArticleTag</text>
<text x="796" y="340" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">→ article_id</text>
<text x="940" y="340" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="360" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">→ tag_id</text>
<text x="940" y="360" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<!-- Legend -->
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(247,89,31,0.04)" stroke="#f7591f" stroke-width="1"/>
<text x="60" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Aggregate root</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(235,108,54,0.04)" stroke="#eb6c36" stroke-width="1"/>
<text x="60" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Aggregate root</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="200" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Entity</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="200" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Entity</text>
<rect x="268" y="436" width="14" height="10" rx="2" fill="rgba(11,13,11,0.04)" stroke="#52534e" stroke-width="1" stroke-dasharray="3,2"/>
<text x="288" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Join table</text>
<rect x="268" y="436" width="14" height="10" rx="2" fill="rgba(45,49,66,0.04)" stroke="#4f5d75" stroke-width="1" stroke-dasharray="3,2"/>
<text x="288" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Join table</text>
<text x="372" y="444" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">#</text>
<text x="388" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Primary key</text>
<text x="372" y="444" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">#</text>
<text x="388" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Primary key</text>
<text x="476" y="444" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">→</text>
<text x="492" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Foreign key</text>
<text x="476" y="444" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">→</text>
<text x="492" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Foreign key</text>
<text x="584" y="444" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">1 / N</text>
<text x="616" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Cardinality</text>
<text x="584" y="444" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">1 / N</text>
<text x="616" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Cardinality</text>
</svg>
</div>
@@ -195,8 +195,8 @@
</div>
<div class="footer">
<span>littlemight content model · ER</span>
<span>example · diagram-design</span>
<span>Content platform · ER model</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+104 -104
View File
@@ -3,15 +3,15 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>littlemight content model · ER</title>
<title>Content platform · ER model</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -56,144 +56,144 @@
<body>
<div class="frame">
<p class="eyebrow">ER · Diagram Design</p>
<h1>littlemight content model</h1>
<h1>Content platform · data model</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#52534e"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Relationship lines (drawn first) -->
<!-- 1. Author — Article (1:N "writes") -->
<line x1="260" y1="240" x2="400" y2="240" stroke="#52534e" stroke-width="1" />
<line x1="260" y1="240" x2="400" y2="240" stroke="#4f5d75" stroke-width="1" />
<!-- 2. Article — ArticleTag (1:N) -->
<line x1="640" y1="320" x2="780" y2="328" stroke="#52534e" stroke-width="1" />
<line x1="640" y1="320" x2="780" y2="328" stroke="#4f5d75" stroke-width="1" />
<!-- 3. Tag — ArticleTag (1:N, vertical) -->
<line x1="880" y1="248" x2="880" y2="280" stroke="#52534e" stroke-width="1" />
<line x1="880" y1="248" x2="880" y2="280" stroke="#4f5d75" stroke-width="1" />
<!-- Cardinality labels -->
<rect x="266" y="232" width="12" height="12" rx="2" fill="#f5f4ed"/>
<text x="272" y="242" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="266" y="232" width="12" height="12" rx="2" fill="#f5f5f5"/>
<text x="272" y="242" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="378" y="232" width="16" height="12" rx="2" fill="#f5f4ed"/>
<text x="386" y="242" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="378" y="232" width="16" height="12" rx="2" fill="#f5f5f5"/>
<text x="386" y="242" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="646" y="316" width="12" height="12" rx="2" fill="#f5f4ed"/>
<text x="652" y="326" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="646" y="316" width="12" height="12" rx="2" fill="#f5f5f5"/>
<text x="652" y="326" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="760" y="324" width="16" height="12" rx="2" fill="#f5f4ed"/>
<text x="768" y="334" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="760" y="324" width="16" height="12" rx="2" fill="#f5f5f5"/>
<text x="768" y="334" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="872" y="252" width="16" height="12" rx="2" fill="#f5f4ed"/>
<text x="880" y="262" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="872" y="252" width="16" height="12" rx="2" fill="#f5f5f5"/>
<text x="880" y="262" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">1</text>
<rect x="872" y="268" width="16" height="12" rx="2" fill="#f5f4ed"/>
<text x="880" y="278" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<rect x="872" y="268" width="16" height="12" rx="2" fill="#f5f5f5"/>
<text x="880" y="278" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="middle" font-weight="600">N</text>
<!-- Relationship labels -->
<rect x="304" y="220" width="56" height="14" rx="2" fill="#f5f4ed"/>
<text x="332" y="230" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">WRITES</text>
<rect x="304" y="220" width="56" height="14" rx="2" fill="#f5f5f5"/>
<text x="332" y="230" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">WRITES</text>
<rect x="688" y="300" width="56" height="14" rx="2" fill="#f5f4ed"/>
<text x="716" y="310" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">TAGGED</text>
<rect x="688" y="300" width="56" height="14" rx="2" fill="#f5f5f5"/>
<text x="716" y="310" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">TAGGED</text>
<!-- Entity: Author -->
<rect x="60" y="160" width="200" height="160" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="60" y="160" width="200" height="40" rx="6" fill="rgba(11,13,11,0.04)" stroke="none"/>
<rect x="60" y="192" width="200" height="8" fill="rgba(11,13,11,0.04)"/>
<line x1="60" y1="200" x2="260" y2="200" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<text x="76" y="176" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="76" y="192" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Author</text>
<text x="76" y="220" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="220" y="220" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="76" y="240" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">handle</text>
<text x="220" y="240" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="260" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="220" y="260" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="280" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">bio</text>
<text x="220" y="280" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="300" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">site_url</text>
<text x="220" y="300" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<rect x="60" y="160" width="200" height="160" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="60" y="160" width="200" height="40" rx="6" fill="rgba(45,49,66,0.04)" stroke="none"/>
<rect x="60" y="192" width="200" height="8" fill="rgba(45,49,66,0.04)"/>
<line x1="60" y1="200" x2="260" y2="200" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<text x="76" y="176" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="76" y="192" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Author</text>
<text x="76" y="220" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="220" y="220" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="76" y="240" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">handle</text>
<text x="220" y="240" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="260" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="220" y="260" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="280" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">bio</text>
<text x="220" y="280" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="76" y="300" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">site_url</text>
<text x="220" y="300" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<!-- Entity: Article (focal coral) -->
<rect x="400" y="120" width="240" height="240" rx="6" fill="rgba(247,89,31,0.04)" stroke="#f7591f" stroke-width="1"/>
<rect x="400" y="120" width="240" height="40" rx="6" fill="rgba(247,89,31,0.10)" stroke="none"/>
<rect x="400" y="152" width="240" height="8" fill="rgba(247,89,31,0.10)"/>
<line x1="400" y1="160" x2="640" y2="160" stroke="rgba(247,89,31,0.40)" stroke-width="1"/>
<text x="416" y="136" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY · AGGREGATE ROOT</text>
<text x="416" y="152" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Article</text>
<text x="416" y="180" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="600" y="180" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="200" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">title</text>
<text x="600" y="200" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="220" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="600" y="220" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="416" y="240" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">body_mdx</text>
<text x="600" y="240" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="260" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">published_at</text>
<text x="600" y="260" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">timestamp</text>
<text x="416" y="280" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">→ author_id</text>
<text x="600" y="280" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="300" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">status</text>
<text x="600" y="300" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">enum</text>
<text x="416" y="320" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">og_image</text>
<text x="600" y="320" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · url</text>
<rect x="400" y="120" width="240" height="240" rx="6" fill="rgba(235,108,54,0.04)" stroke="#eb6c36" stroke-width="1"/>
<rect x="400" y="120" width="240" height="40" rx="6" fill="rgba(235,108,54,0.10)" stroke="none"/>
<rect x="400" y="152" width="240" height="8" fill="rgba(235,108,54,0.10)"/>
<line x1="400" y1="160" x2="640" y2="160" stroke="rgba(235,108,54,0.40)" stroke-width="1"/>
<text x="416" y="136" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY · AGGREGATE ROOT</text>
<text x="416" y="152" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Article</text>
<text x="416" y="180" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="600" y="180" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="200" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">title</text>
<text x="600" y="200" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="220" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="600" y="220" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="416" y="240" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">body_mdx</text>
<text x="600" y="240" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="416" y="260" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">published_at</text>
<text x="600" y="260" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">timestamp</text>
<text x="416" y="280" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">→ author_id</text>
<text x="600" y="280" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="416" y="300" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">status</text>
<text x="600" y="300" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">enum</text>
<text x="416" y="320" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">og_image</text>
<text x="600" y="320" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · url</text>
<!-- Entity: Tag -->
<rect x="780" y="120" width="200" height="128" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="780" y="120" width="200" height="40" rx="6" fill="rgba(11,13,11,0.04)" stroke="none"/>
<rect x="780" y="152" width="200" height="8" fill="rgba(11,13,11,0.04)"/>
<line x1="780" y1="160" x2="980" y2="160" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<text x="796" y="136" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="796" y="152" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Tag</text>
<text x="796" y="180" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="940" y="180" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="200" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="940" y="200" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="796" y="220" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="940" y="220" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="796" y="240" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">description</text>
<text x="940" y="240" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<rect x="780" y="120" width="200" height="128" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="780" y="120" width="200" height="40" rx="6" fill="rgba(45,49,66,0.04)" stroke="none"/>
<rect x="780" y="152" width="200" height="8" fill="rgba(45,49,66,0.04)"/>
<line x1="780" y1="160" x2="980" y2="160" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<text x="796" y="136" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">ENTITY</text>
<text x="796" y="152" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif">Tag</text>
<text x="796" y="180" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace"># id</text>
<text x="940" y="180" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="200" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">slug</text>
<text x="940" y="200" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text · unique</text>
<text x="796" y="220" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">name</text>
<text x="940" y="220" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<text x="796" y="240" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">description</text>
<text x="940" y="240" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">text</text>
<!-- Entity: ArticleTag (join) -->
<rect x="780" y="280" width="200" height="96" rx="6" fill="rgba(11,13,11,0.04)" stroke="#52534e" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="780" y="280" width="200" height="40" rx="6" fill="rgba(11,13,11,0.06)" stroke="none"/>
<rect x="780" y="312" width="200" height="8" fill="rgba(11,13,11,0.06)"/>
<line x1="780" y1="320" x2="980" y2="320" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<text x="796" y="296" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">JOIN</text>
<text x="796" y="312" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif">ArticleTag</text>
<text x="796" y="340" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">→ article_id</text>
<text x="940" y="340" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="360" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace">→ tag_id</text>
<text x="940" y="360" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<rect x="780" y="280" width="200" height="96" rx="6" fill="rgba(45,49,66,0.04)" stroke="#4f5d75" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="780" y="280" width="200" height="40" rx="6" fill="rgba(45,49,66,0.06)" stroke="none"/>
<rect x="780" y="312" width="200" height="8" fill="rgba(45,49,66,0.06)"/>
<line x1="780" y1="320" x2="980" y2="320" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<text x="796" y="296" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">JOIN</text>
<text x="796" y="312" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif">ArticleTag</text>
<text x="796" y="340" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">→ article_id</text>
<text x="940" y="340" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<text x="796" y="360" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace">→ tag_id</text>
<text x="940" y="360" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end">uuid</text>
<!-- Legend -->
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="404" x2="960" y2="404" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="420" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(247,89,31,0.04)" stroke="#f7591f" stroke-width="1"/>
<text x="60" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Aggregate root</text>
<rect x="40" y="436" width="14" height="10" rx="2" fill="rgba(235,108,54,0.04)" stroke="#eb6c36" stroke-width="1"/>
<text x="60" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Aggregate root</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="200" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Entity</text>
<rect x="180" y="436" width="14" height="10" rx="2" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="200" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Entity</text>
<rect x="268" y="436" width="14" height="10" rx="2" fill="rgba(11,13,11,0.04)" stroke="#52534e" stroke-width="1" stroke-dasharray="3,2"/>
<text x="288" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Join table</text>
<rect x="268" y="436" width="14" height="10" rx="2" fill="rgba(45,49,66,0.04)" stroke="#4f5d75" stroke-width="1" stroke-dasharray="3,2"/>
<text x="288" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Join table</text>
<text x="372" y="444" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">#</text>
<text x="388" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Primary key</text>
<text x="372" y="444" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">#</text>
<text x="388" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Primary key</text>
<text x="476" y="444" fill="#0b0d0b" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">→</text>
<text x="492" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Foreign key</text>
<text x="476" y="444" fill="#2d3142" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">→</text>
<text x="492" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Foreign key</text>
<text x="584" y="444" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">1 / N</text>
<text x="616" y="444" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Cardinality</text>
<text x="584" y="444" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" font-weight="600">1 / N</text>
<text x="616" y="444" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Cardinality</text>
</svg>
</div>
</body>
+53 -53
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,93 +61,93 @@
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#a8a69d"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#ff6a30"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f08a59"/></marker>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Arrows (drawn first, behind nodes) -->
<!-- Start → Step -->
<line x1="500" y1="88" x2="500" y2="120" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="500" y1="88" x2="500" y2="120" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Step → Diamond 1 -->
<line x1="500" y1="168" x2="500" y2="192" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="500" y1="168" x2="500" y2="192" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 1 "NO" right -->
<line x1="600" y1="240" x2="720" y2="240" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="600" y1="240" x2="720" y2="240" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 1 "YES" down -->
<line x1="500" y1="288" x2="500" y2="328" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="500" y1="288" x2="500" y2="328" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 2 "NO" right -->
<line x1="600" y1="376" x2="720" y2="376" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="600" y1="376" x2="720" y2="376" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 2 "YES" down (coral — happy path) -->
<line x1="500" y1="424" x2="500" y2="464" stroke="#ff6a30" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="500" y1="424" x2="500" y2="464" stroke="#f08a59" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- Arrow labels -->
<rect x="644" y="230" width="24" height="12" rx="2" fill="#1c1a17"/>
<text x="656" y="239" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="644" y="230" width="24" height="12" rx="2" fill="#2d3142"/>
<text x="656" y="239" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="484" y="298" width="32" height="12" rx="2" fill="#1c1a17"/>
<text x="500" y="307" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<rect x="484" y="298" width="32" height="12" rx="2" fill="#2d3142"/>
<text x="500" y="307" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<rect x="644" y="366" width="24" height="12" rx="2" fill="#1c1a17"/>
<text x="656" y="375" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="644" y="366" width="24" height="12" rx="2" fill="#2d3142"/>
<text x="656" y="375" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="484" y="434" width="32" height="12" rx="2" fill="#1c1a17"/>
<text x="500" y="443" fill="#ff6a30" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<rect x="484" y="434" width="32" height="12" rx="2" fill="#2d3142"/>
<text x="500" y="443" fill="#f08a59" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<!-- Start oval -->
<rect x="420" y="40" width="160" height="48" rx="24" fill="rgba(241,239,231,0.03)" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<text x="500" y="68" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">New workflow</text>
<rect x="420" y="40" width="160" height="48" rx="24" fill="rgba(245,245,245,0.03)" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<text x="500" y="68" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">New workflow</text>
<!-- Rectangle: Step -->
<rect x="420" y="120" width="160" height="48" rx="6" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="500" y="148" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Do it manually once</text>
<rect x="420" y="120" width="160" height="48" rx="6" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="500" y="148" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Do it manually once</text>
<!-- Diamond 1: Repeated >3 times? -->
<polygon points="500,192 600,240 500,288 400,240" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="500" y="238" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Will you repeat</text>
<text x="500" y="252" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">it >3 times?</text>
<polygon points="500,192 600,240 500,288 400,240" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="500" y="238" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Will you repeat</text>
<text x="500" y="252" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">it >3 times?</text>
<!-- End oval: One-off -->
<rect x="720" y="216" width="160" height="48" rx="24" fill="rgba(241,239,231,0.03)" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<text x="800" y="240" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">One-off</text>
<text x="800" y="254" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">keep manual</text>
<rect x="720" y="216" width="160" height="48" rx="24" fill="rgba(245,245,245,0.03)" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<text x="800" y="240" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">One-off</text>
<text x="800" y="254" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">keep manual</text>
<!-- Diamond 2: Reusable across projects? -->
<polygon points="500,328 600,376 500,424 400,376" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="500" y="374" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reusable across</text>
<text x="500" y="388" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">projects?</text>
<polygon points="500,328 600,376 500,424 400,376" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="500" y="374" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reusable across</text>
<text x="500" y="388" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">projects?</text>
<!-- End oval: CLAUDE.md note -->
<rect x="720" y="352" width="160" height="48" rx="24" fill="rgba(241,239,231,0.03)" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<text x="800" y="376" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md note</text>
<text x="800" y="390" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">project-scoped</text>
<rect x="720" y="352" width="160" height="48" rx="24" fill="rgba(245,245,245,0.03)" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<text x="800" y="376" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md note</text>
<text x="800" y="390" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">project-scoped</text>
<!-- End oval: Write a skill (coral focal) -->
<rect x="420" y="464" width="160" height="56" rx="28" fill="rgba(255,106,48,0.08)" stroke="#ff6a30" stroke-width="1"/>
<text x="500" y="492" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Write a skill</text>
<text x="500" y="508" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">reusable + assets</text>
<rect x="420" y="464" width="160" height="56" rx="28" fill="rgba(240,138,89,0.08)" stroke="#f08a59" stroke-width="1"/>
<text x="500" y="492" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Write a skill</text>
<text x="500" y="508" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">reusable + assets</text>
<!-- Legend -->
<line x1="40" y1="540" x2="960" y2="540" stroke="rgba(241,239,231,0.10)" stroke-width="0.8"/>
<text x="40" y="556" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND · SHAPE CARRIES TYPE</text>
<line x1="40" y1="540" x2="960" y2="540" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<text x="40" y="556" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND · SHAPE CARRIES TYPE</text>
<rect x="40" y="572" width="24" height="12" rx="6" fill="rgba(241,239,231,0.03)" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<text x="72" y="582" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Start / end (oval)</text>
<rect x="40" y="572" width="24" height="12" rx="6" fill="rgba(245,245,245,0.03)" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<text x="72" y="582" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Start / end (oval)</text>
<rect x="220" y="572" width="24" height="12" rx="2" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="252" y="582" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Step (rectangle)</text>
<rect x="220" y="572" width="24" height="12" rx="2" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="252" y="582" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Step (rectangle)</text>
<polygon points="412,578 424,572 436,578 424,584" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="448" y="582" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Decision (diamond)</text>
<polygon points="412,578 424,572 436,578 424,584" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="448" y="582" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Decision (diamond)</text>
<line x1="604" y1="580" x2="632" y2="580" stroke="#ff6a30" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="640" y="582" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Happy path</text>
<line x1="604" y1="580" x2="632" y2="580" stroke="#f08a59" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="640" y="582" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Happy path</text>
<line x1="768" y1="580" x2="796" y2="580" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="804" y="582" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Branch</text>
<line x1="768" y1="580" x2="796" y2="580" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="804" y="582" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Branch</text>
</svg>
</div>
</body>
+54 -54
View File
@@ -7,7 +7,7 @@
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root { --color-paper:#f5f4ed; --color-paper-2:#efeee5; --color-ink:#0b0d0b; --color-muted:#52534e; --color-soft:#65655c; --color-rule:rgba(11,13,11,0.12); --color-accent:#f7591f; --color-link:#1a70c7; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --color-link:#2e5aa8; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
@@ -20,14 +20,14 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
@@ -42,93 +42,93 @@
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#52534e"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f7591f"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Arrows (drawn first, behind nodes) -->
<!-- Start → Step -->
<line x1="500" y1="88" x2="500" y2="120" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="500" y1="88" x2="500" y2="120" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Step → Diamond 1 -->
<line x1="500" y1="168" x2="500" y2="192" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="500" y1="168" x2="500" y2="192" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 1 "NO" right -->
<line x1="600" y1="240" x2="720" y2="240" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="600" y1="240" x2="720" y2="240" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 1 "YES" down -->
<line x1="500" y1="288" x2="500" y2="328" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="500" y1="288" x2="500" y2="328" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 2 "NO" right -->
<line x1="600" y1="376" x2="720" y2="376" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="600" y1="376" x2="720" y2="376" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 2 "YES" down (coral — happy path) -->
<line x1="500" y1="424" x2="500" y2="464" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="500" y1="424" x2="500" y2="464" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- Arrow labels -->
<rect x="644" y="230" width="24" height="12" rx="2" fill="#f5f4ed"/>
<text x="656" y="239" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="644" y="230" width="24" height="12" rx="2" fill="#f5f5f5"/>
<text x="656" y="239" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="484" y="298" width="32" height="12" rx="2" fill="#f5f4ed"/>
<text x="500" y="307" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<rect x="484" y="298" width="32" height="12" rx="2" fill="#f5f5f5"/>
<text x="500" y="307" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<rect x="644" y="366" width="24" height="12" rx="2" fill="#f5f4ed"/>
<text x="656" y="375" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="644" y="366" width="24" height="12" rx="2" fill="#f5f5f5"/>
<text x="656" y="375" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="484" y="434" width="32" height="12" rx="2" fill="#f5f4ed"/>
<text x="500" y="443" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<rect x="484" y="434" width="32" height="12" rx="2" fill="#f5f5f5"/>
<text x="500" y="443" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<!-- Start oval -->
<rect x="420" y="40" width="160" height="48" rx="24" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="500" y="68" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">New workflow</text>
<rect x="420" y="40" width="160" height="48" rx="24" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="500" y="68" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">New workflow</text>
<!-- Rectangle: Step -->
<rect x="420" y="120" width="160" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="500" y="148" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Do it manually once</text>
<rect x="420" y="120" width="160" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="500" y="148" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Do it manually once</text>
<!-- Diamond 1: Repeated >3 times? -->
<polygon points="500,192 600,240 500,288 400,240" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="500" y="238" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Will you repeat</text>
<text x="500" y="252" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">it >3 times?</text>
<polygon points="500,192 600,240 500,288 400,240" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="500" y="238" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Will you repeat</text>
<text x="500" y="252" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">it >3 times?</text>
<!-- End oval: One-off -->
<rect x="720" y="216" width="160" height="48" rx="24" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="800" y="240" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">One-off</text>
<text x="800" y="254" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">keep manual</text>
<rect x="720" y="216" width="160" height="48" rx="24" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="800" y="240" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">One-off</text>
<text x="800" y="254" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">keep manual</text>
<!-- Diamond 2: Reusable across projects? -->
<polygon points="500,328 600,376 500,424 400,376" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="500" y="374" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reusable across</text>
<text x="500" y="388" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">projects?</text>
<polygon points="500,328 600,376 500,424 400,376" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="500" y="374" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reusable across</text>
<text x="500" y="388" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">projects?</text>
<!-- End oval: CLAUDE.md note -->
<rect x="720" y="352" width="160" height="48" rx="24" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="800" y="376" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md note</text>
<text x="800" y="390" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">project-scoped</text>
<rect x="720" y="352" width="160" height="48" rx="24" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="800" y="376" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md note</text>
<text x="800" y="390" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">project-scoped</text>
<!-- End oval: Write a skill (coral focal) -->
<rect x="420" y="464" width="160" height="56" rx="28" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="500" y="492" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Write a skill</text>
<text x="500" y="508" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">reusable + assets</text>
<rect x="420" y="464" width="160" height="56" rx="28" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="500" y="492" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Write a skill</text>
<text x="500" y="508" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">reusable + assets</text>
<!-- Legend -->
<line x1="40" y1="540" x2="960" y2="540" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="556" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND · SHAPE CARRIES TYPE</text>
<line x1="40" y1="540" x2="960" y2="540" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="556" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND · SHAPE CARRIES TYPE</text>
<rect x="40" y="572" width="24" height="12" rx="6" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="72" y="582" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Start / end (oval)</text>
<rect x="40" y="572" width="24" height="12" rx="6" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="72" y="582" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Start / end (oval)</text>
<rect x="220" y="572" width="24" height="12" rx="2" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="252" y="582" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Step (rectangle)</text>
<rect x="220" y="572" width="24" height="12" rx="2" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="252" y="582" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Step (rectangle)</text>
<polygon points="412,578 424,572 436,578 424,584" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="448" y="582" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Decision (diamond)</text>
<polygon points="412,578 424,572 436,578 424,584" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="448" y="582" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Decision (diamond)</text>
<line x1="604" y1="580" x2="632" y2="580" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="640" y="582" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Happy path</text>
<line x1="604" y1="580" x2="632" y2="580" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="640" y="582" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Happy path</text>
<line x1="768" y1="580" x2="796" y2="580" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="804" y="582" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Branch</text>
<line x1="768" y1="580" x2="796" y2="580" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="804" y="582" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Branch</text>
</svg>
</div>
@@ -150,7 +150,7 @@
<div class="footer">
<span>flowchart · should I write this as a skill?</span>
<span>example · diagram-design</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+53 -53
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,93 +61,93 @@
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#52534e"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f7591f"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Arrows (drawn first, behind nodes) -->
<!-- Start → Step -->
<line x1="500" y1="88" x2="500" y2="120" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="500" y1="88" x2="500" y2="120" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Step → Diamond 1 -->
<line x1="500" y1="168" x2="500" y2="192" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="500" y1="168" x2="500" y2="192" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 1 "NO" right -->
<line x1="600" y1="240" x2="720" y2="240" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="600" y1="240" x2="720" y2="240" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 1 "YES" down -->
<line x1="500" y1="288" x2="500" y2="328" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="500" y1="288" x2="500" y2="328" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 2 "NO" right -->
<line x1="600" y1="376" x2="720" y2="376" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="600" y1="376" x2="720" y2="376" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Diamond 2 "YES" down (coral — happy path) -->
<line x1="500" y1="424" x2="500" y2="464" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="500" y1="424" x2="500" y2="464" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- Arrow labels -->
<rect x="644" y="230" width="24" height="12" rx="2" fill="#f5f4ed"/>
<text x="656" y="239" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="644" y="230" width="24" height="12" rx="2" fill="#f5f5f5"/>
<text x="656" y="239" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="484" y="298" width="32" height="12" rx="2" fill="#f5f4ed"/>
<text x="500" y="307" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<rect x="484" y="298" width="32" height="12" rx="2" fill="#f5f5f5"/>
<text x="500" y="307" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<rect x="644" y="366" width="24" height="12" rx="2" fill="#f5f4ed"/>
<text x="656" y="375" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="644" y="366" width="24" height="12" rx="2" fill="#f5f5f5"/>
<text x="656" y="375" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">NO</text>
<rect x="484" y="434" width="32" height="12" rx="2" fill="#f5f4ed"/>
<text x="500" y="443" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<rect x="484" y="434" width="32" height="12" rx="2" fill="#f5f5f5"/>
<text x="500" y="443" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">YES</text>
<!-- Start oval -->
<rect x="420" y="40" width="160" height="48" rx="24" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="500" y="68" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">New workflow</text>
<rect x="420" y="40" width="160" height="48" rx="24" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="500" y="68" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">New workflow</text>
<!-- Rectangle: Step -->
<rect x="420" y="120" width="160" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="500" y="148" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Do it manually once</text>
<rect x="420" y="120" width="160" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="500" y="148" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Do it manually once</text>
<!-- Diamond 1: Repeated >3 times? -->
<polygon points="500,192 600,240 500,288 400,240" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="500" y="238" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Will you repeat</text>
<text x="500" y="252" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">it >3 times?</text>
<polygon points="500,192 600,240 500,288 400,240" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="500" y="238" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Will you repeat</text>
<text x="500" y="252" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">it >3 times?</text>
<!-- End oval: One-off -->
<rect x="720" y="216" width="160" height="48" rx="24" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="800" y="240" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">One-off</text>
<text x="800" y="254" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">keep manual</text>
<rect x="720" y="216" width="160" height="48" rx="24" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="800" y="240" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">One-off</text>
<text x="800" y="254" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">keep manual</text>
<!-- Diamond 2: Reusable across projects? -->
<polygon points="500,328 600,376 500,424 400,376" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="500" y="374" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reusable across</text>
<text x="500" y="388" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">projects?</text>
<polygon points="500,328 600,376 500,424 400,376" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="500" y="374" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reusable across</text>
<text x="500" y="388" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">projects?</text>
<!-- End oval: CLAUDE.md note -->
<rect x="720" y="352" width="160" height="48" rx="24" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="800" y="376" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md note</text>
<text x="800" y="390" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">project-scoped</text>
<rect x="720" y="352" width="160" height="48" rx="24" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="800" y="376" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md note</text>
<text x="800" y="390" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">project-scoped</text>
<!-- End oval: Write a skill (coral focal) -->
<rect x="420" y="464" width="160" height="56" rx="28" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="500" y="492" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Write a skill</text>
<text x="500" y="508" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">reusable + assets</text>
<rect x="420" y="464" width="160" height="56" rx="28" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="500" y="492" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Write a skill</text>
<text x="500" y="508" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">reusable + assets</text>
<!-- Legend -->
<line x1="40" y1="540" x2="960" y2="540" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="556" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND · SHAPE CARRIES TYPE</text>
<line x1="40" y1="540" x2="960" y2="540" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="556" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND · SHAPE CARRIES TYPE</text>
<rect x="40" y="572" width="24" height="12" rx="6" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="72" y="582" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Start / end (oval)</text>
<rect x="40" y="572" width="24" height="12" rx="6" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="72" y="582" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Start / end (oval)</text>
<rect x="220" y="572" width="24" height="12" rx="2" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="252" y="582" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Step (rectangle)</text>
<rect x="220" y="572" width="24" height="12" rx="2" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="252" y="582" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Step (rectangle)</text>
<polygon points="412,578 424,572 436,578 424,584" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="448" y="582" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Decision (diamond)</text>
<polygon points="412,578 424,572 436,578 424,584" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="448" y="582" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Decision (diamond)</text>
<line x1="604" y1="580" x2="632" y2="580" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="640" y="582" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Happy path</text>
<line x1="604" y1="580" x2="632" y2="580" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="640" y="582" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Happy path</text>
<line x1="768" y1="580" x2="796" y2="580" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="804" y="582" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Branch</text>
<line x1="768" y1="580" x2="796" y2="580" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="804" y="582" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Branch</text>
</svg>
</div>
</body>
+36 -36
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,60 +61,60 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Direction column (left margin) -->
<text x="60" y="68" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">ABSTRACTION</text>
<line x1="80" y1="80" x2="80" y2="400" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<polygon points="76,80 84,80 80,72" fill="#a8a69d"/>
<text x="60" y="416" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">SILICON</text>
<text x="60" y="68" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">ABSTRACTION</text>
<line x1="80" y1="80" x2="80" y2="400" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<polygon points="76,80 84,80 80,72" fill="#bfc0c0"/>
<text x="60" y="416" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">SILICON</text>
<!-- Stack container hairlines (top + bottom edges) -->
<line x1="120" y1="80" x2="960" y2="80" stroke="rgba(241,239,231,0.12)" stroke-width="1"/>
<line x1="120" y1="400" x2="960" y2="400" stroke="rgba(241,239,231,0.12)" stroke-width="1"/>
<line x1="120" y1="80" x2="960" y2="80" stroke="rgba(245,245,245,0.12)" stroke-width="1"/>
<line x1="120" y1="400" x2="960" y2="400" stroke="rgba(245,245,245,0.12)" stroke-width="1"/>
<!-- L5 — UI (top layer, lifted fill) -->
<rect x="120" y="80" width="840" height="64" fill="#2a2723"/>
<line x1="120" y1="144" x2="960" y2="144" stroke="rgba(241,239,231,0.12)" stroke-width="1"/>
<text x="140" y="116" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L5</text>
<text x="260" y="118" fill="#f1efe7" font-size="16" font-weight="600" font-family="'Geist', sans-serif">UI surface</text>
<text x="940" y="118" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">chat, editor, canvas</text>
<rect x="120" y="80" width="840" height="64" fill="#393e53"/>
<line x1="120" y1="144" x2="960" y2="144" stroke="rgba(245,245,245,0.12)" stroke-width="1"/>
<text x="140" y="116" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L5</text>
<text x="260" y="118" fill="#f5f5f5" font-size="16" font-weight="600" font-family="'Geist', sans-serif">UI surface</text>
<text x="940" y="118" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">chat, editor, canvas</text>
<!-- L4 — Agent harness (FOCAL, coral tint + coral stroke) -->
<rect x="120" y="144" width="840" height="64" fill="rgba(255,106,48,0.12)"/>
<rect x="120" y="144" width="840" height="64" fill="none" stroke="#ff6a30" stroke-width="1"/>
<text x="140" y="180" fill="#ff6a30" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">L4</text>
<text x="260" y="182" fill="#f1efe7" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Agent harness</text>
<text x="940" y="182" fill="#ff6a30" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">tools, memory, loop</text>
<rect x="120" y="144" width="840" height="64" fill="rgba(240,138,89,0.12)"/>
<rect x="120" y="144" width="840" height="64" fill="none" stroke="#f08a59" stroke-width="1"/>
<text x="140" y="180" fill="#f08a59" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">L4</text>
<text x="260" y="182" fill="#f5f5f5" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Agent harness</text>
<text x="940" y="182" fill="#f08a59" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">tools, memory, loop</text>
<!-- L3 — Prompt layer -->
<rect x="120" y="208" width="840" height="64" fill="#1c1a17"/>
<line x1="120" y1="272" x2="960" y2="272" stroke="rgba(241,239,231,0.12)" stroke-width="1"/>
<text x="140" y="244" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L3</text>
<text x="260" y="246" fill="#f1efe7" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Prompt layer</text>
<text x="940" y="246" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">system, few-shot, caching</text>
<rect x="120" y="208" width="840" height="64" fill="#2d3142"/>
<line x1="120" y1="272" x2="960" y2="272" stroke="rgba(245,245,245,0.12)" stroke-width="1"/>
<text x="140" y="244" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L3</text>
<text x="260" y="246" fill="#f5f5f5" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Prompt layer</text>
<text x="940" y="246" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">system, few-shot, caching</text>
<!-- L2 — SDK -->
<rect x="120" y="272" width="840" height="64" fill="#221f1c"/>
<line x1="120" y1="336" x2="960" y2="336" stroke="rgba(241,239,231,0.12)" stroke-width="1"/>
<text x="140" y="308" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L2</text>
<text x="260" y="310" fill="#f1efe7" font-size="16" font-weight="600" font-family="'Geist', sans-serif">SDK / client</text>
<text x="940" y="310" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">auth, retries, streaming</text>
<line x1="120" y1="336" x2="960" y2="336" stroke="rgba(245,245,245,0.12)" stroke-width="1"/>
<text x="140" y="308" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L2</text>
<text x="260" y="310" fill="#f5f5f5" font-size="16" font-weight="600" font-family="'Geist', sans-serif">SDK / client</text>
<text x="940" y="310" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">auth, retries, streaming</text>
<!-- L1 — Model -->
<rect x="120" y="336" width="840" height="64" fill="#221f1c"/>
<text x="140" y="372" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L1</text>
<text x="260" y="374" fill="#f1efe7" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Model weights</text>
<text x="940" y="374" fill="#a8a69d" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">opus, sonnet, haiku</text>
<text x="140" y="372" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L1</text>
<text x="260" y="374" fill="#f5f5f5" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Model weights</text>
<text x="940" y="374" fill="#bfc0c0" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">opus, sonnet, haiku</text>
<!-- Caption -->
<text x="120" y="456" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">FOCAL LAYER</text>
<text x="240" y="456" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">The harness is where most product differentiation actually lives — tools, memory, and the loop that stitches model calls into useful work.</text>
<text x="120" y="456" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">FOCAL LAYER</text>
<text x="240" y="456" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">The harness is where most product differentiation actually lives — tools, memory, and the loop that stitches model calls into useful work.</text>
</svg>
</div>
</body>
+38 -38
View File
@@ -7,7 +7,7 @@
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root { --color-paper:#f5f4ed; --color-paper-2:#efeee5; --color-ink:#0b0d0b; --color-muted:#52534e; --color-soft:#65655c; --color-rule:rgba(11,13,11,0.12); --color-accent:#f7591f; --color-link:#1a70c7; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --color-link:#2e5aa8; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
@@ -20,14 +20,14 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
@@ -42,60 +42,60 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Direction column (left margin) -->
<text x="60" y="68" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">ABSTRACTION</text>
<line x1="80" y1="80" x2="80" y2="400" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<polygon points="76,80 84,80 80,72" fill="#52534e"/>
<text x="60" y="416" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">SILICON</text>
<text x="60" y="68" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">ABSTRACTION</text>
<line x1="80" y1="80" x2="80" y2="400" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<polygon points="76,80 84,80 80,72" fill="#4f5d75"/>
<text x="60" y="416" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">SILICON</text>
<!-- Stack container hairlines (top + bottom edges) -->
<line x1="120" y1="80" x2="960" y2="80" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<line x1="120" y1="400" x2="960" y2="400" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<line x1="120" y1="80" x2="960" y2="80" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<line x1="120" y1="400" x2="960" y2="400" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<!-- L5 — UI (top layer, near-white fill) -->
<rect x="120" y="80" width="840" height="64" fill="#ffffff"/>
<line x1="120" y1="144" x2="960" y2="144" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="140" y="116" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L5</text>
<text x="260" y="118" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif">UI surface</text>
<text x="940" y="118" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">chat, editor, canvas</text>
<line x1="120" y1="144" x2="960" y2="144" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="140" y="116" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L5</text>
<text x="260" y="118" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">UI surface</text>
<text x="940" y="118" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">chat, editor, canvas</text>
<!-- L4 — Agent harness (FOCAL, coral tint + coral stroke) -->
<rect x="120" y="144" width="840" height="64" fill="rgba(247,89,31,0.08)"/>
<rect x="120" y="144" width="840" height="64" fill="none" stroke="#f7591f" stroke-width="1"/>
<text x="140" y="180" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">L4</text>
<text x="260" y="182" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Agent harness</text>
<text x="940" y="182" fill="#f7591f" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">tools, memory, loop</text>
<rect x="120" y="144" width="840" height="64" fill="rgba(235,108,54,0.08)"/>
<rect x="120" y="144" width="840" height="64" fill="none" stroke="#eb6c36" stroke-width="1"/>
<text x="140" y="180" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">L4</text>
<text x="260" y="182" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Agent harness</text>
<text x="940" y="182" fill="#eb6c36" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">tools, memory, loop</text>
<!-- L3 — Prompt layer -->
<rect x="120" y="208" width="840" height="64" fill="#f5f4ed"/>
<line x1="120" y1="272" x2="960" y2="272" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="140" y="244" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L3</text>
<text x="260" y="246" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Prompt layer</text>
<text x="940" y="246" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">system, few-shot, caching</text>
<rect x="120" y="208" width="840" height="64" fill="#f5f5f5"/>
<line x1="120" y1="272" x2="960" y2="272" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="140" y="244" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L3</text>
<text x="260" y="246" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Prompt layer</text>
<text x="940" y="246" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">system, few-shot, caching</text>
<!-- L2 — SDK -->
<rect x="120" y="272" width="840" height="64" fill="#efeee5"/>
<line x1="120" y1="336" x2="960" y2="336" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="140" y="308" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L2</text>
<text x="260" y="310" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif">SDK / client</text>
<text x="940" y="310" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">auth, retries, streaming</text>
<rect x="120" y="272" width="840" height="64" fill="#ececec"/>
<line x1="120" y1="336" x2="960" y2="336" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="140" y="308" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L2</text>
<text x="260" y="310" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">SDK / client</text>
<text x="940" y="310" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">auth, retries, streaming</text>
<!-- L1 — Model -->
<rect x="120" y="336" width="840" height="64" fill="#efeee5"/>
<text x="140" y="372" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L1</text>
<text x="260" y="374" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Model weights</text>
<text x="940" y="374" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">opus, sonnet, haiku</text>
<rect x="120" y="336" width="840" height="64" fill="#ececec"/>
<text x="140" y="372" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L1</text>
<text x="260" y="374" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Model weights</text>
<text x="940" y="374" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">opus, sonnet, haiku</text>
<!-- Caption -->
<text x="120" y="456" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">FOCAL LAYER</text>
<text x="240" y="456" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">The harness is where most product differentiation actually lives — tools, memory, and the loop that stitches model calls into useful work.</text>
<text x="120" y="456" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">FOCAL LAYER</text>
<text x="240" y="456" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">The harness is where most product differentiation actually lives — tools, memory, and the loop that stitches model calls into useful work.</text>
</svg>
</div>
@@ -117,7 +117,7 @@
<div class="footer">
<span>ai app stack · layer hierarchy</span>
<span>example · diagram-design</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+37 -37
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,60 +61,60 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Direction column (left margin) -->
<text x="60" y="68" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">ABSTRACTION</text>
<line x1="80" y1="80" x2="80" y2="400" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<polygon points="76,80 84,80 80,72" fill="#52534e"/>
<text x="60" y="416" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">SILICON</text>
<text x="60" y="68" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">ABSTRACTION</text>
<line x1="80" y1="80" x2="80" y2="400" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<polygon points="76,80 84,80 80,72" fill="#4f5d75"/>
<text x="60" y="416" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">SILICON</text>
<!-- Stack container hairlines (top + bottom edges) -->
<line x1="120" y1="80" x2="960" y2="80" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<line x1="120" y1="400" x2="960" y2="400" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<line x1="120" y1="80" x2="960" y2="80" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<line x1="120" y1="400" x2="960" y2="400" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<!-- L5 — UI (top layer, near-white fill) -->
<rect x="120" y="80" width="840" height="64" fill="#ffffff"/>
<line x1="120" y1="144" x2="960" y2="144" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="140" y="116" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L5</text>
<text x="260" y="118" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif">UI surface</text>
<text x="940" y="118" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">chat, editor, canvas</text>
<line x1="120" y1="144" x2="960" y2="144" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="140" y="116" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L5</text>
<text x="260" y="118" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">UI surface</text>
<text x="940" y="118" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">chat, editor, canvas</text>
<!-- L4 — Agent harness (FOCAL, coral tint + coral stroke) -->
<rect x="120" y="144" width="840" height="64" fill="rgba(247,89,31,0.08)"/>
<rect x="120" y="144" width="840" height="64" fill="none" stroke="#f7591f" stroke-width="1"/>
<text x="140" y="180" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">L4</text>
<text x="260" y="182" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Agent harness</text>
<text x="940" y="182" fill="#f7591f" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">tools, memory, loop</text>
<rect x="120" y="144" width="840" height="64" fill="rgba(235,108,54,0.08)"/>
<rect x="120" y="144" width="840" height="64" fill="none" stroke="#eb6c36" stroke-width="1"/>
<text x="140" y="180" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">L4</text>
<text x="260" y="182" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Agent harness</text>
<text x="940" y="182" fill="#eb6c36" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">tools, memory, loop</text>
<!-- L3 — Prompt layer -->
<rect x="120" y="208" width="840" height="64" fill="#f5f4ed"/>
<line x1="120" y1="272" x2="960" y2="272" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="140" y="244" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L3</text>
<text x="260" y="246" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Prompt layer</text>
<text x="940" y="246" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">system, few-shot, caching</text>
<rect x="120" y="208" width="840" height="64" fill="#f5f5f5"/>
<line x1="120" y1="272" x2="960" y2="272" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="140" y="244" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L3</text>
<text x="260" y="246" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Prompt layer</text>
<text x="940" y="246" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">system, few-shot, caching</text>
<!-- L2 — SDK -->
<rect x="120" y="272" width="840" height="64" fill="#efeee5"/>
<line x1="120" y1="336" x2="960" y2="336" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="140" y="308" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L2</text>
<text x="260" y="310" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif">SDK / client</text>
<text x="940" y="310" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">auth, retries, streaming</text>
<rect x="120" y="272" width="840" height="64" fill="#ececec"/>
<line x1="120" y1="336" x2="960" y2="336" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="140" y="308" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L2</text>
<text x="260" y="310" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">SDK / client</text>
<text x="940" y="310" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">auth, retries, streaming</text>
<!-- L1 — Model -->
<rect x="120" y="336" width="840" height="64" fill="#efeee5"/>
<text x="140" y="372" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L1</text>
<text x="260" y="374" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Model weights</text>
<text x="940" y="374" fill="#52534e" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">opus, sonnet, haiku</text>
<rect x="120" y="336" width="840" height="64" fill="#ececec"/>
<text x="140" y="372" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">L1</text>
<text x="260" y="374" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Model weights</text>
<text x="940" y="374" fill="#4f5d75" font-size="10" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.08em">opus, sonnet, haiku</text>
<!-- Caption -->
<text x="120" y="456" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">FOCAL LAYER</text>
<text x="240" y="456" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">The harness is where most product differentiation actually lives — tools, memory, and the loop that stitches model calls into useful work.</text>
<text x="120" y="456" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">FOCAL LAYER</text>
<text x="240" y="456" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">The harness is where most product differentiation actually lives — tools, memory, and the loop that stitches model calls into useful work.</text>
</svg>
</div>
</body>
+35 -35
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,69 +61,69 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Level 1: ~/.claude/ (global) — outermost -->
<rect x="40" y="60" width="920" height="380" rx="8" fill="rgba(241,239,231,0.015)" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<rect x="40" y="60" width="920" height="380" rx="8" fill="rgba(245,245,245,0.015)" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<!-- Level 2: ~/vault/ -->
<rect x="72" y="96" width="856" height="308" rx="8" fill="rgba(241,239,231,0.02)" stroke="rgba(241,239,231,0.35)" stroke-width="1"/>
<rect x="72" y="96" width="856" height="308" rx="8" fill="rgba(245,245,245,0.02)" stroke="rgba(245,245,245,0.35)" stroke-width="1"/>
<!-- Level 3: /business -->
<rect x="104" y="132" width="792" height="236" rx="8" fill="rgba(241,239,231,0.025)" stroke="rgba(241,239,231,0.45)" stroke-width="1"/>
<rect x="104" y="132" width="792" height="236" rx="8" fill="rgba(245,245,245,0.025)" stroke="rgba(245,245,245,0.45)" stroke-width="1"/>
<!-- Level 4: /marketing -->
<rect x="136" y="168" width="728" height="164" rx="8" fill="rgba(241,239,231,0.03)" stroke="#a8a69d" stroke-width="1"/>
<rect x="136" y="168" width="728" height="164" rx="8" fill="rgba(245,245,245,0.03)" stroke="#bfc0c0" stroke-width="1"/>
<!-- Level 5: /project — innermost, coral focal -->
<rect x="168" y="204" width="664" height="92" rx="8" fill="rgba(255,106,48,0.08)" stroke="#ff6a30" stroke-width="1"/>
<rect x="168" y="204" width="664" height="92" rx="8" fill="rgba(240,138,89,0.08)" stroke="#f08a59" stroke-width="1"/>
<!-- Level labels on paper-colored masks -->
<rect x="56" y="52" width="188" height="16" fill="#1c1a17"/>
<text x="64" y="64" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/.claude/ (global)</text>
<rect x="56" y="52" width="188" height="16" fill="#2d3142"/>
<text x="64" y="64" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/.claude/ (global)</text>
<rect x="88" y="88" width="148" height="16" fill="#1c1a17"/>
<text x="96" y="100" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/vault/ (notes)</text>
<rect x="88" y="88" width="148" height="16" fill="#2d3142"/>
<text x="96" y="100" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/vault/ (notes)</text>
<rect x="120" y="124" width="96" height="16" fill="#1c1a17"/>
<text x="128" y="136" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/business</text>
<rect x="120" y="124" width="96" height="16" fill="#2d3142"/>
<text x="128" y="136" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/business</text>
<rect x="152" y="160" width="108" height="16" fill="#1c1a17"/>
<text x="160" y="172" fill="#f1efe7" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/marketing</text>
<rect x="152" y="160" width="108" height="16" fill="#2d3142"/>
<text x="160" y="172" fill="#f5f5f5" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/marketing</text>
<rect x="184" y="196" width="88" height="16" fill="#1c1a17"/>
<text x="192" y="208" fill="#ff6a30" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">/project</text>
<rect x="184" y="196" width="88" height="16" fill="#2d3142"/>
<text x="192" y="208" fill="#f08a59" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">/project</text>
<!-- File-icon glyphs (simple rect with folded corner) inside each level -->
<g transform="translate(908, 408)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#1c1a17" stroke="rgba(241,239,231,0.35)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(241,239,231,0.35)" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#2d3142" stroke="rgba(245,245,245,0.35)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(245,245,245,0.35)" stroke-width="1"/>
</g>
<g transform="translate(876, 372)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#1c1a17" stroke="rgba(241,239,231,0.40)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(241,239,231,0.40)" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#2d3142" stroke="rgba(245,245,245,0.40)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(245,245,245,0.40)" stroke-width="1"/>
</g>
<g transform="translate(844, 336)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#1c1a17" stroke="rgba(241,239,231,0.50)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(241,239,231,0.50)" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#2d3142" stroke="rgba(245,245,245,0.50)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(245,245,245,0.50)" stroke-width="1"/>
</g>
<g transform="translate(812, 300)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#1c1a17" stroke="#a8a69d" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="#a8a69d" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#2d3142" stroke="#bfc0c0" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="#bfc0c0" stroke-width="1"/>
</g>
<!-- Innermost label — human readable -->
<text x="500" y="248" fill="#f1efe7" font-size="16" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md</text>
<text x="500" y="272" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">inherits every level above</text>
<text x="500" y="248" fill="#f5f5f5" font-size="16" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md</text>
<text x="500" y="272" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">inherits every level above</text>
<!-- Annotation top-right: italic callout with curved arrow -->
<text x="904" y="36" fill="#f1efe7" font-size="14" font-style="italic" font-family="'Instrument Serif', serif" text-anchor="end">no imports, no configuration</text>
<path d="M 820 44 Q 700 84 520 216" fill="none" stroke="rgba(241,239,231,0.40)" stroke-width="1" stroke-dasharray="4,3"/>
<circle cx="520" cy="216" r="2" fill="#f1efe7"/>
<text x="904" y="36" fill="#f5f5f5" font-size="14" font-style="italic" font-family="'Instrument Serif', serif" text-anchor="end">no imports, no configuration</text>
<path d="M 820 44 Q 700 84 520 216" fill="none" stroke="rgba(245,245,245,0.40)" stroke-width="1" stroke-dasharray="4,3"/>
<circle cx="520" cy="216" r="2" fill="#f5f5f5"/>
<!-- Annotation bottom-left: italic callout -->
<text x="40" y="484" fill="#a8a69d" font-size="14" font-style="italic" font-family="'Instrument Serif', serif">structure IS the index</text>
<text x="40" y="484" fill="#bfc0c0" font-size="14" font-style="italic" font-family="'Instrument Serif', serif">structure IS the index</text>
</svg>
</div>
</body>
+36 -36
View File
@@ -7,7 +7,7 @@
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root { --color-paper:#f5f4ed; --color-paper-2:#efeee5; --color-ink:#0b0d0b; --color-muted:#52534e; --color-soft:#65655c; --color-rule:rgba(11,13,11,0.12); --color-accent:#f7591f; --color-link:#1a70c7; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --color-link:#2e5aa8; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
@@ -20,14 +20,14 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
@@ -42,69 +42,69 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Level 1: ~/.claude/ (global) — outermost -->
<rect x="40" y="60" width="920" height="380" rx="8" fill="rgba(11,13,11,0.015)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<rect x="40" y="60" width="920" height="380" rx="8" fill="rgba(45,49,66,0.015)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<!-- Level 2: ~/vault/ -->
<rect x="72" y="96" width="856" height="308" rx="8" fill="rgba(11,13,11,0.02)" stroke="rgba(11,13,11,0.35)" stroke-width="1"/>
<rect x="72" y="96" width="856" height="308" rx="8" fill="rgba(45,49,66,0.02)" stroke="rgba(45,49,66,0.35)" stroke-width="1"/>
<!-- Level 3: /business -->
<rect x="104" y="132" width="792" height="236" rx="8" fill="rgba(11,13,11,0.025)" stroke="rgba(11,13,11,0.45)" stroke-width="1"/>
<rect x="104" y="132" width="792" height="236" rx="8" fill="rgba(45,49,66,0.025)" stroke="rgba(45,49,66,0.45)" stroke-width="1"/>
<!-- Level 4: /marketing -->
<rect x="136" y="168" width="728" height="164" rx="8" fill="rgba(11,13,11,0.03)" stroke="#52534e" stroke-width="1"/>
<rect x="136" y="168" width="728" height="164" rx="8" fill="rgba(45,49,66,0.03)" stroke="#4f5d75" stroke-width="1"/>
<!-- Level 5: /project — innermost, coral focal -->
<rect x="168" y="204" width="664" height="92" rx="8" fill="rgba(247,89,31,0.06)" stroke="#f7591f" stroke-width="1"/>
<rect x="168" y="204" width="664" height="92" rx="8" fill="rgba(235,108,54,0.06)" stroke="#eb6c36" stroke-width="1"/>
<!-- Level labels on paper-2-colored masks (match diagram-container bg) -->
<rect x="56" y="52" width="188" height="16" fill="#efeee5"/>
<text x="64" y="64" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/.claude/ (global)</text>
<rect x="56" y="52" width="188" height="16" fill="#ececec"/>
<text x="64" y="64" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/.claude/ (global)</text>
<rect x="88" y="88" width="148" height="16" fill="#efeee5"/>
<text x="96" y="100" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/vault/ (notes)</text>
<rect x="88" y="88" width="148" height="16" fill="#ececec"/>
<text x="96" y="100" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/vault/ (notes)</text>
<rect x="120" y="124" width="96" height="16" fill="#efeee5"/>
<text x="128" y="136" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/business</text>
<rect x="120" y="124" width="96" height="16" fill="#ececec"/>
<text x="128" y="136" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/business</text>
<rect x="152" y="160" width="108" height="16" fill="#efeee5"/>
<text x="160" y="172" fill="#0b0d0b" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/marketing</text>
<rect x="152" y="160" width="108" height="16" fill="#ececec"/>
<text x="160" y="172" fill="#2d3142" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/marketing</text>
<rect x="184" y="196" width="88" height="16" fill="#efeee5"/>
<text x="192" y="208" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">/project</text>
<rect x="184" y="196" width="88" height="16" fill="#ececec"/>
<text x="192" y="208" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">/project</text>
<!-- File-icon glyphs inside each level -->
<g transform="translate(908, 408)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#efeee5" stroke="rgba(11,13,11,0.35)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(11,13,11,0.35)" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#ececec" stroke="rgba(45,49,66,0.35)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(45,49,66,0.35)" stroke-width="1"/>
</g>
<g transform="translate(876, 372)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#efeee5" stroke="rgba(11,13,11,0.40)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(11,13,11,0.40)" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#ececec" stroke="rgba(45,49,66,0.40)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(45,49,66,0.40)" stroke-width="1"/>
</g>
<g transform="translate(844, 336)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#efeee5" stroke="rgba(11,13,11,0.50)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(11,13,11,0.50)" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#ececec" stroke="rgba(45,49,66,0.50)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(45,49,66,0.50)" stroke-width="1"/>
</g>
<g transform="translate(812, 300)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#efeee5" stroke="#52534e" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#ececec" stroke="#4f5d75" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="#4f5d75" stroke-width="1"/>
</g>
<!-- Innermost label — human readable -->
<text x="500" y="248" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md</text>
<text x="500" y="272" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">inherits every level above</text>
<text x="500" y="248" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md</text>
<text x="500" y="272" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">inherits every level above</text>
<!-- Annotation top-right: italic callout with curved arrow -->
<text x="904" y="36" fill="#0b0d0b" font-size="14" font-style="italic" font-family="'Instrument Serif', serif" text-anchor="end">no imports, no configuration</text>
<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"/>
<circle cx="520" cy="216" r="2" fill="#0b0d0b"/>
<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>
<path d="M 820 44 Q 700 84 520 216" fill="none" stroke="rgba(45,49,66,0.40)" stroke-width="1" stroke-dasharray="4,3"/>
<circle cx="520" cy="216" r="2" fill="#2d3142"/>
<!-- Annotation bottom-left: italic callout -->
<text x="40" y="484" fill="#52534e" font-size="14" font-style="italic" font-family="'Instrument Serif', serif">structure IS the index</text>
<text x="40" y="484" fill="#4f5d75" font-size="14" font-style="italic" font-family="'Instrument Serif', serif">structure IS the index</text>
</svg>
</div>
@@ -126,7 +126,7 @@
<div class="footer">
<span>the claude.md hierarchy · nested containment</span>
<span>example · diagram-design</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+35 -35
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,73 +61,73 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Level 1: ~/.claude/ (global) — outermost -->
<rect x="40" y="60" width="920" height="380" rx="8" fill="rgba(11,13,11,0.015)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<rect x="40" y="60" width="920" height="380" rx="8" fill="rgba(45,49,66,0.015)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<!-- Level 2: ~/vault/ -->
<rect x="72" y="96" width="856" height="308" rx="8" fill="rgba(11,13,11,0.02)" stroke="rgba(11,13,11,0.35)" stroke-width="1"/>
<rect x="72" y="96" width="856" height="308" rx="8" fill="rgba(45,49,66,0.02)" stroke="rgba(45,49,66,0.35)" stroke-width="1"/>
<!-- Level 3: /business -->
<rect x="104" y="132" width="792" height="236" rx="8" fill="rgba(11,13,11,0.025)" stroke="rgba(11,13,11,0.45)" stroke-width="1"/>
<rect x="104" y="132" width="792" height="236" rx="8" fill="rgba(45,49,66,0.025)" stroke="rgba(45,49,66,0.45)" stroke-width="1"/>
<!-- Level 4: /marketing -->
<rect x="136" y="168" width="728" height="164" rx="8" fill="rgba(11,13,11,0.03)" stroke="#52534e" stroke-width="1"/>
<rect x="136" y="168" width="728" height="164" rx="8" fill="rgba(45,49,66,0.03)" stroke="#4f5d75" stroke-width="1"/>
<!-- Level 5: /project — innermost, coral focal -->
<rect x="168" y="204" width="664" height="92" rx="8" fill="rgba(247,89,31,0.06)" stroke="#f7591f" stroke-width="1"/>
<rect x="168" y="204" width="664" height="92" rx="8" fill="rgba(235,108,54,0.06)" stroke="#eb6c36" stroke-width="1"/>
<!-- Level labels on paper-colored masks -->
<rect x="56" y="52" width="188" height="16" fill="#f5f4ed"/>
<text x="64" y="64" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/.claude/ (global)</text>
<rect x="56" y="52" width="188" height="16" fill="#f5f5f5"/>
<text x="64" y="64" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/.claude/ (global)</text>
<rect x="88" y="88" width="148" height="16" fill="#f5f4ed"/>
<text x="96" y="100" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/vault/ (notes)</text>
<rect x="88" y="88" width="148" height="16" fill="#f5f5f5"/>
<text x="96" y="100" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">~/vault/ (notes)</text>
<rect x="120" y="124" width="96" height="16" fill="#f5f4ed"/>
<text x="128" y="136" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/business</text>
<rect x="120" y="124" width="96" height="16" fill="#f5f5f5"/>
<text x="128" y="136" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/business</text>
<rect x="152" y="160" width="108" height="16" fill="#f5f4ed"/>
<text x="160" y="172" fill="#0b0d0b" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/marketing</text>
<rect x="152" y="160" width="108" height="16" fill="#f5f5f5"/>
<text x="160" y="172" fill="#2d3142" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">/marketing</text>
<rect x="184" y="196" width="88" height="16" fill="#f5f4ed"/>
<text x="192" y="208" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">/project</text>
<rect x="184" y="196" width="88" height="16" fill="#f5f5f5"/>
<text x="192" y="208" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em" font-weight="600">/project</text>
<!-- File-icon glyphs (simple rect with folded corner) inside each level -->
<!-- Glyph in level 1 (bottom-right area of outer ring) -->
<g transform="translate(908, 408)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#f5f4ed" stroke="rgba(11,13,11,0.35)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(11,13,11,0.35)" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#f5f5f5" stroke="rgba(45,49,66,0.35)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(45,49,66,0.35)" stroke-width="1"/>
</g>
<!-- Glyph in level 2 ring -->
<g transform="translate(876, 372)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#f5f4ed" stroke="rgba(11,13,11,0.40)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(11,13,11,0.40)" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#f5f5f5" stroke="rgba(45,49,66,0.40)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(45,49,66,0.40)" stroke-width="1"/>
</g>
<!-- Glyph in level 3 ring -->
<g transform="translate(844, 336)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#f5f4ed" stroke="rgba(11,13,11,0.50)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(11,13,11,0.50)" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#f5f5f5" stroke="rgba(45,49,66,0.50)" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="rgba(45,49,66,0.50)" stroke-width="1"/>
</g>
<!-- Glyph in level 4 ring -->
<g transform="translate(812, 300)">
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#f5f4ed" stroke="#52534e" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M0 0 L16 0 L20 4 L20 20 L0 20 Z" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1"/>
<path d="M16 0 L16 4 L20 4" fill="none" stroke="#4f5d75" stroke-width="1"/>
</g>
<!-- Innermost label — human readable -->
<text x="500" y="248" fill="#0b0d0b" font-size="16" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md</text>
<text x="500" y="272" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">inherits every level above</text>
<text x="500" y="248" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CLAUDE.md</text>
<text x="500" y="272" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">inherits every level above</text>
<!-- Annotation top-right: italic callout with curved arrow -->
<text x="904" y="36" fill="#0b0d0b" font-size="14" font-style="italic" font-family="'Instrument Serif', serif" text-anchor="end">no imports, no configuration</text>
<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"/>
<circle cx="520" cy="216" r="2" fill="#0b0d0b"/>
<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>
<path d="M 820 44 Q 700 84 520 216" fill="none" stroke="rgba(45,49,66,0.40)" stroke-width="1" stroke-dasharray="4,3"/>
<circle cx="520" cy="216" r="2" fill="#2d3142"/>
<!-- Annotation bottom-left: italic callout -->
<text x="40" y="484" fill="#52534e" font-size="14" font-style="italic" font-family="'Instrument Serif', serif">structure IS the index</text>
<text x="40" y="484" fill="#4f5d75" font-size="14" font-style="italic" font-family="'Instrument Serif', serif">structure IS the index</text>
</svg>
</div>
</body>
+34 -34
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,56 +61,56 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Left axis: direction of rarity -->
<line x1="100" y1="112" x2="100" y2="320" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<polygon points="96,112 104,112 100,100" fill="rgba(241,239,231,0.45)"/>
<text x="80" y="216" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="middle" transform="rotate(-90 80 216)">RARER · FEWER · COMPOUNDS ↑</text>
<line x1="100" y1="40" x2="100" y2="320" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<polygon points="96,40 104,40 100,28" fill="rgba(245,245,245,0.45)"/>
<text x="80" y="216" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="middle" transform="rotate(-90 80 216)">RARER · FEWER · COMPOUNDS ↑</text>
<!-- Base layer: Short posts -->
<polygon points="240,280 760,280 820,344 180,344" fill="rgba(241,239,231,0.04)" stroke="rgba(241,239,231,0.12)" stroke-width="1"/>
<text x="500" y="308" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Short posts</text>
<text x="500" y="324" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">daily · ~200 words</text>
<text x="836" y="316" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~240/yr</text>
<polygon points="244,280 756,280 820,344 180,344" fill="rgba(245,245,245,0.04)" stroke="rgba(245,245,245,0.12)" stroke-width="1"/>
<text x="500" y="308" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Short posts</text>
<text x="500" y="324" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">daily · ~200 words</text>
<text x="836" y="316" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~240/yr</text>
<!-- L3: Essays -->
<polygon points="300,216 700,216 760,280 240,280" fill="rgba(241,239,231,0.04)" stroke="rgba(241,239,231,0.12)" stroke-width="1"/>
<text x="500" y="244" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Essays</text>
<text x="500" y="260" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">weekly · 800–1,500 words</text>
<text x="776" y="252" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~48/yr</text>
<polygon points="308,216 692,216 756,280 244,280" fill="rgba(245,245,245,0.04)" stroke="rgba(245,245,245,0.12)" stroke-width="1"/>
<text x="500" y="244" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Essays</text>
<text x="500" y="260" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">weekly · 800–1,500 words</text>
<text x="776" y="252" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~48/yr</text>
<!-- L2: Long-form guides -->
<polygon points="360,152 640,152 700,216 300,216" fill="rgba(241,239,231,0.04)" stroke="rgba(241,239,231,0.12)" stroke-width="1"/>
<text x="500" y="180" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Long-form guides</text>
<text x="500" y="196" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">quarterly · 4,000+ words</text>
<text x="716" y="188" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~4/yr</text>
<polygon points="372,152 628,152 692,216 308,216" fill="rgba(245,245,245,0.04)" stroke="rgba(245,245,245,0.12)" stroke-width="1"/>
<text x="500" y="180" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Long-form guides</text>
<text x="500" y="196" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">quarterly · 4,000+ words</text>
<text x="716" y="188" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~4/yr</text>
<!-- Apex: Flagship book — CORAL FOCAL (triangle, pointed) -->
<polygon points="500,76 640,152 360,152" fill="rgba(255,106,48,0.10)" stroke="#ff6a30" stroke-width="1"/>
<text x="500" y="120" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Flagship book</text>
<text x="500" y="136" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">every 3–5 years</text>
<text x="656" y="112" fill="#ff6a30" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">the apex</text>
<!-- Apex: Flagship book — CORAL FOCAL (true pyramid peak — single triangle, consistent slope with layers below) -->
<polygon points="500,24 628,152 372,152" fill="rgba(240,138,89,0.10)" stroke="#f08a59" stroke-width="1"/>
<text x="500" y="120" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Flagship book</text>
<text x="500" y="136" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">every 3–5 years</text>
<text x="656" y="112" fill="#f08a59" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">the apex</text>
<!-- Footnote under pyramid -->
<text x="500" y="384" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif" text-anchor="middle" font-style="italic">The base funds the apex. The apex defines the base.</text>
<text x="500" y="384" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif" text-anchor="middle" font-style="italic">The base funds the apex. The apex defines the base.</text>
<!-- Legend -->
<line x1="40" y1="436" x2="960" y2="436" stroke="rgba(241,239,231,0.10)" stroke-width="0.8"/>
<text x="40" y="452" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="436" x2="960" y2="436" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<text x="40" y="452" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="464" width="16" height="12" fill="rgba(255,106,48,0.10)" stroke="#ff6a30" stroke-width="1"/>
<text x="64" y="474" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Apex — rarest, highest leverage</text>
<rect x="40" y="464" width="16" height="12" fill="rgba(240,138,89,0.10)" stroke="#f08a59" stroke-width="1"/>
<text x="64" y="474" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Apex — rarest, highest leverage</text>
<rect x="280" y="464" width="16" height="12" fill="rgba(241,239,231,0.04)" stroke="rgba(241,239,231,0.25)" stroke-width="1"/>
<text x="304" y="474" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Supporting layer — the volume work</text>
<rect x="280" y="464" width="16" height="12" fill="rgba(245,245,245,0.04)" stroke="rgba(245,245,245,0.25)" stroke-width="1"/>
<text x="304" y="474" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Supporting layer — the volume work</text>
<text x="560" y="474" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Layer width is honest: narrower = rarer shipping cadence.</text>
<text x="560" y="474" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Layer width is honest: narrower = rarer shipping cadence.</text>
</svg>
</div>
</body>
+35 -35
View File
@@ -7,7 +7,7 @@
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root { --color-paper:#f5f4ed; --color-paper-2:#efeee5; --color-ink:#0b0d0b; --color-muted:#52534e; --color-soft:#65655c; --color-rule:rgba(11,13,11,0.12); --color-accent:#f7591f; --color-link:#1a70c7; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --color-link:#2e5aa8; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
@@ -20,14 +20,14 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
@@ -42,56 +42,56 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Left axis: direction of rarity -->
<line x1="100" y1="112" x2="100" y2="320" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<polygon points="96,112 104,112 100,100" fill="rgba(11,13,11,0.45)"/>
<text x="80" y="216" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="middle" transform="rotate(-90 80 216)">RARER · FEWER · COMPOUNDS ↑</text>
<line x1="100" y1="40" x2="100" y2="320" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<polygon points="96,40 104,40 100,28" fill="rgba(45,49,66,0.45)"/>
<text x="80" y="216" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="middle" transform="rotate(-90 80 216)">RARER · FEWER · COMPOUNDS ↑</text>
<!-- Base layer: Short posts -->
<polygon points="240,280 760,280 820,344 180,344" fill="#efeee5" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="500" y="308" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Short posts</text>
<text x="500" y="324" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">daily · ~200 words</text>
<text x="836" y="316" fill="#65655c" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~240/yr</text>
<polygon points="244,280 756,280 820,344 180,344" fill="#ececec" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="500" y="308" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Short posts</text>
<text x="500" y="324" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">daily · ~200 words</text>
<text x="836" y="316" fill="#7a8399" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~240/yr</text>
<!-- L3: Essays -->
<polygon points="300,216 700,216 760,280 240,280" fill="#efeee5" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="500" y="244" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Essays</text>
<text x="500" y="260" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">weekly · 800–1,500 words</text>
<text x="776" y="252" fill="#65655c" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~48/yr</text>
<polygon points="308,216 692,216 756,280 244,280" fill="#ececec" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="500" y="244" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Essays</text>
<text x="500" y="260" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">weekly · 800–1,500 words</text>
<text x="776" y="252" fill="#7a8399" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~48/yr</text>
<!-- L2: Long-form guides -->
<polygon points="360,152 640,152 700,216 300,216" fill="#efeee5" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="500" y="180" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Long-form guides</text>
<text x="500" y="196" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">quarterly · 4,000+ words</text>
<text x="716" y="188" fill="#65655c" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~4/yr</text>
<polygon points="372,152 628,152 692,216 308,216" fill="#ececec" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="500" y="180" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Long-form guides</text>
<text x="500" y="196" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">quarterly · 4,000+ words</text>
<text x="716" y="188" fill="#7a8399" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~4/yr</text>
<!-- Apex: Flagship book — CORAL FOCAL (triangle, pointed) -->
<polygon points="500,76 640,152 360,152" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="500" y="120" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Flagship book</text>
<text x="500" y="136" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">every 3–5 years</text>
<text x="656" y="112" fill="#f7591f" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">the apex</text>
<!-- Apex: Flagship book — CORAL FOCAL (true pyramid peak — single triangle, consistent slope with layers below) -->
<polygon points="500,24 628,152 372,152" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="500" y="120" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Flagship book</text>
<text x="500" y="136" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">every 3–5 years</text>
<text x="656" y="112" fill="#eb6c36" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">the apex</text>
<!-- Footnote under pyramid -->
<text x="500" y="384" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" text-anchor="middle" font-style="italic">The base funds the apex. The apex defines the base.</text>
<text x="500" y="384" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" text-anchor="middle" font-style="italic">The base funds the apex. The apex defines the base.</text>
<!-- Legend -->
<line x1="40" y1="436" x2="960" y2="436" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="452" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="436" x2="960" y2="436" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="452" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="464" width="16" height="12" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="64" y="474" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Apex — rarest, highest leverage</text>
<rect x="40" y="464" width="16" height="12" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="64" y="474" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Apex — rarest, highest leverage</text>
<rect x="280" y="464" width="16" height="12" fill="#efeee5" stroke="rgba(11,13,11,0.25)" stroke-width="1"/>
<text x="304" y="474" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Supporting layer — the volume work</text>
<rect x="280" y="464" width="16" height="12" fill="#ececec" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<text x="304" y="474" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Supporting layer — the volume work</text>
<text x="560" y="474" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Layer width is honest: narrower = rarer shipping cadence.</text>
<text x="560" y="474" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Layer width is honest: narrower = rarer shipping cadence.</text>
</svg>
</div>
@@ -113,7 +113,7 @@
<div class="footer">
<span>content pyramid · what compounds</span>
<span>example · diagram-design</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+34 -34
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,56 +61,56 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Left axis: direction of rarity -->
<line x1="100" y1="112" x2="100" y2="320" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<polygon points="96,112 104,112 100,100" fill="rgba(11,13,11,0.45)"/>
<text x="80" y="216" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="middle" transform="rotate(-90 80 216)">RARER · FEWER · COMPOUNDS ↑</text>
<line x1="100" y1="40" x2="100" y2="320" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<polygon points="96,40 104,40 100,28" fill="rgba(45,49,66,0.45)"/>
<text x="80" y="216" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="middle" transform="rotate(-90 80 216)">RARER · FEWER · COMPOUNDS ↑</text>
<!-- Base layer: Short posts -->
<polygon points="240,280 760,280 820,344 180,344" fill="#efeee5" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="500" y="308" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Short posts</text>
<text x="500" y="324" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">daily · ~200 words</text>
<text x="836" y="316" fill="#65655c" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~240/yr</text>
<polygon points="244,280 756,280 820,344 180,344" fill="#ececec" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="500" y="308" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Short posts</text>
<text x="500" y="324" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">daily · ~200 words</text>
<text x="836" y="316" fill="#7a8399" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~240/yr</text>
<!-- L3: Essays -->
<polygon points="300,216 700,216 760,280 240,280" fill="#efeee5" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="500" y="244" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Essays</text>
<text x="500" y="260" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">weekly · 800–1,500 words</text>
<text x="776" y="252" fill="#65655c" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~48/yr</text>
<polygon points="308,216 692,216 756,280 244,280" fill="#ececec" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="500" y="244" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Essays</text>
<text x="500" y="260" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">weekly · 800–1,500 words</text>
<text x="776" y="252" fill="#7a8399" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~48/yr</text>
<!-- L2: Long-form guides -->
<polygon points="360,152 640,152 700,216 300,216" fill="#efeee5" stroke="rgba(11,13,11,0.12)" stroke-width="1"/>
<text x="500" y="180" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Long-form guides</text>
<text x="500" y="196" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">quarterly · 4,000+ words</text>
<text x="716" y="188" fill="#65655c" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~4/yr</text>
<polygon points="372,152 628,152 692,216 308,216" fill="#ececec" stroke="rgba(45,49,66,0.12)" stroke-width="1"/>
<text x="500" y="180" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Long-form guides</text>
<text x="500" y="196" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">quarterly · 4,000+ words</text>
<text x="716" y="188" fill="#7a8399" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">~4/yr</text>
<!-- Apex: Flagship book — CORAL FOCAL (triangle, pointed) -->
<polygon points="500,76 640,152 360,152" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="500" y="120" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Flagship book</text>
<text x="500" y="136" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">every 3–5 years</text>
<text x="656" y="112" fill="#f7591f" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">the apex</text>
<!-- Apex: Flagship book — CORAL FOCAL (true pyramid peak — single triangle, consistent slope with layers below) -->
<polygon points="500,24 628,152 372,152" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="500" y="120" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Flagship book</text>
<text x="500" y="136" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">every 3–5 years</text>
<text x="656" y="112" fill="#eb6c36" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.08em">the apex</text>
<!-- Footnote under pyramid -->
<text x="500" y="384" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" text-anchor="middle" font-style="italic">The base funds the apex. The apex defines the base.</text>
<text x="500" y="384" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" text-anchor="middle" font-style="italic">The base funds the apex. The apex defines the base.</text>
<!-- Legend -->
<line x1="40" y1="436" x2="960" y2="436" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="452" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="436" x2="960" y2="436" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="452" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="464" width="16" height="12" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="64" y="474" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Apex — rarest, highest leverage</text>
<rect x="40" y="464" width="16" height="12" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="64" y="474" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Apex — rarest, highest leverage</text>
<rect x="280" y="464" width="16" height="12" fill="#efeee5" stroke="rgba(11,13,11,0.25)" stroke-width="1"/>
<text x="304" y="474" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Supporting layer — the volume work</text>
<rect x="280" y="464" width="16" height="12" fill="#ececec" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<text x="304" y="474" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Supporting layer — the volume work</text>
<text x="560" y="474" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Layer width is honest: narrower = rarer shipping cadence.</text>
<text x="560" y="474" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Layer width is honest: narrower = rarer shipping cadence.</text>
</svg>
</div>
</body>
+169
View File
@@ -0,0 +1,169 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Workplace 2030 · Remote work × AI automation</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f5f5;
--color-paper-2: #ececec;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-soft: #7a8399;
--color-rule: rgba(45,49,66,0.12);
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
}
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
.header-eyebrow { font-family: var(--font-mono); font-size: 0.66rem; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.75rem; }
h1 { font-family: var(--font-serif); font-size: clamp(1.75rem, 3vw + 1rem, 2.5rem); font-weight: 400; letter-spacing: -0.02em; line-height: 1.1; margin-bottom: 0.5rem; }
.subtitle { font-size: 1rem; line-height: 1.55; color: var(--color-muted); max-width: 58ch; }
.diagram-container { background: transparent; border: none; padding: 0; overflow-x: auto; }
svg { width: 100%; min-width: 900px; display: block; }
.cards { display: grid; grid-template-columns: 1.1fr 1fr 0.9fr; gap: 1rem; margin-top: 1.5rem; }
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); }
.card-dot.muted { background: var(--color-muted); }
.card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<p class="header-eyebrow">Quadrant · Consultant special</p>
<h1>Workplace 2030 · Remote × AI automation</h1>
<p class="subtitle">Four named futures, one matrix. Scenario planning in the consultant 2×2 form — two independent drivers, four equal-weight cells, one quadrant carrying the coral bet.</p>
</div>
<div class="diagram-container">
<svg viewBox="0 0 1000 660" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Double-ended axis markers -->
<marker id="axis-end" markerWidth="9" markerHeight="7" refX="8" refY="3.5" orient="auto">
<polygon points="0 0, 9 3.5, 0 7" fill="#2d3142"/>
</marker>
<marker id="axis-start" markerWidth="9" markerHeight="7" refX="1" refY="3.5" orient="auto">
<polygon points="9 0, 0 3.5, 9 7" fill="#2d3142"/>
</marker>
</defs>
<!-- Clean paper background, no dot pattern -->
<rect width="100%" height="100%" fill="#f5f5f5"/>
<!-- Focal quadrant tint (TR) — coral at 3% -->
<rect x="500" y="80" width="400" height="220" fill="rgba(235,108,54,0.04)"/>
<!-- Scenario cells — store treatment with hairline rule, slightly varied -->
<!-- TL: Distributed humans -->
<rect x="140" y="120" width="300" height="160" rx="6" fill="rgba(45,49,66,0.04)" stroke="rgba(79,93,117,0.28)" stroke-width="1"/>
<text x="156" y="144" fill="#4f5d75" font-size="8" font-weight="500" font-family="'Geist Mono', monospace" letter-spacing="0.18em">01 · HIGH REMOTE / LOW AI</text>
<text x="156" y="180" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Distributed humans</text>
<text x="156" y="216" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Async-first, global hiring,</text>
<text x="156" y="232" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Slack-heavy. Human-centric</text>
<text x="156" y="248" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">workflows, low AI leverage.</text>
<!-- TR: Agent teams (FOCAL) -->
<rect x="560" y="120" width="300" height="160" rx="6" fill="rgba(235,108,54,0.06)" stroke="#eb6c36" stroke-width="1.2"/>
<text x="576" y="144" fill="#eb6c36" font-size="8" font-weight="600" font-family="'Geist Mono', monospace" letter-spacing="0.18em">02 · HIGH REMOTE / HIGH AI</text>
<text x="576" y="180" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Agent teams <tspan fill="#eb6c36" font-size="13">●</tspan></text>
<text x="576" y="216" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Humans orchestrate; AI</text>
<text x="576" y="232" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">handles the routine layer.</text>
<text x="576" y="248" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Small, high-leverage teams.</text>
<!-- BL: Office classic -->
<rect x="140" y="320" width="300" height="160" rx="6" fill="rgba(45,49,66,0.04)" stroke="rgba(79,93,117,0.28)" stroke-width="1"/>
<text x="156" y="344" fill="#4f5d75" font-size="8" font-weight="500" font-family="'Geist Mono', monospace" letter-spacing="0.18em">03 · LOW REMOTE / LOW AI</text>
<text x="156" y="380" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">Office classic</text>
<text x="156" y="416" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Return-to-office mandates,</text>
<text x="156" y="432" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">manual work. Techlash</text>
<text x="156" y="448" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">prolongs the status quo.</text>
<!-- BR: In-person + AI -->
<rect x="560" y="320" width="300" height="160" rx="6" fill="rgba(45,49,66,0.04)" stroke="rgba(79,93,117,0.28)" stroke-width="1"/>
<text x="576" y="344" fill="#4f5d75" font-size="8" font-weight="500" font-family="'Geist Mono', monospace" letter-spacing="0.18em">04 · LOW REMOTE / HIGH AI</text>
<text x="576" y="380" fill="#2d3142" font-size="16" font-weight="600" font-family="'Geist', sans-serif">In-person + AI</text>
<text x="576" y="416" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Smart offices, AI-augmented</text>
<text x="576" y="432" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">staff. Physical presence is</text>
<text x="576" y="448" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">the moat, AI is the lever.</text>
<!-- Axis cross — ink, heavier than standard quadrant, double-ended -->
<line x1="80" y1="300" x2="920" y2="300"
stroke="#2d3142" stroke-width="1.2"
marker-start="url(#axis-start)" marker-end="url(#axis-end)"/>
<line x1="500" y1="60" x2="500" y2="540"
stroke="#2d3142" stroke-width="1.2"
marker-start="url(#axis-start)" marker-end="url(#axis-end)"/>
<!-- Axis labels — driver name + range (eyebrow + sublabel) -->
<!-- Top (vertical axis, maximum) -->
<text x="508" y="40" fill="#2d3142" font-size="9" font-weight="600" font-family="'Geist Mono', monospace" letter-spacing="0.18em">↑ AI AUTOMATION</text>
<text x="508" y="56" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">high</text>
<!-- Bottom (vertical axis, minimum) -->
<text x="508" y="560" fill="#2d3142" font-size="9" font-weight="600" font-family="'Geist Mono', monospace" letter-spacing="0.18em">↓ AI AUTOMATION</text>
<text x="508" y="576" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">low</text>
<!-- Left (horizontal axis, minimum) -->
<text x="60" y="292" fill="#2d3142" font-size="9" font-weight="600" font-family="'Geist Mono', monospace" letter-spacing="0.18em">← REMOTE WORK</text>
<text x="60" y="308" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">low</text>
<!-- Right (horizontal axis, maximum) -->
<text x="940" y="292" fill="#2d3142" font-size="9" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">REMOTE WORK →</text>
<text x="940" y="308" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end">high</text>
<!-- Legend — horizontal strip, placed BELOW the bottom axis labels (y=560/576) -->
<line x1="40" y1="604" x2="960" y2="604" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<rect x="40" y="616" width="16" height="16" rx="3" fill="rgba(235,108,54,0.06)" stroke="#eb6c36" stroke-width="1"/>
<text x="64" y="628" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Headline bet</text>
<rect x="160" y="616" width="16" height="16" rx="3" fill="rgba(45,49,66,0.04)" stroke="rgba(79,93,117,0.28)" stroke-width="1"/>
<text x="184" y="628" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Candidate future</text>
<text x="304" y="628" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Every cell is named. The axes carry the range; the coral quadrant carries the commitment.</text>
</svg>
</div>
<div class="cards">
<div class="card">
<p class="eyebrow">THE HEADLINE</p>
<div class="card-header"><span class="card-dot coral"></span><h3>Name every future</h3></div>
<p>Scenario planning fails when three of the four cells are placeholders. Forcing a name on each future — even the "won't happen" ones — surfaces the assumptions hiding in the axes.</p>
</div>
<div class="card">
<div class="card-header"><span class="card-dot ink"></span><h3>Variant rules</h3></div>
<ul>
<li>Double-ended arrows on both axes (spectrum, not flow)</li>
<li>Named cells, not plotted items</li>
<li>Driver name + range on each arrow tip</li>
<li>Coral on one focal quadrant max</li>
</ul>
</div>
<div class="card">
<div class="card-header"><span class="card-dot muted"></span><h3>When to use</h3></div>
<p>Reach for the consultant 2×2 for scenario planning, positioning frames, or strategy sessions where four named archetypes beat a plotted point cloud. If you're prioritising, use the standard quadrant instead.</p>
</div>
</div>
<div class="footer">
<span>workplace 2030 · remote × AI automation</span>
<span>example · consultant special</span>
</div>
</div>
</body>
</html>
+40 -40
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,72 +61,72 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Quadrant backgrounds (very subtle, only coral on DO FIRST) -->
<rect x="120" y="80" width="380" height="170" fill="rgba(255,106,48,0.03)"/>
<rect x="120" y="80" width="380" height="170" fill="rgba(240,138,89,0.03)"/>
<!-- Axis cross -->
<line x1="120" y1="250" x2="880" y2="250" stroke="rgba(241,239,231,0.45)" stroke-width="1"/>
<line x1="500" y1="80" x2="500" y2="420" stroke="rgba(241,239,231,0.45)" stroke-width="1"/>
<line x1="120" y1="250" x2="880" y2="250" stroke="rgba(245,245,245,0.45)" stroke-width="1"/>
<line x1="500" y1="80" x2="500" y2="420" stroke="rgba(245,245,245,0.45)" stroke-width="1"/>
<!-- Axis end labels -->
<text x="880" y="266" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.14em">HIGH EFFORT →</text>
<text x="120" y="266" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">← LOW EFFORT</text>
<text x="512" y="80" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↑ HIGH IMPACT</text>
<text x="512" y="432" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↓ LOW IMPACT</text>
<text x="880" y="266" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.14em">HIGH EFFORT →</text>
<text x="120" y="266" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">← LOW EFFORT</text>
<text x="512" y="80" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↑ HIGH IMPACT</text>
<text x="512" y="432" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↓ LOW IMPACT</text>
<!-- Quadrant corner labels -->
<text x="140" y="104" fill="#ff6a30" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em" font-weight="600">DO FIRST</text>
<text x="860" y="104" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">MAJOR PROJECTS</text>
<text x="140" y="412" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">QUICK WINS</text>
<text x="860" y="412" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">AVOID</text>
<text x="140" y="104" fill="#f08a59" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em" font-weight="600">DO FIRST</text>
<text x="860" y="104" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">MAJOR PROJECTS</text>
<text x="140" y="412" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">QUICK WINS</text>
<text x="860" y="412" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">AVOID</text>
<!-- Items: TL (Do First) -->
<!-- coral focal -->
<circle cx="220" cy="140" r="6" fill="#ff6a30"/>
<text x="232" y="144" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif">diagram-design</text>
<circle cx="220" cy="140" r="6" fill="#f08a59"/>
<text x="232" y="144" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif">Schematic skill v4</text>
<circle cx="320" cy="200" r="4" fill="#f1efe7"/>
<text x="332" y="204" fill="#a8a69d" font-size="11" font-family="'Geist', sans-serif">Update changelog</text>
<circle cx="320" cy="200" r="4" fill="#f5f5f5"/>
<text x="332" y="204" fill="#bfc0c0" font-size="11" font-family="'Geist', sans-serif">Update changelog</text>
<!-- Items: TR (Major Projects) -->
<circle cx="620" cy="140" r="4" fill="#f1efe7"/>
<text x="632" y="144" fill="#a8a69d" font-size="11" font-family="'Geist', sans-serif">Design v4 refresh</text>
<circle cx="620" cy="140" r="4" fill="#f5f5f5"/>
<text x="632" y="144" fill="#bfc0c0" font-size="11" font-family="'Geist', sans-serif">Design v4 refresh</text>
<circle cx="760" cy="180" r="4" fill="#f1efe7"/>
<text x="772" y="184" fill="#a8a69d" font-size="11" font-family="'Geist', sans-serif">New publication</text>
<circle cx="760" cy="180" r="4" fill="#f5f5f5"/>
<text x="772" y="184" fill="#bfc0c0" font-size="11" font-family="'Geist', sans-serif">New publication</text>
<!-- Items: BL (Quick Wins) -->
<circle cx="260" cy="320" r="4" fill="#f1efe7"/>
<text x="272" y="324" fill="#a8a69d" font-size="11" font-family="'Geist', sans-serif">Fix footer link</text>
<circle cx="260" cy="320" r="4" fill="#f5f5f5"/>
<text x="272" y="324" fill="#bfc0c0" font-size="11" font-family="'Geist', sans-serif">Fix footer link</text>
<circle cx="360" cy="380" r="4" fill="#f1efe7"/>
<text x="372" y="384" fill="#a8a69d" font-size="11" font-family="'Geist', sans-serif">Update OG tags</text>
<circle cx="360" cy="380" r="4" fill="#f5f5f5"/>
<text x="372" y="384" fill="#bfc0c0" font-size="11" font-family="'Geist', sans-serif">Update OG tags</text>
<!-- Items: BR (Avoid) -->
<circle cx="640" cy="380" r="4" fill="#f1efe7"/>
<text x="652" y="384" fill="#a8a69d" font-size="11" font-family="'Geist', sans-serif">Rewrite build pipeline</text>
<circle cx="640" cy="380" r="4" fill="#f5f5f5"/>
<text x="652" y="384" fill="#bfc0c0" font-size="11" font-family="'Geist', sans-serif">Rewrite build pipeline</text>
<circle cx="780" cy="320" r="4" fill="#f1efe7"/>
<text x="792" y="324" fill="#a8a69d" font-size="11" font-family="'Geist', sans-serif">Port to Nuxt</text>
<circle cx="780" cy="320" r="4" fill="#f5f5f5"/>
<text x="792" y="324" fill="#bfc0c0" font-size="11" font-family="'Geist', sans-serif">Port to Nuxt</text>
<!-- Legend -->
<line x1="40" y1="456" x2="960" y2="456" stroke="rgba(241,239,231,0.10)" stroke-width="0.8"/>
<text x="40" y="472" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="456" x2="960" y2="456" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<text x="40" y="472" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<circle cx="52" cy="488" r="6" fill="#ff6a30"/>
<text x="68" y="492" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Start tomorrow</text>
<circle cx="52" cy="488" r="6" fill="#f08a59"/>
<text x="68" y="492" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Start tomorrow</text>
<circle cx="192" cy="488" r="4" fill="#f1efe7"/>
<text x="208" y="492" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Candidate project</text>
<circle cx="192" cy="488" r="4" fill="#f5f5f5"/>
<text x="208" y="492" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Candidate project</text>
<text x="336" y="492" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Position is the signal. Colour is reserved for the single action item.</text>
<text x="336" y="492" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Position is the signal. Colour is reserved for the single action item.</text>
</svg>
</div>
</body>
+41 -41
View File
@@ -7,7 +7,7 @@
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root { --color-paper:#f5f4ed; --color-paper-2:#efeee5; --color-ink:#0b0d0b; --color-muted:#52534e; --color-soft:#65655c; --color-rule:rgba(11,13,11,0.12); --color-accent:#f7591f; --color-link:#1a70c7; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --color-link:#2e5aa8; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
@@ -20,14 +20,14 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
@@ -42,72 +42,72 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Quadrant backgrounds (very subtle, only coral on DO FIRST) -->
<rect x="120" y="80" width="380" height="170" fill="rgba(247,89,31,0.03)"/>
<rect x="120" y="80" width="380" height="170" fill="rgba(235,108,54,0.03)"/>
<!-- Axis cross -->
<line x1="120" y1="250" x2="880" y2="250" stroke="rgba(11,13,11,0.45)" stroke-width="1"/>
<line x1="500" y1="80" x2="500" y2="420" stroke="rgba(11,13,11,0.45)" stroke-width="1"/>
<line x1="120" y1="250" x2="880" y2="250" stroke="rgba(45,49,66,0.45)" stroke-width="1"/>
<line x1="500" y1="80" x2="500" y2="420" stroke="rgba(45,49,66,0.45)" stroke-width="1"/>
<!-- Axis end labels -->
<text x="880" y="266" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.14em">HIGH EFFORT →</text>
<text x="120" y="266" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">← LOW EFFORT</text>
<text x="512" y="80" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↑ HIGH IMPACT</text>
<text x="512" y="432" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↓ LOW IMPACT</text>
<text x="880" y="266" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.14em">HIGH EFFORT →</text>
<text x="120" y="266" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">← LOW EFFORT</text>
<text x="512" y="80" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↑ HIGH IMPACT</text>
<text x="512" y="432" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↓ LOW IMPACT</text>
<!-- Quadrant corner labels -->
<text x="140" y="104" fill="#f7591f" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em" font-weight="600">DO FIRST</text>
<text x="860" y="104" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">MAJOR PROJECTS</text>
<text x="140" y="412" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">QUICK WINS</text>
<text x="860" y="412" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">AVOID</text>
<text x="140" y="104" fill="#eb6c36" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em" font-weight="600">DO FIRST</text>
<text x="860" y="104" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">MAJOR PROJECTS</text>
<text x="140" y="412" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">QUICK WINS</text>
<text x="860" y="412" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">AVOID</text>
<!-- Items: TL (Do First) -->
<!-- coral focal -->
<circle cx="220" cy="140" r="6" fill="#f7591f"/>
<text x="232" y="144" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif">diagram-design</text>
<circle cx="220" cy="140" r="6" fill="#eb6c36"/>
<text x="232" y="144" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif">Schematic skill v4</text>
<circle cx="320" cy="200" r="4" fill="#0b0d0b"/>
<text x="332" y="204" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Update changelog</text>
<circle cx="320" cy="200" r="4" fill="#2d3142"/>
<text x="332" y="204" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Update changelog</text>
<!-- Items: TR (Major Projects) -->
<circle cx="620" cy="140" r="4" fill="#0b0d0b"/>
<text x="632" y="144" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Design v4 refresh</text>
<circle cx="620" cy="140" r="4" fill="#2d3142"/>
<text x="632" y="144" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Design v4 refresh</text>
<circle cx="760" cy="180" r="4" fill="#0b0d0b"/>
<text x="772" y="184" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">New publication</text>
<circle cx="760" cy="180" r="4" fill="#2d3142"/>
<text x="772" y="184" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">New publication</text>
<!-- Items: BL (Quick Wins) -->
<circle cx="260" cy="320" r="4" fill="#0b0d0b"/>
<text x="272" y="324" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Fix footer link</text>
<circle cx="260" cy="320" r="4" fill="#2d3142"/>
<text x="272" y="324" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Fix footer link</text>
<circle cx="360" cy="380" r="4" fill="#0b0d0b"/>
<text x="372" y="384" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Update OG tags</text>
<circle cx="360" cy="380" r="4" fill="#2d3142"/>
<text x="372" y="384" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Update OG tags</text>
<!-- Items: BR (Avoid) -->
<circle cx="640" cy="380" r="4" fill="#0b0d0b"/>
<text x="652" y="384" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Rewrite build pipeline</text>
<circle cx="640" cy="380" r="4" fill="#2d3142"/>
<text x="652" y="384" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Rewrite build pipeline</text>
<circle cx="780" cy="320" r="4" fill="#0b0d0b"/>
<text x="792" y="324" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Port to Nuxt</text>
<circle cx="780" cy="320" r="4" fill="#2d3142"/>
<text x="792" y="324" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Port to Nuxt</text>
<!-- Legend -->
<line x1="40" y1="456" x2="960" y2="456" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="472" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="456" x2="960" y2="456" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="472" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<circle cx="52" cy="488" r="6" fill="#f7591f"/>
<text x="68" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Start tomorrow</text>
<circle cx="52" cy="488" r="6" fill="#eb6c36"/>
<text x="68" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Start tomorrow</text>
<circle cx="192" cy="488" r="4" fill="#0b0d0b"/>
<text x="208" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Candidate project</text>
<circle cx="192" cy="488" r="4" fill="#2d3142"/>
<text x="208" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Candidate project</text>
<text x="336" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Position is the signal. Colour is reserved for the single action item.</text>
<text x="336" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Position is the signal. Colour is reserved for the single action item.</text>
</svg>
</div>
@@ -129,7 +129,7 @@
<div class="footer">
<span>content ideas · impact × effort</span>
<span>example · diagram-design</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+40 -40
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,72 +61,72 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Quadrant backgrounds (very subtle, only coral on DO FIRST) -->
<rect x="120" y="80" width="380" height="170" fill="rgba(247,89,31,0.03)"/>
<rect x="120" y="80" width="380" height="170" fill="rgba(235,108,54,0.03)"/>
<!-- Axis cross -->
<line x1="120" y1="250" x2="880" y2="250" stroke="rgba(11,13,11,0.45)" stroke-width="1"/>
<line x1="500" y1="80" x2="500" y2="420" stroke="rgba(11,13,11,0.45)" stroke-width="1"/>
<line x1="120" y1="250" x2="880" y2="250" stroke="rgba(45,49,66,0.45)" stroke-width="1"/>
<line x1="500" y1="80" x2="500" y2="420" stroke="rgba(45,49,66,0.45)" stroke-width="1"/>
<!-- Axis end labels -->
<text x="880" y="266" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.14em">HIGH EFFORT →</text>
<text x="120" y="266" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">← LOW EFFORT</text>
<text x="512" y="80" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↑ HIGH IMPACT</text>
<text x="512" y="432" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↓ LOW IMPACT</text>
<text x="880" y="266" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.14em">HIGH EFFORT →</text>
<text x="120" y="266" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">← LOW EFFORT</text>
<text x="512" y="80" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↑ HIGH IMPACT</text>
<text x="512" y="432" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">↓ LOW IMPACT</text>
<!-- Quadrant corner labels -->
<text x="140" y="104" fill="#f7591f" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em" font-weight="600">DO FIRST</text>
<text x="860" y="104" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">MAJOR PROJECTS</text>
<text x="140" y="412" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">QUICK WINS</text>
<text x="860" y="412" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">AVOID</text>
<text x="140" y="104" fill="#eb6c36" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em" font-weight="600">DO FIRST</text>
<text x="860" y="104" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">MAJOR PROJECTS</text>
<text x="140" y="412" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">QUICK WINS</text>
<text x="860" y="412" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.18em">AVOID</text>
<!-- Items: TL (Do First) -->
<!-- coral focal -->
<circle cx="220" cy="140" r="6" fill="#f7591f"/>
<text x="232" y="144" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif">diagram-design</text>
<circle cx="220" cy="140" r="6" fill="#eb6c36"/>
<text x="232" y="144" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif">Schematic skill v4</text>
<circle cx="320" cy="200" r="4" fill="#0b0d0b"/>
<text x="332" y="204" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Update changelog</text>
<circle cx="320" cy="200" r="4" fill="#2d3142"/>
<text x="332" y="204" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Update changelog</text>
<!-- Items: TR (Major Projects) -->
<circle cx="620" cy="140" r="4" fill="#0b0d0b"/>
<text x="632" y="144" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Design v4 refresh</text>
<circle cx="620" cy="140" r="4" fill="#2d3142"/>
<text x="632" y="144" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Design v4 refresh</text>
<circle cx="760" cy="180" r="4" fill="#0b0d0b"/>
<text x="772" y="184" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">New publication</text>
<circle cx="760" cy="180" r="4" fill="#2d3142"/>
<text x="772" y="184" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">New publication</text>
<!-- Items: BL (Quick Wins) -->
<circle cx="260" cy="320" r="4" fill="#0b0d0b"/>
<text x="272" y="324" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Fix footer link</text>
<circle cx="260" cy="320" r="4" fill="#2d3142"/>
<text x="272" y="324" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Fix footer link</text>
<circle cx="360" cy="380" r="4" fill="#0b0d0b"/>
<text x="372" y="384" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Update OG tags</text>
<circle cx="360" cy="380" r="4" fill="#2d3142"/>
<text x="372" y="384" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Update OG tags</text>
<!-- Items: BR (Avoid) -->
<circle cx="640" cy="380" r="4" fill="#0b0d0b"/>
<text x="652" y="384" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Rewrite build pipeline</text>
<circle cx="640" cy="380" r="4" fill="#2d3142"/>
<text x="652" y="384" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Rewrite build pipeline</text>
<circle cx="780" cy="320" r="4" fill="#0b0d0b"/>
<text x="792" y="324" fill="#52534e" font-size="11" font-family="'Geist', sans-serif">Port to Nuxt</text>
<circle cx="780" cy="320" r="4" fill="#2d3142"/>
<text x="792" y="324" fill="#4f5d75" font-size="11" font-family="'Geist', sans-serif">Port to Nuxt</text>
<!-- Legend -->
<line x1="40" y1="456" x2="960" y2="456" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="472" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="456" x2="960" y2="456" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="472" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<circle cx="52" cy="488" r="6" fill="#f7591f"/>
<text x="68" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Start tomorrow</text>
<circle cx="52" cy="488" r="6" fill="#eb6c36"/>
<text x="68" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Start tomorrow</text>
<circle cx="192" cy="488" r="4" fill="#0b0d0b"/>
<text x="208" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Candidate project</text>
<circle cx="192" cy="488" r="4" fill="#2d3142"/>
<text x="208" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Candidate project</text>
<text x="336" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Position is the signal. Colour is reserved for the single action item.</text>
<text x="336" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Position is the signal. Colour is reserved for the single action item.</text>
</svg>
</div>
</body>
+68 -68
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -62,42 +62,42 @@
<defs>
<!-- Dot grid background -->
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
<!-- Arrow markers -->
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#a8a69d"/>
<polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/>
</marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#ff6a30"/>
<polygon points="0 0, 8 3, 0 6" fill="#f08a59"/>
</marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#5ba8eb"/>
<polygon points="0 0, 8 3, 0 6" fill="#6a95d8"/>
</marker>
</defs>
<!-- Background: paper + dot grid -->
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- =================================================================
LIFELINES — dashed vertical lines from each actor, behind everything.
Actor lifeline x-coords: 128, 352, 584, 800
================================================================= -->
<line x1="128" y1="128" x2="128" y2="488" stroke="rgba(241,239,231,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="352" y1="128" x2="352" y2="488" stroke="rgba(241,239,231,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="584" y1="128" x2="584" y2="488" stroke="rgba(241,239,231,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="800" y1="128" x2="800" y2="488" stroke="rgba(241,239,231,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="128" y1="128" x2="128" y2="488" stroke="rgba(245,245,245,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="352" y1="128" x2="352" y2="488" stroke="rgba(245,245,245,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="584" y1="128" x2="584" y2="488" stroke="rgba(245,245,245,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="800" y1="128" x2="800" y2="488" stroke="rgba(245,245,245,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<!-- =================================================================
ACTIVATION BARS — w=8 rects on lifelines showing control duration.
Drawn before message arrows so arrows land on their edges.
================================================================= -->
<!-- Cloudflare activation: receives at y=176, responds at y=408 -->
<rect x="348" y="180" width="8" height="232" fill="rgba(241,239,231,0.06)" stroke="#a8a69d" stroke-width="0.8"/>
<rect x="348" y="180" width="8" height="232" fill="rgba(245,245,245,0.06)" stroke="#bfc0c0" stroke-width="0.8"/>
<!-- Astro activation: called at y=232, returns at y=352 -->
<rect x="580" y="236" width="8" height="120" fill="rgba(241,239,231,0.06)" stroke="#a8a69d" stroke-width="0.8"/>
<rect x="580" y="236" width="8" height="120" fill="rgba(245,245,245,0.06)" stroke="#bfc0c0" stroke-width="0.8"/>
<!-- =================================================================
MESSAGE ARROWS — time flows top→down.
@@ -105,50 +105,50 @@
================================================================= -->
<!-- M1: Reader → Cloudflare (HTTPS request · link-blue) -->
<line x1="128" y1="176" x2="352" y2="176" stroke="#5ba8eb" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<line x1="128" y1="176" x2="352" y2="176" stroke="#6a95d8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<!-- M2: Cloudflare → Astro (cache miss · muted) -->
<line x1="352" y1="232" x2="580" y2="232" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="352" y1="232" x2="580" y2="232" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- M3: Astro self-message (render MDX · muted U-loop) -->
<path d="M 588 284 L 624 284 L 624 316 L 588 316" fill="none" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<path d="M 588 284 L 624 284 L 624 316 L 588 316" fill="none" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- M4: Astro → Cloudflare (return HTML · muted dashed) -->
<line x1="580" y1="352" x2="356" y2="352" stroke="#a8a69d" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<line x1="580" y1="352" x2="356" y2="352" stroke="#bfc0c0" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- M5: Cloudflare → Reader (primary success · coral) -->
<line x1="348" y1="408" x2="128" y2="408" stroke="#ff6a30" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="348" y1="408" x2="128" y2="408" stroke="#f08a59" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- M6: Reader → Analytics (async beacon · muted dashed) -->
<line x1="128" y1="464" x2="800" y2="464" stroke="#a8a69d" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<line x1="128" y1="464" x2="800" y2="464" stroke="#bfc0c0" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- =================================================================
MESSAGE LABELS — each with an opaque paper-colored mask.
================================================================= -->
<!-- M1 label -->
<rect x="188" y="160" width="104" height="12" rx="2" fill="#1c1a17"/>
<text x="240" y="170" fill="#5ba8eb" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">GET /ARTICLES/SLUG</text>
<rect x="188" y="160" width="104" height="12" rx="2" fill="#2d3142"/>
<text x="240" y="170" fill="#6a95d8" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">GET /ARTICLES/SLUG</text>
<!-- M2 label -->
<rect x="416" y="216" width="100" height="12" rx="2" fill="#1c1a17"/>
<text x="466" y="226" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CACHE MISS · ORIGIN</text>
<rect x="416" y="216" width="100" height="12" rx="2" fill="#2d3142"/>
<text x="466" y="226" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CACHE MISS · ORIGIN</text>
<!-- M3 label (to the right of the self-loop) -->
<rect x="632" y="292" width="72" height="12" rx="2" fill="#1c1a17"/>
<text x="668" y="302" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">RENDER MDX</text>
<rect x="632" y="292" width="72" height="12" rx="2" fill="#2d3142"/>
<text x="668" y="302" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">RENDER MDX</text>
<!-- M4 label -->
<rect x="420" y="336" width="96" height="12" rx="2" fill="#1c1a17"/>
<text x="468" y="346" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · HTML + MAX-AGE</text>
<rect x="420" y="336" width="96" height="12" rx="2" fill="#2d3142"/>
<text x="468" y="346" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · HTML + MAX-AGE</text>
<!-- M5 label (coral · primary response) -->
<rect x="192" y="392" width="96" height="12" rx="2" fill="#1c1a17"/>
<text x="240" y="402" fill="#ff6a30" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · EDGE-CACHED</text>
<rect x="192" y="392" width="96" height="12" rx="2" fill="#2d3142"/>
<text x="240" y="402" fill="#f08a59" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · EDGE-CACHED</text>
<!-- M6 label (placed between Astro and Analytics lifelines, a clear gap) -->
<rect x="648" y="448" width="96" height="12" rx="2" fill="#1c1a17"/>
<text x="696" y="458" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PAGEVIEW BEACON</text>
<rect x="648" y="448" width="96" height="12" rx="2" fill="#2d3142"/>
<text x="696" y="458" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PAGEVIEW BEACON</text>
<!-- =================================================================
ACTOR BOXES — drawn after arrows/labels.
@@ -156,63 +156,63 @@
================================================================= -->
<!-- Actor 1: Reader (external / soft) -->
<rect x="56" y="72" width="144" height="56" rx="6" fill="#1c1a17"/>
<rect x="56" y="72" width="144" height="56" rx="6" fill="rgba(168,166,157,0.10)" stroke="#8e8c83" stroke-width="1"/>
<rect x="56" y="72" width="144" height="56" rx="6" fill="#2d3142"/>
<rect x="56" y="72" width="144" height="56" rx="6" fill="rgba(191,192,192,0.10)" stroke="#8e98ac" stroke-width="1"/>
<rect x="64" y="80" width="28" height="12" rx="2" fill="transparent" stroke="rgba(142,140,131,0.40)" stroke-width="0.8"/>
<text x="78" y="89" fill="#8e8c83" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="128" y="104" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="128" y="119" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<text x="78" y="89" fill="#8e98ac" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="128" y="104" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="128" y="119" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<!-- Actor 2: Cloudflare (cloud / muted) -->
<rect x="280" y="72" width="144" height="56" rx="6" fill="#1c1a17"/>
<rect x="280" y="72" width="144" height="56" rx="6" fill="rgba(241,239,231,0.03)" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<rect x="288" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(241,239,231,0.22)" stroke-width="0.8"/>
<text x="304" y="89" fill="#8e8c83" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="352" y="104" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="352" y="119" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<rect x="280" y="72" width="144" height="56" rx="6" fill="#2d3142"/>
<rect x="280" y="72" width="144" height="56" rx="6" fill="rgba(245,245,245,0.03)" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<rect x="288" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.22)" stroke-width="0.8"/>
<text x="304" y="89" fill="#8e98ac" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="352" y="104" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="352" y="119" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<!-- Actor 3: Astro Origin (focal / coral) -->
<rect x="504" y="72" width="160" height="56" rx="6" fill="#1c1a17"/>
<rect x="504" y="72" width="160" height="56" rx="6" fill="rgba(255,106,48,0.08)" stroke="#ff6a30" stroke-width="1"/>
<rect x="512" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(255,106,48,0.50)" stroke-width="0.8"/>
<text x="528" y="89" fill="#ff6a30" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="584" y="104" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="584" y="119" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<rect x="504" y="72" width="160" height="56" rx="6" fill="#2d3142"/>
<rect x="504" y="72" width="160" height="56" rx="6" fill="rgba(240,138,89,0.08)" stroke="#f08a59" stroke-width="1"/>
<rect x="512" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(240,138,89,0.50)" stroke-width="0.8"/>
<text x="528" y="89" fill="#f08a59" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="584" y="104" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="584" y="119" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<!-- Actor 4: Analytics (optional / dashed) -->
<rect x="728" y="72" width="144" height="56" rx="6" fill="#1c1a17"/>
<rect x="728" y="72" width="144" height="56" rx="6" fill="rgba(241,239,231,0.02)" stroke="rgba(241,239,231,0.22)" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="736" y="80" width="28" height="12" rx="2" fill="transparent" stroke="rgba(241,239,231,0.22)" stroke-width="0.8"/>
<text x="750" y="89" fill="#8e8c83" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ASY</text>
<text x="800" y="104" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Analytics</text>
<text x="800" y="119" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Beacon · async</text>
<rect x="728" y="72" width="144" height="56" rx="6" fill="#2d3142"/>
<rect x="728" y="72" width="144" height="56" rx="6" fill="rgba(245,245,245,0.02)" stroke="rgba(245,245,245,0.22)" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="736" y="80" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.22)" stroke-width="0.8"/>
<text x="750" y="89" fill="#8e98ac" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ASY</text>
<text x="800" y="104" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Analytics</text>
<text x="800" y="119" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Beacon · async</text>
<!-- =================================================================
LEGEND — horizontal strip at the bottom.
Separator at y=504, eyebrow at y=520, items at y=540–548.
================================================================= -->
<line x1="56" y1="504" x2="944" y2="504" stroke="rgba(241,239,231,0.10)" stroke-width="0.8"/>
<text x="56" y="520" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="56" y1="504" x2="944" y2="504" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<text x="56" y="520" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<!-- Item 1: Actor swatch (coral focal) -->
<rect x="56" y="540" width="14" height="10" rx="2" fill="rgba(255,106,48,0.08)" stroke="#ff6a30" stroke-width="1"/>
<text x="76" y="548" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Focal actor</text>
<rect x="56" y="540" width="14" height="10" rx="2" fill="rgba(240,138,89,0.08)" stroke="#f08a59" stroke-width="1"/>
<text x="76" y="548" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Focal actor</text>
<!-- Item 2: Activation bar swatch -->
<rect x="188" y="536" width="4" height="18" fill="rgba(241,239,231,0.06)" stroke="#a8a69d" stroke-width="0.8"/>
<text x="200" y="548" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Activation</text>
<rect x="188" y="536" width="4" height="18" fill="rgba(245,245,245,0.06)" stroke="#bfc0c0" stroke-width="0.8"/>
<text x="200" y="548" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Activation</text>
<!-- Item 3: Request arrow (link-blue) -->
<line x1="308" y1="546" x2="336" y2="546" stroke="#5ba8eb" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="344" y="548" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<line x1="308" y1="546" x2="336" y2="546" stroke="#6a95d8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="344" y="548" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<!-- Item 4: Return / async (muted dashed) -->
<line x1="476" y1="546" x2="504" y2="546" stroke="#a8a69d" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<text x="512" y="548" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Return / async</text>
<line x1="476" y1="546" x2="504" y2="546" stroke="#bfc0c0" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<text x="512" y="548" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Return / async</text>
<!-- Item 5: Primary response (coral) -->
<line x1="652" y1="546" x2="680" y2="546" stroke="#ff6a30" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="688" y="548" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Primary response</text>
<line x1="652" y1="546" x2="680" y2="546" stroke="#f08a59" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="688" y="548" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Primary response</text>
</svg>
</div>
+81 -81
View File
@@ -9,16 +9,16 @@
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-paper-2: #efeee5;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-soft: #65655c;
--color-rule: rgba(11,13,11,0.12);
--color-rule-solid: rgba(135,139,134,0.25);
--color-accent: #f7591f;
--color-accent-tint: rgba(247,89,31,0.08);
--color-link: #1a70c7;
--color-paper: #f5f5f5;
--color-paper-2: #ececec;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-soft: #7a8399;
--color-rule: rgba(45,49,66,0.12);
--color-rule-solid: rgba(79,93,117,0.25);
--color-accent: #eb6c36;
--color-accent-tint: rgba(235,108,54,0.08);
--color-link: #2e5aa8;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', 'Times New Roman', serif;
--font-mono: 'Geist Mono', ui-monospace, Menlo, monospace;
@@ -107,7 +107,7 @@
gap: 0.6rem;
margin-bottom: 0.875rem;
padding-bottom: 0.875rem;
border-bottom: 1px solid rgba(11,13,11,0.08);
border-bottom: 1px solid rgba(45,49,66,0.08);
}
.card-dot {
@@ -151,14 +151,14 @@
content: '—';
position: absolute;
left: 0;
color: rgba(11,13,11,0.25);
color: rgba(45,49,66,0.25);
font-size: 0.75rem;
}
.footer {
margin-top: 2rem;
padding-top: 1.5rem;
border-top: 1px solid rgba(11,13,11,0.10);
border-top: 1px solid rgba(45,49,66,0.10);
font-family: var(--font-mono);
font-size: 0.72rem;
letter-spacing: 0.06em;
@@ -178,7 +178,7 @@
<div class="header">
<p class="header-eyebrow">Sequence · Diagram Design</p>
<h1>Article request, cold cache</h1>
<p class="subtitle">How littlemight.com serves a reader when the requested slug isn't already sitting in Cloudflare's edge cache — origin render, beacon, and back in one round trip.</p>
<p class="subtitle">How a content site serves a reader when the requested slug isn't already sitting in Cloudflare's edge cache — origin render, beacon, and back in one round trip.</p>
</div>
<!-- Sequence Diagram -->
@@ -187,42 +187,42 @@
<defs>
<!-- Dot grid background -->
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<!-- Arrow markers -->
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#52534e"/>
<polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/>
</marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#f7591f"/>
<polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/>
</marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#1a70c7"/>
<polygon points="0 0, 8 3, 0 6" fill="#2e5aa8"/>
</marker>
</defs>
<!-- Background: paper + dot grid -->
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- =================================================================
LIFELINES — dashed vertical lines from each actor, behind everything.
Actor lifeline x-coords: 128, 352, 584, 800
================================================================= -->
<line x1="128" y1="128" x2="128" y2="488" stroke="rgba(11,13,11,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="352" y1="128" x2="352" y2="488" stroke="rgba(11,13,11,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="584" y1="128" x2="584" y2="488" stroke="rgba(11,13,11,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="800" y1="128" x2="800" y2="488" stroke="rgba(11,13,11,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="128" y1="128" x2="128" y2="488" stroke="rgba(45,49,66,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="352" y1="128" x2="352" y2="488" stroke="rgba(45,49,66,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="584" y1="128" x2="584" y2="488" stroke="rgba(45,49,66,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="800" y1="128" x2="800" y2="488" stroke="rgba(45,49,66,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<!-- =================================================================
ACTIVATION BARS — w=8 rects on lifelines showing control duration.
Drawn before message arrows so arrows land on their edges.
================================================================= -->
<!-- Cloudflare activation: receives at y=176, responds at y=408 -->
<rect x="348" y="180" width="8" height="232" fill="rgba(11,13,11,0.06)" stroke="#52534e" stroke-width="0.8"/>
<rect x="348" y="180" width="8" height="232" fill="rgba(45,49,66,0.06)" stroke="#4f5d75" stroke-width="0.8"/>
<!-- Astro activation: called at y=232, returns at y=352 -->
<rect x="580" y="236" width="8" height="120" fill="rgba(11,13,11,0.06)" stroke="#52534e" stroke-width="0.8"/>
<rect x="580" y="236" width="8" height="120" fill="rgba(45,49,66,0.06)" stroke="#4f5d75" stroke-width="0.8"/>
<!-- =================================================================
MESSAGE ARROWS — time flows top→down.
@@ -230,50 +230,50 @@
================================================================= -->
<!-- M1: Reader → Cloudflare (HTTPS request · link-blue) -->
<line x1="128" y1="176" x2="352" y2="176" stroke="#1a70c7" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<line x1="128" y1="176" x2="352" y2="176" stroke="#2e5aa8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<!-- M2: Cloudflare → Astro (cache miss · muted) -->
<line x1="352" y1="232" x2="580" y2="232" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="352" y1="232" x2="580" y2="232" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- M3: Astro self-message (render MDX · muted U-loop) -->
<path d="M 588 284 L 624 284 L 624 316 L 588 316" fill="none" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<path d="M 588 284 L 624 284 L 624 316 L 588 316" fill="none" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- M4: Astro → Cloudflare (return HTML · muted dashed) -->
<line x1="580" y1="352" x2="356" y2="352" stroke="#52534e" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<line x1="580" y1="352" x2="356" y2="352" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- M5: Cloudflare → Reader (primary success · coral) -->
<line x1="348" y1="408" x2="128" y2="408" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="348" y1="408" x2="128" y2="408" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- M6: Reader → Analytics (async beacon · muted dashed) -->
<line x1="128" y1="464" x2="800" y2="464" stroke="#52534e" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<line x1="128" y1="464" x2="800" y2="464" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- =================================================================
MESSAGE LABELS — each with an opaque paper-colored mask.
================================================================= -->
<!-- M1 label -->
<rect x="188" y="160" width="104" height="12" rx="2" fill="#f5f4ed"/>
<text x="240" y="170" fill="#1a70c7" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">GET /ARTICLES/SLUG</text>
<rect x="188" y="160" width="104" height="12" rx="2" fill="#f5f5f5"/>
<text x="240" y="170" fill="#2e5aa8" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">GET /ARTICLES/SLUG</text>
<!-- M2 label -->
<rect x="416" y="216" width="100" height="12" rx="2" fill="#f5f4ed"/>
<text x="466" y="226" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CACHE MISS · ORIGIN</text>
<rect x="416" y="216" width="100" height="12" rx="2" fill="#f5f5f5"/>
<text x="466" y="226" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CACHE MISS · ORIGIN</text>
<!-- M3 label (to the right of the self-loop) -->
<rect x="632" y="292" width="72" height="12" rx="2" fill="#f5f4ed"/>
<text x="668" y="302" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">RENDER MDX</text>
<rect x="632" y="292" width="72" height="12" rx="2" fill="#f5f5f5"/>
<text x="668" y="302" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">RENDER MDX</text>
<!-- M4 label -->
<rect x="420" y="336" width="96" height="12" rx="2" fill="#f5f4ed"/>
<text x="468" y="346" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · HTML + MAX-AGE</text>
<rect x="420" y="336" width="96" height="12" rx="2" fill="#f5f5f5"/>
<text x="468" y="346" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · HTML + MAX-AGE</text>
<!-- M5 label (coral · primary response) -->
<rect x="192" y="392" width="96" height="12" rx="2" fill="#f5f4ed"/>
<text x="240" y="402" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · EDGE-CACHED</text>
<rect x="192" y="392" width="96" height="12" rx="2" fill="#f5f5f5"/>
<text x="240" y="402" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · EDGE-CACHED</text>
<!-- M6 label (placed between Astro and Analytics lifelines, a clear gap) -->
<rect x="648" y="448" width="96" height="12" rx="2" fill="#f5f4ed"/>
<text x="696" y="458" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PAGEVIEW BEACON</text>
<rect x="648" y="448" width="96" height="12" rx="2" fill="#f5f5f5"/>
<text x="696" y="458" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PAGEVIEW BEACON</text>
<!-- =================================================================
ACTOR BOXES — drawn after arrows/labels.
@@ -281,63 +281,63 @@
================================================================= -->
<!-- Actor 1: Reader (external / soft) -->
<rect x="56" y="72" width="144" height="56" rx="6" fill="#f5f4ed"/>
<rect x="56" y="72" width="144" height="56" rx="6" fill="rgba(82,83,78,0.10)" stroke="#65655c" stroke-width="1"/>
<rect x="64" y="80" width="28" height="12" rx="2" fill="transparent" stroke="rgba(101,101,92,0.40)" stroke-width="0.8"/>
<text x="78" y="89" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="128" y="104" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="128" y="119" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<rect x="56" y="72" width="144" height="56" rx="6" fill="#f5f5f5"/>
<rect x="56" y="72" width="144" height="56" rx="6" fill="rgba(79,93,117,0.10)" stroke="#7a8399" stroke-width="1"/>
<rect x="64" y="80" width="28" height="12" rx="2" fill="transparent" stroke="rgba(122,131,153,0.40)" stroke-width="0.8"/>
<text x="78" y="89" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="128" y="104" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="128" y="119" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<!-- Actor 2: Cloudflare (cloud / muted) -->
<rect x="280" y="72" width="144" height="56" rx="6" fill="#f5f4ed"/>
<rect x="280" y="72" width="144" height="56" rx="6" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<rect x="288" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.22)" stroke-width="0.8"/>
<text x="304" y="89" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="352" y="104" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="352" y="119" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<rect x="280" y="72" width="144" height="56" rx="6" fill="#f5f5f5"/>
<rect x="280" y="72" width="144" height="56" rx="6" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<rect x="288" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.22)" stroke-width="0.8"/>
<text x="304" y="89" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="352" y="104" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="352" y="119" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<!-- Actor 3: Astro Origin (focal / coral) -->
<rect x="504" y="72" width="160" height="56" rx="6" fill="#f5f4ed"/>
<rect x="504" y="72" width="160" height="56" rx="6" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<rect x="512" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(247,89,31,0.50)" stroke-width="0.8"/>
<text x="528" y="89" fill="#f7591f" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="584" y="104" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="584" y="119" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<rect x="504" y="72" width="160" height="56" rx="6" fill="#f5f5f5"/>
<rect x="504" y="72" width="160" height="56" rx="6" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<rect x="512" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="528" y="89" fill="#eb6c36" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="584" y="104" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="584" y="119" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<!-- Actor 4: Analytics (optional / dashed) -->
<rect x="728" y="72" width="144" height="56" rx="6" fill="#f5f4ed"/>
<rect x="728" y="72" width="144" height="56" rx="6" fill="rgba(11,13,11,0.02)" stroke="rgba(11,13,11,0.22)" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="736" y="80" width="28" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.22)" stroke-width="0.8"/>
<text x="750" y="89" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ASY</text>
<text x="800" y="104" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Analytics</text>
<text x="800" y="119" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Beacon · async</text>
<rect x="728" y="72" width="144" height="56" rx="6" fill="#f5f5f5"/>
<rect x="728" y="72" width="144" height="56" rx="6" fill="rgba(45,49,66,0.02)" stroke="rgba(45,49,66,0.22)" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="736" y="80" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.22)" stroke-width="0.8"/>
<text x="750" y="89" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ASY</text>
<text x="800" y="104" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Analytics</text>
<text x="800" y="119" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Beacon · async</text>
<!-- =================================================================
LEGEND — horizontal strip at the bottom.
Separator at y=504, eyebrow at y=520, items at y=540–548.
================================================================= -->
<line x1="56" y1="504" x2="944" y2="504" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="56" y="520" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="56" y1="504" x2="944" y2="504" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="56" y="520" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<!-- Item 1: Actor swatch (coral focal) -->
<rect x="56" y="540" width="14" height="10" rx="2" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="76" y="548" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Focal actor</text>
<rect x="56" y="540" width="14" height="10" rx="2" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="76" y="548" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Focal actor</text>
<!-- Item 2: Activation bar swatch -->
<rect x="188" y="536" width="4" height="18" fill="rgba(11,13,11,0.06)" stroke="#52534e" stroke-width="0.8"/>
<text x="200" y="548" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Activation</text>
<rect x="188" y="536" width="4" height="18" fill="rgba(45,49,66,0.06)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="200" y="548" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Activation</text>
<!-- Item 3: Request arrow (link-blue) -->
<line x1="308" y1="546" x2="336" y2="546" stroke="#1a70c7" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="344" y="548" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<line x1="308" y1="546" x2="336" y2="546" stroke="#2e5aa8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="344" y="548" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<!-- Item 4: Return / async (muted dashed) -->
<line x1="476" y1="546" x2="504" y2="546" stroke="#52534e" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<text x="512" y="548" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Return / async</text>
<line x1="476" y1="546" x2="504" y2="546" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<text x="512" y="548" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Return / async</text>
<!-- Item 5: Primary response (coral) -->
<line x1="652" y1="546" x2="680" y2="546" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="688" y="548" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Primary response</text>
<line x1="652" y1="546" x2="680" y2="546" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="688" y="548" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Primary response</text>
</svg>
</div>
@@ -377,8 +377,8 @@
<!-- Footer -->
<div class="footer">
<span>littlemight.com · article request sequence</span>
<span>example · diagram-design</span>
<span>content site · article request sequence</span>
<span>example · schematic skill</span>
</div>
</div>
+69 -69
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -62,42 +62,42 @@
<defs>
<!-- Dot grid background -->
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<!-- Arrow markers -->
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#52534e"/>
<polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/>
</marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#f7591f"/>
<polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/>
</marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#1a70c7"/>
<polygon points="0 0, 8 3, 0 6" fill="#2e5aa8"/>
</marker>
</defs>
<!-- Background: paper + dot grid -->
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- =================================================================
LIFELINES — dashed vertical lines from each actor, behind everything.
Actor lifeline x-coords: 128, 352, 584, 800
================================================================= -->
<line x1="128" y1="128" x2="128" y2="488" stroke="rgba(11,13,11,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="352" y1="128" x2="352" y2="488" stroke="rgba(11,13,11,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="584" y1="128" x2="584" y2="488" stroke="rgba(11,13,11,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="800" y1="128" x2="800" y2="488" stroke="rgba(11,13,11,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="128" y1="128" x2="128" y2="488" stroke="rgba(45,49,66,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="352" y1="128" x2="352" y2="488" stroke="rgba(45,49,66,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="584" y1="128" x2="584" y2="488" stroke="rgba(45,49,66,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<line x1="800" y1="128" x2="800" y2="488" stroke="rgba(45,49,66,0.22)" stroke-width="1" stroke-dasharray="3,3"/>
<!-- =================================================================
ACTIVATION BARS — w=8 rects on lifelines showing control duration.
Drawn before message arrows so arrows land on their edges.
================================================================= -->
<!-- Cloudflare activation: receives at y=176, responds at y=408 -->
<rect x="348" y="180" width="8" height="232" fill="rgba(11,13,11,0.06)" stroke="#52534e" stroke-width="0.8"/>
<rect x="348" y="180" width="8" height="232" fill="rgba(45,49,66,0.06)" stroke="#4f5d75" stroke-width="0.8"/>
<!-- Astro activation: called at y=232, returns at y=352 -->
<rect x="580" y="236" width="8" height="120" fill="rgba(11,13,11,0.06)" stroke="#52534e" stroke-width="0.8"/>
<rect x="580" y="236" width="8" height="120" fill="rgba(45,49,66,0.06)" stroke="#4f5d75" stroke-width="0.8"/>
<!-- =================================================================
MESSAGE ARROWS — time flows top→down.
@@ -105,50 +105,50 @@
================================================================= -->
<!-- M1: Reader → Cloudflare (HTTPS request · link-blue) -->
<line x1="128" y1="176" x2="352" y2="176" stroke="#1a70c7" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<line x1="128" y1="176" x2="352" y2="176" stroke="#2e5aa8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<!-- M2: Cloudflare → Astro (cache miss · muted) -->
<line x1="352" y1="232" x2="580" y2="232" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="352" y1="232" x2="580" y2="232" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- M3: Astro self-message (render MDX · muted U-loop) -->
<path d="M 588 284 L 624 284 L 624 316 L 588 316" fill="none" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<path d="M 588 284 L 624 284 L 624 316 L 588 316" fill="none" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- M4: Astro → Cloudflare (return HTML · muted dashed) -->
<line x1="580" y1="352" x2="356" y2="352" stroke="#52534e" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<line x1="580" y1="352" x2="356" y2="352" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- M5: Cloudflare → Reader (primary success · coral) -->
<line x1="348" y1="408" x2="128" y2="408" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="348" y1="408" x2="128" y2="408" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- M6: Reader → Analytics (async beacon · muted dashed) -->
<line x1="128" y1="464" x2="800" y2="464" stroke="#52534e" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<line x1="128" y1="464" x2="800" y2="464" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- =================================================================
MESSAGE LABELS — each with an opaque paper-colored mask.
================================================================= -->
<!-- M1 label -->
<rect x="188" y="160" width="104" height="12" rx="2" fill="#f5f4ed"/>
<text x="240" y="170" fill="#1a70c7" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">GET /ARTICLES/SLUG</text>
<rect x="188" y="160" width="104" height="12" rx="2" fill="#f5f5f5"/>
<text x="240" y="170" fill="#2e5aa8" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">GET /ARTICLES/SLUG</text>
<!-- M2 label -->
<rect x="416" y="216" width="100" height="12" rx="2" fill="#f5f4ed"/>
<text x="466" y="226" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CACHE MISS · ORIGIN</text>
<rect x="416" y="216" width="100" height="12" rx="2" fill="#f5f5f5"/>
<text x="466" y="226" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CACHE MISS · ORIGIN</text>
<!-- M3 label (to the right of the self-loop) -->
<rect x="632" y="292" width="72" height="12" rx="2" fill="#f5f4ed"/>
<text x="668" y="302" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">RENDER MDX</text>
<rect x="632" y="292" width="72" height="12" rx="2" fill="#f5f5f5"/>
<text x="668" y="302" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">RENDER MDX</text>
<!-- M4 label -->
<rect x="420" y="336" width="96" height="12" rx="2" fill="#f5f4ed"/>
<text x="468" y="346" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · HTML + MAX-AGE</text>
<rect x="420" y="336" width="96" height="12" rx="2" fill="#f5f5f5"/>
<text x="468" y="346" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · HTML + MAX-AGE</text>
<!-- M5 label (coral · primary response) -->
<rect x="192" y="392" width="96" height="12" rx="2" fill="#f5f4ed"/>
<text x="240" y="402" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · EDGE-CACHED</text>
<rect x="192" y="392" width="96" height="12" rx="2" fill="#f5f5f5"/>
<text x="240" y="402" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">200 · EDGE-CACHED</text>
<!-- M6 label (placed between Astro and Analytics lifelines, a clear gap) -->
<rect x="648" y="448" width="96" height="12" rx="2" fill="#f5f4ed"/>
<text x="696" y="458" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PAGEVIEW BEACON</text>
<rect x="648" y="448" width="96" height="12" rx="2" fill="#f5f5f5"/>
<text x="696" y="458" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PAGEVIEW BEACON</text>
<!-- =================================================================
ACTOR BOXES — drawn after arrows/labels.
@@ -156,63 +156,63 @@
================================================================= -->
<!-- Actor 1: Reader (external / soft) -->
<rect x="56" y="72" width="144" height="56" rx="6" fill="#f5f4ed"/>
<rect x="56" y="72" width="144" height="56" rx="6" fill="rgba(82,83,78,0.10)" stroke="#65655c" stroke-width="1"/>
<rect x="64" y="80" width="28" height="12" rx="2" fill="transparent" stroke="rgba(101,101,92,0.40)" stroke-width="0.8"/>
<text x="78" y="89" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="128" y="104" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="128" y="119" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<rect x="56" y="72" width="144" height="56" rx="6" fill="#f5f5f5"/>
<rect x="56" y="72" width="144" height="56" rx="6" fill="rgba(79,93,117,0.10)" stroke="#7a8399" stroke-width="1"/>
<rect x="64" y="80" width="28" height="12" rx="2" fill="transparent" stroke="rgba(122,131,153,0.40)" stroke-width="0.8"/>
<text x="78" y="89" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<text x="128" y="104" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Reader</text>
<text x="128" y="119" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser</text>
<!-- Actor 2: Cloudflare (cloud / muted) -->
<rect x="280" y="72" width="144" height="56" rx="6" fill="#f5f4ed"/>
<rect x="280" y="72" width="144" height="56" rx="6" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<rect x="288" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.22)" stroke-width="0.8"/>
<text x="304" y="89" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="352" y="104" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="352" y="119" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<rect x="280" y="72" width="144" height="56" rx="6" fill="#f5f5f5"/>
<rect x="280" y="72" width="144" height="56" rx="6" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<rect x="288" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.22)" stroke-width="0.8"/>
<text x="304" y="89" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
<text x="352" y="104" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Cloudflare</text>
<text x="352" y="119" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Pages · cache</text>
<!-- Actor 3: Astro Origin (focal / coral) -->
<rect x="504" y="72" width="160" height="56" rx="6" fill="#f5f4ed"/>
<rect x="504" y="72" width="160" height="56" rx="6" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<rect x="512" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(247,89,31,0.50)" stroke-width="0.8"/>
<text x="528" y="89" fill="#f7591f" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="584" y="104" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="584" y="119" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<rect x="504" y="72" width="160" height="56" rx="6" fill="#f5f5f5"/>
<rect x="504" y="72" width="160" height="56" rx="6" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<rect x="512" y="80" width="32" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="528" y="89" fill="#eb6c36" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORIG</text>
<text x="584" y="104" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Astro Origin</text>
<text x="584" y="119" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">SSR + MDX</text>
<!-- Actor 4: Analytics (optional / dashed) -->
<rect x="728" y="72" width="144" height="56" rx="6" fill="#f5f4ed"/>
<rect x="728" y="72" width="144" height="56" rx="6" fill="rgba(11,13,11,0.02)" stroke="rgba(11,13,11,0.22)" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="736" y="80" width="28" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.22)" stroke-width="0.8"/>
<text x="750" y="89" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ASY</text>
<text x="800" y="104" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Analytics</text>
<text x="800" y="119" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Beacon · async</text>
<rect x="728" y="72" width="144" height="56" rx="6" fill="#f5f5f5"/>
<rect x="728" y="72" width="144" height="56" rx="6" fill="rgba(45,49,66,0.02)" stroke="rgba(45,49,66,0.22)" stroke-width="1" stroke-dasharray="4,3"/>
<rect x="736" y="80" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.22)" stroke-width="0.8"/>
<text x="750" y="89" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ASY</text>
<text x="800" y="104" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Analytics</text>
<text x="800" y="119" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Beacon · async</text>
<!-- =================================================================
LEGEND — horizontal strip at the bottom.
Separator at y=504, eyebrow at y=520, items at y=540–548.
================================================================= -->
<line x1="56" y1="504" x2="944" y2="504" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="56" y="520" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="56" y1="504" x2="944" y2="504" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="56" y="520" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<!-- Item 1: Actor swatch (coral focal) -->
<rect x="56" y="540" width="14" height="10" rx="2" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="76" y="548" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Focal actor</text>
<rect x="56" y="540" width="14" height="10" rx="2" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="76" y="548" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Focal actor</text>
<!-- Item 2: Activation bar swatch -->
<rect x="188" y="536" width="4" height="18" fill="rgba(11,13,11,0.06)" stroke="#52534e" stroke-width="0.8"/>
<text x="200" y="548" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Activation</text>
<rect x="188" y="536" width="4" height="18" fill="rgba(45,49,66,0.06)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="200" y="548" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Activation</text>
<!-- Item 3: Request arrow (link-blue) -->
<line x1="308" y1="546" x2="336" y2="546" stroke="#1a70c7" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="344" y="548" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<line x1="308" y1="546" x2="336" y2="546" stroke="#2e5aa8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="344" y="548" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">HTTP request</text>
<!-- Item 4: Return / async (muted dashed) -->
<line x1="476" y1="546" x2="504" y2="546" stroke="#52534e" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<text x="512" y="548" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Return / async</text>
<line x1="476" y1="546" x2="504" y2="546" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<text x="512" y="548" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Return / async</text>
<!-- Item 5: Primary response (coral) -->
<line x1="652" y1="546" x2="680" y2="546" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="688" y="548" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Primary response</text>
<line x1="652" y1="546" x2="680" y2="546" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="688" y="548" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Primary response</text>
</svg>
</div>
+50 -50
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,84 +61,84 @@
<svg viewBox="0 0 1000 460" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#a8a69d"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#ff6a30"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f08a59"/></marker>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Transitions (drawn first) -->
<!-- Start → Draft -->
<line x1="68" y1="200" x2="120" y2="200" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="68" y1="200" x2="120" y2="200" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Draft → In Review -->
<line x1="280" y1="200" x2="340" y2="200" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="280" y1="200" x2="340" y2="200" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- In Review → Published (coral — happy path) -->
<line x1="500" y1="200" x2="560" y2="200" stroke="#ff6a30" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="500" y1="200" x2="560" y2="200" stroke="#f08a59" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- Published → Archived (down) -->
<line x1="640" y1="240" x2="640" y2="300" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="640" y1="240" x2="640" y2="300" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Archived → End (down) -->
<line x1="640" y1="400" x2="640" y2="432" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="640" y1="400" x2="640" y2="432" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- In Review → Draft (curved back up-and-left) -->
<path d="M 420 160 C 420 96, 200 96, 200 160" fill="none" stroke="#a8a69d" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<path d="M 420 160 C 420 96, 200 96, 200 160" fill="none" stroke="#bfc0c0" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- Transition labels -->
<rect x="172" y="184" width="48" height="12" rx="2" fill="#1c1a17"/>
<text x="196" y="194" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CREATE</text>
<rect x="172" y="184" width="48" height="12" rx="2" fill="#2d3142"/>
<text x="196" y="194" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CREATE</text>
<rect x="288" y="184" width="48" height="12" rx="2" fill="#1c1a17"/>
<text x="312" y="194" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SUBMIT</text>
<rect x="288" y="184" width="48" height="12" rx="2" fill="#2d3142"/>
<text x="312" y="194" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SUBMIT</text>
<rect x="500" y="184" width="60" height="12" rx="2" fill="#1c1a17"/>
<text x="530" y="194" fill="#ff6a30" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">APPROVE</text>
<rect x="500" y="184" width="60" height="12" rx="2" fill="#2d3142"/>
<text x="530" y="194" fill="#f08a59" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">APPROVE</text>
<rect x="612" y="264" width="56" height="12" rx="2" fill="#1c1a17"/>
<text x="640" y="274" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXPIRE</text>
<rect x="612" y="264" width="56" height="12" rx="2" fill="#2d3142"/>
<text x="640" y="274" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXPIRE</text>
<rect x="620" y="416" width="40" height="12" rx="2" fill="#1c1a17"/>
<text x="640" y="426" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PURGE</text>
<rect x="620" y="416" width="40" height="12" rx="2" fill="#2d3142"/>
<text x="640" y="426" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PURGE</text>
<!-- Reject label on curved path -->
<rect x="276" y="92" width="80" height="12" rx="2" fill="#1c1a17"/>
<text x="316" y="102" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">REJECT · REVISE</text>
<rect x="276" y="92" width="80" height="12" rx="2" fill="#2d3142"/>
<text x="316" y="102" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">REJECT · REVISE</text>
<!-- Start dot (filled ink) -->
<circle cx="60" cy="200" r="6" fill="#f1efe7"/>
<circle cx="60" cy="200" r="6" fill="#f5f5f5"/>
<!-- State: Draft -->
<rect x="120" y="160" width="160" height="80" rx="8" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<rect x="128" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(241,239,231,0.40)" stroke-width="0.8"/>
<text x="148" y="177" fill="#f1efe7" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="200" y="208" fill="#f1efe7" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft</text>
<text x="200" y="224" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">unpublished</text>
<rect x="120" y="160" width="160" height="80" rx="8" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<rect x="128" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.40)" stroke-width="0.8"/>
<text x="148" y="177" fill="#f5f5f5" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="200" y="208" fill="#f5f5f5" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft</text>
<text x="200" y="224" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">unpublished</text>
<!-- State: In Review -->
<rect x="340" y="160" width="160" height="80" rx="8" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<rect x="348" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(241,239,231,0.40)" stroke-width="0.8"/>
<text x="368" y="177" fill="#f1efe7" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="420" y="208" fill="#f1efe7" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">In Review</text>
<text x="420" y="224" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">awaiting approval</text>
<rect x="340" y="160" width="160" height="80" rx="8" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<rect x="348" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.40)" stroke-width="0.8"/>
<text x="368" y="177" fill="#f5f5f5" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="420" y="208" fill="#f5f5f5" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">In Review</text>
<text x="420" y="224" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">awaiting approval</text>
<!-- State: Published (focal coral) -->
<rect x="560" y="160" width="160" height="80" rx="8" fill="rgba(255,106,48,0.08)" stroke="#ff6a30" stroke-width="1"/>
<rect x="568" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(255,106,48,0.50)" stroke-width="0.8"/>
<text x="588" y="177" fill="#ff6a30" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="208" fill="#f1efe7" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Published</text>
<text x="640" y="224" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">live on site</text>
<rect x="560" y="160" width="160" height="80" rx="8" fill="rgba(240,138,89,0.08)" stroke="#f08a59" stroke-width="1"/>
<rect x="568" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(240,138,89,0.50)" stroke-width="0.8"/>
<text x="588" y="177" fill="#f08a59" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="208" fill="#f5f5f5" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Published</text>
<text x="640" y="224" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">live on site</text>
<!-- State: Archived -->
<rect x="560" y="300" width="160" height="100" rx="8" fill="rgba(241,239,231,0.05)" stroke="#a8a69d" stroke-width="1"/>
<rect x="568" y="308" width="40" height="12" rx="2" fill="transparent" stroke="rgba(168,166,157,0.50)" stroke-width="0.8"/>
<text x="588" y="317" fill="#a8a69d" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="348" fill="#f1efe7" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Archived</text>
<text x="640" y="364" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">noindex · hidden</text>
<text x="640" y="382" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">redirect retained</text>
<rect x="560" y="300" width="160" height="100" rx="8" fill="rgba(245,245,245,0.05)" stroke="#bfc0c0" stroke-width="1"/>
<rect x="568" y="308" width="40" height="12" rx="2" fill="transparent" stroke="rgba(191,192,192,0.50)" stroke-width="0.8"/>
<text x="588" y="317" fill="#bfc0c0" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="348" fill="#f5f5f5" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Archived</text>
<text x="640" y="364" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">noindex · hidden</text>
<text x="640" y="382" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">redirect retained</text>
<!-- End ring dot -->
<circle cx="640" cy="440" r="8" fill="none" stroke="#f1efe7" stroke-width="1"/>
<circle cx="640" cy="440" r="5" fill="#f1efe7"/>
<circle cx="640" cy="440" r="8" fill="none" stroke="#f5f5f5" stroke-width="1"/>
<circle cx="640" cy="440" r="5" fill="#f5f5f5"/>
</svg>
</div>
</body>
+51 -51
View File
@@ -7,7 +7,7 @@
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root { --color-paper:#f5f4ed; --color-paper-2:#efeee5; --color-ink:#0b0d0b; --color-muted:#52534e; --color-soft:#65655c; --color-rule:rgba(11,13,11,0.12); --color-accent:#f7591f; --color-link:#1a70c7; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --color-link:#2e5aa8; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
@@ -20,14 +20,14 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
@@ -42,84 +42,84 @@
<svg viewBox="0 0 1000 460" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#52534e"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f7591f"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Transitions (drawn first) -->
<!-- Start → Draft -->
<line x1="68" y1="200" x2="120" y2="200" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="68" y1="200" x2="120" y2="200" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Draft → In Review -->
<line x1="280" y1="200" x2="340" y2="200" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="280" y1="200" x2="340" y2="200" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- In Review → Published (coral — happy path) -->
<line x1="500" y1="200" x2="560" y2="200" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="500" y1="200" x2="560" y2="200" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- Published → Archived (down) -->
<line x1="640" y1="240" x2="640" y2="300" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="640" y1="240" x2="640" y2="300" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Archived → End (down) -->
<line x1="640" y1="400" x2="640" y2="432" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="640" y1="400" x2="640" y2="432" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- In Review → Draft (curved back up-and-left) -->
<path d="M 420 160 C 420 96, 200 96, 200 160" fill="none" stroke="#52534e" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<path d="M 420 160 C 420 96, 200 96, 200 160" fill="none" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- Transition labels -->
<rect x="172" y="184" width="48" height="12" rx="2" fill="#f5f4ed"/>
<text x="196" y="194" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CREATE</text>
<rect x="172" y="184" width="48" height="12" rx="2" fill="#f5f5f5"/>
<text x="196" y="194" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CREATE</text>
<rect x="288" y="184" width="48" height="12" rx="2" fill="#f5f4ed"/>
<text x="312" y="194" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SUBMIT</text>
<rect x="288" y="184" width="48" height="12" rx="2" fill="#f5f5f5"/>
<text x="312" y="194" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SUBMIT</text>
<rect x="500" y="184" width="60" height="12" rx="2" fill="#f5f4ed"/>
<text x="530" y="194" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">APPROVE</text>
<rect x="500" y="184" width="60" height="12" rx="2" fill="#f5f5f5"/>
<text x="530" y="194" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">APPROVE</text>
<rect x="612" y="264" width="56" height="12" rx="2" fill="#f5f4ed"/>
<text x="640" y="274" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXPIRE</text>
<rect x="612" y="264" width="56" height="12" rx="2" fill="#f5f5f5"/>
<text x="640" y="274" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXPIRE</text>
<rect x="620" y="416" width="40" height="12" rx="2" fill="#f5f4ed"/>
<text x="640" y="426" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PURGE</text>
<rect x="620" y="416" width="40" height="12" rx="2" fill="#f5f5f5"/>
<text x="640" y="426" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PURGE</text>
<!-- Reject label on curved path -->
<rect x="276" y="92" width="80" height="12" rx="2" fill="#f5f4ed"/>
<text x="316" y="102" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">REJECT · REVISE</text>
<rect x="276" y="92" width="80" height="12" rx="2" fill="#f5f5f5"/>
<text x="316" y="102" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">REJECT · REVISE</text>
<!-- Start dot (filled ink) -->
<circle cx="60" cy="200" r="6" fill="#0b0d0b"/>
<circle cx="60" cy="200" r="6" fill="#2d3142"/>
<!-- State: Draft -->
<rect x="120" y="160" width="160" height="80" rx="8" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="128" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="148" y="177" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="200" y="208" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft</text>
<text x="200" y="224" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">unpublished</text>
<rect x="120" y="160" width="160" height="80" rx="8" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="128" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="148" y="177" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="200" y="208" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft</text>
<text x="200" y="224" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">unpublished</text>
<!-- State: In Review -->
<rect x="340" y="160" width="160" height="80" rx="8" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="348" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="368" y="177" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="420" y="208" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">In Review</text>
<text x="420" y="224" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">awaiting approval</text>
<rect x="340" y="160" width="160" height="80" rx="8" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="348" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="368" y="177" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="420" y="208" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">In Review</text>
<text x="420" y="224" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">awaiting approval</text>
<!-- State: Published (focal coral) -->
<rect x="560" y="160" width="160" height="80" rx="8" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<rect x="568" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(247,89,31,0.50)" stroke-width="0.8"/>
<text x="588" y="177" fill="#f7591f" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="208" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Published</text>
<text x="640" y="224" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">live on site</text>
<rect x="560" y="160" width="160" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<rect x="568" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="588" y="177" fill="#eb6c36" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="208" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Published</text>
<text x="640" y="224" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">live on site</text>
<!-- State: Archived -->
<rect x="560" y="300" width="160" height="100" rx="8" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="1"/>
<rect x="568" y="308" width="40" height="12" rx="2" fill="transparent" stroke="rgba(82,83,78,0.50)" stroke-width="0.8"/>
<text x="588" y="317" fill="#52534e" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="348" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Archived</text>
<text x="640" y="364" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">noindex · hidden</text>
<text x="640" y="382" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">redirect retained</text>
<rect x="560" y="300" width="160" height="100" rx="8" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="1"/>
<rect x="568" y="308" width="40" height="12" rx="2" fill="transparent" stroke="rgba(79,93,117,0.50)" stroke-width="0.8"/>
<text x="588" y="317" fill="#4f5d75" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="348" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Archived</text>
<text x="640" y="364" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">noindex · hidden</text>
<text x="640" y="382" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">redirect retained</text>
<!-- End ring dot -->
<circle cx="640" cy="440" r="8" fill="none" stroke="#0b0d0b" stroke-width="1"/>
<circle cx="640" cy="440" r="5" fill="#0b0d0b"/>
<circle cx="640" cy="440" r="8" fill="none" stroke="#2d3142" stroke-width="1"/>
<circle cx="640" cy="440" r="5" fill="#2d3142"/>
</svg>
</div>
@@ -141,7 +141,7 @@
<div class="footer">
<span>article lifecycle · state machine</span>
<span>example · diagram-design</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+50 -50
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,84 +61,84 @@
<svg viewBox="0 0 1000 460" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#52534e"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f7591f"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Transitions (drawn first) -->
<!-- Start → Draft -->
<line x1="68" y1="200" x2="120" y2="200" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="68" y1="200" x2="120" y2="200" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Draft → In Review -->
<line x1="280" y1="200" x2="340" y2="200" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="280" y1="200" x2="340" y2="200" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- In Review → Published (coral — happy path) -->
<line x1="500" y1="200" x2="560" y2="200" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="500" y1="200" x2="560" y2="200" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- Published → Archived (down) -->
<line x1="640" y1="240" x2="640" y2="300" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="640" y1="240" x2="640" y2="300" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Archived → End (down) -->
<line x1="640" y1="400" x2="640" y2="432" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="640" y1="400" x2="640" y2="432" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- In Review → Draft (curved back up-and-left) -->
<path d="M 420 160 C 420 96, 200 96, 200 160" fill="none" stroke="#52534e" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<path d="M 420 160 C 420 96, 200 96, 200 160" fill="none" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- Transition labels -->
<rect x="172" y="184" width="48" height="12" rx="2" fill="#f5f4ed"/>
<text x="196" y="194" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CREATE</text>
<rect x="172" y="184" width="48" height="12" rx="2" fill="#f5f5f5"/>
<text x="196" y="194" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CREATE</text>
<rect x="288" y="184" width="48" height="12" rx="2" fill="#f5f4ed"/>
<text x="312" y="194" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SUBMIT</text>
<rect x="288" y="184" width="48" height="12" rx="2" fill="#f5f5f5"/>
<text x="312" y="194" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">SUBMIT</text>
<rect x="500" y="184" width="60" height="12" rx="2" fill="#f5f4ed"/>
<text x="530" y="194" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">APPROVE</text>
<rect x="500" y="184" width="60" height="12" rx="2" fill="#f5f5f5"/>
<text x="530" y="194" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">APPROVE</text>
<rect x="612" y="264" width="56" height="12" rx="2" fill="#f5f4ed"/>
<text x="640" y="274" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXPIRE</text>
<rect x="612" y="264" width="56" height="12" rx="2" fill="#f5f5f5"/>
<text x="640" y="274" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXPIRE</text>
<rect x="620" y="416" width="40" height="12" rx="2" fill="#f5f4ed"/>
<text x="640" y="426" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PURGE</text>
<rect x="620" y="416" width="40" height="12" rx="2" fill="#f5f5f5"/>
<text x="640" y="426" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PURGE</text>
<!-- Reject label on curved path -->
<rect x="276" y="92" width="80" height="12" rx="2" fill="#f5f4ed"/>
<text x="316" y="102" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">REJECT · REVISE</text>
<rect x="276" y="92" width="80" height="12" rx="2" fill="#f5f5f5"/>
<text x="316" y="102" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">REJECT · REVISE</text>
<!-- Start dot (filled ink) -->
<circle cx="60" cy="200" r="6" fill="#0b0d0b"/>
<circle cx="60" cy="200" r="6" fill="#2d3142"/>
<!-- State: Draft -->
<rect x="120" y="160" width="160" height="80" rx="8" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="128" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="148" y="177" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="200" y="208" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft</text>
<text x="200" y="224" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">unpublished</text>
<rect x="120" y="160" width="160" height="80" rx="8" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="128" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="148" y="177" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="200" y="208" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft</text>
<text x="200" y="224" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">unpublished</text>
<!-- State: In Review -->
<rect x="340" y="160" width="160" height="80" rx="8" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="348" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="368" y="177" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="420" y="208" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">In Review</text>
<text x="420" y="224" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">awaiting approval</text>
<rect x="340" y="160" width="160" height="80" rx="8" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="348" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="368" y="177" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="420" y="208" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">In Review</text>
<text x="420" y="224" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">awaiting approval</text>
<!-- State: Published (focal coral) -->
<rect x="560" y="160" width="160" height="80" rx="8" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<rect x="568" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(247,89,31,0.50)" stroke-width="0.8"/>
<text x="588" y="177" fill="#f7591f" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="208" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Published</text>
<text x="640" y="224" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">live on site</text>
<rect x="560" y="160" width="160" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<rect x="568" y="168" width="40" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="588" y="177" fill="#eb6c36" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="208" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Published</text>
<text x="640" y="224" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">live on site</text>
<!-- State: Archived -->
<rect x="560" y="300" width="160" height="100" rx="8" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="1"/>
<rect x="568" y="308" width="40" height="12" rx="2" fill="transparent" stroke="rgba(82,83,78,0.50)" stroke-width="0.8"/>
<text x="588" y="317" fill="#52534e" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="348" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Archived</text>
<text x="640" y="364" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">noindex · hidden</text>
<text x="640" y="382" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">redirect retained</text>
<rect x="560" y="300" width="160" height="100" rx="8" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="1"/>
<rect x="568" y="308" width="40" height="12" rx="2" fill="transparent" stroke="rgba(79,93,117,0.50)" stroke-width="0.8"/>
<text x="588" y="317" fill="#4f5d75" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STATE</text>
<text x="640" y="348" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Archived</text>
<text x="640" y="364" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">noindex · hidden</text>
<text x="640" y="382" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">redirect retained</text>
<!-- End ring dot -->
<circle cx="640" cy="440" r="8" fill="none" stroke="#0b0d0b" stroke-width="1"/>
<circle cx="640" cy="440" r="5" fill="#0b0d0b"/>
<circle cx="640" cy="440" r="8" fill="none" stroke="#2d3142" stroke-width="1"/>
<circle cx="640" cy="440" r="5" fill="#2d3142"/>
</svg>
</div>
</body>
+63 -63
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,109 +61,109 @@
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#a8a69d"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#ff6a30"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f08a59"/></marker>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Lane dividers -->
<line x1="40" y1="80" x2="960" y2="80" stroke="rgba(241,239,231,0.22)" stroke-width="1"/>
<line x1="40" y1="160" x2="960" y2="160" stroke="rgba(241,239,231,0.10)" stroke-width="1"/>
<line x1="40" y1="240" x2="960" y2="240" stroke="rgba(241,239,231,0.10)" stroke-width="1"/>
<line x1="40" y1="320" x2="960" y2="320" stroke="rgba(241,239,231,0.10)" stroke-width="1"/>
<line x1="40" y1="400" x2="960" y2="400" stroke="rgba(241,239,231,0.22)" stroke-width="1"/>
<line x1="40" y1="80" x2="960" y2="80" stroke="rgba(245,245,245,0.22)" stroke-width="1"/>
<line x1="40" y1="160" x2="960" y2="160" stroke="rgba(245,245,245,0.10)" stroke-width="1"/>
<line x1="40" y1="240" x2="960" y2="240" stroke="rgba(245,245,245,0.10)" stroke-width="1"/>
<line x1="40" y1="320" x2="960" y2="320" stroke="rgba(245,245,245,0.10)" stroke-width="1"/>
<line x1="40" y1="400" x2="960" y2="400" stroke="rgba(245,245,245,0.22)" stroke-width="1"/>
<!-- Actor column divider -->
<line x1="160" y1="80" x2="160" y2="400" stroke="rgba(241,239,231,0.22)" stroke-width="1"/>
<line x1="160" y1="80" x2="160" y2="400" stroke="rgba(245,245,245,0.22)" stroke-width="1"/>
<!-- Lane labels -->
<text x="60" y="124" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">AUTHOR</text>
<text x="60" y="204" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">REVIEWER</text>
<text x="60" y="284" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">EDITOR</text>
<text x="60" y="364" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">CI / CD</text>
<text x="60" y="124" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">AUTHOR</text>
<text x="60" y="204" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">REVIEWER</text>
<text x="60" y="284" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">EDITOR</text>
<text x="60" y="364" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">CI / CD</text>
<!-- Arrows (drawn first) -->
<!-- 1. Draft → Open PR (within Author) -->
<line x1="300" y1="120" x2="340" y2="120" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="300" y1="120" x2="340" y2="120" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- 2. Open PR → Review (Author → Reviewer handoff, diagonal down-right) -->
<line x1="460" y1="144" x2="500" y2="176" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="460" y1="144" x2="500" y2="176" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- 3. Review → Polish (Reviewer → Editor, vertical down) -->
<line x1="570" y1="224" x2="570" y2="256" stroke="#a8a69d" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<line x1="570" y1="224" x2="570" y2="256" stroke="#bfc0c0" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- 4. Polish → Approve (within Editor) -->
<line x1="640" y1="280" x2="680" y2="280" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="640" y1="280" x2="680" y2="280" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- 5. Approve → Build (Editor → CI/CD, coral handoff) -->
<line x1="750" y1="304" x2="720" y2="336" stroke="#ff6a30" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="750" y1="304" x2="720" y2="336" stroke="#f08a59" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- 6. Build → Deploy (within CI/CD) -->
<line x1="760" y1="360" x2="800" y2="360" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="760" y1="360" x2="800" y2="360" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Arrow labels -->
<rect x="452" y="140" width="60" height="12" rx="2" fill="#1c1a17"/>
<text x="482" y="150" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">HANDOFF</text>
<rect x="452" y="140" width="60" height="12" rx="2" fill="#2d3142"/>
<text x="482" y="150" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">HANDOFF</text>
<rect x="548" y="228" width="52" height="12" rx="2" fill="#2a2723"/>
<text x="574" y="238" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">REVISE</text>
<rect x="548" y="228" width="52" height="12" rx="2" fill="#393e53"/>
<text x="574" y="238" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">REVISE</text>
<rect x="712" y="308" width="80" height="12" rx="2" fill="#1c1a17"/>
<text x="752" y="318" fill="#ff6a30" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">DEPLOY TRIGGER</text>
<rect x="712" y="308" width="80" height="12" rx="2" fill="#2d3142"/>
<text x="752" y="318" fill="#f08a59" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">DEPLOY TRIGGER</text>
<!-- Steps -->
<!-- Author: Draft MDX -->
<rect x="180" y="96" width="120" height="48" rx="6" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="240" y="118" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft MDX</text>
<text x="240" y="132" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/…</text>
<rect x="180" y="96" width="120" height="48" rx="6" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="240" y="118" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft MDX</text>
<text x="240" y="132" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/…</text>
<!-- Author: Open PR -->
<rect x="340" y="96" width="120" height="48" rx="6" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="400" y="118" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Open PR</text>
<text x="400" y="132" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">gh pr create</text>
<rect x="340" y="96" width="120" height="48" rx="6" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="400" y="118" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Open PR</text>
<text x="400" y="132" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">gh pr create</text>
<!-- Reviewer: Review content -->
<rect x="500" y="176" width="140" height="48" rx="6" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="570" y="198" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Review content</text>
<text x="570" y="212" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">fact-check · voice</text>
<rect x="500" y="176" width="140" height="48" rx="6" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="570" y="198" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Review content</text>
<text x="570" y="212" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">fact-check · voice</text>
<!-- Editor: Polish copy -->
<rect x="500" y="256" width="140" height="48" rx="6" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="570" y="278" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Polish copy</text>
<text x="570" y="292" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">style · line edits</text>
<rect x="500" y="256" width="140" height="48" rx="6" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="570" y="278" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Polish copy</text>
<text x="570" y="292" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">style · line edits</text>
<!-- Editor: Approve merge -->
<rect x="680" y="256" width="140" height="48" rx="6" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="750" y="278" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Approve merge</text>
<text x="750" y="292" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">squash · main</text>
<rect x="680" y="256" width="140" height="48" rx="6" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="750" y="278" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Approve merge</text>
<text x="750" y="292" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">squash · main</text>
<!-- CI/CD: Build -->
<rect x="680" y="336" width="80" height="48" rx="6" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="720" y="358" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Build</text>
<text x="720" y="372" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">astro build</text>
<rect x="680" y="336" width="80" height="48" rx="6" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="720" y="358" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Build</text>
<text x="720" y="372" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">astro build</text>
<!-- CI/CD: Deploy (coral focal) -->
<rect x="800" y="336" width="120" height="48" rx="6" fill="rgba(255,106,48,0.08)" stroke="#ff6a30" stroke-width="1"/>
<text x="860" y="358" fill="#f1efe7" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Deploy</text>
<text x="860" y="372" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">cloudflare pages</text>
<rect x="800" y="336" width="120" height="48" rx="6" fill="rgba(240,138,89,0.08)" stroke="#f08a59" stroke-width="1"/>
<text x="860" y="358" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Deploy</text>
<text x="860" y="372" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">cloudflare pages</text>
<!-- Legend -->
<line x1="40" y1="428" x2="960" y2="428" stroke="rgba(241,239,231,0.10)" stroke-width="0.8"/>
<text x="40" y="444" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="428" x2="960" y2="428" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<text x="40" y="444" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="460" width="14" height="10" rx="2" fill="#2a2723" stroke="#f1efe7" stroke-width="1"/>
<text x="60" y="468" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Step</text>
<rect x="40" y="460" width="14" height="10" rx="2" fill="#393e53" stroke="#f5f5f5" stroke-width="1"/>
<text x="60" y="468" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Step</text>
<rect x="132" y="460" width="14" height="10" rx="2" fill="rgba(255,106,48,0.08)" stroke="#ff6a30" stroke-width="1"/>
<text x="152" y="468" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Focal outcome</text>
<rect x="132" y="460" width="14" height="10" rx="2" fill="rgba(240,138,89,0.08)" stroke="#f08a59" stroke-width="1"/>
<text x="152" y="468" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Focal outcome</text>
<line x1="268" y1="466" x2="296" y2="466" stroke="#a8a69d" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="304" y="468" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Within-lane step</text>
<line x1="268" y1="466" x2="296" y2="466" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="304" y="468" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Within-lane step</text>
<line x1="444" y1="466" x2="472" y2="466" stroke="#a8a69d" stroke-width="1.2" stroke-dasharray="4,3" marker-end="url(#arrow)"/>
<text x="480" y="468" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Revision loop</text>
<line x1="444" y1="466" x2="472" y2="466" stroke="#bfc0c0" stroke-width="1.2" stroke-dasharray="4,3" marker-end="url(#arrow)"/>
<text x="480" y="468" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Revision loop</text>
<line x1="608" y1="466" x2="636" y2="466" stroke="#ff6a30" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="644" y="468" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Critical handoff</text>
<line x1="608" y1="466" x2="636" y2="466" stroke="#f08a59" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="644" y="468" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Critical handoff</text>
</svg>
</div>
</body>
+64 -64
View File
@@ -7,7 +7,7 @@
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root { --color-paper:#f5f4ed; --color-paper-2:#efeee5; --color-ink:#0b0d0b; --color-muted:#52534e; --color-soft:#65655c; --color-rule:rgba(11,13,11,0.12); --color-accent:#f7591f; --color-link:#1a70c7; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --color-link:#2e5aa8; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
@@ -20,14 +20,14 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
@@ -42,109 +42,109 @@
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#52534e"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f7591f"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Lane dividers -->
<line x1="40" y1="80" x2="960" y2="80" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<line x1="40" y1="160" x2="960" y2="160" stroke="rgba(11,13,11,0.10)" stroke-width="1"/>
<line x1="40" y1="240" x2="960" y2="240" stroke="rgba(11,13,11,0.10)" stroke-width="1"/>
<line x1="40" y1="320" x2="960" y2="320" stroke="rgba(11,13,11,0.10)" stroke-width="1"/>
<line x1="40" y1="400" x2="960" y2="400" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<line x1="40" y1="80" x2="960" y2="80" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<line x1="40" y1="160" x2="960" y2="160" stroke="rgba(45,49,66,0.10)" stroke-width="1"/>
<line x1="40" y1="240" x2="960" y2="240" stroke="rgba(45,49,66,0.10)" stroke-width="1"/>
<line x1="40" y1="320" x2="960" y2="320" stroke="rgba(45,49,66,0.10)" stroke-width="1"/>
<line x1="40" y1="400" x2="960" y2="400" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<!-- Actor column divider -->
<line x1="160" y1="80" x2="160" y2="400" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<line x1="160" y1="80" x2="160" y2="400" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<!-- Lane labels -->
<text x="60" y="124" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">AUTHOR</text>
<text x="60" y="204" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">REVIEWER</text>
<text x="60" y="284" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">EDITOR</text>
<text x="60" y="364" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">CI / CD</text>
<text x="60" y="124" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">AUTHOR</text>
<text x="60" y="204" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">REVIEWER</text>
<text x="60" y="284" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">EDITOR</text>
<text x="60" y="364" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">CI / CD</text>
<!-- Arrows (drawn first) -->
<!-- 1. Draft → Open PR (within Author) -->
<line x1="300" y1="120" x2="340" y2="120" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="300" y1="120" x2="340" y2="120" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- 2. Open PR → Review (Author → Reviewer handoff, diagonal down-right) -->
<line x1="460" y1="144" x2="500" y2="176" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="460" y1="144" x2="500" y2="176" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- 3. Review → Polish (Reviewer → Editor, vertical down) -->
<line x1="570" y1="224" x2="570" y2="256" stroke="#52534e" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<line x1="570" y1="224" x2="570" y2="256" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- 4. Polish → Approve (within Editor) -->
<line x1="640" y1="280" x2="680" y2="280" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="640" y1="280" x2="680" y2="280" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- 5. Approve → Build (Editor → CI/CD, coral handoff) -->
<line x1="750" y1="304" x2="720" y2="336" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="750" y1="304" x2="720" y2="336" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- 6. Build → Deploy (within CI/CD) -->
<line x1="760" y1="360" x2="800" y2="360" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="760" y1="360" x2="800" y2="360" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Arrow labels -->
<rect x="452" y="140" width="60" height="12" rx="2" fill="#f5f4ed"/>
<text x="482" y="150" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">HANDOFF</text>
<rect x="452" y="140" width="60" height="12" rx="2" fill="#f5f5f5"/>
<text x="482" y="150" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">HANDOFF</text>
<rect x="548" y="228" width="52" height="12" rx="2" fill="#efeee5"/>
<text x="574" y="238" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">REVISE</text>
<rect x="548" y="228" width="52" height="12" rx="2" fill="#ececec"/>
<text x="574" y="238" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">REVISE</text>
<rect x="712" y="308" width="80" height="12" rx="2" fill="#f5f4ed"/>
<text x="752" y="318" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">DEPLOY TRIGGER</text>
<rect x="712" y="308" width="80" height="12" rx="2" fill="#f5f5f5"/>
<text x="752" y="318" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">DEPLOY TRIGGER</text>
<!-- Steps -->
<!-- Author: Draft MDX -->
<rect x="180" y="96" width="120" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="240" y="118" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft MDX</text>
<text x="240" y="132" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/…</text>
<rect x="180" y="96" width="120" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="240" y="118" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft MDX</text>
<text x="240" y="132" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/…</text>
<!-- Author: Open PR -->
<rect x="340" y="96" width="120" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="400" y="118" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Open PR</text>
<text x="400" y="132" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">gh pr create</text>
<rect x="340" y="96" width="120" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="400" y="118" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Open PR</text>
<text x="400" y="132" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">gh pr create</text>
<!-- Reviewer: Review content -->
<rect x="500" y="176" width="140" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="570" y="198" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Review content</text>
<text x="570" y="212" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">fact-check · voice</text>
<rect x="500" y="176" width="140" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="570" y="198" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Review content</text>
<text x="570" y="212" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">fact-check · voice</text>
<!-- Editor: Polish copy -->
<rect x="500" y="256" width="140" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="570" y="278" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Polish copy</text>
<text x="570" y="292" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">style · line edits</text>
<rect x="500" y="256" width="140" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="570" y="278" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Polish copy</text>
<text x="570" y="292" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">style · line edits</text>
<!-- Editor: Approve merge -->
<rect x="680" y="256" width="140" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="750" y="278" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Approve merge</text>
<text x="750" y="292" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">squash · main</text>
<rect x="680" y="256" width="140" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="750" y="278" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Approve merge</text>
<text x="750" y="292" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">squash · main</text>
<!-- CI/CD: Build -->
<rect x="680" y="336" width="80" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="720" y="358" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Build</text>
<text x="720" y="372" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">astro build</text>
<rect x="680" y="336" width="80" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="720" y="358" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Build</text>
<text x="720" y="372" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">astro build</text>
<!-- CI/CD: Deploy (coral focal) -->
<rect x="800" y="336" width="120" height="48" rx="6" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="860" y="358" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Deploy</text>
<text x="860" y="372" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">cloudflare pages</text>
<rect x="800" y="336" width="120" height="48" rx="6" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="860" y="358" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Deploy</text>
<text x="860" y="372" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">cloudflare pages</text>
<!-- Legend -->
<line x1="40" y1="428" x2="960" y2="428" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="444" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="428" x2="960" y2="428" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="444" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="460" width="14" height="10" rx="2" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="60" y="468" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Step</text>
<rect x="40" y="460" width="14" height="10" rx="2" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="60" y="468" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Step</text>
<rect x="132" y="460" width="14" height="10" rx="2" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="152" y="468" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Focal outcome</text>
<rect x="132" y="460" width="14" height="10" rx="2" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="152" y="468" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Focal outcome</text>
<line x1="268" y1="466" x2="296" y2="466" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="304" y="468" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Within-lane step</text>
<line x1="268" y1="466" x2="296" y2="466" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="304" y="468" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Within-lane step</text>
<line x1="444" y1="466" x2="472" y2="466" stroke="#52534e" stroke-width="1.2" stroke-dasharray="4,3" marker-end="url(#arrow)"/>
<text x="480" y="468" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Revision loop</text>
<line x1="444" y1="466" x2="472" y2="466" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="4,3" marker-end="url(#arrow)"/>
<text x="480" y="468" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Revision loop</text>
<line x1="608" y1="466" x2="636" y2="466" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="644" y="468" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Critical handoff</text>
<line x1="608" y1="466" x2="636" y2="466" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="644" y="468" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Critical handoff</text>
</svg>
</div>
@@ -166,7 +166,7 @@
<div class="footer">
<span>publishing an article · swimlane</span>
<span>example · diagram-design</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+63 -63
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,109 +61,109 @@
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#52534e"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f7591f"/></marker>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Lane dividers -->
<line x1="40" y1="80" x2="960" y2="80" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<line x1="40" y1="160" x2="960" y2="160" stroke="rgba(11,13,11,0.10)" stroke-width="1"/>
<line x1="40" y1="240" x2="960" y2="240" stroke="rgba(11,13,11,0.10)" stroke-width="1"/>
<line x1="40" y1="320" x2="960" y2="320" stroke="rgba(11,13,11,0.10)" stroke-width="1"/>
<line x1="40" y1="400" x2="960" y2="400" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<line x1="40" y1="80" x2="960" y2="80" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<line x1="40" y1="160" x2="960" y2="160" stroke="rgba(45,49,66,0.10)" stroke-width="1"/>
<line x1="40" y1="240" x2="960" y2="240" stroke="rgba(45,49,66,0.10)" stroke-width="1"/>
<line x1="40" y1="320" x2="960" y2="320" stroke="rgba(45,49,66,0.10)" stroke-width="1"/>
<line x1="40" y1="400" x2="960" y2="400" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<!-- Actor column divider -->
<line x1="160" y1="80" x2="160" y2="400" stroke="rgba(11,13,11,0.22)" stroke-width="1"/>
<line x1="160" y1="80" x2="160" y2="400" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<!-- Lane labels -->
<text x="60" y="124" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">AUTHOR</text>
<text x="60" y="204" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">REVIEWER</text>
<text x="60" y="284" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">EDITOR</text>
<text x="60" y="364" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">CI / CD</text>
<text x="60" y="124" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">AUTHOR</text>
<text x="60" y="204" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">REVIEWER</text>
<text x="60" y="284" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">EDITOR</text>
<text x="60" y="364" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.18em">CI / CD</text>
<!-- Arrows (drawn first) -->
<!-- 1. Draft → Open PR (within Author) -->
<line x1="300" y1="120" x2="340" y2="120" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="300" y1="120" x2="340" y2="120" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- 2. Open PR → Review (Author → Reviewer handoff, diagonal down-right) -->
<line x1="460" y1="144" x2="500" y2="176" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="460" y1="144" x2="500" y2="176" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- 3. Review → Polish (Reviewer → Editor, vertical down) -->
<line x1="570" y1="224" x2="570" y2="256" stroke="#52534e" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<line x1="570" y1="224" x2="570" y2="256" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="5,4" marker-end="url(#arrow)"/>
<!-- 4. Polish → Approve (within Editor) -->
<line x1="640" y1="280" x2="680" y2="280" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="640" y1="280" x2="680" y2="280" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- 5. Approve → Build (Editor → CI/CD, coral handoff) -->
<line x1="750" y1="304" x2="720" y2="336" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<line x1="750" y1="304" x2="720" y2="336" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<!-- 6. Build → Deploy (within CI/CD) -->
<line x1="760" y1="360" x2="800" y2="360" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="760" y1="360" x2="800" y2="360" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Arrow labels -->
<rect x="452" y="140" width="60" height="12" rx="2" fill="#f5f4ed"/>
<text x="482" y="150" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">HANDOFF</text>
<rect x="452" y="140" width="60" height="12" rx="2" fill="#f5f5f5"/>
<text x="482" y="150" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">HANDOFF</text>
<rect x="548" y="228" width="52" height="12" rx="2" fill="#efeee5"/>
<text x="574" y="238" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">REVISE</text>
<rect x="548" y="228" width="52" height="12" rx="2" fill="#ececec"/>
<text x="574" y="238" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">REVISE</text>
<rect x="712" y="308" width="80" height="12" rx="2" fill="#f5f4ed"/>
<text x="752" y="318" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">DEPLOY TRIGGER</text>
<rect x="712" y="308" width="80" height="12" rx="2" fill="#f5f5f5"/>
<text x="752" y="318" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.12em">DEPLOY TRIGGER</text>
<!-- Steps -->
<!-- Author: Draft MDX -->
<rect x="180" y="96" width="120" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="240" y="118" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft MDX</text>
<text x="240" y="132" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/…</text>
<rect x="180" y="96" width="120" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="240" y="118" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Draft MDX</text>
<text x="240" y="132" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">src/content/…</text>
<!-- Author: Open PR -->
<rect x="340" y="96" width="120" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="400" y="118" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Open PR</text>
<text x="400" y="132" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">gh pr create</text>
<rect x="340" y="96" width="120" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="400" y="118" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Open PR</text>
<text x="400" y="132" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">gh pr create</text>
<!-- Reviewer: Review content -->
<rect x="500" y="176" width="140" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="570" y="198" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Review content</text>
<text x="570" y="212" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">fact-check · voice</text>
<rect x="500" y="176" width="140" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="570" y="198" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Review content</text>
<text x="570" y="212" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">fact-check · voice</text>
<!-- Editor: Polish copy -->
<rect x="500" y="256" width="140" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="570" y="278" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Polish copy</text>
<text x="570" y="292" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">style · line edits</text>
<rect x="500" y="256" width="140" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="570" y="278" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Polish copy</text>
<text x="570" y="292" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">style · line edits</text>
<!-- Editor: Approve merge -->
<rect x="680" y="256" width="140" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="750" y="278" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Approve merge</text>
<text x="750" y="292" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">squash · main</text>
<rect x="680" y="256" width="140" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="750" y="278" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Approve merge</text>
<text x="750" y="292" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">squash · main</text>
<!-- CI/CD: Build -->
<rect x="680" y="336" width="80" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="720" y="358" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Build</text>
<text x="720" y="372" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">astro build</text>
<rect x="680" y="336" width="80" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="720" y="358" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Build</text>
<text x="720" y="372" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">astro build</text>
<!-- CI/CD: Deploy (coral focal) -->
<rect x="800" y="336" width="120" height="48" rx="6" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="860" y="358" fill="#0b0d0b" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Deploy</text>
<text x="860" y="372" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">cloudflare pages</text>
<rect x="800" y="336" width="120" height="48" rx="6" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="860" y="358" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Deploy</text>
<text x="860" y="372" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">cloudflare pages</text>
<!-- Legend -->
<line x1="40" y1="428" x2="960" y2="428" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="444" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="428" x2="960" y2="428" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="444" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="460" width="14" height="10" rx="2" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="60" y="468" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Step</text>
<rect x="40" y="460" width="14" height="10" rx="2" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="60" y="468" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Step</text>
<rect x="132" y="460" width="14" height="10" rx="2" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="152" y="468" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Focal outcome</text>
<rect x="132" y="460" width="14" height="10" rx="2" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="152" y="468" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Focal outcome</text>
<line x1="268" y1="466" x2="296" y2="466" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="304" y="468" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Within-lane step</text>
<line x1="268" y1="466" x2="296" y2="466" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="304" y="468" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Within-lane step</text>
<line x1="444" y1="466" x2="472" y2="466" stroke="#52534e" stroke-width="1.2" stroke-dasharray="4,3" marker-end="url(#arrow)"/>
<text x="480" y="468" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Revision loop</text>
<line x1="444" y1="466" x2="472" y2="466" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="4,3" marker-end="url(#arrow)"/>
<text x="480" y="468" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Revision loop</text>
<line x1="608" y1="466" x2="636" y2="466" stroke="#f7591f" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="644" y="468" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Critical handoff</text>
<line x1="608" y1="466" x2="636" y2="466" stroke="#eb6c36" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
<text x="644" y="468" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Critical handoff</text>
</svg>
</div>
</body>
+44 -44
View File
@@ -3,15 +3,15 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>littlemight milestones · Timeline</title>
<title>Product milestones · Timeline</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -56,77 +56,77 @@
<body>
<div class="frame">
<p class="eyebrow">Timeline · Diagram Design</p>
<h1>littlemight, fourteen months</h1>
<h1>Product launch · fourteen months</h1>
<svg viewBox="0 0 1000 420" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Year markers (background) -->
<text x="60" y="340" fill="rgba(241,239,231,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2025</text>
<text x="700" y="340" fill="rgba(241,239,231,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2026</text>
<text x="60" y="340" fill="rgba(245,245,245,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2025</text>
<text x="700" y="340" fill="rgba(245,245,245,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2026</text>
<!-- Baseline -->
<line x1="80" y1="240" x2="920" y2="240" stroke="rgba(150,146,138,0.45)" stroke-width="1"/>
<!-- Year boundary tick (between 2025 and 2026) -->
<line x1="680" y1="232" x2="680" y2="248" stroke="rgba(241,239,231,0.20)" stroke-width="1"/>
<text x="680" y="260" fill="#8e8c83" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN '26</text>
<line x1="680" y1="232" x2="680" y2="248" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<text x="680" y="260" fill="#8e98ac" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN '26</text>
<!-- Start / end caps -->
<line x1="80" y1="232" x2="80" y2="248" stroke="rgba(241,239,231,0.20)" stroke-width="1"/>
<line x1="920" y1="232" x2="920" y2="248" stroke="rgba(241,239,231,0.20)" stroke-width="1"/>
<line x1="80" y1="232" x2="80" y2="248" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<line x1="920" y1="232" x2="920" y2="248" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<!-- Event 1: FEB 2025 · First post (below) -->
<line x1="100" y1="240" x2="100" y2="296" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<circle cx="100" cy="240" r="4" fill="#f1efe7"/>
<text x="100" y="312" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">FEB 2025</text>
<text x="100" y="328" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">First post</text>
<line x1="100" y1="240" x2="100" y2="296" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<circle cx="100" cy="240" r="4" fill="#f5f5f5"/>
<text x="100" y="312" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">FEB 2025</text>
<text x="100" y="328" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">First post</text>
<!-- Event 2: APR 2025 · Design v1 (above) -->
<line x1="240" y1="184" x2="240" y2="240" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<circle cx="240" cy="240" r="4" fill="#f1efe7"/>
<text x="240" y="156" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2025</text>
<text x="240" y="172" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v1</text>
<line x1="240" y1="184" x2="240" y2="240" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<circle cx="240" cy="240" r="4" fill="#f5f5f5"/>
<text x="240" y="156" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2025</text>
<text x="240" y="172" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v1</text>
<!-- Event 3: SEP 2025 · Design v2 (below) -->
<line x1="500" y1="240" x2="500" y2="296" stroke="rgba(241,239,231,0.30)" stroke-width="1"/>
<circle cx="500" cy="240" r="4" fill="#f1efe7"/>
<text x="500" y="312" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">SEP 2025</text>
<text x="500" y="328" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v2</text>
<text x="500" y="344" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">typography pass</text>
<line x1="500" y1="240" x2="500" y2="296" stroke="rgba(245,245,245,0.30)" stroke-width="1"/>
<circle cx="500" cy="240" r="4" fill="#f5f5f5"/>
<text x="500" y="312" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">SEP 2025</text>
<text x="500" y="328" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v2</text>
<text x="500" y="344" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">typography pass</text>
<!-- Event 4: JAN 2026 · Design v3 (above, coral major) -->
<line x1="740" y1="160" x2="740" y2="240" stroke="#ff6a30" stroke-width="1"/>
<circle cx="740" cy="240" r="6" fill="#ff6a30"/>
<text x="740" y="128" fill="#ff6a30" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN 2026</text>
<text x="740" y="148" fill="#f1efe7" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v3</text>
<text x="740" y="164" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">complexity budget</text>
<line x1="740" y1="160" x2="740" y2="240" stroke="#f08a59" stroke-width="1"/>
<circle cx="740" cy="240" r="6" fill="#f08a59"/>
<text x="740" y="128" fill="#f08a59" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN 2026</text>
<text x="740" y="148" fill="#f5f5f5" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v3</text>
<text x="740" y="164" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">complexity budget</text>
<!-- Event 5: APR 2026 · now · Diagram Design skill (below, coral) -->
<line x1="900" y1="240" x2="900" y2="296" stroke="#ff6a30" stroke-width="1"/>
<circle cx="900" cy="240" r="6" fill="#ff6a30"/>
<text x="900" y="312" fill="#ff6a30" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2026 · NOW</text>
<text x="900" y="328" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">diagram-design</text>
<text x="900" y="344" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">eight diagram types</text>
<line x1="900" y1="240" x2="900" y2="296" stroke="#f08a59" stroke-width="1"/>
<circle cx="900" cy="240" r="6" fill="#f08a59"/>
<text x="900" y="312" fill="#f08a59" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2026 · NOW</text>
<text x="900" y="328" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Schematic skill</text>
<text x="900" y="344" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">eight diagram types</text>
<!-- Legend -->
<line x1="40" y1="376" x2="960" y2="376" stroke="rgba(241,239,231,0.10)" stroke-width="0.8"/>
<text x="40" y="392" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="376" x2="960" y2="376" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<text x="40" y="392" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<circle cx="52" cy="408" r="4" fill="#f1efe7"/>
<text x="68" y="412" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Event</text>
<circle cx="52" cy="408" r="4" fill="#f5f5f5"/>
<text x="68" y="412" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Event</text>
<circle cx="148" cy="408" r="6" fill="#ff6a30"/>
<text x="164" y="412" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Major milestone</text>
<circle cx="148" cy="408" r="6" fill="#f08a59"/>
<text x="164" y="412" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Major milestone</text>
<text x="296" y="412" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Spacing is proportional to real elapsed time.</text>
<text x="296" y="412" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Spacing is proportional to real elapsed time.</text>
</svg>
</div>
</body>
+48 -48
View File
@@ -3,11 +3,11 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>littlemight milestones · Timeline</title>
<title>Product milestones · Timeline</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root { --color-paper:#f5f4ed; --color-paper-2:#efeee5; --color-ink:#0b0d0b; --color-muted:#52534e; --color-soft:#65655c; --color-rule:rgba(11,13,11,0.12); --color-accent:#f7591f; --color-link:#1a70c7; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --color-link:#2e5aa8; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
@@ -20,94 +20,94 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<p class="header-eyebrow">Timeline · Diagram Design</p>
<h1>littlemight, fourteen months</h1>
<p class="subtitle">Five design moments from the first post to the current diagram-design overhaul. Spacing is proportional to calendar time — the five-month gap between v1 and v2 is genuinely wider on the page.</p>
<h1>Product launch · fourteen months</h1>
<p class="subtitle">Five design moments from the first post to the current schematic overhaul. Spacing is proportional to calendar time — the five-month gap between v1 and v2 is genuinely wider on the page.</p>
</div>
<div class="diagram-container">
<svg viewBox="0 0 1000 420" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Year markers (background) -->
<text x="60" y="340" fill="rgba(11,13,11,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2025</text>
<text x="700" y="340" fill="rgba(11,13,11,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2026</text>
<text x="60" y="340" fill="rgba(45,49,66,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2025</text>
<text x="700" y="340" fill="rgba(45,49,66,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2026</text>
<!-- Baseline -->
<line x1="80" y1="240" x2="920" y2="240" stroke="rgba(135,139,134,0.45)" stroke-width="1"/>
<line x1="80" y1="240" x2="920" y2="240" stroke="rgba(79,93,117,0.45)" stroke-width="1"/>
<!-- Year boundary tick (between 2025 and 2026) -->
<line x1="680" y1="232" x2="680" y2="248" stroke="rgba(11,13,11,0.20)" stroke-width="1"/>
<text x="680" y="260" fill="#65655c" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN '26</text>
<line x1="680" y1="232" x2="680" y2="248" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
<text x="680" y="260" fill="#7a8399" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN '26</text>
<!-- Start / end caps -->
<line x1="80" y1="232" x2="80" y2="248" stroke="rgba(11,13,11,0.20)" stroke-width="1"/>
<line x1="920" y1="232" x2="920" y2="248" stroke="rgba(11,13,11,0.20)" stroke-width="1"/>
<line x1="80" y1="232" x2="80" y2="248" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
<line x1="920" y1="232" x2="920" y2="248" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
<!-- Event 1: FEB 2025 · First post (below) -->
<line x1="100" y1="240" x2="100" y2="296" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<circle cx="100" cy="240" r="4" fill="#0b0d0b"/>
<text x="100" y="312" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">FEB 2025</text>
<text x="100" y="328" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">First post</text>
<line x1="100" y1="240" x2="100" y2="296" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<circle cx="100" cy="240" r="4" fill="#2d3142"/>
<text x="100" y="312" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">FEB 2025</text>
<text x="100" y="328" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">First post</text>
<!-- Event 2: APR 2025 · Design v1 (above) -->
<line x1="240" y1="184" x2="240" y2="240" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<circle cx="240" cy="240" r="4" fill="#0b0d0b"/>
<text x="240" y="156" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2025</text>
<text x="240" y="172" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v1</text>
<line x1="240" y1="184" x2="240" y2="240" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<circle cx="240" cy="240" r="4" fill="#2d3142"/>
<text x="240" y="156" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2025</text>
<text x="240" y="172" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v1</text>
<!-- Event 3: SEP 2025 · Design v2 (below) -->
<line x1="500" y1="240" x2="500" y2="296" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<circle cx="500" cy="240" r="4" fill="#0b0d0b"/>
<text x="500" y="312" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">SEP 2025</text>
<text x="500" y="328" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v2</text>
<text x="500" y="344" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">typography pass</text>
<line x1="500" y1="240" x2="500" y2="296" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<circle cx="500" cy="240" r="4" fill="#2d3142"/>
<text x="500" y="312" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">SEP 2025</text>
<text x="500" y="328" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v2</text>
<text x="500" y="344" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">typography pass</text>
<!-- Event 4: JAN 2026 · Design v3 (above, coral major) -->
<line x1="740" y1="160" x2="740" y2="240" stroke="#f7591f" stroke-width="1"/>
<circle cx="740" cy="240" r="6" fill="#f7591f"/>
<text x="740" y="128" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN 2026</text>
<text x="740" y="148" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v3</text>
<text x="740" y="164" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">complexity budget</text>
<line x1="740" y1="160" x2="740" y2="240" stroke="#eb6c36" stroke-width="1"/>
<circle cx="740" cy="240" r="6" fill="#eb6c36"/>
<text x="740" y="128" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN 2026</text>
<text x="740" y="148" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v3</text>
<text x="740" y="164" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">complexity budget</text>
<!-- Event 5: APR 2026 · now · Diagram Design skill (below, coral) -->
<line x1="900" y1="240" x2="900" y2="296" stroke="#f7591f" stroke-width="1"/>
<circle cx="900" cy="240" r="6" fill="#f7591f"/>
<text x="900" y="312" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2026 · NOW</text>
<text x="900" y="328" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">diagram-design</text>
<text x="900" y="344" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">eight diagram types</text>
<line x1="900" y1="240" x2="900" y2="296" stroke="#eb6c36" stroke-width="1"/>
<circle cx="900" cy="240" r="6" fill="#eb6c36"/>
<text x="900" y="312" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2026 · NOW</text>
<text x="900" y="328" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Schematic skill</text>
<text x="900" y="344" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">eight diagram types</text>
<!-- Legend -->
<line x1="40" y1="376" x2="960" y2="376" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="392" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="376" x2="960" y2="376" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="392" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<circle cx="52" cy="408" r="4" fill="#0b0d0b"/>
<text x="68" y="412" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Event</text>
<circle cx="52" cy="408" r="4" fill="#2d3142"/>
<text x="68" y="412" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Event</text>
<circle cx="148" cy="408" r="6" fill="#f7591f"/>
<text x="164" y="412" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Major milestone</text>
<circle cx="148" cy="408" r="6" fill="#eb6c36"/>
<text x="164" y="412" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Major milestone</text>
<text x="296" y="412" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Spacing is proportional to real elapsed time.</text>
<text x="296" y="412" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Spacing is proportional to real elapsed time.</text>
</svg>
</div>
@@ -128,8 +128,8 @@
</div>
<div class="footer">
<span>littlemight · design lineage</span>
<span>example · diagram-design</span>
<span>product · design lineage</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+45 -45
View File
@@ -3,15 +3,15 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>littlemight milestones · Timeline</title>
<title>Product milestones · Timeline</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -56,77 +56,77 @@
<body>
<div class="frame">
<p class="eyebrow">Timeline · Diagram Design</p>
<h1>littlemight, fourteen months</h1>
<h1>Product launch · fourteen months</h1>
<svg viewBox="0 0 1000 420" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Year markers (background) -->
<text x="60" y="340" fill="rgba(11,13,11,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2025</text>
<text x="700" y="340" fill="rgba(11,13,11,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2026</text>
<text x="60" y="340" fill="rgba(45,49,66,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2025</text>
<text x="700" y="340" fill="rgba(45,49,66,0.06)" font-size="72" font-weight="600" font-family="'Geist Mono', monospace">2026</text>
<!-- Baseline -->
<line x1="80" y1="240" x2="920" y2="240" stroke="rgba(135,139,134,0.45)" stroke-width="1"/>
<line x1="80" y1="240" x2="920" y2="240" stroke="rgba(79,93,117,0.45)" stroke-width="1"/>
<!-- Year boundary tick (between 2025 and 2026) -->
<line x1="680" y1="232" x2="680" y2="248" stroke="rgba(11,13,11,0.20)" stroke-width="1"/>
<text x="680" y="260" fill="#65655c" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN '26</text>
<line x1="680" y1="232" x2="680" y2="248" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
<text x="680" y="260" fill="#7a8399" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN '26</text>
<!-- Start / end caps -->
<line x1="80" y1="232" x2="80" y2="248" stroke="rgba(11,13,11,0.20)" stroke-width="1"/>
<line x1="920" y1="232" x2="920" y2="248" stroke="rgba(11,13,11,0.20)" stroke-width="1"/>
<line x1="80" y1="232" x2="80" y2="248" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
<line x1="920" y1="232" x2="920" y2="248" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
<!-- Event 1: FEB 2025 · First post (below) -->
<line x1="100" y1="240" x2="100" y2="296" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<circle cx="100" cy="240" r="4" fill="#0b0d0b"/>
<text x="100" y="312" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">FEB 2025</text>
<text x="100" y="328" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">First post</text>
<line x1="100" y1="240" x2="100" y2="296" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<circle cx="100" cy="240" r="4" fill="#2d3142"/>
<text x="100" y="312" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">FEB 2025</text>
<text x="100" y="328" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">First post</text>
<!-- Event 2: APR 2025 · Design v1 (above) -->
<line x1="240" y1="184" x2="240" y2="240" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<circle cx="240" cy="240" r="4" fill="#0b0d0b"/>
<text x="240" y="156" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2025</text>
<text x="240" y="172" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v1</text>
<line x1="240" y1="184" x2="240" y2="240" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<circle cx="240" cy="240" r="4" fill="#2d3142"/>
<text x="240" y="156" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2025</text>
<text x="240" y="172" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v1</text>
<!-- Event 3: SEP 2025 · Design v2 (below) -->
<line x1="500" y1="240" x2="500" y2="296" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<circle cx="500" cy="240" r="4" fill="#0b0d0b"/>
<text x="500" y="312" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">SEP 2025</text>
<text x="500" y="328" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v2</text>
<text x="500" y="344" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">typography pass</text>
<line x1="500" y1="240" x2="500" y2="296" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<circle cx="500" cy="240" r="4" fill="#2d3142"/>
<text x="500" y="312" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">SEP 2025</text>
<text x="500" y="328" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v2</text>
<text x="500" y="344" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">typography pass</text>
<!-- Event 4: JAN 2026 · Design v3 (above, coral major) -->
<line x1="740" y1="160" x2="740" y2="240" stroke="#f7591f" stroke-width="1"/>
<circle cx="740" cy="240" r="6" fill="#f7591f"/>
<text x="740" y="128" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN 2026</text>
<text x="740" y="148" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v3</text>
<text x="740" y="164" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">complexity budget</text>
<line x1="740" y1="160" x2="740" y2="240" stroke="#eb6c36" stroke-width="1"/>
<circle cx="740" cy="240" r="6" fill="#eb6c36"/>
<text x="740" y="128" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">JAN 2026</text>
<text x="740" y="148" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design v3</text>
<text x="740" y="164" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">complexity budget</text>
<!-- Event 5: APR 2026 · now · Diagram Design skill (below, coral) -->
<line x1="900" y1="240" x2="900" y2="296" stroke="#f7591f" stroke-width="1"/>
<circle cx="900" cy="240" r="6" fill="#f7591f"/>
<text x="900" y="312" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2026 · NOW</text>
<text x="900" y="328" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">diagram-design</text>
<text x="900" y="344" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">eight diagram types</text>
<line x1="900" y1="240" x2="900" y2="296" stroke="#eb6c36" stroke-width="1"/>
<circle cx="900" cy="240" r="6" fill="#eb6c36"/>
<text x="900" y="312" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">APR 2026 · NOW</text>
<text x="900" y="328" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Schematic skill</text>
<text x="900" y="344" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">eight diagram types</text>
<!-- Legend -->
<line x1="40" y1="376" x2="960" y2="376" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="392" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="376" x2="960" y2="376" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="392" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<circle cx="52" cy="408" r="4" fill="#0b0d0b"/>
<text x="68" y="412" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Event</text>
<circle cx="52" cy="408" r="4" fill="#2d3142"/>
<text x="68" y="412" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Event</text>
<circle cx="148" cy="408" r="6" fill="#f7591f"/>
<text x="164" y="412" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Major milestone</text>
<circle cx="148" cy="408" r="6" fill="#eb6c36"/>
<text x="164" y="412" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Major milestone</text>
<text x="296" y="412" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Spacing is proportional to real elapsed time.</text>
<text x="296" y="412" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Spacing is proportional to real elapsed time.</text>
</svg>
</div>
</body>
+69 -69
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,110 +61,110 @@
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Tier tags (left margin) -->
<text x="40" y="108" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">TIER 0 · ROOT</text>
<text x="40" y="224" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 1</text>
<text x="40" y="324" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 2</text>
<text x="40" y="108" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">TIER 0 · ROOT</text>
<text x="40" y="224" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 1</text>
<text x="40" y="324" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 2</text>
<!-- Connectors drawn first (behind nodes) -->
<!-- Root → Tier 1 bus -->
<path d="M 500 128 L 500 168 L 220 168 L 220 208" fill="none" stroke="#a8a69d" stroke-width="1"/>
<path d="M 500 168 L 500 208" fill="none" stroke="#a8a69d" stroke-width="1"/>
<path d="M 500 168 L 780 168 L 780 208" fill="none" stroke="#a8a69d" stroke-width="1"/>
<path d="M 500 128 L 500 168 L 220 168 L 220 208" fill="none" stroke="#bfc0c0" stroke-width="1"/>
<path d="M 500 168 L 500 208" fill="none" stroke="#bfc0c0" stroke-width="1"/>
<path d="M 500 168 L 780 168 L 780 208" fill="none" stroke="#bfc0c0" stroke-width="1"/>
<!-- Design → leaves -->
<path d="M 220 256 L 220 296 L 140 296 L 140 336" fill="none" stroke="#a8a69d" stroke-width="1"/>
<path d="M 220 296 L 300 296 L 300 336" fill="none" stroke="#a8a69d" stroke-width="1"/>
<path d="M 220 256 L 220 296 L 140 296 L 140 336" fill="none" stroke="#bfc0c0" stroke-width="1"/>
<path d="M 220 296 L 300 296 L 300 336" fill="none" stroke="#bfc0c0" stroke-width="1"/>
<!-- Engineering → leaves -->
<path d="M 500 256 L 500 296 L 480 296 L 480 336" fill="none" stroke="#a8a69d" stroke-width="1"/>
<path d="M 500 296 L 660 296 L 660 336" fill="none" stroke="#a8a69d" stroke-width="1"/>
<path d="M 500 256 L 500 296 L 480 296 L 480 336" fill="none" stroke="#bfc0c0" stroke-width="1"/>
<path d="M 500 296 L 660 296 L 660 336" fill="none" stroke="#bfc0c0" stroke-width="1"/>
<!-- Research → single leaf -->
<path d="M 780 256 L 780 296 L 840 296 L 840 336" fill="none" stroke="#a8a69d" stroke-width="1"/>
<path d="M 780 256 L 780 296 L 840 296 L 840 336" fill="none" stroke="#bfc0c0" stroke-width="1"/>
<!-- Root node: Skills (coral focal) -->
<rect x="420" y="80" width="160" height="48" rx="6" fill="#1c1a17"/>
<rect x="420" y="80" width="160" height="48" rx="6" fill="rgba(255,106,48,0.10)" stroke="#ff6a30" stroke-width="1"/>
<rect x="428" y="88" width="32" height="12" rx="2" fill="transparent" stroke="rgba(255,106,48,0.50)" stroke-width="0.8"/>
<text x="444" y="97" fill="#ff6a30" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ROOT</text>
<text x="500" y="118" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Skills</text>
<rect x="420" y="80" width="160" height="48" rx="6" fill="#2d3142"/>
<rect x="420" y="80" width="160" height="48" rx="6" fill="rgba(240,138,89,0.10)" stroke="#f08a59" stroke-width="1"/>
<rect x="428" y="88" width="32" height="12" rx="2" fill="transparent" stroke="rgba(240,138,89,0.50)" stroke-width="0.8"/>
<text x="444" y="97" fill="#f08a59" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ROOT</text>
<text x="500" y="118" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Skills</text>
<!-- Tier 1: Design -->
<rect x="140" y="208" width="160" height="48" rx="6" fill="#1c1a17"/>
<rect x="140" y="208" width="160" height="48" rx="6" fill="rgba(241,239,231,0.04)" stroke="#f1efe7" stroke-width="1"/>
<rect x="148" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(241,239,231,0.40)" stroke-width="0.8"/>
<text x="162" y="225" fill="#f1efe7" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="220" y="240" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design</text>
<text x="220" y="252" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ui · visual · ux</text>
<rect x="140" y="208" width="160" height="48" rx="6" fill="#2d3142"/>
<rect x="140" y="208" width="160" height="48" rx="6" fill="rgba(245,245,245,0.04)" stroke="#f5f5f5" stroke-width="1"/>
<rect x="148" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.40)" stroke-width="0.8"/>
<text x="162" y="225" fill="#f5f5f5" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="220" y="240" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design</text>
<text x="220" y="252" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ui · visual · ux</text>
<!-- Tier 1: Engineering -->
<rect x="420" y="208" width="160" height="48" rx="6" fill="#1c1a17"/>
<rect x="420" y="208" width="160" height="48" rx="6" fill="rgba(241,239,231,0.04)" stroke="#f1efe7" stroke-width="1"/>
<rect x="428" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(241,239,231,0.40)" stroke-width="0.8"/>
<text x="442" y="225" fill="#f1efe7" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="500" y="240" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Engineering</text>
<text x="500" y="252" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ship · review · test</text>
<rect x="420" y="208" width="160" height="48" rx="6" fill="#2d3142"/>
<rect x="420" y="208" width="160" height="48" rx="6" fill="rgba(245,245,245,0.04)" stroke="#f5f5f5" stroke-width="1"/>
<rect x="428" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.40)" stroke-width="0.8"/>
<text x="442" y="225" fill="#f5f5f5" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="500" y="240" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Engineering</text>
<text x="500" y="252" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ship · review · test</text>
<!-- Tier 1: Research -->
<rect x="700" y="208" width="160" height="48" rx="6" fill="#1c1a17"/>
<rect x="700" y="208" width="160" height="48" rx="6" fill="rgba(241,239,231,0.04)" stroke="#f1efe7" stroke-width="1"/>
<rect x="708" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(241,239,231,0.40)" stroke-width="0.8"/>
<text x="722" y="225" fill="#f1efe7" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="780" y="240" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Research</text>
<text x="780" y="252" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">investigate · analyze</text>
<rect x="700" y="208" width="160" height="48" rx="6" fill="#2d3142"/>
<rect x="700" y="208" width="160" height="48" rx="6" fill="rgba(245,245,245,0.04)" stroke="#f5f5f5" stroke-width="1"/>
<rect x="708" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.40)" stroke-width="0.8"/>
<text x="722" y="225" fill="#f5f5f5" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="780" y="240" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Research</text>
<text x="780" y="252" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">investigate · analyze</text>
<!-- Tier 2: polish -->
<rect x="60" y="336" width="160" height="48" rx="6" fill="#1c1a17"/>
<rect x="60" y="336" width="160" height="48" rx="6" fill="rgba(241,239,231,0.05)" stroke="#a8a69d" stroke-width="0.8"/>
<text x="140" y="360" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">polish</text>
<text x="140" y="372" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">align · space · rhythm</text>
<rect x="60" y="336" width="160" height="48" rx="6" fill="#2d3142"/>
<rect x="60" y="336" width="160" height="48" rx="6" fill="rgba(245,245,245,0.05)" stroke="#bfc0c0" stroke-width="0.8"/>
<text x="140" y="360" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">polish</text>
<text x="140" y="372" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">align · space · rhythm</text>
<!-- Tier 2: critique -->
<rect x="220" y="336" width="160" height="48" rx="6" fill="#1c1a17"/>
<rect x="220" y="336" width="160" height="48" rx="6" fill="rgba(241,239,231,0.05)" stroke="#a8a69d" stroke-width="0.8"/>
<text x="300" y="360" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">critique</text>
<text x="300" y="372" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">hierarchy · density</text>
<rect x="220" y="336" width="160" height="48" rx="6" fill="#2d3142"/>
<rect x="220" y="336" width="160" height="48" rx="6" fill="rgba(245,245,245,0.05)" stroke="#bfc0c0" stroke-width="0.8"/>
<text x="300" y="360" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">critique</text>
<text x="300" y="372" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">hierarchy · density</text>
<!-- Tier 2: review -->
<rect x="400" y="336" width="160" height="48" rx="6" fill="#1c1a17"/>
<rect x="400" y="336" width="160" height="48" rx="6" fill="rgba(241,239,231,0.05)" stroke="#a8a69d" stroke-width="0.8"/>
<text x="480" y="360" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">review</text>
<text x="480" y="372" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">pre-land diff · sql</text>
<rect x="400" y="336" width="160" height="48" rx="6" fill="#2d3142"/>
<rect x="400" y="336" width="160" height="48" rx="6" fill="rgba(245,245,245,0.05)" stroke="#bfc0c0" stroke-width="0.8"/>
<text x="480" y="360" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">review</text>
<text x="480" y="372" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">pre-land diff · sql</text>
<!-- Tier 2: ship -->
<rect x="580" y="336" width="160" height="48" rx="6" fill="#1c1a17"/>
<rect x="580" y="336" width="160" height="48" rx="6" fill="rgba(241,239,231,0.05)" stroke="#a8a69d" stroke-width="0.8"/>
<text x="660" y="360" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">ship</text>
<text x="660" y="372" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">merge · deploy · verify</text>
<rect x="580" y="336" width="160" height="48" rx="6" fill="#2d3142"/>
<rect x="580" y="336" width="160" height="48" rx="6" fill="rgba(245,245,245,0.05)" stroke="#bfc0c0" stroke-width="0.8"/>
<text x="660" y="360" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">ship</text>
<text x="660" y="372" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">merge · deploy · verify</text>
<!-- Tier 2: investigate -->
<rect x="760" y="336" width="160" height="48" rx="6" fill="#1c1a17"/>
<rect x="760" y="336" width="160" height="48" rx="6" fill="rgba(241,239,231,0.05)" stroke="#a8a69d" stroke-width="0.8"/>
<text x="840" y="360" fill="#f1efe7" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">investigate</text>
<text x="840" y="372" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">root cause · evidence</text>
<rect x="760" y="336" width="160" height="48" rx="6" fill="#2d3142"/>
<rect x="760" y="336" width="160" height="48" rx="6" fill="rgba(245,245,245,0.05)" stroke="#bfc0c0" stroke-width="0.8"/>
<text x="840" y="360" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">investigate</text>
<text x="840" y="372" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">root cause · evidence</text>
<!-- Legend strip -->
<line x1="40" y1="412" x2="960" y2="412" stroke="rgba(241,239,231,0.10)" stroke-width="0.8"/>
<text x="40" y="428" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="412" x2="960" y2="412" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<text x="40" y="428" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="444" width="14" height="10" rx="2" fill="rgba(255,106,48,0.10)" stroke="#ff6a30" stroke-width="1"/>
<text x="60" y="452" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Root · focal</text>
<rect x="40" y="444" width="14" height="10" rx="2" fill="rgba(240,138,89,0.10)" stroke="#f08a59" stroke-width="1"/>
<text x="60" y="452" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Root · focal</text>
<rect x="180" y="444" width="14" height="10" rx="2" fill="rgba(241,239,231,0.04)" stroke="#f1efe7" stroke-width="1"/>
<text x="200" y="452" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Category branch</text>
<rect x="180" y="444" width="14" height="10" rx="2" fill="rgba(245,245,245,0.04)" stroke="#f5f5f5" stroke-width="1"/>
<text x="200" y="452" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Category branch</text>
<rect x="340" y="444" width="14" height="10" rx="2" fill="rgba(241,239,231,0.05)" stroke="#a8a69d" stroke-width="0.8"/>
<text x="360" y="452" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Leaf skill</text>
<rect x="340" y="444" width="14" height="10" rx="2" fill="rgba(245,245,245,0.05)" stroke="#bfc0c0" stroke-width="0.8"/>
<text x="360" y="452" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Leaf skill</text>
<text x="500" y="452" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Orthogonal connectors only. Coral marks the root — every branch descends from one idea.</text>
<text x="500" y="452" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Orthogonal connectors only. Coral marks the root — every branch descends from one idea.</text>
</svg>
</div>
</body>
+70 -70
View File
@@ -7,7 +7,7 @@
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root { --color-paper:#f5f4ed; --color-paper-2:#efeee5; --color-ink:#0b0d0b; --color-muted:#52534e; --color-soft:#65655c; --color-rule:rgba(11,13,11,0.12); --color-accent:#f7591f; --color-link:#1a70c7; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --color-link:#2e5aa8; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
@@ -20,14 +20,14 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
@@ -42,110 +42,110 @@
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Tier tags (left margin) -->
<text x="40" y="108" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">TIER 0 · ROOT</text>
<text x="40" y="224" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 1</text>
<text x="40" y="324" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 2</text>
<text x="40" y="108" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">TIER 0 · ROOT</text>
<text x="40" y="224" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 1</text>
<text x="40" y="324" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 2</text>
<!-- Connectors drawn first (behind nodes) -->
<!-- Root → Tier 1 bus -->
<path d="M 500 128 L 500 168 L 220 168 L 220 208" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 500 168 L 500 208" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 500 168 L 780 168 L 780 208" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 500 128 L 500 168 L 220 168 L 220 208" fill="none" stroke="#4f5d75" stroke-width="1"/>
<path d="M 500 168 L 500 208" fill="none" stroke="#4f5d75" stroke-width="1"/>
<path d="M 500 168 L 780 168 L 780 208" fill="none" stroke="#4f5d75" stroke-width="1"/>
<!-- Design → leaves -->
<path d="M 220 256 L 220 296 L 140 296 L 140 336" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 220 296 L 300 296 L 300 336" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 220 256 L 220 296 L 140 296 L 140 336" fill="none" stroke="#4f5d75" stroke-width="1"/>
<path d="M 220 296 L 300 296 L 300 336" fill="none" stroke="#4f5d75" stroke-width="1"/>
<!-- Engineering → leaves -->
<path d="M 500 256 L 500 296 L 480 296 L 480 336" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 500 296 L 660 296 L 660 336" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 500 256 L 500 296 L 480 296 L 480 336" fill="none" stroke="#4f5d75" stroke-width="1"/>
<path d="M 500 296 L 660 296 L 660 336" fill="none" stroke="#4f5d75" stroke-width="1"/>
<!-- Research → single leaf -->
<path d="M 780 256 L 780 296 L 840 296 L 840 336" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 780 256 L 780 296 L 840 296 L 840 336" fill="none" stroke="#4f5d75" stroke-width="1"/>
<!-- Root node: Skills (coral focal) -->
<rect x="420" y="80" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="420" y="80" width="160" height="48" rx="6" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<rect x="428" y="88" width="32" height="12" rx="2" fill="transparent" stroke="rgba(247,89,31,0.50)" stroke-width="0.8"/>
<text x="444" y="97" fill="#f7591f" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ROOT</text>
<text x="500" y="118" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Skills</text>
<rect x="420" y="80" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="420" y="80" width="160" height="48" rx="6" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<rect x="428" y="88" width="32" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="444" y="97" fill="#eb6c36" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ROOT</text>
<text x="500" y="118" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Skills</text>
<!-- Tier 1: Design -->
<rect x="140" y="208" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="140" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="148" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="162" y="225" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="220" y="240" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design</text>
<text x="220" y="252" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ui · visual · ux</text>
<rect x="140" y="208" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="140" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="148" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="162" y="225" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="220" y="240" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design</text>
<text x="220" y="252" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ui · visual · ux</text>
<!-- Tier 1: Engineering -->
<rect x="420" y="208" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="420" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="428" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="442" y="225" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="500" y="240" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Engineering</text>
<text x="500" y="252" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ship · review · test</text>
<rect x="420" y="208" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="420" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="428" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="442" y="225" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="500" y="240" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Engineering</text>
<text x="500" y="252" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ship · review · test</text>
<!-- Tier 1: Research -->
<rect x="700" y="208" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="700" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="708" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="722" y="225" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="780" y="240" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Research</text>
<text x="780" y="252" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">investigate · analyze</text>
<rect x="700" y="208" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="700" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="708" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="722" y="225" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="780" y="240" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Research</text>
<text x="780" y="252" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">investigate · analyze</text>
<!-- Tier 2: polish -->
<rect x="60" y="336" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="60" y="336" width="160" height="48" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="140" y="360" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">polish</text>
<text x="140" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">align · space · rhythm</text>
<rect x="60" y="336" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="60" y="336" width="160" height="48" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="140" y="360" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">polish</text>
<text x="140" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">align · space · rhythm</text>
<!-- Tier 2: critique -->
<rect x="220" y="336" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="220" y="336" width="160" height="48" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="300" y="360" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">critique</text>
<text x="300" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">hierarchy · density</text>
<rect x="220" y="336" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="220" y="336" width="160" height="48" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="300" y="360" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">critique</text>
<text x="300" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">hierarchy · density</text>
<!-- Tier 2: review -->
<rect x="400" y="336" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="400" y="336" width="160" height="48" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="480" y="360" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">review</text>
<text x="480" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">pre-land diff · sql</text>
<rect x="400" y="336" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="400" y="336" width="160" height="48" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="480" y="360" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">review</text>
<text x="480" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">pre-land diff · sql</text>
<!-- Tier 2: ship -->
<rect x="580" y="336" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="580" y="336" width="160" height="48" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="660" y="360" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">ship</text>
<text x="660" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">merge · deploy · verify</text>
<rect x="580" y="336" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="580" y="336" width="160" height="48" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="660" y="360" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">ship</text>
<text x="660" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">merge · deploy · verify</text>
<!-- Tier 2: investigate -->
<rect x="760" y="336" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="760" y="336" width="160" height="48" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="840" y="360" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">investigate</text>
<text x="840" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">root cause · evidence</text>
<rect x="760" y="336" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="760" y="336" width="160" height="48" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="840" y="360" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">investigate</text>
<text x="840" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">root cause · evidence</text>
<!-- Legend strip -->
<line x1="40" y1="412" x2="960" y2="412" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="428" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="412" x2="960" y2="412" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="428" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="444" width="14" height="10" rx="2" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="60" y="452" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Root · focal</text>
<rect x="40" y="444" width="14" height="10" rx="2" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="60" y="452" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Root · focal</text>
<rect x="180" y="444" width="14" height="10" rx="2" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="200" y="452" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Category branch</text>
<rect x="180" y="444" width="14" height="10" rx="2" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="200" y="452" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Category branch</text>
<rect x="340" y="444" width="14" height="10" rx="2" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="360" y="452" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Leaf skill</text>
<rect x="340" y="444" width="14" height="10" rx="2" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="360" y="452" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Leaf skill</text>
<text x="500" y="452" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Orthogonal connectors only. Coral marks the root — every branch descends from one idea.</text>
<text x="500" y="452" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Orthogonal connectors only. Coral marks the root — every branch descends from one idea.</text>
</svg>
</div>
@@ -167,7 +167,7 @@
<div class="footer">
<span>claude code skill taxonomy</span>
<span>example · diagram-design</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+69 -69
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,110 +61,110 @@
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Tier tags (left margin) -->
<text x="40" y="108" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">TIER 0 · ROOT</text>
<text x="40" y="224" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 1</text>
<text x="40" y="324" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 2</text>
<text x="40" y="108" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">TIER 0 · ROOT</text>
<text x="40" y="224" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 1</text>
<text x="40" y="324" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="start">TIER 2</text>
<!-- Connectors drawn first (behind nodes) -->
<!-- Root → Tier 1 bus -->
<path d="M 500 128 L 500 168 L 220 168 L 220 208" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 500 168 L 500 208" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 500 168 L 780 168 L 780 208" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 500 128 L 500 168 L 220 168 L 220 208" fill="none" stroke="#4f5d75" stroke-width="1"/>
<path d="M 500 168 L 500 208" fill="none" stroke="#4f5d75" stroke-width="1"/>
<path d="M 500 168 L 780 168 L 780 208" fill="none" stroke="#4f5d75" stroke-width="1"/>
<!-- Design → leaves -->
<path d="M 220 256 L 220 296 L 140 296 L 140 336" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 220 296 L 300 296 L 300 336" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 220 256 L 220 296 L 140 296 L 140 336" fill="none" stroke="#4f5d75" stroke-width="1"/>
<path d="M 220 296 L 300 296 L 300 336" fill="none" stroke="#4f5d75" stroke-width="1"/>
<!-- Engineering → leaves -->
<path d="M 500 256 L 500 296 L 480 296 L 480 336" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 500 296 L 660 296 L 660 336" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 500 256 L 500 296 L 480 296 L 480 336" fill="none" stroke="#4f5d75" stroke-width="1"/>
<path d="M 500 296 L 660 296 L 660 336" fill="none" stroke="#4f5d75" stroke-width="1"/>
<!-- Research → single leaf -->
<path d="M 780 256 L 780 296 L 840 296 L 840 336" fill="none" stroke="#52534e" stroke-width="1"/>
<path d="M 780 256 L 780 296 L 840 296 L 840 336" fill="none" stroke="#4f5d75" stroke-width="1"/>
<!-- Root node: Skills (coral focal) -->
<rect x="420" y="80" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="420" y="80" width="160" height="48" rx="6" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<rect x="428" y="88" width="32" height="12" rx="2" fill="transparent" stroke="rgba(247,89,31,0.50)" stroke-width="0.8"/>
<text x="444" y="97" fill="#f7591f" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ROOT</text>
<text x="500" y="118" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Skills</text>
<rect x="420" y="80" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="420" y="80" width="160" height="48" rx="6" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<rect x="428" y="88" width="32" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="444" y="97" fill="#eb6c36" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ROOT</text>
<text x="500" y="118" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Skills</text>
<!-- Tier 1: Design -->
<rect x="140" y="208" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="140" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="148" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="162" y="225" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="220" y="240" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design</text>
<text x="220" y="252" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ui · visual · ux</text>
<rect x="140" y="208" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="140" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="148" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="162" y="225" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="220" y="240" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Design</text>
<text x="220" y="252" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ui · visual · ux</text>
<!-- Tier 1: Engineering -->
<rect x="420" y="208" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="420" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="428" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="442" y="225" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="500" y="240" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Engineering</text>
<text x="500" y="252" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ship · review · test</text>
<rect x="420" y="208" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="420" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="428" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="442" y="225" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="500" y="240" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Engineering</text>
<text x="500" y="252" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">ship · review · test</text>
<!-- Tier 1: Research -->
<rect x="700" y="208" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="700" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="708" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="722" y="225" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="780" y="240" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Research</text>
<text x="780" y="252" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">investigate · analyze</text>
<rect x="700" y="208" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="700" y="208" width="160" height="48" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="708" y="216" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="722" y="225" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CAT</text>
<text x="780" y="240" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Research</text>
<text x="780" y="252" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">investigate · analyze</text>
<!-- Tier 2: polish -->
<rect x="60" y="336" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="60" y="336" width="160" height="48" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="140" y="360" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">polish</text>
<text x="140" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">align · space · rhythm</text>
<rect x="60" y="336" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="60" y="336" width="160" height="48" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="140" y="360" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">polish</text>
<text x="140" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">align · space · rhythm</text>
<!-- Tier 2: critique -->
<rect x="220" y="336" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="220" y="336" width="160" height="48" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="300" y="360" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">critique</text>
<text x="300" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">hierarchy · density</text>
<rect x="220" y="336" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="220" y="336" width="160" height="48" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="300" y="360" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">critique</text>
<text x="300" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">hierarchy · density</text>
<!-- Tier 2: review -->
<rect x="400" y="336" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="400" y="336" width="160" height="48" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="480" y="360" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">review</text>
<text x="480" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">pre-land diff · sql</text>
<rect x="400" y="336" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="400" y="336" width="160" height="48" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="480" y="360" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">review</text>
<text x="480" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">pre-land diff · sql</text>
<!-- Tier 2: ship -->
<rect x="580" y="336" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="580" y="336" width="160" height="48" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="660" y="360" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">ship</text>
<text x="660" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">merge · deploy · verify</text>
<rect x="580" y="336" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="580" y="336" width="160" height="48" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="660" y="360" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">ship</text>
<text x="660" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">merge · deploy · verify</text>
<!-- Tier 2: investigate -->
<rect x="760" y="336" width="160" height="48" rx="6" fill="#f5f4ed"/>
<rect x="760" y="336" width="160" height="48" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="840" y="360" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">investigate</text>
<text x="840" y="372" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">root cause · evidence</text>
<rect x="760" y="336" width="160" height="48" rx="6" fill="#f5f5f5"/>
<rect x="760" y="336" width="160" height="48" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="840" y="360" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">investigate</text>
<text x="840" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">root cause · evidence</text>
<!-- Legend strip -->
<line x1="40" y1="412" x2="960" y2="412" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="428" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="412" x2="960" y2="412" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="428" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<rect x="40" y="444" width="14" height="10" rx="2" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="60" y="452" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Root · focal</text>
<rect x="40" y="444" width="14" height="10" rx="2" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="60" y="452" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Root · focal</text>
<rect x="180" y="444" width="14" height="10" rx="2" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="200" y="452" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Category branch</text>
<rect x="180" y="444" width="14" height="10" rx="2" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="200" y="452" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Category branch</text>
<rect x="340" y="444" width="14" height="10" rx="2" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="0.8"/>
<text x="360" y="452" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Leaf skill</text>
<rect x="340" y="444" width="14" height="10" rx="2" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="0.8"/>
<text x="360" y="452" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Leaf skill</text>
<text x="500" y="452" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Orthogonal connectors only. Coral marks the root — every branch descends from one idea.</text>
<text x="500" y="452" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Orthogonal connectors only. Coral marks the root — every branch descends from one idea.</text>
</svg>
</div>
</body>
+31 -31
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17;
--color-ink: #f1efe7;
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142;
--color-ink: #f5f5f5;
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -61,7 +61,7 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
</pattern>
<clipPath id="clip-center">
<circle cx="500" cy="180" r="140"/>
@@ -71,59 +71,59 @@
</clipPath>
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Three set circles (stroke + very-low-opacity tint; tints compound in overlaps) -->
<!-- Desirable — top, ink -->
<circle cx="500" cy="180" r="140" fill="rgba(241,239,231,0.04)" stroke="#f1efe7" stroke-width="1"/>
<circle cx="500" cy="180" r="140" fill="rgba(245,245,245,0.04)" stroke="#f5f5f5" stroke-width="1"/>
<!-- Feasible — bottom-left, muted -->
<circle cx="428" cy="320" r="140" fill="rgba(168,166,157,0.05)" stroke="#a8a69d" stroke-width="1"/>
<circle cx="428" cy="320" r="140" fill="rgba(191,192,192,0.05)" stroke="#bfc0c0" stroke-width="1"/>
<!-- Viable — bottom-right, soft -->
<circle cx="572" cy="320" r="140" fill="rgba(142,140,131,0.05)" stroke="#8e8c83" stroke-width="1"/>
<circle cx="572" cy="320" r="140" fill="rgba(142,140,131,0.05)" stroke="#8e98ac" stroke-width="1"/>
<!-- Coral focal tint on the all-three intersection -->
<g clip-path="url(#clip-center)">
<g clip-path="url(#clip-center-2)">
<circle cx="572" cy="320" r="140" fill="rgba(255,106,48,0.14)"/>
<circle cx="572" cy="320" r="140" fill="rgba(240,138,89,0.14)"/>
</g>
</g>
<!-- Set labels -->
<text x="500" y="20" fill="#f1efe7" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Desirable</text>
<text x="500" y="36" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">PEOPLE WANT IT</text>
<text x="500" y="20" fill="#f5f5f5" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Desirable</text>
<text x="500" y="36" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">PEOPLE WANT IT</text>
<text x="152" y="400" fill="#a8a69d" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">Feasible</text>
<text x="152" y="416" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="start" letter-spacing="0.14em">WE CAN BUILD IT</text>
<text x="152" y="400" fill="#bfc0c0" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">Feasible</text>
<text x="152" y="416" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="start" letter-spacing="0.14em">WE CAN BUILD IT</text>
<text x="848" y="400" fill="#8e8c83" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">Viable</text>
<text x="848" y="416" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.14em">BUSINESS SUSTAINS</text>
<text x="848" y="400" fill="#8e98ac" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">Viable</text>
<text x="848" y="416" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.14em">BUSINESS SUSTAINS</text>
<!-- Pairwise intersection labels -->
<text x="360" y="232" fill="#a8a69d" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Prototype</text>
<text x="360" y="248" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">no business model</text>
<text x="360" y="232" fill="#bfc0c0" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Prototype</text>
<text x="360" y="248" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">no business model</text>
<text x="640" y="232" fill="#a8a69d" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Vaporware</text>
<text x="640" y="248" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">can't build it</text>
<text x="640" y="232" fill="#bfc0c0" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Vaporware</text>
<text x="640" y="248" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">can't build it</text>
<text x="500" y="368" fill="#a8a69d" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Internal tool</text>
<text x="500" y="384" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">nobody wants it</text>
<text x="500" y="368" fill="#bfc0c0" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Internal tool</text>
<text x="500" y="384" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">nobody wants it</text>
<!-- Focal: all-three center -->
<text x="500" y="260" fill="#ff6a30" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Shippable</text>
<text x="500" y="276" fill="#a8a69d" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">THE SWEET SPOT</text>
<text x="500" y="260" fill="#f08a59" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Shippable</text>
<text x="500" y="276" fill="#bfc0c0" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">THE SWEET SPOT</text>
<!-- Legend strip -->
<line x1="40" y1="456" x2="960" y2="456" stroke="rgba(241,239,231,0.10)" stroke-width="0.8"/>
<text x="40" y="472" fill="#a8a69d" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="456" x2="960" y2="456" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<text x="40" y="472" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<circle cx="52" cy="488" r="6" fill="none" stroke="#ff6a30" stroke-width="1.2"/>
<text x="68" y="492" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">All three — ship it</text>
<circle cx="52" cy="488" r="6" fill="none" stroke="#f08a59" stroke-width="1.2"/>
<text x="68" y="492" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">All three — ship it</text>
<circle cx="192" cy="488" r="6" fill="none" stroke="#a8a69d" stroke-width="1"/>
<text x="208" y="492" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif">Two of three — incomplete</text>
<circle cx="192" cy="488" r="6" fill="none" stroke="#bfc0c0" stroke-width="1"/>
<text x="208" y="492" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif">Two of three — incomplete</text>
<text x="380" y="492" fill="#a8a69d" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Coral marks the intersection that earns the work. The others name the traps.</text>
<text x="380" y="492" fill="#bfc0c0" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Coral marks the intersection that earns the work. The others name the traps.</text>
</svg>
</div>
</body>
+32 -32
View File
@@ -7,7 +7,7 @@
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root { --color-paper:#f5f4ed; --color-paper-2:#efeee5; --color-ink:#0b0d0b; --color-muted:#52534e; --color-soft:#65655c; --color-rule:rgba(11,13,11,0.12); --color-accent:#f7591f; --color-link:#1a70c7; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --color-link:#2e5aa8; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family: var(--font-sans); background: var(--color-paper); min-height: 100vh; padding: 3rem 2rem; color: var(--color-ink); }
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2.5rem; }
@@ -20,14 +20,14 @@
@media (max-width: 820px) { .cards { grid-template-columns: 1fr; } }
.card { background: #fff; border-radius: 6px; border: 1px solid var(--color-rule); padding: 1.25rem; }
.card .eyebrow { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(11,13,11,0.08); }
.card-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.875rem; padding-bottom: 0.875rem; border-bottom: 1px solid rgba(45,49,66,0.08); }
.card-dot { width: 7px; height: 7px; border-radius: 50%; }
.card-dot.ink { background: var(--color-ink); } .card-dot.muted { background: var(--color-muted); } .card-dot.coral { background: var(--color-accent); }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card p, .card ul { color: var(--color-muted); font-size: 0.8125rem; line-height: 1.55; list-style: none; }
.card li { margin-bottom: 0.3rem; padding-left: 0.875rem; position: relative; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(11,13,11,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(11,13,11,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
.card li::before { content: '—'; position: absolute; left: 0; color: rgba(45,49,66,0.25); font-size: 0.75rem; }
.footer { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid rgba(45,49,66,0.10); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--color-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
</style>
</head>
<body>
@@ -42,7 +42,7 @@
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<clipPath id="clip-center">
<circle cx="500" cy="180" r="140"/>
@@ -52,59 +52,59 @@
</clipPath>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<!-- Three set circles (stroke + very-low-opacity tint; tints compound in overlaps) -->
<!-- Desirable — top, ink -->
<circle cx="500" cy="180" r="140" fill="rgba(11,13,11,0.04)" stroke="#0b0d0b" stroke-width="1"/>
<circle cx="500" cy="180" r="140" fill="rgba(45,49,66,0.04)" stroke="#2d3142" stroke-width="1"/>
<!-- Feasible — bottom-left, muted -->
<circle cx="428" cy="320" r="140" fill="rgba(82,83,78,0.05)" stroke="#52534e" stroke-width="1"/>
<circle cx="428" cy="320" r="140" fill="rgba(79,93,117,0.05)" stroke="#4f5d75" stroke-width="1"/>
<!-- Viable — bottom-right, soft -->
<circle cx="572" cy="320" r="140" fill="rgba(101,101,92,0.05)" stroke="#65655c" stroke-width="1"/>
<circle cx="572" cy="320" r="140" fill="rgba(122,131,153,0.05)" stroke="#7a8399" stroke-width="1"/>
<!-- Coral focal tint on the all-three intersection -->
<g clip-path="url(#clip-center)">
<g clip-path="url(#clip-center-2)">
<circle cx="572" cy="320" r="140" fill="rgba(247,89,31,0.10)"/>
<circle cx="572" cy="320" r="140" fill="rgba(235,108,54,0.10)"/>
</g>
</g>
<!-- Set labels -->
<text x="500" y="20" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Desirable</text>
<text x="500" y="36" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">PEOPLE WANT IT</text>
<text x="500" y="20" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Desirable</text>
<text x="500" y="36" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">PEOPLE WANT IT</text>
<text x="152" y="400" fill="#52534e" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">Feasible</text>
<text x="152" y="416" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="start" letter-spacing="0.14em">WE CAN BUILD IT</text>
<text x="152" y="400" fill="#4f5d75" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">Feasible</text>
<text x="152" y="416" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="start" letter-spacing="0.14em">WE CAN BUILD IT</text>
<text x="848" y="400" fill="#65655c" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">Viable</text>
<text x="848" y="416" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.14em">BUSINESS SUSTAINS</text>
<text x="848" y="400" fill="#7a8399" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">Viable</text>
<text x="848" y="416" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.14em">BUSINESS SUSTAINS</text>
<!-- Pairwise intersection labels -->
<text x="360" y="232" fill="#52534e" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Prototype</text>
<text x="360" y="248" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">no business model</text>
<text x="360" y="232" fill="#4f5d75" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Prototype</text>
<text x="360" y="248" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">no business model</text>
<text x="640" y="232" fill="#52534e" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Vaporware</text>
<text x="640" y="248" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">can't build it</text>
<text x="640" y="232" fill="#4f5d75" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Vaporware</text>
<text x="640" y="248" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">can't build it</text>
<text x="500" y="368" fill="#52534e" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Internal tool</text>
<text x="500" y="384" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">nobody wants it</text>
<text x="500" y="368" fill="#4f5d75" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Internal tool</text>
<text x="500" y="384" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">nobody wants it</text>
<!-- Focal: all-three center -->
<text x="500" y="260" fill="#f7591f" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Shippable</text>
<text x="500" y="276" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">THE SWEET SPOT</text>
<text x="500" y="260" fill="#eb6c36" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Shippable</text>
<text x="500" y="276" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">THE SWEET SPOT</text>
<!-- Legend strip -->
<line x1="40" y1="456" x2="960" y2="456" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="472" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<line x1="40" y1="456" x2="960" y2="456" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="472" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<circle cx="52" cy="488" r="6" fill="none" stroke="#f7591f" stroke-width="1.2"/>
<text x="68" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">All three — ship it</text>
<circle cx="52" cy="488" r="6" fill="none" stroke="#eb6c36" stroke-width="1.2"/>
<text x="68" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">All three — ship it</text>
<circle cx="192" cy="488" r="6" fill="none" stroke="#52534e" stroke-width="1"/>
<text x="208" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Two of three — incomplete</text>
<circle cx="192" cy="488" r="6" fill="none" stroke="#4f5d75" stroke-width="1"/>
<text x="208" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Two of three — incomplete</text>
<text x="380" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Coral marks the intersection that earns the work. The others name the traps.</text>
<text x="380" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Coral marks the intersection that earns the work. The others name the traps.</text>
</svg>
</div>
@@ -126,7 +126,7 @@
<div class="footer">
<span>good design · desirable × feasible × viable</span>
<span>example · diagram-design</span>
<span>example · schematic skill</span>
</div>
</div>
</body>
+29 -58
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-accent: #eb6c36;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -58,79 +58,50 @@
<p class="eyebrow">Venn · Diagram Design</p>
<h1>Good design · Desirable × Feasible × Viable</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg">
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
</pattern>
<!-- Clip to the all-three intersection (centroid region) for the coral tint -->
<clipPath id="clip-center">
<!-- Chained clips isolate the all-three intersection: clip to Desirable, then to Feasible, then fill via the third circle. -->
<clipPath id="clip-desirable">
<circle cx="500" cy="180" r="140"/>
</clipPath>
<clipPath id="clip-center-2">
<clipPath id="clip-feasible">
<circle cx="428" cy="320" r="140"/>
</clipPath>
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<!-- Three set circles (stroke + very-low-opacity tint; tints compound in overlaps) -->
<!-- Desirable — top, ink -->
<circle cx="500" cy="180" r="140" fill="rgba(11,13,11,0.04)" stroke="#0b0d0b" stroke-width="1"/>
<circle cx="500" cy="180" r="140" fill="rgba(45,49,66,0.04)" stroke="#2d3142" stroke-width="1"/>
<!-- Feasible — bottom-left, muted -->
<circle cx="428" cy="320" r="140" fill="rgba(82,83,78,0.05)" stroke="#52534e" stroke-width="1"/>
<circle cx="428" cy="320" r="140" fill="rgba(79,93,117,0.05)" stroke="#4f5d75" stroke-width="1"/>
<!-- Viable — bottom-right, soft -->
<circle cx="572" cy="320" r="140" fill="rgba(101,101,92,0.05)" stroke="#65655c" stroke-width="1"/>
<circle cx="572" cy="320" r="140" fill="rgba(122,131,153,0.05)" stroke="#7a8399" stroke-width="1"/>
<!-- Coral focal tint on the all-three intersection -->
<g clip-path="url(#clip-center)">
<g clip-path="url(#clip-center-2)">
<circle cx="572" cy="320" r="140" fill="rgba(247,89,31,0.10)"/>
<!-- Focal: solid-ink triple intersection (dark fill for white text to read against) -->
<g clip-path="url(#clip-desirable)">
<g clip-path="url(#clip-feasible)">
<circle cx="572" cy="320" r="140" fill="#2d3142"/>
</g>
</g>
<!-- Set labels (outside circles, pinned to far side) -->
<!-- Desirable -->
<text x="500" y="20" fill="#0b0d0b" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Desirable</text>
<text x="500" y="36" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">PEOPLE WANT IT</text>
<!-- Set labels — positioned INSIDE each circle's non-overlapping lobe, so the diagram reads like a classic Venn -->
<!-- Desirable — top lobe (centered inside top of Desirable circle) -->
<text x="500" y="96" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Desirable</text>
<text x="500" y="112" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">PEOPLE WANT IT</text>
<!-- Feasible -->
<text x="152" y="400" fill="#52534e" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">Feasible</text>
<text x="152" y="416" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="start" letter-spacing="0.14em">WE CAN BUILD IT</text>
<!-- Feasible — bottom-left lobe -->
<text x="340" y="386" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Feasible</text>
<text x="340" y="402" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">WE CAN BUILD IT</text>
<!-- Viable -->
<text x="848" y="400" fill="#65655c" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">Viable</text>
<text x="848" y="416" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end" letter-spacing="0.14em">BUSINESS SUSTAINS</text>
<!-- Viable — bottom-right lobe -->
<text x="660" y="386" fill="#2d3142" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Viable</text>
<text x="660" y="402" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">BUSINESS SUSTAINS</text>
<!-- Pairwise intersection labels (inside overlap regions) -->
<!-- Desirable ∩ Feasible (upper-left overlap): "Prototype" — between top and BL -->
<text x="360" y="232" fill="#52534e" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Prototype</text>
<text x="360" y="248" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">no business model</text>
<!-- Desirable ∩ Viable (upper-right overlap): "Vaporware" -->
<text x="640" y="232" fill="#52534e" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Vaporware</text>
<text x="640" y="248" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">can't build it</text>
<!-- Feasible ∩ Viable (lower overlap): "Internal tool" -->
<text x="500" y="368" fill="#52534e" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Internal tool</text>
<text x="500" y="384" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">nobody wants it</text>
<!-- Focal: all-three center -->
<text x="500" y="260" fill="#f7591f" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Shippable</text>
<text x="500" y="276" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">THE SWEET SPOT</text>
<!-- Legend strip -->
<line x1="40" y1="456" x2="960" y2="456" stroke="rgba(11,13,11,0.10)" stroke-width="0.8"/>
<text x="40" y="472" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
<circle cx="52" cy="488" r="6" fill="none" stroke="#f7591f" stroke-width="1.2"/>
<text x="68" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">All three — ship it</text>
<circle cx="192" cy="488" r="6" fill="none" stroke="#52534e" stroke-width="1"/>
<text x="208" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif">Two of three — incomplete</text>
<text x="380" y="492" fill="#52534e" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Coral marks the intersection that earns the work. The others name the traps.</text>
<!-- Focal label: white text on the dark intersection -->
<text x="500" y="268" fill="#ffffff" font-size="14" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Shippable</text>
<text x="500" y="284" fill="rgba(245,245,245,0.75)" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">THE SWEET SPOT</text>
</svg>
</div>
</body>
+13 -10
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #1c1a17; /* deep warm charcoal */
--color-ink: #f1efe7; /* warm off-white */
--color-muted: #a8a69d;
--color-accent: #ff6a30;
--color-paper: #2d3142; /* deep warm charcoal */
--color-ink: #f5f5f5; /* warm off-white */
--color-muted: #bfc0c0;
--color-accent: #f08a59;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -60,16 +60,19 @@
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f08a59"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#6a95d8"/></marker>
<!-- OPTIONAL: dot-pattern background. Uncomment and add <rect fill="url(#dots)"/> after the paper rect to enable. -->
<!--
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(241,239,231,0.08)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.08)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#a8a69d"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#ff6a30"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#5ba8eb"/></marker>
-->
</defs>
<rect width="100%" height="100%" fill="#1c1a17"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.6"/>
<rect width="100%" height="100%" fill="#2d3142"/>
<!-- Draw arrows first, then nodes. Replace with your content. -->
+117 -110
View File
@@ -10,16 +10,16 @@
/* ── Tokens ─────────────────────────────────────────────────── */
:root {
--color-paper: #f5f4ed;
--color-paper-2: #efeee5;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-soft: #65655c;
--color-rule: rgba(11,13,11,0.12);
--color-rule-solid: rgba(135,139,134,0.25);
--color-accent: #f7591f;
--color-accent-tint: rgba(247,89,31,0.08);
--color-link: #1a70c7;
--color-paper: #f5f5f5;
--color-paper-2: #ececec;
--color-ink: #2d3142;
--color-muted: #4f5d75;
--color-soft: #7a8399;
--color-rule: rgba(45,49,66,0.12);
--color-rule-solid: rgba(79,93,117,0.25);
--color-accent: #eb6c36;
--color-accent-tint: rgba(235,108,54,0.08);
--color-link: #2e5aa8;
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', 'Times New Roman', serif;
--font-mono: 'Geist Mono', ui-monospace, Menlo, monospace;
@@ -67,12 +67,17 @@
}
/* ── Diagram container ────────────────────────────────────────── */
/* Default: clean, borderless — diagram sits directly on the page paper.
For the framed/boxed variant, uncomment the background/border/padding below. */
.diagram-container {
background: var(--color-paper-2);
border-radius: 8px;
border: 1px solid var(--color-rule);
padding: 1.5rem;
background: transparent;
border: none;
padding: 0;
overflow-x: auto;
/* background: var(--color-paper-2); */
/* border: 1px solid var(--color-rule); */
/* border-radius: 8px; */
/* padding: 1.5rem; */
}
svg { width: 100%; min-width: 900px; display: block; }
@@ -98,7 +103,7 @@
gap: 0.6rem;
margin-bottom: 0.875rem;
padding-bottom: 0.875rem;
border-bottom: 1px solid rgba(11,13,11,0.08);
border-bottom: 1px solid rgba(45,49,66,0.08);
}
.card-dot {
@@ -137,7 +142,7 @@
content: '—';
position: absolute;
left: 0;
color: rgba(11,13,11,0.25);
color: rgba(45,49,66,0.25);
font-size: 0.75rem;
}
@@ -145,7 +150,7 @@
.footer {
margin-top: 2rem;
padding-top: 1.5rem;
border-top: 1px solid rgba(11,13,11,0.10);
border-top: 1px solid rgba(45,49,66,0.10);
font-family: var(--font-mono);
font-size: 0.72rem;
letter-spacing: 0.06em;
@@ -173,55 +178,57 @@
<svg viewBox="0 0 1000 700" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Dot grid background (matches site .hero-terminal pattern) -->
<!-- OPTIONAL: dot-pattern background. Uncomment the <pattern> below and the second <rect> in the bg section to enable. -->
<!--
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
-->
<!-- Arrow: muted (default — generic / internal connections) -->
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#52534e"/>
<polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/>
</marker>
<!-- Arrow: coral (accent — primary / highlighted flows) -->
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#f7591f"/>
<polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/>
</marker>
<!-- Arrow: link-blue (#1a70c7 — HTTP/API / external calls) -->
<!-- Arrow: link-blue (#2e5aa8 — HTTP/API / external calls) -->
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#1a70c7"/>
<polygon points="0 0, 8 3, 0 6" fill="#2e5aa8"/>
</marker>
</defs>
<!-- Background: paper + dot grid -->
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.6"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<!-- <rect width="100%" height="100%" fill="url(#dots)" opacity="0.6"/> -->
<!-- =================================================================
DRAW ARROWS FIRST — they paint behind boxes (SVG document order).
================================================================= -->
<!-- HTTP/API arrow (link-blue) with label -->
<line x1="130" y1="305" x2="195" y2="305" stroke="#1a70c7" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="162" y="297" fill="#1a70c7" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">HTTPS</text>
<line x1="130" y1="305" x2="195" y2="305" stroke="#2e5aa8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="162" y="297" fill="#2e5aa8" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">HTTPS</text>
<!-- Generic internal arrow -->
<line x1="310" y1="305" x2="356" y2="305" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="310" y1="305" x2="356" y2="305" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Vertical arrow -->
<line x1="253" y1="332" x2="253" y2="376" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<line x1="253" y1="332" x2="253" y2="376" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<!-- Auth / security flow (dashed coral) -->
<path d="M 80 140 L 80 200 Q 80 218 98 218 L 200 218 Q 218 218 218 236 L 218 276"
fill="none" stroke="#f7591f" stroke-width="1.2" stroke-dasharray="5,4"
fill="none" stroke="#eb6c36" stroke-width="1.2" stroke-dasharray="5,4"
marker-end="url(#arrow-accent)"/>
<text x="148" y="212" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">JWT</text>
<text x="148" y="212" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">JWT</text>
<!-- Primary data flow (coral) -->
<line x1="620" y1="305" x2="696" y2="305" stroke="#f7591f" stroke-width="1.2" marker-end="url(#arrow-accent)"/>
<text x="655" y="297" fill="#f7591f" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">TLS</text>
<line x1="620" y1="305" x2="696" y2="305" stroke="#eb6c36" stroke-width="1.2" marker-end="url(#arrow-accent)"/>
<text x="655" y="297" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">TLS</text>
<!-- =================================================================
@@ -231,121 +238,121 @@
================================================================= -->
<!-- ── External / User ──────────────────────────────────────── -->
<rect x="30" y="278" width="100" height="54" rx="6" fill="#f5f4ed"/>
<rect x="30" y="278" width="100" height="54" rx="6" fill="rgba(82,83,78,0.10)" stroke="#65655c" stroke-width="1"/>
<rect x="30" y="278" width="100" height="54" rx="6" fill="#f5f5f5"/>
<rect x="30" y="278" width="100" height="54" rx="6" fill="rgba(79,93,117,0.10)" stroke="#7a8399" stroke-width="1"/>
<!-- Rectangular type tag (not rounded — brand rule) -->
<rect x="38" y="284" width="26" height="12" rx="2" fill="transparent" stroke="rgba(101,101,92,0.4)" stroke-width="0.8"/>
<text x="51" y="293" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<rect x="38" y="284" width="26" height="12" rx="2" fill="transparent" stroke="rgba(122,131,153,0.4)" stroke-width="0.8"/>
<text x="51" y="293" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<!-- Main label -->
<text x="80" y="308" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Users</text>
<text x="80" y="323" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser / Mobile</text>
<text x="80" y="308" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Users</text>
<text x="80" y="323" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Browser / Mobile</text>
<!-- ── Security / Auth ──────────────────────────────────────── -->
<rect x="30" y="78" width="100" height="56" rx="6" fill="#f5f4ed"/>
<rect x="30" y="78" width="100" height="56" rx="6" fill="rgba(247,89,31,0.06)" stroke="rgba(247,89,31,0.50)" stroke-width="1"/>
<rect x="38" y="84" width="28" height="12" rx="2" fill="transparent" stroke="rgba(247,89,31,0.40)" stroke-width="0.8"/>
<text x="52" y="93" fill="rgba(247,89,31,0.8)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">AUTH</text>
<text x="80" y="110" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Auth Provider</text>
<text x="80" y="125" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">OAuth 2.0</text>
<rect x="30" y="78" width="100" height="56" rx="6" fill="#f5f5f5"/>
<rect x="30" y="78" width="100" height="56" rx="6" fill="rgba(235,108,54,0.06)" stroke="rgba(235,108,54,0.50)" stroke-width="1"/>
<rect x="38" y="84" width="28" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.40)" stroke-width="0.8"/>
<text x="52" y="93" fill="rgba(235,108,54,0.8)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">AUTH</text>
<text x="80" y="110" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Auth Provider</text>
<text x="80" y="125" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">OAuth 2.0</text>
<!-- ── Region boundary (dashed) ─────────────────────────────── -->
<rect x="158" y="38" width="822" height="624" rx="8" fill="transparent" stroke="rgba(11,13,11,0.18)" stroke-width="1" stroke-dasharray="6,4"/>
<text x="170" y="55" fill="#52534e" font-size="8" font-weight="500" font-family="'Geist Mono', monospace" letter-spacing="0.12em">AWS REGION · US-WEST-2</text>
<rect x="158" y="38" width="822" height="624" rx="8" fill="transparent" stroke="rgba(45,49,66,0.18)" stroke-width="1" stroke-dasharray="6,4"/>
<text x="170" y="55" fill="#4f5d75" font-size="8" font-weight="500" font-family="'Geist Mono', monospace" letter-spacing="0.12em">AWS REGION · US-WEST-2</text>
<!-- ── Cloud / CDN (with faded watermark numeral — slide card pattern) -->
<rect x="198" y="278" width="112" height="54" rx="6" fill="#f5f4ed"/>
<rect x="198" y="278" width="112" height="54" rx="6" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<rect x="198" y="278" width="112" height="54" rx="6" fill="#f5f5f5"/>
<rect x="198" y="278" width="112" height="54" rx="6" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<!-- Faded mono watermark numeral (background) -->
<text x="294" y="323" fill="rgba(11,13,11,0.06)" font-size="40" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">01</text>
<rect x="206" y="284" width="24" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.22)" stroke-width="0.8"/>
<text x="218" y="293" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CDN</text>
<text x="254" y="308" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CloudFront</text>
<text x="254" y="323" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">AWS CDN</text>
<text x="294" y="323" fill="rgba(45,49,66,0.06)" font-size="40" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">01</text>
<rect x="206" y="284" width="24" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.22)" stroke-width="0.8"/>
<text x="218" y="293" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">CDN</text>
<text x="254" y="308" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">CloudFront</text>
<text x="254" y="323" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">AWS CDN</text>
<!-- ── Cloud / Storage ───────────────────────────────────────── -->
<rect x="198" y="378" width="112" height="102" rx="6" fill="#f5f4ed"/>
<rect x="198" y="378" width="112" height="102" rx="6" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="294" y="468" fill="rgba(11,13,11,0.06)" font-size="40" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">02</text>
<rect x="206" y="384" width="22" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.22)" stroke-width="0.8"/>
<text x="217" y="393" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">S3</text>
<text x="254" y="408" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">S3 Buckets</text>
<text x="254" y="426" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">bucket-assets</text>
<text x="254" y="440" fill="#52534e" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">bucket-uploads</text>
<text x="254" y="466" fill="#f7591f" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">OAI PROTECTED</text>
<rect x="198" y="378" width="112" height="102" rx="6" fill="#f5f5f5"/>
<rect x="198" y="378" width="112" height="102" rx="6" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="294" y="468" fill="rgba(45,49,66,0.06)" font-size="40" font-weight="600" font-family="'Geist Mono', monospace" text-anchor="end">02</text>
<rect x="206" y="384" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.22)" stroke-width="0.8"/>
<text x="217" y="393" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">S3</text>
<text x="254" y="408" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">S3 Buckets</text>
<text x="254" y="426" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">bucket-assets</text>
<text x="254" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">bucket-uploads</text>
<text x="254" y="466" fill="#eb6c36" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">OAI PROTECTED</text>
<!-- ── Security group boundary ───────────────────────────────── -->
<rect x="348" y="264" width="120" height="80" rx="6" fill="transparent" stroke="rgba(247,89,31,0.45)" stroke-width="1" stroke-dasharray="4,4"/>
<text x="356" y="278" fill="rgba(247,89,31,0.7)" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.08em">SG · :443</text>
<rect x="348" y="264" width="120" height="80" rx="6" fill="transparent" stroke="rgba(235,108,54,0.45)" stroke-width="1" stroke-dasharray="4,4"/>
<text x="356" y="278" fill="rgba(235,108,54,0.7)" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.08em">SG · :443</text>
<!-- ── Load Balancer (inside security group) ──────────────────── -->
<rect x="358" y="282" width="100" height="54" rx="6" fill="#f5f4ed"/>
<rect x="358" y="282" width="100" height="54" rx="6" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<rect x="366" y="288" width="22" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.22)" stroke-width="0.8"/>
<text x="377" y="297" fill="#65655c" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">LB</text>
<text x="408" y="311" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Load Balancer</text>
<text x="408" y="326" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">HTTPS :443</text>
<rect x="358" y="282" width="100" height="54" rx="6" fill="#f5f5f5"/>
<rect x="358" y="282" width="100" height="54" rx="6" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<rect x="366" y="288" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.22)" stroke-width="0.8"/>
<text x="377" y="297" fill="#7a8399" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">LB</text>
<text x="408" y="311" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Load Balancer</text>
<text x="408" y="326" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">HTTPS :443</text>
<!-- ── Backend / API ─────────────────────────────────────────── -->
<rect x="508" y="278" width="112" height="54" rx="6" fill="#f5f4ed"/>
<rect x="508" y="278" width="112" height="54" rx="6" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<rect x="516" y="284" width="26" height="12" rx="2" fill="transparent" stroke="rgba(11,13,11,0.40)" stroke-width="0.8"/>
<text x="529" y="293" fill="#0b0d0b" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">API</text>
<text x="564" y="308" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">API Server</text>
<text x="564" y="323" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">FastAPI :8000</text>
<rect x="508" y="278" width="112" height="54" rx="6" fill="#f5f5f5"/>
<rect x="508" y="278" width="112" height="54" rx="6" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<rect x="516" y="284" width="26" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
<text x="529" y="293" fill="#2d3142" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">API</text>
<text x="564" y="308" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">API Server</text>
<text x="564" y="323" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">FastAPI :8000</text>
<!-- ── Database ───────────────────────────────────────────────── -->
<rect x="698" y="278" width="120" height="54" rx="6" fill="#f5f4ed"/>
<rect x="698" y="278" width="120" height="54" rx="6" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="1"/>
<rect x="706" y="284" width="22" height="12" rx="2" fill="transparent" stroke="rgba(82,83,78,0.50)" stroke-width="0.8"/>
<text x="717" y="293" fill="#52534e" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DB</text>
<text x="758" y="308" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Database</text>
<text x="758" y="323" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">PostgreSQL</text>
<rect x="698" y="278" width="120" height="54" rx="6" fill="#f5f5f5"/>
<rect x="698" y="278" width="120" height="54" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="1"/>
<rect x="706" y="284" width="22" height="12" rx="2" fill="transparent" stroke="rgba(79,93,117,0.50)" stroke-width="0.8"/>
<text x="717" y="293" fill="#4f5d75" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DB</text>
<text x="758" y="308" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Database</text>
<text x="758" y="323" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">PostgreSQL</text>
<!-- ── Frontend / UI ─────────────────────────────────────────── -->
<rect x="198" y="518" width="200" height="112" rx="6" fill="#f5f4ed"/>
<rect x="198" y="518" width="200" height="112" rx="6" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<rect x="206" y="524" width="22" height="12" rx="2" fill="transparent" stroke="rgba(247,89,31,0.50)" stroke-width="0.8"/>
<text x="217" y="533" fill="#f7591f" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">UI</text>
<text x="298" y="550" fill="#0b0d0b" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Web App</text>
<text x="298" y="567" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">React + TypeScript</text>
<text x="298" y="581" fill="#52534e" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Astro SSG</text>
<rect x="198" y="518" width="200" height="112" rx="6" fill="#f5f5f5"/>
<rect x="198" y="518" width="200" height="112" rx="6" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<rect x="206" y="524" width="22" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="217" y="533" fill="#eb6c36" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">UI</text>
<text x="298" y="550" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Web App</text>
<text x="298" y="567" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">React + TypeScript</text>
<text x="298" y="581" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">Astro SSG</text>
<!-- Link-blue URL label -->
<text x="298" y="614" fill="#1a70c7" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.04em">app.example.com</text>
<text x="298" y="614" fill="#2e5aa8" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.04em">app.example.com</text>
<!-- =================================================================
LEGEND — OUTSIDE all boundary boxes.
Region boundary ends at y=662 → legend starts at y=682.
================================================================= -->
<text x="510" y="544" fill="#0b0d0b" font-size="9" font-weight="500" font-family="'Geist Mono', monospace" letter-spacing="0.12em">LEGEND</text>
<text x="510" y="544" fill="#2d3142" font-size="9" font-weight="500" font-family="'Geist Mono', monospace" letter-spacing="0.12em">LEGEND</text>
<rect x="510" y="558" width="14" height="10" rx="2" fill="rgba(247,89,31,0.08)" stroke="#f7591f" stroke-width="1"/>
<text x="530" y="567" fill="#52534e" font-size="9" font-family="'Geist', sans-serif">Frontend / UI</text>
<rect x="510" y="558" width="14" height="10" rx="2" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
<text x="530" y="567" fill="#4f5d75" font-size="9" font-family="'Geist', sans-serif">Frontend / UI</text>
<rect x="510" y="576" width="14" height="10" rx="2" fill="#ffffff" stroke="#0b0d0b" stroke-width="1"/>
<text x="530" y="585" fill="#52534e" font-size="9" font-family="'Geist', sans-serif">Backend / API</text>
<rect x="510" y="576" width="14" height="10" rx="2" fill="#ffffff" stroke="#2d3142" stroke-width="1"/>
<text x="530" y="585" fill="#4f5d75" font-size="9" font-family="'Geist', sans-serif">Backend / API</text>
<rect x="510" y="594" width="14" height="10" rx="2" fill="rgba(11,13,11,0.03)" stroke="rgba(11,13,11,0.30)" stroke-width="1"/>
<text x="530" y="603" fill="#52534e" font-size="9" font-family="'Geist', sans-serif">Cloud / Service</text>
<rect x="510" y="594" width="14" height="10" rx="2" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
<text x="530" y="603" fill="#4f5d75" font-size="9" font-family="'Geist', sans-serif">Cloud / Service</text>
<rect x="510" y="612" width="14" height="10" rx="2" fill="rgba(11,13,11,0.05)" stroke="#52534e" stroke-width="1"/>
<text x="530" y="621" fill="#52534e" font-size="9" font-family="'Geist', sans-serif">Database</text>
<rect x="510" y="612" width="14" height="10" rx="2" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="1"/>
<text x="530" y="621" fill="#4f5d75" font-size="9" font-family="'Geist', sans-serif">Database</text>
<rect x="510" y="630" width="14" height="10" rx="2" fill="rgba(82,83,78,0.10)" stroke="#65655c" stroke-width="1"/>
<text x="530" y="639" fill="#52534e" font-size="9" font-family="'Geist', sans-serif">External / User</text>
<rect x="510" y="630" width="14" height="10" rx="2" fill="rgba(79,93,117,0.10)" stroke="#7a8399" stroke-width="1"/>
<text x="530" y="639" fill="#4f5d75" font-size="9" font-family="'Geist', sans-serif">External / User</text>
<!-- Arrow types -->
<line x1="510" y1="655" x2="524" y2="655" stroke="#1a70c7" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="530" y="659" fill="#52534e" font-size="9" font-family="'Geist', sans-serif">HTTP / API call</text>
<line x1="510" y1="655" x2="524" y2="655" stroke="#2e5aa8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
<text x="530" y="659" fill="#4f5d75" font-size="9" font-family="'Geist', sans-serif">HTTP / API call</text>
<line x1="510" y1="671" x2="524" y2="671" stroke="#f7591f" stroke-width="1.2" stroke-dasharray="4,3" marker-end="url(#arrow-accent)"/>
<text x="530" y="675" fill="#52534e" font-size="9" font-family="'Geist', sans-serif">Auth flow</text>
<line x1="510" y1="671" x2="524" y2="671" stroke="#eb6c36" stroke-width="1.2" stroke-dasharray="4,3" marker-end="url(#arrow-accent)"/>
<text x="530" y="675" fill="#4f5d75" font-size="9" font-family="'Geist', sans-serif">Auth flow</text>
<line x1="510" y1="687" x2="524" y2="687" stroke="#52534e" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="530" y="691" fill="#52534e" font-size="9" font-family="'Geist', sans-serif">Internal connection</text>
<line x1="510" y1="687" x2="524" y2="687" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
<text x="530" y="691" fill="#4f5d75" font-size="9" font-family="'Geist', sans-serif">Internal connection</text>
<rect x="510" y="698" width="14" height="10" rx="2" fill="transparent" stroke="rgba(247,89,31,0.45)" stroke-width="1" stroke-dasharray="3,3"/>
<text x="530" y="707" fill="#52534e" font-size="9" font-family="'Geist', sans-serif">Security group</text>
<rect x="510" y="698" width="14" height="10" rx="2" fill="transparent" stroke="rgba(235,108,54,0.45)" stroke-width="1" stroke-dasharray="3,3"/>
<text x="530" y="707" fill="#4f5d75" font-size="9" font-family="'Geist', sans-serif">Security group</text>
</svg>
</div>
+14 -10
View File
@@ -8,10 +8,10 @@
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-paper: #f5f4ed;
--color-ink: #0b0d0b;
--color-muted: #52534e;
--color-accent: #f7591f;
--color-paper: #f5f5f5; /* white-smoke */
--color-ink: #2d3142; /* jet-black */
--color-muted: #4f5d75; /* blue-slate */
--color-accent: #eb6c36; /* atomic-tangerine */
--font-sans: 'Geist', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'Geist Mono', ui-monospace, monospace;
@@ -60,16 +60,20 @@
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#2e5aa8"/></marker>
<!-- OPTIONAL: dot-pattern background. Uncomment the <pattern> and the second <rect> below if you want the dotted paper look. -->
<!--
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(11,13,11,0.10)"/>
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
</pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#52534e"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f7591f"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#1a70c7"/></marker>
-->
</defs>
<rect width="100%" height="100%" fill="#f5f4ed"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
<rect width="100%" height="100%" fill="#f5f5f5"/>
<!-- <rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/> -->
<!-- Draw arrows first, then nodes. Replace with your content. -->
Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 144 KiB

+6 -6
View File
@@ -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 -6
View File
@@ -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.
+1 -1
View File
@@ -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.
+52
View File
@@ -18,3 +18,55 @@
- `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 (→ HIGH EFFORT) | **double-ended** (← LOW ↔ HIGH →) |
| 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 · HIGH / LOW`) |
| 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) |
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).
- **Axis labels**: two-line — `↑ DRIVER NAME` in Geist Mono 9px weight 600 uppercase tracked, `range` sublabel in Geist Mono 9px regular `muted`.
### 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; two-line axis labels beyond the tips.
- 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.
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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