* Align webapp pricing page with website design
* Clarify pricing headline to avoid implying unlimited usage
* Simplify pricing headline to Pick a plan
-top-[5px] centers the crossbar on the section's top rule (was 1px
high), and z-[31] lifts the marks over the frosted eyebrow band
(z-30), which was swallowing the right tick's downward stem.
Claude-Session: https://claude.ai/code/session_01YBoaBEt3gynzTwogBFtn4B
The whole frame (rule, eyebrow, ticks) now assembles once on first
entry and stays built — the scrub-linked reversal read as
inconsistent against the one-shot content. And the section-top
crosses become half ticks (.tick-half: crossbar + downward stem):
the full plus poked its upper arm above the boundary into the
frosted sticky eyebrow band.
Claude-Session: https://claude.ai/code/session_01YBoaBEt3gynzTwogBFtn4B
The eyebrow carries readable text and rides sticky with the reader,
so it must never fade back out under them. It now reveals once (same
tween as the cells) while the rule and ticks keep the scrubbed,
reversible draw. Verified: scroll back un-draws the rule to zero with
the eyebrow holding at full opacity.
Claude-Session: https://claude.ai/code/session_01YBoaBEt3gynzTwogBFtn4B
The sticky eyebrow band now owns BOTH hairlines (border-y): its top
edge was the section's drawn rule, which the frosted background
painted over at rest and which vanished entirely once the band stuck
mid-section. The band also fades as one unit with the draw
choreography — frost, rules, and contents together — coinciding with
the drawn rule at rest so they read as a single line.
Group content reveals move from one group-level trigger to per-CHILD
ScrollTriggers: the old single trigger fired when a tall grid's top
entered, revealing every cell below the fold unseen — so scrolled-to
content sat static while only the frames animated. Each cell now
assembles as it arrives, cells sharing a row cascading left to right
(delay derived from horizontal position), consistent with the drawn
frames at every scroll depth.
Claude-Session: https://claude.ai/code/session_01YBoaBEt3gynzTwogBFtn4B
Premium transition-in for the scrolled page, in the instrument voice:
- Structural draw-up, scrub-linked and reversible: as a section enters
the viewport its top rule DRAWS across, the eyebrow's mono contents
settle in, and the corner ticks pop — all tied to scroll position
(scrub 0.35), so pulling back down un-draws the frame. Content
reveals stay one-shot: text never wiggles under the reader. Rules
render complete in server HTML; only motion-capable visitors get
the choreography.
- Section eyebrows ("01 / Crafting features") are sticky while their
section scrolls — frosted (backdrop blur over translucent page
background) like the ruler rail, pinned under the navbar, pushed
away by the next section rather than stacking.
- The studio demo moves out of the hero into Features as the lead
cell: the announce strip becomes its header row and the
blocking↔render comparator its 21:9 body (cursor hint as an
invert chip over the footage, md+ only). The hero ends at the
poster. Image to Location returns to the grid, which now splits
evenly: seven feature cells plus a full-sized eighth cell — the
launch CTA, a clickable door to the webapp with an arrow chip
and the same header/body/copy anatomy as its siblings.
Verified in Firefox: rule at 52% mid-viewport and back to 0 on
scroll-back (reversible), eyebrow pinned at 48px deep into the
section, zero page errors.
Claude-Session: https://claude.ai/code/session_01YBoaBEt3gynzTwogBFtn4B
The scroll ruler is now truly absent on small screens — the
capability gate went live (media-query listeners instead of a
one-shot mount check) and the component renders nothing when
incapable: no rail element, no data-ruler stamp, native scrollbar,
no hero heading choreography. Resizing across the boundary
mounts/unmounts the instrument in place: a late mount comes up
settled instantly (an intro cascade firing on a window resize reads
as a glitch), and unmounting releases every inline style HeadingFlow
wrote on the hero wordmark letters so the masthead stands naturally.
The spiral's mobile profile graduates to its own tuner group (Galaxy
mobile): below the area threshold its dials replace the Galaxy-layout
values wholesale — arms, turns, card count (fixed, not scaled from
the desktop knob), outer radius, card height cap, birth radius,
density — so small screens get an independently tuned composition.
Verified in Firefox: phone shows no rail/attr and an untouched
wordmark; growing to 1500px mounts the settled instrument (ticks up,
HeadingFlow at identity rest pose); shrinking unmounts and restores.
Claude-Session: https://claude.ai/code/session_01YBoaBEt3gynzTwogBFtn4B
The pulse comets are now choreographed into the intro: their
visibility is gated by the same trailing radial wave that uncovers
the cards (uWaveR/uWaveBand uniforms fed from the rollout clock), so
they appear rolling outward with the field instead of materializing
across the whole spiral at the instrument beat. Post-intro the wave
radius sits past every arm; the tuner replay rewinds it for free.
Baked the user's tuned values as defaults: cardN back to 64 (the
0.76 arm desync scatters it cleanly in slot units), guide lines 1×,
line 2px, pulses 0.72 alpha / 0.19 speed / 0.05 length / 3 per arm /
0.4 hue spread / 0.62 light-mode gray.
Claude-Session: https://claude.ai/code/session_01YBoaBEt3gynzTwogBFtn4B
Dark theme keeps the hue-spread accent comets. Light theme now drops
color entirely: pulses render as plain dark gray (ink mixed over the
paper by the Pulse gray knob, default 0.75) and read through the
ribbon thickness alone — colored trails fought the paper background
no matter how dark they sank. The hue spread is zeroed through the
same cross-fade that drives the color, so a theme toggle morphs
between the two treatments instead of snapping.
Claude-Session: https://claude.ai/code/session_01YBoaBEt3gynzTwogBFtn4B
Pulse feedback round. The arm guides move from GL lines (stuck at
1px) to thin ribbon meshes — each sample extrudes two vertices along
the curve normal and the vertex shader sets the width — so the
colored part can swell above the resting hairline (Pulse thick px,
default 3.5; base Line px 1.2).
Light theme sinks the pulse color toward ink (Pulse dark, default
0.65): bright accents washed out on the paper background; near-black
trails carry the needed contrast. Dark theme keeps the luminous
accent. The mix tracks background luminance, so theme cross-fades
morph it rather than snapping.
Trails are now comets — asymmetric falloff (sharp head, longer tail
behind the direction of travel), shorter (Pulse length 0.05 → 0.035)
and faster than the conveyor (Pulse speed 0.12 → 0.22).
Underlay density: Guide lines × (default 2) interleaves phantom guide
curves between the card arms — pulses ride those too. The mobile
profile pins 1× (its whole point is fewer, cheaper elements).
Claude-Session: https://claude.ai/code/session_013vwLpYJbWEqTJg9PGV6B6H
Three queued improvements, all tunable:
Mobile profile (Galaxy layout: Mobile < Mpx / arms / turns / density ×).
Below the area threshold the spiral switches to fewer, straighter arms
— at the tuned desktop angle, consecutive cards along an arm sit
radially close, so the neighbor-gap collision bound forced them small
on phones. Straighter arms space the ladder out and a density
multiplier lets cards claim the larger gaps.
Proximity dedup (Galaxy layout: Dedup px). Rebirth's least-recently-
shown pick spreads clip repeats over time, but cross-arm neighbors at
similar radii keep a constant angular offset — the same clip could
ride side by side indefinitely. A sweep on the cull cadence catches
visible pairs sharing a clip within the radius and reassigns the
blurrier card (the swap hides inside its birth blur) to the clip whose
current users sit furthest away, recency as tiebreak.
Arm color pulses (Galaxy look: Pulse alpha/speed/width/count/hue).
The arm guide lines move to a ShaderMaterial carrying arc-length and
arm-index attributes: a gaussian band of the theme accent travels
outward along each arm (with the cards' direction), hue-rotated per
arm for the colorful spread and dephased by the golden conjugate so
arms never flash in lockstep. Base hairline color/alpha and the
intro draw-up match the old line material; pulses fade out over the
blurred birth zone and lerp with theme cross-fades.
Also ported onto this branch: the pre-flight WebGL probe (cherry-pick)
and the 35-clip showcase pool.
Claude-Session: https://claude.ai/code/session_013vwLpYJbWEqTJg9PGV6B6H
When WebGL context creation fails (exhausted drivers, blocklisted
GPU, webgl.disabled), THREE.WebGLRenderer throws inside r3f's async
init — an unhandled REJECTION that the render-phase CanvasBoundary
never catches, surfacing as a page error instead of the designed
static fallback.
Both r3f canvas gates (galaxy, comparator blocking scene) now consult
a shared cached probe (src/lib/webgl-support.ts) before mounting the
<Canvas>: no context available → the canvas never mounts, the page's
static layers stand, and the slate chrome already hides itself via
the dead-instrument rule. The probe releases its test context through
WEBGL_lose_context so it never eats a context slot.
Verified with Playwright Firefox: webgl.disabled=true → zero
canvases, zero page errors, copy/ruler fully functional; normal run →
both canvases mount, zero errors.
Claude-Session: https://claude.ai/code/session_013vwLpYJbWEqTJg9PGV6B6H