From 8bc049e024c44cbe2c8a4440164f5fd1ad7feace Mon Sep 17 00:00:00 2001 From: vanelsas <58037137+avanelsas@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:08:34 +0200 Subject: [PATCH 1/7] Redesign Kinetic Launch template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lean harder into BareDOM's kinetic surface. The template now visits seven kinetic components in one cohesive launch-page narrative, instead of the four it shipped with at v0.1.0. - Background layers: x-metaball-cursor, x-soft-body, plus a toned-down x-gaussian-blur (opacity 0.35 from 0.65) so the three layers share the canvas without fighting. - Hero: x-kinetic-typography preset wave (kept from v0.1.0). - Reveal section: a new large x-kinetic-font header above an x-bento-grid (replaces the old x-grid). The hero's scroll- driven preset text and the reveal's cursor-driven physics text put both kinetic-text flavours on the same page. - Bento grid: featured 2x2 cell wraps x-liquid-glass; two 1x1 side cells; one wide 3-col closing strip for visual rhythm. - Mid-page x-ripple-effect accent. - Voices section: x-scroll-stack with three rotating cards. - Same closing organic-divider + x-particle-button CTA as before. x-morph-stack deliberately omitted — its active-state contract makes it a live-data component and a starter template should demonstrate the visual surface before pulling the user into state plumbing. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/bareforge/ui/templates.cljs | 207 +++++++++++++++++++++++++------- 1 file changed, 162 insertions(+), 45 deletions(-) diff --git a/src/bareforge/ui/templates.cljs b/src/bareforge/ui/templates.cljs index c35ffc8..bcb4259 100644 --- a/src/bareforge/ui/templates.cljs +++ b/src/bareforge/ui/templates.cljs @@ -478,18 +478,37 @@ (defn- kinetic-showcase [] (let [d (m/empty-document) - ;; animated background blob — sets the kinetic tone - {d :doc} (ops/insert-new d "root" "default" 0 "x-gaussian-blur" + ;; --- background layers (placement :background) --- + ;; metaball cursor — fluid blobs follow the pointer + {d :doc} (ops/insert-new d "root" "default" 0 "x-metaball-cursor" + {:attrs {"blob-count" "5" + "blob-size" "60" + "blur" "20" + "noise" "" + "noise-scale" "0.8" + "noise-speed" "0.4" + "palette" "#f43f5e,#a855f7,#06b6d4"} + :layout {:placement :background}}) + ;; soft-body — squishy physics blobs in the backdrop + {d :doc} (ops/insert-new d "root" "default" 1 "x-soft-body" + {:attrs {"stiffness" "0.4" + "damping" "0.6" + "intensity" "0.5" + "radius" "120" + "grab-radius" "180"} + :layout {:placement :background}}) + ;; gaussian blur — toned down so the metaball + soft-body get room + {d :doc} (ops/insert-new d "root" "default" 2 "x-gaussian-blur" {:attrs {"colors" "#f43f5e,#a855f7,#06b6d4" "blur" "100" - "speed" "5" - "count" "4" + "speed" "3" + "count" "3" "size" "45" - "opacity" "0.65" + "opacity" "0.35" "animation" "float"} :layout {:placement :background}}) - ;; navbar - {d :doc nav-id :id} (ops/insert-new d "root" "default" 1 "x-navbar") + ;; --- navbar --- + {d :doc nav-id :id} (ops/insert-new d "root" "default" 3 "x-navbar") {d :doc} (add-text d nav-id "brand" 0 "h5" "Pulse") {d :doc} (ops/insert-new d nav-id "end" 0 "x-button" {:text "Story" :attrs {"variant" "ghost"}}) @@ -499,23 +518,23 @@ {:text "Reserve" :attrs {"variant" "primary" "size" "sm" "mode" "dust"}}) - ;; hero — kinetic headline - {d :doc} (ops/insert-new d "root" "default" 2 "x-spacer" + ;; --- hero — kinetic-typography headline (kept) --- + {d :doc} (ops/insert-new d "root" "default" 4 "x-spacer" {:attrs {"size" "3rem" "axis" "vertical"}}) - {d :doc} (ops/insert-new d "root" "default" 3 "x-badge" - {:text "Launching October 12" + {d :doc} (ops/insert-new d "root" "default" 5 "x-badge" + {:text "Launching January 15, 2027" :attrs {"variant" "info" "pill" ""}}) - {d :doc} (ops/insert-new d "root" "default" 4 "x-kinetic-typography" + {d :doc} (ops/insert-new d "root" "default" 6 "x-kinetic-typography" {:attrs {"text" "Something extraordinary is coming" "preset" "wave" "animation" "scroll"}}) - {d :doc} (add-text+align d "root" "default" 5 "body1" + {d :doc} (add-text+align d "root" "default" 7 "body1" "Six years of work, one launch event. Reserve your seat or watch the teaser to see what we've been building." "center") - {d :doc} (ops/insert-new d "root" "default" 6 "x-spacer" + {d :doc} (ops/insert-new d "root" "default" 8 "x-spacer" {:attrs {"size" "1rem" "axis" "vertical"}}) ;; CTA pair — burst + dust particle buttons - {d :doc cta-id :id} (ops/insert-new d "root" "default" 7 "x-grid" + {d :doc cta-id :id} (ops/insert-new d "root" "default" 9 "x-grid" {:attrs {"columns" "repeat(2, 1fr)" "gap" "md" "row-gap" "md"}}) @@ -527,55 +546,153 @@ {:text "Watch the teaser" :attrs {"variant" "secondary" "size" "lg" "mode" "dust"}}) - ;; animated divider into the "what's launching" section - {d :doc} (ops/insert-new d "root" "default" 8 "x-spacer" + ;; --- divider + kinetic-font reveal-section header --- + {d :doc} (ops/insert-new d "root" "default" 10 "x-spacer" {:attrs {"size" "3rem" "axis" "vertical"}}) - {d :doc} (ops/insert-new d "root" "default" 9 "x-organic-divider" + {d :doc} (ops/insert-new d "root" "default" 11 "x-organic-divider" {:attrs {"shape" "wave" "animation" "drift" "height" "3rem"}}) - {d :doc} (add-text+align d "root" "default" 10 "overline" + {d :doc} (add-text+align d "root" "default" 12 "overline" "WHAT'S LAUNCHING" "center") - {d :doc} (add-text+align d "root" "default" 11 "h2" - "Three things we couldn't wait to share" "center") - {d :doc} (ops/insert-new d "root" "default" 12 "x-spacer" + ;; physics-driven, per-character header. Pairs with the + ;; scroll-driven kinetic-typography hero so designers see + ;; both flavours of kinetic text on the same page. + {d :doc} (ops/insert-new d "root" "default" 13 "x-kinetic-font" + {:attrs {"text" "Three things we couldn't wait to share" + "trigger" "both" + "mode" "wave" + "per-char" "" + "mass" "1" + "tension" "180" + "friction" "12" + "intensity" "0.7"} + :layout {:extra-style "font-size: 3rem; text-align: center;"}}) + {d :doc} (ops/insert-new d "root" "default" 14 "x-spacer" {:attrs {"size" "1.5rem" "axis" "vertical"}}) - ;; three teaser cards — structural contrast against the kinetic chaos - {d :doc reveal-id :id} (ops/insert-new d "root" "default" 13 "x-grid" - {:attrs {"columns" "repeat(3, 1fr)" - "gap" "lg" - "row-gap" "lg"}}) - {d :doc rc1 :id} (ops/insert-new d reveal-id "default" 0 "x-card" + ;; --- featured reveal — bento-grid with liquid-glass hero cell --- + {d :doc bento-id :id} + (ops/insert-new d "root" "default" 15 "x-bento-grid" + {:attrs {"columns" "repeat(3, 1fr)" + "gap" "lg" + "row-gap" "lg" + "row-height" "minmax(180px, auto)"}}) + ;; cell 1 — featured (col-span 2, row-span 2) wrapping + ;; an x-liquid-glass backdrop around the headline card + {d :doc feat-item :id} + (ops/insert-new d bento-id "default" 0 "x-bento-item" + {:attrs {"col-span" "2" "row-span" "2"}}) + {d :doc glass-id :id} + (ops/insert-new d feat-item "default" 0 "x-liquid-glass" + {:attrs {"blobs" "3" + "speed" "0.6" + "amplitude" "20" + "goo" "0.7" + "specular" "" + "specular-size" "0.5" + "specular-intensity" "0.6" + "frost" "0.3" + "tint" "#a855f7" + "color-1" "#f43f5e" + "color-2" "#06b6d4"}}) + {d :doc fc1 :id} (ops/insert-new d glass-id "default" 0 "x-card" {:attrs {"variant" "elevated" "padding" "lg"}}) - {d :doc} (add-text d rc1 "default" 0 "h4" "Reimagined editor") - {d :doc} (add-text d rc1 "default" 1 "body2" - "Six years of feedback distilled into a tool that actually feels good to use.") - {d :doc rc2 :id} (ops/insert-new d reveal-id "default" 1 "x-card" + {d :doc} (add-text d fc1 "default" 0 "h3" "Reimagined editor") + {d :doc} (add-text d fc1 "default" 1 "body1" + "Six years of feedback distilled into a tool that actually feels good to use. Multi-cursor, conflict-free, and faster than your last keyboard shortcut.") + ;; cell 2 — Live collaboration (1×1) + {d :doc bi2 :id} + (ops/insert-new d bento-id "default" 1 "x-bento-item" + {:attrs {"col-span" "1" "row-span" "1"}}) + {d :doc fc2 :id} (ops/insert-new d bi2 "default" 0 "x-card" {:attrs {"variant" "elevated" "padding" "lg"}}) - {d :doc} (add-text d rc2 "default" 0 "h4" "Live collaboration") - {d :doc} (add-text d rc2 "default" 1 "body2" + {d :doc} (add-text d fc2 "default" 0 "h4" "Live collaboration") + {d :doc} (add-text d fc2 "default" 1 "body2" "Multiple cursors, sub-second sync, and conflict-free history out of the box.") - {d :doc rc3 :id} (ops/insert-new d reveal-id "default" 2 "x-card" + ;; cell 3 — Open API (1×1) + {d :doc bi3 :id} + (ops/insert-new d bento-id "default" 2 "x-bento-item" + {:attrs {"col-span" "1" "row-span" "1"}}) + {d :doc fc3 :id} (ops/insert-new d bi3 "default" 0 "x-card" {:attrs {"variant" "elevated" "padding" "lg"}}) - {d :doc} (add-text d rc3 "default" 0 "h4" "Open API") - {d :doc} (add-text d rc3 "default" 1 "body2" + {d :doc} (add-text d fc3 "default" 0 "h4" "Open API") + {d :doc} (add-text d fc3 "default" 1 "body2" "Every action exposed as a typed endpoint. Build on top from day one.") - ;; another animated divider into the closing CTA - {d :doc} (ops/insert-new d "root" "default" 14 "x-spacer" + ;; cell 4 — full-width closing strip (col-span 3, row-span 1) + {d :doc bi4 :id} + (ops/insert-new d bento-id "default" 3 "x-bento-item" + {:attrs {"col-span" "3" "row-span" "1"}}) + {d :doc fc4 :id} (ops/insert-new d bi4 "default" 0 "x-card" + {:attrs {"variant" "outlined" "padding" "lg"}}) + {d :doc} (add-text d fc4 "default" 0 "h4" "Roadmap from day one") + {d :doc} (add-text d fc4 "default" 1 "body2" + "Public roadmap, open RFCs, and a Discord where the team ships in real time.") + ;; --- mid-page ripple accent --- + {d :doc} (ops/insert-new d "root" "default" 16 "x-spacer" + {:attrs {"size" "2rem" "axis" "vertical"}}) + {d :doc} (ops/insert-new d "root" "default" 17 "x-ripple-effect" + {:attrs {"intensity" "0.4" + "duration" "1500" + "frequency" "3"} + :layout {:extra-style "height: 4rem;"}}) + {d :doc} (ops/insert-new d "root" "default" 18 "x-spacer" + {:attrs {"size" "2rem" "axis" "vertical"}}) + ;; --- voices — scroll-stack testimonials --- + {d :doc} (add-text+align d "root" "default" 19 "overline" + "VOICES" "center") + {d :doc} (add-text+align d "root" "default" 20 "h2" + "Early users on what's coming" "center") + {d :doc} (ops/insert-new d "root" "default" 21 "x-spacer" + {:attrs {"size" "1rem" "axis" "vertical"}}) + {d :doc stack-id :id} + (ops/insert-new d "root" "default" 22 "x-scroll-stack" + {:attrs {"peek" "0.12" + "rotation" "3" + "scroll-distance" "100" + "align" "center"}}) + ;; testimonial 1 + {d :doc t1 :id} (ops/insert-new d stack-id "default" 0 "x-card" + {:attrs {"variant" "elevated" "padding" "lg"}}) + {d :doc} (add-text d t1 "default" 0 "blockquote" + "I haven't been this excited about a tool launch in years. The editor genuinely feels like it was made by someone who ships every day.") + {d :doc} (ops/insert-new d t1 "default" 1 "x-avatar" + {:attrs {"initials" "MA" "size" "lg"}}) + {d :doc} (add-text d t1 "default" 2 "caption" + "Mira A., Staff engineer at Lattice") + ;; testimonial 2 + {d :doc t2 :id} (ops/insert-new d stack-id "default" 1 "x-card" + {:attrs {"variant" "elevated" "padding" "lg"}}) + {d :doc} (add-text d t2 "default" 0 "blockquote" + "Live collab that actually works on a slow connection. Our remote team got back two hours of merge-conflict pain a week.") + {d :doc} (ops/insert-new d t2 "default" 1 "x-avatar" + {:attrs {"initials" "RD" "size" "lg"}}) + {d :doc} (add-text d t2 "default" 2 "caption" + "Rohan D., Tech lead at Nimbus") + ;; testimonial 3 + {d :doc t3 :id} (ops/insert-new d stack-id "default" 2 "x-card" + {:attrs {"variant" "elevated" "padding" "lg"}}) + {d :doc} (add-text d t3 "default" 0 "blockquote" + "The open API meant I had a Slack integration running on day two. No SDK, no boilerplate — just a typed endpoint and I was off.") + {d :doc} (ops/insert-new d t3 "default" 1 "x-avatar" + {:attrs {"initials" "SK" "size" "lg"}}) + {d :doc} (add-text d t3 "default" 2 "caption" + "Sara K., Indie dev") + ;; --- divider into the closing CTA --- + {d :doc} (ops/insert-new d "root" "default" 23 "x-spacer" {:attrs {"size" "3rem" "axis" "vertical"}}) - {d :doc} (ops/insert-new d "root" "default" 15 "x-organic-divider" + {d :doc} (ops/insert-new d "root" "default" 24 "x-organic-divider" {:attrs {"shape" "blob-edge" "animation" "drift" "height" "3rem"}}) - ;; closing CTA - {d :doc} (add-text+align d "root" "default" 16 "h2" + ;; --- closing CTA --- + {d :doc} (add-text+align d "root" "default" 25 "h2" "Be there from day one" "center") - {d :doc} (add-text+align d "root" "default" 17 "body1" + {d :doc} (add-text+align d "root" "default" 26 "body1" "Drop your email and we'll send you the launch link the moment doors open." "center") - {d :doc} (ops/insert-new d "root" "default" 18 "x-spacer" + {d :doc} (ops/insert-new d "root" "default" 27 "x-spacer" {:attrs {"size" "1rem" "axis" "vertical"}}) - {d :doc cta2-id :id} (ops/insert-new d "root" "default" 19 "x-grid" + {d :doc cta2-id :id} (ops/insert-new d "root" "default" 28 "x-grid" {:attrs {"columns" "repeat(1, 1fr)" "justify-items" "center"}}) {d :doc} (ops/insert-new d cta2-id "default" 0 "x-particle-button" From 0f5a820feb39b806ed5343e5048de8a1194952bf Mon Sep 17 00:00:00 2001 From: vanelsas <58037137+avanelsas@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:21:19 +0200 Subject: [PATCH 2/7] Fix Kinetic Launch render bugs + ask-before-PR rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four rendering issues fixed in the Kinetic Launch template: - **Liquid-glass hidden by elevated x-card.** The featured bento cell wrapped its headline in `x-card variant "elevated"`, whose solid background painted over the glass effect. The card is dropped — `x-liquid-glass` already pads its slotted content via `[part=content]`. The h3 + body now sit directly inside the glass with extra body2 copy so the cell fills its 2x2 area without dead space. - **Bento grid laid out as 4 columns instead of 3.** `x-bento-grid` parses `columns` as a single integer (1–12) and composes `repeat(N,minmax(0,1fr))` itself; passing `"repeat(3, 1fr)"` failed `parseInt` and silently fell back to the 4-column default. Also dropped the `row-height "minmax(180px, auto)"` override, which forced row-span 2 cells to a 360px minimum and produced "a lot of empty height" behind the featured cell. Falls back to the component's `row-height "auto"` default — rows size to content. - **Standalone `x-ripple-effect` was invisible.** The component is a wrapper around clickable content (clicks on slotted children produce ripples) — not a standalone "ambient heartbeat" surface. Removed from the template entirely; the page already showcases six kinetic components without it. Worth revisiting later as a wrapper around an actual CTA or card. - **`x-scroll-stack` rendered statically.** Stacking is driven by a `position:sticky;height:100dvh` inner container, so the host needs height greater than the viewport to give scroll-distance for the stacking animation. Added `extra-style "height: 250vh;"` — one and a half viewports of scroll room for three cards. Also: codify in CLAUDE.md that AI assistants ALWAYS ask for explicit permission before opening a pull request, even when the four PR-readiness gates are green. Pushing the feature branch and reporting gate results is fine; running `gh pr create` without the maintainer's go-ahead is not. Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 9 ++++ src/bareforge/ui/templates.cljs | 95 ++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 44 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 82da08a..47db1fe 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -45,6 +45,15 @@ maintainer's review time. The CI workflow at `.github/workflows/ci.yml` enforces the same four gates; matching them locally first is the contract. +**AI assistants: ALWAYS ask for explicit permission before +opening a pull request.** Even when the four gates above are +green and the work looks ready, do not run `gh pr create` +without the maintainer's go-ahead. PR creation is a public, +shared-state action (notifies reviewers, kicks CI, lands in the +PR list); the maintainer wants the final call on timing, title, +and body. Push the feature branch if needed, summarise the +gate results, and wait for a "yes" before opening the PR. + ## Onboarding a new BareDOM component Two-step recipe: diff --git a/src/bareforge/ui/templates.cljs b/src/bareforge/ui/templates.cljs index bcb4259..c61c8e0 100644 --- a/src/bareforge/ui/templates.cljs +++ b/src/bareforge/ui/templates.cljs @@ -571,35 +571,42 @@ {d :doc} (ops/insert-new d "root" "default" 14 "x-spacer" {:attrs {"size" "1.5rem" "axis" "vertical"}}) ;; --- featured reveal — bento-grid with liquid-glass hero cell --- + ;; columns is a single integer (1–12); the grid composes its + ;; own track-list internally. row-height left at the "auto" + ;; default so cells size to content rather than padding into + ;; empty space behind a row-span 2 hero cell. {d :doc bento-id :id} (ops/insert-new d "root" "default" 15 "x-bento-grid" - {:attrs {"columns" "repeat(3, 1fr)" - "gap" "lg" - "row-gap" "lg" - "row-height" "minmax(180px, auto)"}}) - ;; cell 1 — featured (col-span 2, row-span 2) wrapping - ;; an x-liquid-glass backdrop around the headline card + {:attrs {"columns" "3" + "gap" "lg" + "row-gap" "lg"}}) + ;; cell 1 — featured (col-span 2, row-span 2) with an + ;; x-liquid-glass directly hosting the headline. No + ;; intermediate x-card: an elevated card paints a solid + ;; background that hides the glass effect. liquid-glass + ;; already pads its slotted content via [part=content]. {d :doc feat-item :id} (ops/insert-new d bento-id "default" 0 "x-bento-item" {:attrs {"col-span" "2" "row-span" "2"}}) {d :doc glass-id :id} (ops/insert-new d feat-item "default" 0 "x-liquid-glass" - {:attrs {"blobs" "3" - "speed" "0.6" - "amplitude" "20" - "goo" "0.7" - "specular" "" - "specular-size" "0.5" - "specular-intensity" "0.6" - "frost" "0.3" - "tint" "#a855f7" - "color-1" "#f43f5e" - "color-2" "#06b6d4"}}) - {d :doc fc1 :id} (ops/insert-new d glass-id "default" 0 "x-card" - {:attrs {"variant" "elevated" "padding" "lg"}}) - {d :doc} (add-text d fc1 "default" 0 "h3" "Reimagined editor") - {d :doc} (add-text d fc1 "default" 1 "body1" + {:attrs {"blobs" "3" + "speed" "0.6" + "amplitude" "20" + "goo" "0.7" + "specular" "" + "specular-size" "0.5" + "specular-intensity" "0.6" + "frost" "0.3" + "tint" "#a855f7" + "color-1" "#f43f5e" + "color-2" "#06b6d4"} + :layout {:extra-style "min-height: 320px;"}}) + {d :doc} (add-text d glass-id "default" 0 "h3" "Reimagined editor") + {d :doc} (add-text d glass-id "default" 1 "body1" "Six years of feedback distilled into a tool that actually feels good to use. Multi-cursor, conflict-free, and faster than your last keyboard shortcut.") + {d :doc} (add-text d glass-id "default" 2 "body2" + "Sub-second sync across machines. Typed open API. Public roadmap from day one.") ;; cell 2 — Live collaboration (1×1) {d :doc bi2 :id} (ops/insert-new d bento-id "default" 1 "x-bento-item" @@ -627,29 +634,29 @@ {d :doc} (add-text d fc4 "default" 0 "h4" "Roadmap from day one") {d :doc} (add-text d fc4 "default" 1 "body2" "Public roadmap, open RFCs, and a Discord where the team ships in real time.") - ;; --- mid-page ripple accent --- + ;; --- voices — scroll-stack testimonials --- {d :doc} (ops/insert-new d "root" "default" 16 "x-spacer" {:attrs {"size" "2rem" "axis" "vertical"}}) - {d :doc} (ops/insert-new d "root" "default" 17 "x-ripple-effect" - {:attrs {"intensity" "0.4" - "duration" "1500" - "frequency" "3"} - :layout {:extra-style "height: 4rem;"}}) - {d :doc} (ops/insert-new d "root" "default" 18 "x-spacer" - {:attrs {"size" "2rem" "axis" "vertical"}}) - ;; --- voices — scroll-stack testimonials --- - {d :doc} (add-text+align d "root" "default" 19 "overline" + {d :doc} (add-text+align d "root" "default" 17 "overline" "VOICES" "center") - {d :doc} (add-text+align d "root" "default" 20 "h2" + {d :doc} (add-text+align d "root" "default" 18 "h2" "Early users on what's coming" "center") - {d :doc} (ops/insert-new d "root" "default" 21 "x-spacer" + {d :doc} (ops/insert-new d "root" "default" 19 "x-spacer" {:attrs {"size" "1rem" "axis" "vertical"}}) + ;; x-scroll-stack uses a sticky-positioned inner container at + ;; height:100dvh and stacks its slotted children as the host + ;; scrolls past. The host needs height greater than the + ;; viewport for the sticky-stack effect to play out — without + ;; a height the cards just render statically. 250vh gives one + ;; and a half viewports of scroll-stacking room for three + ;; cards. {d :doc stack-id :id} - (ops/insert-new d "root" "default" 22 "x-scroll-stack" - {:attrs {"peek" "0.12" - "rotation" "3" - "scroll-distance" "100" - "align" "center"}}) + (ops/insert-new d "root" "default" 20 "x-scroll-stack" + {:attrs {"peek" "0.12" + "rotation" "3" + "scroll-distance" "100" + "align" "center"} + :layout {:extra-style "height: 250vh;"}}) ;; testimonial 1 {d :doc t1 :id} (ops/insert-new d stack-id "default" 0 "x-card" {:attrs {"variant" "elevated" "padding" "lg"}}) @@ -678,21 +685,21 @@ {d :doc} (add-text d t3 "default" 2 "caption" "Sara K., Indie dev") ;; --- divider into the closing CTA --- - {d :doc} (ops/insert-new d "root" "default" 23 "x-spacer" + {d :doc} (ops/insert-new d "root" "default" 21 "x-spacer" {:attrs {"size" "3rem" "axis" "vertical"}}) - {d :doc} (ops/insert-new d "root" "default" 24 "x-organic-divider" + {d :doc} (ops/insert-new d "root" "default" 22 "x-organic-divider" {:attrs {"shape" "blob-edge" "animation" "drift" "height" "3rem"}}) ;; --- closing CTA --- - {d :doc} (add-text+align d "root" "default" 25 "h2" + {d :doc} (add-text+align d "root" "default" 23 "h2" "Be there from day one" "center") - {d :doc} (add-text+align d "root" "default" 26 "body1" + {d :doc} (add-text+align d "root" "default" 24 "body1" "Drop your email and we'll send you the launch link the moment doors open." "center") - {d :doc} (ops/insert-new d "root" "default" 27 "x-spacer" + {d :doc} (ops/insert-new d "root" "default" 25 "x-spacer" {:attrs {"size" "1rem" "axis" "vertical"}}) - {d :doc cta2-id :id} (ops/insert-new d "root" "default" 28 "x-grid" + {d :doc cta2-id :id} (ops/insert-new d "root" "default" 26 "x-grid" {:attrs {"columns" "repeat(1, 1fr)" "justify-items" "center"}}) {d :doc} (ops/insert-new d cta2-id "default" 0 "x-particle-button" From 19df5dd2a7dd8db2f6ed66c9bd9b22a9b37463f6 Mon Sep 17 00:00:00 2001 From: vanelsas <58037137+avanelsas@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:27:22 +0200 Subject: [PATCH 3/7] Kinetic Launch: x-soft-body cards, x-ripple wrap, scroll-stack attrs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - **x-card → x-soft-body** across the bento cells (Live collaboration, Open API, Roadmap) and the three voices testimonials. x-soft-body fills the same surface role as x-card (filled background, border, shadow, dark-mode aware, padded slot via [part=content]) but morphs its outline on hover/touch via SVG path deformation. Same mid-range stiffness/damping/intensity across all six instances so the reveal section reads as physically deformable end-to-end. - **x-ripple-effect re-added** as a wrapper around the closing "Notify me on launch" CTA. It's a click-handler component: clicks on slotted children kick off a goo-style ripple through the shadow DOM. Stacks naturally with the particle-button's own burst — two complementary effects on the same click. - **x-scroll-stack attribute corrections.** The earlier draft had `peek "0.12"` (peek is in PIXELS, default 6 — 0.12 is effectively zero) and `scroll-distance "100"` (small for the default 150). Bumped to `peek "20"` and `scroll-distance "300"` so each card has visible peek and meaningful per-card scroll-room. Dropped the host's manual height override — the component sets its own height in connectedCallback (vh + n*scroll-distance). Added an inline comment about the editor-canvas vs. window scrollport caveat: x-scroll-stack listens to window.scroll, so its animation only plays where the page itself is the scrollport — i.e. every exported artefact, but not necessarily the in-editor preview when the canvas-host has overflow:auto. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/bareforge/ui/templates.cljs | 87 +++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/src/bareforge/ui/templates.cljs b/src/bareforge/ui/templates.cljs index c61c8e0..9a5af19 100644 --- a/src/bareforge/ui/templates.cljs +++ b/src/bareforge/ui/templates.cljs @@ -611,8 +611,17 @@ {d :doc bi2 :id} (ops/insert-new d bento-id "default" 1 "x-bento-item" {:attrs {"col-span" "1" "row-span" "1"}}) - {d :doc fc2 :id} (ops/insert-new d bi2 "default" 0 "x-card" - {:attrs {"variant" "elevated" "padding" "lg"}}) + ;; bento + testimonial cells use x-soft-body in place of + ;; x-card so the entire reveal section reads as physically + ;; deformable. x-soft-body provides the same surface + + ;; padding role as x-card (filled background, border, shadow) + ;; while morphing its outline on hover/touch via SVG path + ;; deformation. Tuned with mid-range stiffness/damping so the + ;; effect is felt without being distracting at rest. + {d :doc fc2 :id} (ops/insert-new d bi2 "default" 0 "x-soft-body" + {:attrs {"stiffness" "0.5" + "damping" "0.7" + "intensity" "0.5"}}) {d :doc} (add-text d fc2 "default" 0 "h4" "Live collaboration") {d :doc} (add-text d fc2 "default" 1 "body2" "Multiple cursors, sub-second sync, and conflict-free history out of the box.") @@ -620,8 +629,10 @@ {d :doc bi3 :id} (ops/insert-new d bento-id "default" 2 "x-bento-item" {:attrs {"col-span" "1" "row-span" "1"}}) - {d :doc fc3 :id} (ops/insert-new d bi3 "default" 0 "x-card" - {:attrs {"variant" "elevated" "padding" "lg"}}) + {d :doc fc3 :id} (ops/insert-new d bi3 "default" 0 "x-soft-body" + {:attrs {"stiffness" "0.5" + "damping" "0.7" + "intensity" "0.5"}}) {d :doc} (add-text d fc3 "default" 0 "h4" "Open API") {d :doc} (add-text d fc3 "default" 1 "body2" "Every action exposed as a typed endpoint. Build on top from day one.") @@ -629,8 +640,10 @@ {d :doc bi4 :id} (ops/insert-new d bento-id "default" 3 "x-bento-item" {:attrs {"col-span" "3" "row-span" "1"}}) - {d :doc fc4 :id} (ops/insert-new d bi4 "default" 0 "x-card" - {:attrs {"variant" "outlined" "padding" "lg"}}) + {d :doc fc4 :id} (ops/insert-new d bi4 "default" 0 "x-soft-body" + {:attrs {"stiffness" "0.5" + "damping" "0.7" + "intensity" "0.5"}}) {d :doc} (add-text d fc4 "default" 0 "h4" "Roadmap from day one") {d :doc} (add-text d fc4 "default" 1 "body2" "Public roadmap, open RFCs, and a Discord where the team ships in real time.") @@ -643,23 +656,33 @@ "Early users on what's coming" "center") {d :doc} (ops/insert-new d "root" "default" 19 "x-spacer" {:attrs {"size" "1rem" "axis" "vertical"}}) - ;; x-scroll-stack uses a sticky-positioned inner container at - ;; height:100dvh and stacks its slotted children as the host - ;; scrolls past. The host needs height greater than the - ;; viewport for the sticky-stack effect to play out — without - ;; a height the cards just render statically. 250vh gives one - ;; and a half viewports of scroll-stacking room for three - ;; cards. + ;; x-scroll-stack stacks its slotted children as the host + ;; element scrolls past the viewport. The component sets its + ;; OWN host height in connectedCallback (vh + n*scroll- + ;; distance) so we don't need to. Two attribute corrections + ;; vs. an earlier draft: peek is in PIXELS (default 6, not a + ;; fraction) and scroll-distance is the per-card scroll-room + ;; in pixels (default 150). The earlier "0.12" / "100" values + ;; produced an effectively static stack. + ;; + ;; Note: x-scroll-stack listens to window scroll events. + ;; Inside Bareforge's editor canvas-host (which has its own + ;; overflow:auto scrollport), the stacking animation will + ;; only animate when the page itself scrolls — which is the + ;; case in every exported artefact (HTML / bundle / CLJS / + ;; vanilla-JS) but not necessarily in the in-editor preview + ;; if the canvas-host is the scrollport. {d :doc stack-id :id} (ops/insert-new d "root" "default" 20 "x-scroll-stack" - {:attrs {"peek" "0.12" - "rotation" "3" - "scroll-distance" "100" - "align" "center"} - :layout {:extra-style "height: 250vh;"}}) + {:attrs {"peek" "20" + "rotation" "3" + "scroll-distance" "300" + "align" "center"}}) ;; testimonial 1 - {d :doc t1 :id} (ops/insert-new d stack-id "default" 0 "x-card" - {:attrs {"variant" "elevated" "padding" "lg"}}) + {d :doc t1 :id} (ops/insert-new d stack-id "default" 0 "x-soft-body" + {:attrs {"stiffness" "0.5" + "damping" "0.7" + "intensity" "0.5"}}) {d :doc} (add-text d t1 "default" 0 "blockquote" "I haven't been this excited about a tool launch in years. The editor genuinely feels like it was made by someone who ships every day.") {d :doc} (ops/insert-new d t1 "default" 1 "x-avatar" @@ -667,8 +690,10 @@ {d :doc} (add-text d t1 "default" 2 "caption" "Mira A., Staff engineer at Lattice") ;; testimonial 2 - {d :doc t2 :id} (ops/insert-new d stack-id "default" 1 "x-card" - {:attrs {"variant" "elevated" "padding" "lg"}}) + {d :doc t2 :id} (ops/insert-new d stack-id "default" 1 "x-soft-body" + {:attrs {"stiffness" "0.5" + "damping" "0.7" + "intensity" "0.5"}}) {d :doc} (add-text d t2 "default" 0 "blockquote" "Live collab that actually works on a slow connection. Our remote team got back two hours of merge-conflict pain a week.") {d :doc} (ops/insert-new d t2 "default" 1 "x-avatar" @@ -676,8 +701,10 @@ {d :doc} (add-text d t2 "default" 2 "caption" "Rohan D., Tech lead at Nimbus") ;; testimonial 3 - {d :doc t3 :id} (ops/insert-new d stack-id "default" 2 "x-card" - {:attrs {"variant" "elevated" "padding" "lg"}}) + {d :doc t3 :id} (ops/insert-new d stack-id "default" 2 "x-soft-body" + {:attrs {"stiffness" "0.5" + "damping" "0.7" + "intensity" "0.5"}}) {d :doc} (add-text d t3 "default" 0 "blockquote" "The open API meant I had a Slack integration running on day two. No SDK, no boilerplate — just a typed endpoint and I was off.") {d :doc} (ops/insert-new d t3 "default" 1 "x-avatar" @@ -702,7 +729,17 @@ {d :doc cta2-id :id} (ops/insert-new d "root" "default" 26 "x-grid" {:attrs {"columns" "repeat(1, 1fr)" "justify-items" "center"}}) - {d :doc} (ops/insert-new d cta2-id "default" 0 "x-particle-button" + ;; Wrap the closing CTA in x-ripple-effect so clicks on the + ;; button kick off a goo-style ripple that distorts the + ;; surrounding shadow DOM. Stacks naturally with the + ;; particle-button's own burst — particles fly outward while + ;; the ripple radiates from the click point. + {d :doc ripple-id :id} + (ops/insert-new d cta2-id "default" 0 "x-ripple-effect" + {:attrs {"intensity" "0.5" + "duration" "1500" + "frequency" "3"}}) + {d :doc} (ops/insert-new d ripple-id "default" 0 "x-particle-button" {:text "Notify me on launch" :attrs {"variant" "primary" "size" "lg" "mode" "burst"}})] From decc9bbf7b0022370110dc7a832ee23f7618f253 Mon Sep 17 00:00:00 2001 From: vanelsas <58037137+avanelsas@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:32:35 +0200 Subject: [PATCH 4/7] Drop x-scroll-stack for x-grid; turn up x-soft-body intensity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - **x-scroll-stack → x-grid for testimonials.** Every scroll-driven BareDOM component (x-scroll-stack / -parallax / -story / -timeline) listens to window scroll events. In Bareforge's editor canvas-host (which has its own overflow:auto scrollport) those events never fire, so the scroll-driven section read as static while editing. A plain three-column grid keeps the testimonials kinetic via the soft-body cards' own pointer-driven physics, without depending on a scroll source the editor doesn't expose. - **x-soft-body parameters tuned for a visible effect.** The earlier `stiffness "0.5" damping "0.7" intensity "0.5"` were below or at the lower clamps of x-soft-body's parse ranges (stiffness 10–1000, damping 1–100, intensity 0–5) — the effect rendered but with such mild deformation it was easy to miss. Now: `stiffness "60" damping "5" intensity "4" grab-radius "250" radius "40"`. Lower stiffness + lower damping = more squish and visible bounce; higher intensity + wider grab-radius = a much larger pointer-driven distortion; larger corner radius reads as more "blob" than "card". Same values across all six instances (3 bento cells + 3 testimonials) so the reveal section feels physically cohesive. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/bareforge/ui/templates.cljs | 81 +++++++++++++++++---------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/src/bareforge/ui/templates.cljs b/src/bareforge/ui/templates.cljs index 9a5af19..0b6c114 100644 --- a/src/bareforge/ui/templates.cljs +++ b/src/bareforge/ui/templates.cljs @@ -619,9 +619,11 @@ ;; deformation. Tuned with mid-range stiffness/damping so the ;; effect is felt without being distracting at rest. {d :doc fc2 :id} (ops/insert-new d bi2 "default" 0 "x-soft-body" - {:attrs {"stiffness" "0.5" - "damping" "0.7" - "intensity" "0.5"}}) + {:attrs {"stiffness" "60" + "damping" "5" + "intensity" "4" + "grab-radius" "250" + "radius" "40"}}) {d :doc} (add-text d fc2 "default" 0 "h4" "Live collaboration") {d :doc} (add-text d fc2 "default" 1 "body2" "Multiple cursors, sub-second sync, and conflict-free history out of the box.") @@ -630,9 +632,11 @@ (ops/insert-new d bento-id "default" 2 "x-bento-item" {:attrs {"col-span" "1" "row-span" "1"}}) {d :doc fc3 :id} (ops/insert-new d bi3 "default" 0 "x-soft-body" - {:attrs {"stiffness" "0.5" - "damping" "0.7" - "intensity" "0.5"}}) + {:attrs {"stiffness" "60" + "damping" "5" + "intensity" "4" + "grab-radius" "250" + "radius" "40"}}) {d :doc} (add-text d fc3 "default" 0 "h4" "Open API") {d :doc} (add-text d fc3 "default" 1 "body2" "Every action exposed as a typed endpoint. Build on top from day one.") @@ -641,9 +645,11 @@ (ops/insert-new d bento-id "default" 3 "x-bento-item" {:attrs {"col-span" "3" "row-span" "1"}}) {d :doc fc4 :id} (ops/insert-new d bi4 "default" 0 "x-soft-body" - {:attrs {"stiffness" "0.5" - "damping" "0.7" - "intensity" "0.5"}}) + {:attrs {"stiffness" "60" + "damping" "5" + "intensity" "4" + "grab-radius" "250" + "radius" "40"}}) {d :doc} (add-text d fc4 "default" 0 "h4" "Roadmap from day one") {d :doc} (add-text d fc4 "default" 1 "body2" "Public roadmap, open RFCs, and a Discord where the team ships in real time.") @@ -656,33 +662,26 @@ "Early users on what's coming" "center") {d :doc} (ops/insert-new d "root" "default" 19 "x-spacer" {:attrs {"size" "1rem" "axis" "vertical"}}) - ;; x-scroll-stack stacks its slotted children as the host - ;; element scrolls past the viewport. The component sets its - ;; OWN host height in connectedCallback (vh + n*scroll- - ;; distance) so we don't need to. Two attribute corrections - ;; vs. an earlier draft: peek is in PIXELS (default 6, not a - ;; fraction) and scroll-distance is the per-card scroll-room - ;; in pixels (default 150). The earlier "0.12" / "100" values - ;; produced an effectively static stack. - ;; - ;; Note: x-scroll-stack listens to window scroll events. - ;; Inside Bareforge's editor canvas-host (which has its own - ;; overflow:auto scrollport), the stacking animation will - ;; only animate when the page itself scrolls — which is the - ;; case in every exported artefact (HTML / bundle / CLJS / - ;; vanilla-JS) but not necessarily in the in-editor preview - ;; if the canvas-host is the scrollport. + ;; A plain x-grid here instead of x-scroll-stack. Every + ;; scroll-driven BareDOM component (x-scroll-stack / + ;; -parallax / -story / -timeline) listens to window scroll + ;; events; inside Bareforge's editor canvas-host (its own + ;; overflow:auto scrollport) those events never fire, so a + ;; scroll-driven section reads as static during editing. + ;; The x-soft-body cards still react to hover/pointer, so the + ;; section stays kinetic without depending on scroll. {d :doc stack-id :id} - (ops/insert-new d "root" "default" 20 "x-scroll-stack" - {:attrs {"peek" "20" - "rotation" "3" - "scroll-distance" "300" - "align" "center"}}) + (ops/insert-new d "root" "default" 20 "x-grid" + {:attrs {"columns" "repeat(3, 1fr)" + "gap" "lg" + "row-gap" "lg"}}) ;; testimonial 1 {d :doc t1 :id} (ops/insert-new d stack-id "default" 0 "x-soft-body" - {:attrs {"stiffness" "0.5" - "damping" "0.7" - "intensity" "0.5"}}) + {:attrs {"stiffness" "60" + "damping" "5" + "intensity" "4" + "grab-radius" "250" + "radius" "40"}}) {d :doc} (add-text d t1 "default" 0 "blockquote" "I haven't been this excited about a tool launch in years. The editor genuinely feels like it was made by someone who ships every day.") {d :doc} (ops/insert-new d t1 "default" 1 "x-avatar" @@ -691,9 +690,11 @@ "Mira A., Staff engineer at Lattice") ;; testimonial 2 {d :doc t2 :id} (ops/insert-new d stack-id "default" 1 "x-soft-body" - {:attrs {"stiffness" "0.5" - "damping" "0.7" - "intensity" "0.5"}}) + {:attrs {"stiffness" "60" + "damping" "5" + "intensity" "4" + "grab-radius" "250" + "radius" "40"}}) {d :doc} (add-text d t2 "default" 0 "blockquote" "Live collab that actually works on a slow connection. Our remote team got back two hours of merge-conflict pain a week.") {d :doc} (ops/insert-new d t2 "default" 1 "x-avatar" @@ -702,9 +703,11 @@ "Rohan D., Tech lead at Nimbus") ;; testimonial 3 {d :doc t3 :id} (ops/insert-new d stack-id "default" 2 "x-soft-body" - {:attrs {"stiffness" "0.5" - "damping" "0.7" - "intensity" "0.5"}}) + {:attrs {"stiffness" "60" + "damping" "5" + "intensity" "4" + "grab-radius" "250" + "radius" "40"}}) {d :doc} (add-text d t3 "default" 0 "blockquote" "The open API meant I had a Slack integration running on day two. No SDK, no boilerplate — just a typed endpoint and I was off.") {d :doc} (ops/insert-new d t3 "default" 1 "x-avatar" From a37fb59c74ab03ea270ed4d8aa46f5b616d2408f Mon Sep 17 00:00:00 2001 From: vanelsas <58037137+avanelsas@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:37:36 +0200 Subject: [PATCH 5/7] Kinetic Launch: drop background x-soft-body; double hero font MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - **x-metaball-cursor was hidden by an opaque sibling.** x-soft-body isn't a backdrop component — it's a card whose SVG path paints a solid rounded-rect filled with --x-soft-body-bg (--x-color-surface, white). Sitting beside x-metaball-cursor under :placement :background, with its host stretched to inset:0, it covered the entire backdrop with a white shape that hid the metaball blobs underneath. Dropped the background-layer x-soft-body; ambient backdrop is now metaball-cursor + gaussian-blur, the original v0.1.0 pairing. x-soft-body still appears extensively on the bento cells and testimonial cards, where it's correctly used as a surface container. - **x-kinetic-typography hero doubled in size.** The component reads its size from the `font-size` attribute (default 24px). Set to `3rem` (~48px) so the hero reads as a hero, not a subhead. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/bareforge/ui/templates.cljs | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/bareforge/ui/templates.cljs b/src/bareforge/ui/templates.cljs index 0b6c114..36166ef 100644 --- a/src/bareforge/ui/templates.cljs +++ b/src/bareforge/ui/templates.cljs @@ -479,26 +479,19 @@ (defn- kinetic-showcase [] (let [d (m/empty-document) ;; --- background layers (placement :background) --- - ;; metaball cursor — fluid blobs follow the pointer + ;; metaball cursor — fluid blobs follow the pointer. + ;; Paired with gaussian-blur for ambient colour. x-soft-body + ;; isn't a backdrop component (its SVG path paints a solid + ;; rounded-rect that covers anything beneath it); it lives + ;; on the bento + testimonial cards instead. {d :doc} (ops/insert-new d "root" "default" 0 "x-metaball-cursor" {:attrs {"blob-count" "5" "blob-size" "60" "blur" "20" "noise" "" - "noise-scale" "0.8" - "noise-speed" "0.4" "palette" "#f43f5e,#a855f7,#06b6d4"} :layout {:placement :background}}) - ;; soft-body — squishy physics blobs in the backdrop - {d :doc} (ops/insert-new d "root" "default" 1 "x-soft-body" - {:attrs {"stiffness" "0.4" - "damping" "0.6" - "intensity" "0.5" - "radius" "120" - "grab-radius" "180"} - :layout {:placement :background}}) - ;; gaussian blur — toned down so the metaball + soft-body get room - {d :doc} (ops/insert-new d "root" "default" 2 "x-gaussian-blur" + {d :doc} (ops/insert-new d "root" "default" 1 "x-gaussian-blur" {:attrs {"colors" "#f43f5e,#a855f7,#06b6d4" "blur" "100" "speed" "3" @@ -508,7 +501,7 @@ "animation" "float"} :layout {:placement :background}}) ;; --- navbar --- - {d :doc nav-id :id} (ops/insert-new d "root" "default" 3 "x-navbar") + {d :doc nav-id :id} (ops/insert-new d "root" "default" 2 "x-navbar") {d :doc} (add-text d nav-id "brand" 0 "h5" "Pulse") {d :doc} (ops/insert-new d nav-id "end" 0 "x-button" {:text "Story" :attrs {"variant" "ghost"}}) @@ -527,7 +520,8 @@ {d :doc} (ops/insert-new d "root" "default" 6 "x-kinetic-typography" {:attrs {"text" "Something extraordinary is coming" "preset" "wave" - "animation" "scroll"}}) + "animation" "scroll" + "font-size" "3rem"}}) {d :doc} (add-text+align d "root" "default" 7 "body1" "Six years of work, one launch event. Reserve your seat or watch the teaser to see what we've been building." "center") From 6698170ce70458f01b05c65de7faa4c58b825a18 Mon Sep 17 00:00:00 2001 From: vanelsas <58037137+avanelsas@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:40:19 +0200 Subject: [PATCH 6/7] Pin x-metaball-cursor above all content via position:fixed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cursor blobs were intermittently disappearing behind content because :placement :background stamps z-index:0 on the host (via the canvas-host stylesheet rule), and content gets z-index:1 — so flow elements paint over the metaball-cursor whenever a card, button, or grid landed in the cursor's path. The metaball-cursor's own :host { z-index:9999 } rule loses to the outer attribute selector's specificity, so the inner declaration is moot. Switched the layout to plain extra-style with `position: fixed; inset: 0; width/height: 100%; z-index: 9999; pointer-events: none;`. Three things this fixes: - **Always on top**: z-index 9999 is far above any content stacking context the page can produce. - **Viewport-relative**: position:fixed is what a cursor- following effect actually wants. The blobs follow the pointer across the whole viewport regardless of where the page has scrolled. - **Clicks pass through**: pointer-events:none means content underneath stays clickable; the metaball-cursor doesn't swallow clicks even though it sits above everything. Trade-off: dropping :placement :background means the cursor isn't tagged as a background layer, so it can't be selected by clicking the canvas. Designers can still select it from the layers panel — and a cursor-following overlay shouldn't intercept canvas clicks anyway. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/bareforge/ui/templates.cljs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/bareforge/ui/templates.cljs b/src/bareforge/ui/templates.cljs index 36166ef..1942975 100644 --- a/src/bareforge/ui/templates.cljs +++ b/src/bareforge/ui/templates.cljs @@ -478,19 +478,24 @@ (defn- kinetic-showcase [] (let [d (m/empty-document) - ;; --- background layers (placement :background) --- - ;; metaball cursor — fluid blobs follow the pointer. - ;; Paired with gaussian-blur for ambient colour. x-soft-body - ;; isn't a backdrop component (its SVG path paints a solid - ;; rounded-rect that covers anything beneath it); it lives - ;; on the bento + testimonial cards instead. + ;; --- background layers --- + ;; metaball cursor — fluid blobs follow the pointer. NOT + ;; :placement :background: that route stamps z-index:0 on + ;; the host (per the canvas-host stylesheet rule), which + ;; means content (z-index:1) paints over the cursor blobs. + ;; Instead use position:fixed at z-index:9999 with + ;; pointer-events:none so the blobs always render above + ;; everything while clicks fall through to content beneath. + ;; Fixed positioning is also what a cursor-following effect + ;; wants — relative to the viewport, not to a parent. {d :doc} (ops/insert-new d "root" "default" 0 "x-metaball-cursor" {:attrs {"blob-count" "5" "blob-size" "60" "blur" "20" "noise" "" "palette" "#f43f5e,#a855f7,#06b6d4"} - :layout {:placement :background}}) + :layout {:extra-style + "position: fixed; inset: 0; width: 100%; height: 100%; z-index: 9999; pointer-events: none;"}}) {d :doc} (ops/insert-new d "root" "default" 1 "x-gaussian-blur" {:attrs {"colors" "#f43f5e,#a855f7,#06b6d4" "blur" "100" From 02bb706fe7e3b7c37906109fb9eb7dad82ac89ad Mon Sep 17 00:00:00 2001 From: vanelsas <58037137+avanelsas@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:42:19 +0200 Subject: [PATCH 7/7] =?UTF-8?q?Tune=20kinetic-typography=20hero=20font-siz?= =?UTF-8?q?e:=203rem=20=E2=86=92=202rem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 (1M context) --- src/bareforge/ui/templates.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bareforge/ui/templates.cljs b/src/bareforge/ui/templates.cljs index 1942975..9fa7cdc 100644 --- a/src/bareforge/ui/templates.cljs +++ b/src/bareforge/ui/templates.cljs @@ -526,7 +526,7 @@ {:attrs {"text" "Something extraordinary is coming" "preset" "wave" "animation" "scroll" - "font-size" "3rem"}}) + "font-size" "2rem"}}) {d :doc} (add-text+align d "root" "default" 7 "body1" "Six years of work, one launch event. Reserve your seat or watch the teaser to see what we've been building." "center")