- caption-emoji-pop: shadowForColor now builds its glow via color-mix()
instead of hex-pair slicing, so the strict 6-digit brand-color gate is
gone — any CSS color the sibling templates accept (#fff, rgb(), named)
now renders instead of silently falling back to the default palette
- caption-weight-shift: fitFontSize now sizes against the WIDEST split
line rather than the joined group text (two-line groups no longer shrink
unnecessarily), and avoidSingleWordGroups' merges re-check fitsInTwoLines
like makeGroups' first pass does (merged groups can no longer overflow
the split budget)
- all 5: hfApplyStageConfig clamps resolution to the published validator's
<=8192 bound (validator is optional pre-flight; unbounded stages OOM
render workers), and fit floors carry a comment documenting that the
minimum size is returned unverified by design
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two review findings on the caption-data runtime, applied to all 5 templates:
- hfValidate's version gate used Math.floor(Number(v)) > HF_CONTRACT_VERSION,
and Number("v2") is NaN — NaN comparisons are always false, so malformed
versions slid through with no unsupported-version signal. An explicit
Number.isFinite check closes it.
- hfBoot's sibling-fetch .then called hfAttach unconditionally; a manual
window.__HF_CAPTION_ATTACH__ call landing while the fetch or fonts.ready
was still pending got clobbered by the late boot payload. Boot now yields
if a timeline already exists.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
caption-highlight was already IIFE-wrapped; the other four leaked their
runtime (hfAttach/hfBuild/...) as script-scope globals. Harmless when boot
was synchronous, but the data-driven retrofit defers attach behind
fonts.ready + the sibling fetch — with two caption components pasted into
one composition document, every script finishes before any deferred boot
runs, the last script's definitions win the shared scope, and the first
component never registers its timeline (a renderer waiting on it hangs to
timeout). Wrapping each template's script keeps its internals private so
each boot attaches its own component. window.__HF_CAPTION_ATTACH__ remains
intentionally window-scoped (last-defined-wins).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
hfApplyStageConfig (Block B, verbatim across all 5 retrofitted caption
identities) only ever set --hf-caption-primary/--hf-caption-accent when the
corresponding brand.primaryColor/accentColor key was present, with no else
branch to clear it when absent. Re-attaching a brand-less payload after a
branded one left the custom property (and any JS-cached color derived from
it, e.g. caption-pill-karaoke's hfColorActive and caption-emoji-pop's
hfAccentColors) stuck at the stale value instead of reverting to the CSS
fallback, violating idempotent re-attach.
Also removes caption-editorial-emphasis's dead .word--italic CSS rule and
CLASS_MAP.i entry — hfMakeBlocks only ever emits "n"/"e" tags, "i" was only
reachable via the old hand-authored BLOCKS literal this task replaced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Caption components are overlays — their root element should not
intercept pointer events, allowing clicks to pass through to the
underlying composition content in Studio.
Replace opaque backgrounds (#0a0a0a, #000, #000000) with transparent
on both html/body and the composition root div for all 15 caption
components. Captions are overlays — opaque backgrounds cover the
underlying video when loaded as sub-compositions.
Timeline locking:
- Add data-timeline-locked attribute support — fully disables move,
trim-start, and trim-end in Studio for clips that carry this attr
- Runtime propagates the attribute from inner composition root to host
element so component authors control it from their HTML
- All 15 caption components in the registry now carry the attribute
Font fix:
- Extract <link rel="stylesheet"> and <link rel="preconnect"> from
sub-composition <head> alongside existing <style>/<script> extraction
- Fixes caption components (and any sub-comp using Google Fonts via
<link> tags) losing their font-family when loaded as sub-compositions
- Applied in both runtime (compositionLoader) and compiler
(inlineSubCompositions) paths
The deterministic font system now supplements its embedded font bundle
with Google Fonts fetches for any weights not in the pre-bundled set.
This fixes compositions that request font weights (e.g. Montserrat 300)
not included in the CANONICAL_FONTS faces array — previously those
weights were silently dropped, causing invisible text in renders.
Also replaces caption-glitch-rgb and caption-weight-shift with improved
versions from avatar preview compositions, adapted to 1920x1080 with
standard demo transcript.
- clip-wipe: slower reveal (0.3s), longer hold, smoother exit
- glitch-rgb: 2.5x larger RGB split, stronger scanlines, more dramatic jitter
- gradient-fill: smoother word transitions (0.15s), longer exit
- typewriter: extended group hold times so text lingers on screen
- weight-shift: per-word font-weight animation (200→900), was broken
with only line-level shift that never triggered on single-line groups
- Add caption-highlight: red background sweep behind active word (TikTok-style)
- Re-rendered and uploaded preview videos for all 6 components
- Fix timeline_id_mismatch on all 15 caption components: __timelines key
now matches data-composition-id (e.g. "caption-clip-wipe" not "clip-wipe")
- Regenerate docs/public/catalog-index.json with 15 new caption entries
- Add "Captions" group mapping to generate-catalog-pages.ts (priority 0)
- Regenerate docs.json nav and mdx pages via the catalog script
- Upload docs preview videos to docs/images CDN path
- Add 15 .mdx doc pages under docs/catalog/components/ for all caption styles
- Add "Captions" group as first section in the Catalog tab navigation
- Add canvas-based fitFontSize to 14 caption components to prevent text overflow
- Fix parallax-layers vertical clipping by repositioning the behind safe zone
- Re-render all 15 preview videos at high quality and upload to CDN