mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-02 20:18:35 +00:00
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.
This commit is contained in:
@@ -180,7 +180,7 @@ If any are missing from the beat spec, the beat is under-defined. Don't fill the
|
||||
- DETERMINISTIC: no `Math.random()`, `Date.now()`, `requestAnimationFrame`, `repeat:-1`.
|
||||
- Always `tl.fromTo()` not `tl.from()` for entrances.
|
||||
- Never stack two transform tweens on same element at same time.
|
||||
- FONTS: brand fonts with `capture/assets/fonts/` path need `@font-face` in `<style>`.
|
||||
- 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.
|
||||
|
||||
## Easing — pick per intent
|
||||
|
||||
|
||||
@@ -99,22 +99,22 @@ The runtime registers these adapters in order; each implements `discover()` / `s
|
||||
|
||||
### The 14 shaders
|
||||
|
||||
| Name | Visual | Notes |
|
||||
| ------------------- | -------------------------------------------------------------------------------------- | -------------------------------------- |
|
||||
| domain-warp | Multi-octave FBM warps both scenes oppositely; organic dissolve edge with accent flash | Uses NQ noise bundle |
|
||||
| ridged-burn | Ridged multifractal mask reveals B; accent → bright → white burn ramp; sparks | NQ |
|
||||
| whip-pan | 10-sample horizontal motion blur + lateral crossfade | No noise |
|
||||
| sdf-iris | Aspect-corrected circle SDF expansion + accent-tinted glow rings | — |
|
||||
| ripple-waves | Radial standing-wave UV displacement + tinted crossfade | — |
|
||||
| gravitational-lens | Pinch pull toward center + R/B chromatic separation | — |
|
||||
| cinematic-zoom | 12 RGB-offset radial zoom blur samples (chromatic zoom streak) | — |
|
||||
| chromatic-split | R/B radial channel shift outward / inward; G fixed | Distinct from CSS chromatic aberration |
|
||||
| swirl-vortex | CCW swirl with FBM noise; reciprocal on incoming | NQ |
|
||||
| thermal-distortion | Vertical sin + FBM horizontal displacement; warm haze | NQ |
|
||||
| flash-through-white | Fade through white midpoint; ideal as invisible bridge at `duration: 0.01` | No accent |
|
||||
| cross-warp-morph | FBM vector field displaces both scenes; third FBM biases irregular wipe | NQ |
|
||||
| light-leak | Fixed off-frame leak with exponential falloff + accent warmth + ridge flare | Hard-coded leak anchor |
|
||||
| glitch | Line displacement + RGB lateral split + scan modulation + posterization + flicker | Deterministic |
|
||||
| Name | Visual | Notes |
|
||||
| ------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| domain-warp | Multi-octave FBM warps both scenes oppositely; organic dissolve edge with accent flash | Uses NQ noise bundle |
|
||||
| ridged-burn | Ridged multifractal mask reveals B; accent → bright → white burn ramp; sparks | NQ |
|
||||
| whip-pan | 10-sample horizontal motion blur + lateral crossfade | No noise |
|
||||
| sdf-iris | Aspect-corrected circle SDF expansion + accent-tinted glow rings | — |
|
||||
| ripple-waves | Radial standing-wave UV displacement + tinted crossfade | — |
|
||||
| gravitational-lens | Pinch pull toward center + R/B chromatic separation | — |
|
||||
| cinematic-zoom | 12 RGB-offset radial zoom blur samples (chromatic zoom streak) | — |
|
||||
| chromatic-split | R/B radial channel shift outward / inward; G fixed | Distinct from CSS chromatic aberration |
|
||||
| swirl-vortex | CCW swirl with FBM noise; reciprocal on incoming | NQ |
|
||||
| thermal-distortion | Vertical sin + FBM horizontal displacement; warm haze | NQ |
|
||||
| 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. |
|
||||
| cross-warp-morph | FBM vector field displaces both scenes; third FBM biases irregular wipe | NQ |
|
||||
| light-leak | Fixed off-frame leak with exponential falloff + accent warmth + ridge flare | Hard-coded leak anchor |
|
||||
| glitch | Line displacement + RGB lateral split + scan modulation + posterization + flicker | Deterministic |
|
||||
|
||||
### Public API
|
||||
|
||||
|
||||
@@ -55,38 +55,75 @@ A flat lookup of the values sub-agents grab while composing beats. Two sub-secti
|
||||
|
||||
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.
|
||||
|
||||
**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.
|
||||
|
||||
**Example:**
|
||||
|
||||
```markdown
|
||||
#### Colors
|
||||
|
||||
- **Stripe Purple** (`#533AFD`): Primary CTA, interactive elements, focus rings — the brand's action signal
|
||||
- **Deep Navy** (`#061B31`): Primary text, headings — gravitas color
|
||||
- On Pure White: 6.2:1 ✅ — On Deep Navy: 3.8:1 ⚠ AA-only-Large
|
||||
- **Deep Navy** (`#061B31`): Primary text on light surfaces, also a dark surface tier
|
||||
- As text on Pure White: 17.4:1 ✅ — As surface: see Slate-on-Navy pairings below
|
||||
- **Pure White** (`#FFFFFF`): Page background, card surfaces
|
||||
- **Light Gray** (`#F5F7FA`): Surface tier 2 (cards on white pages, alternating sections)
|
||||
- **Slate Blue** (`#273951`): Secondary text, subheadings, lower-emphasis content
|
||||
- **Light Slate** (`#64748D`): Metadata, captions, disabled-adjacent text
|
||||
- **Subtle Border** (`#D4DEE9`): Card borders, dividers
|
||||
- **Vibrant Orange** (`#FF6118`): Energy accent — gradient endpoints, highlight bursts (never primary)
|
||||
- **Error Red** (`#FF0022`): Validation errors
|
||||
- **Success Green** (`#4CD963`): Confirmation states
|
||||
- **Slate Blue** (`#273951`): Secondary text on LIGHT surfaces
|
||||
- On Pure White: 12.6:1 ✅ — On Light Gray: 11.8:1 ✅ — On Deep Navy: 1.4:1 ❌ DO NOT USE
|
||||
- **Light Slate** (`#64748D`): Metadata, captions on light surfaces only
|
||||
- On Pure White: 4.8:1 ✅ — On Light Gray: 4.5:1 ✅ — On Deep Navy: 3.0:1 ❌ — On Dark Panel: 2.9:1 ❌
|
||||
- **For dark-surface metadata, use `#9A9A9E` instead: 6.4:1 on Deep Navy ✅, 6.1:1 on Dark Panel ✅**
|
||||
- **Subtle Border** (`#D4DEE9`): Card borders, dividers (not text — borders don't need AA)
|
||||
- **Vibrant Orange** (`#FF6118`): Energy accent — gradient endpoints, highlight bursts (never primary text)
|
||||
- **Error Red** (`#FF0022`): Validation errors. On Pure White: 4.5:1 ✅
|
||||
- **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
|
||||
```
|
||||
|
||||
**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.
|
||||
|
||||
#### Fonts
|
||||
|
||||
List font families (with availability notes) + the headline / body / mono trio if applicable:
|
||||
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).
|
||||
|
||||
**Example:**
|
||||
|
||||
```markdown
|
||||
````markdown
|
||||
#### Fonts
|
||||
|
||||
- **Display + Body:** `sohne-var` (variable 100–900, captured ✓) — weights 300 / 400 used in production
|
||||
- **Mono:** `"JetBrains Mono"` — code, metadata, technical content
|
||||
- **Display:** `"ES Build Neutral"` — wordmarks, headlines
|
||||
- 600: `capture/assets/fonts/14d7ce3e41dcbb66-s.p.woff2`
|
||||
- 700: `capture/assets/fonts/e8b276476c0ac6fa-s.p.woff2`
|
||||
- **Body:** `"Inter"` (variable 100–900, captured ✓) — body, labels, UI
|
||||
- 400: `capture/assets/fonts/9a8d3f06c4e89f2b-s.p.woff2`
|
||||
- 600: `capture/assets/fonts/1b0b3615811be75b-s.p.woff2`
|
||||
- **Mono:** `"JetBrains Mono"` — code, metadata
|
||||
- 400: `capture/assets/fonts/c7d2e9f5a1b3c8d4-s.p.woff2`
|
||||
- **Fallback stack:** `-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`
|
||||
|
||||
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.
|
||||
**`@font-face` block to paste in every composition** (sub-agents copy this verbatim — do not invent file paths):
|
||||
|
||||
```css
|
||||
@font-face {
|
||||
font-family: "ES Build Neutral";
|
||||
src: url("capture/assets/fonts/14d7ce3e41dcbb66-s.p.woff2") format("woff2");
|
||||
font-weight: 600;
|
||||
font-display: block;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
src: url("capture/assets/fonts/9a8d3f06c4e89f2b-s.p.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
}
|
||||
/* + any other family/weight combinations the storyboard's beats need */
|
||||
```
|
||||
````
|
||||
|
||||
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.)
|
||||
|
||||
````
|
||||
|
||||
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."
|
||||
|
||||
That's the whole typography section. If sub-agents need exact line-heights or letter-spacing, they read `design-styles.json` directly.
|
||||
|
||||
@@ -132,7 +169,7 @@ Cover every variant the site uses — typically Primary, Secondary/Ghost, and Ic
|
||||
- **Font:** sohne-var 14px / 400
|
||||
- **Padding:** `12px 0`
|
||||
- **Hover:** background `rgba(83, 58, 253, 0.08)`, optional underline
|
||||
```
|
||||
````
|
||||
|
||||
#### Cards & Containers (always required if the site uses any)
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ Some are style suggestions you can safely ignore:
|
||||
- **Deprecated attributes** (data-layer, data-end) — still work, just not preferred
|
||||
- **Dense tracks** — informational, not a bug
|
||||
|
||||
**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.
|
||||
|
||||
Don't blindly ignore 158 warnings. Don't blindly fix all of them either. Read them.
|
||||
|
||||
## Visual Verification (snapshot)
|
||||
|
||||
Reference in New Issue
Block a user