Skip to content

Commit 523391d

Browse files
committed
fix(skill): eval feedback — font src paths, WCAG pairings, flash-through-white regression
Five fixes from Ular's first-pass workflow run: 1. step-1-design.md Fonts section — sub-agents pointed @font-face for "ES Build Neutral" at the Inter .woff2 files because DESIGN.md only named families, never emitted exact src: paths. Now the Fonts section example shows per-family + per-weight file paths AND a copy-verbatim @font-face block sub-agents can paste, so there's no inference step. Adds an explicit narrative of the real failure mode and how to avoid it. 2. beat-builder-guide.md FONTS rule — was "brand fonts with capture/assets/fonts/ path need @font-face in <style>." Now: "copy the @font-face block VERBATIM from DESIGN.md. Do NOT guess which .woff2 file belongs to which family — capture filenames are content-hashed and there is no visible mapping. If DESIGN.md doesn't include exact src: paths per family, STOP and ask the main agent; never pair an arbitrary .woff2 with a family name from memory." 3. step-1-design.md Colors section — Sub-agents reproduced brand colors faithfully and hit WCAG AA failures on dark surfaces (#68686A on #18191B = 3.16:1). Now the Colors section example computes per-pairing contrast ratios with ✅/⚠/❌ markers, documents the dark-surface substitute color when the brand's own palette fails, and points at the /hyperframes-contrast skill for ratio computation. Sub-agents pick text colors by surface context, not by "this is the brand's secondary text color." 4. capabilities.md flash-through-white entry — the "ideal as invisible bridge at duration: 0.01" framing caused agents to scatter white flashes through every composition as transition bridges. The fix was documented in the branch's HANDOFF but never landed. Now: "Fade through white midpoint — a visible white flash between scenes. Use only when the brand specifically calls for a white-flash beat boundary; this is NOT a neutral 'default' transition." 5. step-6-validate.md Warnings list — adds a paragraph on WCAG contrast false positives. The validator samples at fixed timestamps; elements at opacity:0 / mid-fade get measured as if fully visible, producing spurious failures. Tells the agent to verify visually before changing colors to clear a WCAG warning — bumping a color to fix a sampling artifact changes brand identity for no real benefit.
1 parent bb6a3d2 commit 523391d

4 files changed

Lines changed: 69 additions & 30 deletions

File tree

skills/website-to-hyperframes/references/beat-builder-guide.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ If any are missing from the beat spec, the beat is under-defined. Don't fill the
180180
- DETERMINISTIC: no `Math.random()`, `Date.now()`, `requestAnimationFrame`, `repeat:-1`.
181181
- Always `tl.fromTo()` not `tl.from()` for entrances.
182182
- Never stack two transform tweens on same element at same time.
183-
- FONTS: brand fonts with `capture/assets/fonts/` path need `@font-face` in `<style>`.
183+
- FONTS: copy the `@font-face` block VERBATIM from DESIGN.md's Fonts section. Do NOT guess which `.woff2` file belongs to which family — capture filenames are content-hashed (`14d7ce3e41dcbb66-s.p.woff2`) and there is no visible mapping. If DESIGN.md doesn't include exact `src:` paths per family, STOP and ask the main agent to add them; never pair an arbitrary `.woff2` file with a family name from memory.
184184

185185
## Easing — pick per intent
186186

skills/website-to-hyperframes/references/capabilities.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -99,22 +99,22 @@ The runtime registers these adapters in order; each implements `discover()` / `s
9999

100100
### The 14 shaders
101101

102-
| Name | Visual | Notes |
103-
| ------------------- | -------------------------------------------------------------------------------------- | -------------------------------------- |
104-
| domain-warp | Multi-octave FBM warps both scenes oppositely; organic dissolve edge with accent flash | Uses NQ noise bundle |
105-
| ridged-burn | Ridged multifractal mask reveals B; accent → bright → white burn ramp; sparks | NQ |
106-
| whip-pan | 10-sample horizontal motion blur + lateral crossfade | No noise |
107-
| sdf-iris | Aspect-corrected circle SDF expansion + accent-tinted glow rings ||
108-
| ripple-waves | Radial standing-wave UV displacement + tinted crossfade ||
109-
| gravitational-lens | Pinch pull toward center + R/B chromatic separation ||
110-
| cinematic-zoom | 12 RGB-offset radial zoom blur samples (chromatic zoom streak) ||
111-
| chromatic-split | R/B radial channel shift outward / inward; G fixed | Distinct from CSS chromatic aberration |
112-
| swirl-vortex | CCW swirl with FBM noise; reciprocal on incoming | NQ |
113-
| thermal-distortion | Vertical sin + FBM horizontal displacement; warm haze | NQ |
114-
| flash-through-white | Fade through white midpoint; ideal as invisible bridge at `duration: 0.01` | No accent |
115-
| cross-warp-morph | FBM vector field displaces both scenes; third FBM biases irregular wipe | NQ |
116-
| light-leak | Fixed off-frame leak with exponential falloff + accent warmth + ridge flare | Hard-coded leak anchor |
117-
| glitch | Line displacement + RGB lateral split + scan modulation + posterization + flicker | Deterministic |
102+
| Name | Visual | Notes |
103+
| ------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
104+
| domain-warp | Multi-octave FBM warps both scenes oppositely; organic dissolve edge with accent flash | Uses NQ noise bundle |
105+
| ridged-burn | Ridged multifractal mask reveals B; accent → bright → white burn ramp; sparks | NQ |
106+
| whip-pan | 10-sample horizontal motion blur + lateral crossfade | No noise |
107+
| sdf-iris | Aspect-corrected circle SDF expansion + accent-tinted glow rings | |
108+
| ripple-waves | Radial standing-wave UV displacement + tinted crossfade | |
109+
| gravitational-lens | Pinch pull toward center + R/B chromatic separation | |
110+
| cinematic-zoom | 12 RGB-offset radial zoom blur samples (chromatic zoom streak) | |
111+
| chromatic-split | R/B radial channel shift outward / inward; G fixed | Distinct from CSS chromatic aberration |
112+
| swirl-vortex | CCW swirl with FBM noise; reciprocal on incoming | NQ |
113+
| thermal-distortion | Vertical sin + FBM horizontal displacement; warm haze | NQ |
114+
| flash-through-white | Fade through white midpoint — a visible white flash between scenes | No accent. Use only when the brand specifically calls for a white-flash beat boundary; this is NOT a neutral "default" transition. |
115+
| cross-warp-morph | FBM vector field displaces both scenes; third FBM biases irregular wipe | NQ |
116+
| light-leak | Fixed off-frame leak with exponential falloff + accent warmth + ridge flare | Hard-coded leak anchor |
117+
| glitch | Line displacement + RGB lateral split + scan modulation + posterization + flicker | Deterministic |
118118

119119
### Public API
120120

skills/website-to-hyperframes/references/step-1-design.md

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,38 +55,75 @@ A flat lookup of the values sub-agents grab while composing beats. Two sub-secti
5555

5656
List 8–12 colors with brand-specific names + HEX + role. Not generic ("Accent 1") but evocative ("Stripe Purple", "Deep Navy", "Slate Border"). The name carries meaning; "blue 4" doesn't.
5757

58+
**For each text-on-surface combination the brand uses, compute the WCAG AA contrast ratio and flag failing pairings explicitly.** A real failure mode from prior runs: the brand's secondary-text color (`#68686A`) on its dark panel color (`#18191B`) = 3.16:1, which fails AA's 4.5:1 minimum. Sub-agents faithfully reproduced the brand's color choice and the result was unreadable. Encode the safe / unsafe pairings here so sub-agents pick text colors by surface context, not by "this is the brand's secondary text color." The `/hyperframes-contrast` skill audits ratios — run it before finalizing DESIGN.md.
59+
5860
**Example:**
5961

6062
```markdown
6163
#### Colors
6264

6365
- **Stripe Purple** (`#533AFD`): Primary CTA, interactive elements, focus rings — the brand's action signal
64-
- **Deep Navy** (`#061B31`): Primary text, headings — gravitas color
66+
- On Pure White: 6.2:1 ✅ — On Deep Navy: 3.8:1 ⚠ AA-only-Large
67+
- **Deep Navy** (`#061B31`): Primary text on light surfaces, also a dark surface tier
68+
- As text on Pure White: 17.4:1 ✅ — As surface: see Slate-on-Navy pairings below
6569
- **Pure White** (`#FFFFFF`): Page background, card surfaces
6670
- **Light Gray** (`#F5F7FA`): Surface tier 2 (cards on white pages, alternating sections)
67-
- **Slate Blue** (`#273951`): Secondary text, subheadings, lower-emphasis content
68-
- **Light Slate** (`#64748D`): Metadata, captions, disabled-adjacent text
69-
- **Subtle Border** (`#D4DEE9`): Card borders, dividers
70-
- **Vibrant Orange** (`#FF6118`): Energy accent — gradient endpoints, highlight bursts (never primary)
71-
- **Error Red** (`#FF0022`): Validation errors
72-
- **Success Green** (`#4CD963`): Confirmation states
71+
- **Slate Blue** (`#273951`): Secondary text on LIGHT surfaces
72+
- On Pure White: 12.6:1 ✅ — On Light Gray: 11.8:1 ✅ — On Deep Navy: 1.4:1 ❌ DO NOT USE
73+
- **Light Slate** (`#64748D`): Metadata, captions on light surfaces only
74+
- On Pure White: 4.8:1 ✅ — On Light Gray: 4.5:1 ✅ — On Deep Navy: 3.0:1 ❌ — On Dark Panel: 2.9:1 ❌
75+
- **For dark-surface metadata, use `#9A9A9E` instead: 6.4:1 on Deep Navy ✅, 6.1:1 on Dark Panel ✅**
76+
- **Subtle Border** (`#D4DEE9`): Card borders, dividers (not text — borders don't need AA)
77+
- **Vibrant Orange** (`#FF6118`): Energy accent — gradient endpoints, highlight bursts (never primary text)
78+
- **Error Red** (`#FF0022`): Validation errors. On Pure White: 4.5:1 ✅
79+
- **Success Green** (`#4CD963`): Confirmation states. On Pure White: 1.7:1 ❌ — must be paired with a darker outline or use as accent on dark surfaces
7380
```
7481

82+
**Where the brand's own palette fails WCAG**, document the substitute (like the `#9A9A9E` override above). Sub-agents pick the safe color by surface — and if the deviation matters to the brand identity, the user can revisit at Step 6.
83+
7584
#### Fonts
7685

77-
List font families (with availability notes) + the headline / body / mono trio if applicable:
86+
List font families with their role AND **the exact file path per family + weight** from `fonts-manifest.json`. Sub-agents will copy the `@font-face` block verbatim — if you only name the family without the path, sub-agents have to guess which `.woff2` file belongs to which family and get it wrong half the time (a real failure mode from prior runs: agents pointed `@font-face` for "ES Build Neutral" at the Inter `.woff2` files and the wordmark rendered in Inter).
7887

7988
**Example:**
8089

81-
```markdown
90+
````markdown
8291
#### Fonts
8392

84-
- **Display + Body:** `sohne-var` (variable 100–900, captured ✓) — weights 300 / 400 used in production
85-
- **Mono:** `"JetBrains Mono"` — code, metadata, technical content
93+
- **Display:** `"ES Build Neutral"` — wordmarks, headlines
94+
- 600: `capture/assets/fonts/14d7ce3e41dcbb66-s.p.woff2`
95+
- 700: `capture/assets/fonts/e8b276476c0ac6fa-s.p.woff2`
96+
- **Body:** `"Inter"` (variable 100–900, captured ✓) — body, labels, UI
97+
- 400: `capture/assets/fonts/9a8d3f06c4e89f2b-s.p.woff2`
98+
- 600: `capture/assets/fonts/1b0b3615811be75b-s.p.woff2`
99+
- **Mono:** `"JetBrains Mono"` — code, metadata
100+
- 400: `capture/assets/fonts/c7d2e9f5a1b3c8d4-s.p.woff2`
86101
- **Fallback stack:** `-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`
87102

88-
The brand uses **size for hierarchy, weight for emphasis**. Display 1: 48px/300, Display 2: 32px/300, Body: 14px/400. Never use weights above 400 — this brand has no bold variant in production.
103+
**`@font-face` block to paste in every composition** (sub-agents copy this verbatim — do not invent file paths):
104+
105+
```css
106+
@font-face {
107+
font-family: "ES Build Neutral";
108+
src: url("capture/assets/fonts/14d7ce3e41dcbb66-s.p.woff2") format("woff2");
109+
font-weight: 600;
110+
font-display: block;
111+
}
112+
@font-face {
113+
font-family: "Inter";
114+
src: url("capture/assets/fonts/9a8d3f06c4e89f2b-s.p.woff2") format("woff2");
115+
font-weight: 400;
116+
font-display: block;
117+
}
118+
/* + any other family/weight combinations the storyboard's beats need */
89119
```
120+
````
121+
122+
The brand uses **size for hierarchy, weight for emphasis**. Display 1: 48px/600, Display 2: 32px/600, Body: 14px/400. (Adjust to the actual brand's hierarchy.)
123+
124+
````
125+
126+
The exact `@font-face` block lets sub-agents copy verbatim instead of constructing one from inference. If a beat needs a weight that isn't in the manifest, flag it explicitly here: e.g., "ES Build Neutral 900 NOT in capture; use ES Build Neutral 700 as substitute, or fall back to Inter 700."
90127
91128
That's the whole typography section. If sub-agents need exact line-heights or letter-spacing, they read `design-styles.json` directly.
92129
@@ -132,7 +169,7 @@ Cover every variant the site uses — typically Primary, Secondary/Ghost, and Ic
132169
- **Font:** sohne-var 14px / 400
133170
- **Padding:** `12px 0`
134171
- **Hover:** background `rgba(83, 58, 253, 0.08)`, optional underline
135-
```
172+
````
136173

137174
#### Cards & Containers (always required if the site uses any)
138175

skills/website-to-hyperframes/references/step-6-validate.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ Some are style suggestions you can safely ignore:
6262
- **Deprecated attributes** (data-layer, data-end) — still work, just not preferred
6363
- **Dense tracks** — informational, not a bug
6464

65+
**WCAG contrast false positives** — the validator samples text colors at fixed timestamps. Elements that are at `opacity: 0` (pre-entrance) or mid-fade at those sample timestamps get measured against the background as if they were fully visible, which produces spurious contrast failures. Before changing a color to clear a WCAG warning, verify visually that the element is actually unreadable when on-screen at full opacity. If it's only flagged for pre-entrance / exit moments, the warning is a sampling artifact, not a real failure. Bumping the color to "fix" these false positives changes the brand identity for no real benefit.
66+
6567
Don't blindly ignore 158 warnings. Don't blindly fix all of them either. Read them.
6668

6769
## Visual Verification (snapshot)

0 commit comments

Comments
 (0)