Add Loop type (flywheel) + palette linter
- New type #27: Loop — ring of 5-8 stations around exactly one hub, solid flow arrows around the ring, dashed write-back spokes into the hub. Reference doc with ring layout math, budget, and anti-patterns; flagship example "The self-improving loop" in light/dark/full variants; gallery tab; README showcase under the hero image. - scripts/lint-skin.py — contributor palette linter: reads allowed tokens from style-guide.md at runtime, flags off-palette hexes, pure black, external assets, scripts, and off-system fonts. Baseline file grandfathers pre-2.0 examples; --all --baseline is green. - Linter immediately caught 36 near-miss hexes in 9 of the newly regenerated examples; swapped to exact series-palette tokens and recaptured the affected screenshots.
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>The self-improving loop · Dark</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 {
|
||||
--paper: #2d3142; --ink: #f5f5f5; --muted: #bfc0c0; --soft: #8e98ac;
|
||||
--accent: #f08a59; --accent-tint: rgba(240,138,89,0.10); --link: #6a95d8;
|
||||
--sans: 'Geist', system-ui, sans-serif; --serif: 'Instrument Serif', serif;
|
||||
--mono: 'Geist Mono', ui-monospace, monospace;
|
||||
}
|
||||
body { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 3rem 2rem; background: var(--paper); color: var(--ink); font-family: var(--sans); }
|
||||
.frame { width: 100%; max-width: 1200px; }
|
||||
.eyebrow { margin-bottom: 0.5rem; color: var(--muted); font: 500 0.66rem var(--mono); letter-spacing: 0.18em; text-transform: uppercase; }
|
||||
h1 { margin-bottom: 1.5rem; color: var(--ink); font: 400 clamp(1.5rem, 2.4vw + 0.75rem, 2rem)/1.15 var(--serif); letter-spacing: -0.02em; }
|
||||
svg { display: block; width: 100%; min-width: 900px; }
|
||||
.ring { fill: none; stroke: var(--muted); stroke-width: 1.2; }
|
||||
.spoke { fill: none; stroke: var(--soft); stroke-width: 1; stroke-dasharray: 5 4; }
|
||||
.station { fill: var(--paper); stroke: var(--ink); stroke-width: 1; }
|
||||
.station.focal { fill: var(--accent-tint); stroke: var(--accent); stroke-width: 1.2; }
|
||||
.hub { fill: var(--ink); }
|
||||
.node-name { fill: var(--ink); font: 600 12px var(--sans); text-anchor: middle; }
|
||||
.focal-name { fill: var(--accent); }
|
||||
.sublabel { fill: var(--soft); font: 400 8px var(--mono); text-anchor: middle; }
|
||||
.hub-name { fill: var(--paper); font: 600 16px var(--sans); text-anchor: middle; }
|
||||
.hub-sub { fill: var(--paper); opacity: 0.72; font: 400 8px var(--mono); text-anchor: middle; }
|
||||
.arrow-label { fill: var(--soft); font: 400 8px var(--mono); letter-spacing: 0.06em; text-anchor: middle; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="frame">
|
||||
<p class="eyebrow">Loop · Diagram Design</p>
|
||||
<h1>The self-improving loop</h1>
|
||||
|
||||
<svg viewBox="0 0 1040 680" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="loop-title loop-desc">
|
||||
<title id="loop-title">The self-improving loop</title>
|
||||
<desc id="loop-desc">Six stations flow clockwise from Capture through Learn and back to Capture. Each station writes shared state into one central memory hub, with Decide highlighted as the human approval gate.</desc>
|
||||
<defs>
|
||||
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><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="#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>
|
||||
<marker id="arrow-soft" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#8e98ac"/></marker>
|
||||
</defs>
|
||||
<rect width="1040" height="680" fill="#2d3142"/>
|
||||
<rect width="1040" height="680" fill="url(#dots)" opacity="0.55"/>
|
||||
|
||||
<!-- Solid clockwise ring: every endpoint lands on a station edge. -->
|
||||
<path class="ring" d="M600 92 C648 100 696 140 672 188" marker-end="url(#arrow)"/>
|
||||
<path class="ring" d="M808 236 H824 Q832 236 832 244 V436 Q832 444 824 444 H808" marker-end="url(#arrow)"/>
|
||||
<path class="ring" d="M672 492 C696 520 648 564 600 572" marker-end="url(#arrow)"/>
|
||||
<path class="ring" d="M440 572 C392 564 344 520 368 492" marker-end="url(#arrow)"/>
|
||||
<path class="ring" d="M232 444 H216 Q208 444 208 436 V244 Q208 236 216 236 H232" marker-end="url(#arrow)"/>
|
||||
<path class="ring" d="M368 188 C344 140 392 100 440 92" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Dashed write-backs: station inner edge to 6px before the hub stroke. -->
|
||||
<path class="spoke" d="M520 132 V280" marker-end="url(#arrow-soft)"/>
|
||||
<path class="spoke" d="M672 252 L616 284" marker-end="url(#arrow-soft)"/>
|
||||
<path class="spoke" d="M672 428 L616 396" marker-end="url(#arrow-soft)"/>
|
||||
<path class="spoke" d="M520 548 V400" marker-end="url(#arrow-soft)"/>
|
||||
<path class="spoke" d="M368 428 L424 396" marker-end="url(#arrow-soft)"/>
|
||||
<path class="spoke" d="M368 252 L424 284" marker-end="url(#arrow-soft)"/>
|
||||
|
||||
<!-- Curated spoke labels sit beside the line with an 8px visible gap. -->
|
||||
<rect x="532" y="200" width="48" height="16" rx="4" fill="#2d3142"/>
|
||||
<text x="556" y="212" class="arrow-label">SIGNALS</text>
|
||||
<rect x="460" y="464" width="52" height="16" rx="4" fill="#2d3142"/>
|
||||
<text x="486" y="476" class="arrow-label">OUTCOMES</text>
|
||||
|
||||
<!-- Stations -->
|
||||
<rect class="station" x="440" y="68" width="160" height="64" rx="6"/>
|
||||
<text x="520" y="96" class="node-name">Capture</text><text x="520" y="116" class="sublabel">signals in / intake</text>
|
||||
|
||||
<rect class="station" x="648" y="188" width="160" height="64" rx="6"/>
|
||||
<text x="728" y="216" class="node-name">Research</text><text x="728" y="236" class="sublabel">evidence pulled</text>
|
||||
|
||||
<rect class="station focal" x="648" y="428" width="160" height="64" rx="6"/>
|
||||
<text x="728" y="456" class="node-name focal-name">Decide</text><text x="728" y="476" class="sublabel">human approves</text>
|
||||
|
||||
<rect class="station" x="440" y="548" width="160" height="64" rx="6"/>
|
||||
<text x="520" y="576" class="node-name">Act</text><text x="520" y="596" class="sublabel">work ships</text>
|
||||
|
||||
<rect class="station" x="232" y="428" width="160" height="64" rx="6"/>
|
||||
<text x="312" y="456" class="node-name">Measure</text><text x="312" y="476" class="sublabel">outcomes logged</text>
|
||||
|
||||
<rect class="station" x="232" y="188" width="160" height="64" rx="6"/>
|
||||
<text x="312" y="216" class="node-name">Learn</text><text x="312" y="236" class="sublabel">playbook updated</text>
|
||||
|
||||
<!-- The one shared-state hub. -->
|
||||
<rect class="hub" x="420" y="288" width="200" height="104" rx="8"/>
|
||||
<text x="520" y="336" class="hub-name">Shared memory</text>
|
||||
<text x="520" y="360" class="hub-sub">one record, every loop</text>
|
||||
</svg>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user