Summary
The HyperFrames style bridge (lib/hyperframes_style_bridge.py) reads two style tokens from keys that do not exist in the playbook schema, so both silently fall back to the built-in defaults regardless of what the playbook specifies.
1. Heading font read from the wrong key
style_bridge() calls _font(typo, "heading", ...) (singular), but schemas/styles/playbook.schema.json defines the typography property as headings (plural), it is required, and the block is additionalProperties: false — so a singular heading key can never exist. lib/playbook_generator.py also writes typography.headings. Result: every HyperFrames composition ignores the playbook heading font and renders the fallback Inter. (body/code use the correct keys, which isolates this to a key typo.)
2. Motion pace read from the wrong block
_motion_easing() reads motion.get("pace"), but per the schema pace lives under identity (enum: slow|deliberate|moderate|fast|rapid); motion is additionalProperties: false and has no pace. So the fast/slow branches are dead code and every render uses the moderate default. Additionally the mapping only handled fast/slow, so even a correctly-placed deliberate/rapid would collapse to moderate.
Repro
from lib.hyperframes_style_bridge import style_bridge
pb = {"identity": {"pace": "fast"},
"typography": {"headings": {"font": "Montserrat"}, "body": {"font": "Lora"}}}
css, _ = style_bridge(pb)
print(css["--font-heading"]) # -> "Inter" (expected "Montserrat")
print(css["--duration-entrance"]) # -> "0.6s" (expected "0.4s" for fast)
Expected
Playbook-specified heading font and motion pace flow into the emitted CSS custom properties; every schema enum pace maps to a distinct motion profile.
Summary
The HyperFrames style bridge (
lib/hyperframes_style_bridge.py) reads two style tokens from keys that do not exist in the playbook schema, so both silently fall back to the built-in defaults regardless of what the playbook specifies.1. Heading font read from the wrong key
style_bridge()calls_font(typo, "heading", ...)(singular), butschemas/styles/playbook.schema.jsondefines the typography property asheadings(plural), it isrequired, and the block isadditionalProperties: false— so a singularheadingkey can never exist.lib/playbook_generator.pyalso writestypography.headings. Result: every HyperFrames composition ignores the playbook heading font and renders the fallbackInter. (body/codeuse the correct keys, which isolates this to a key typo.)2. Motion pace read from the wrong block
_motion_easing()readsmotion.get("pace"), but per the schemapacelives underidentity(enum:slow|deliberate|moderate|fast|rapid);motionisadditionalProperties: falseand has nopace. So the fast/slow branches are dead code and every render uses the moderate default. Additionally the mapping only handledfast/slow, so even a correctly-placeddeliberate/rapidwould collapse to moderate.Repro
Expected
Playbook-specified heading font and motion pace flow into the emitted CSS custom properties; every schema enum pace maps to a distinct motion profile.