* 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
Ports /seedance-2, /seedance2-5, /minimax-h3, and /creators/jboogxcreative
from the Vite site into the instrument design language, reusing the
landing's own Features / Ownership / Made-with sections (now taking an
`index` prop so eyebrow numbers stay sequential) plus a small set of
campaign building blocks (components/campaign): centered hero with reel
figure, section heading block, prose + flagged note, numbered tip grid,
native <details> FAQ, five-reasons cell grid with the "every model"
marquee, Discord/GitHub strip, closing CTA, and a shared CTA pair that
routes subscribers into the webapp and everyone else to pricing, with the
OS-detected desktop download and post-download signup modal.
- Seedance 2.5: overview with rumor disclaimer, prompt tips, FAQ (FAQPage
JSON-LD), scroll-scrubbed manifesto word reveal (the Vite page's Three.js
walking character and scrubbed knight video were not carried over), then
the reused feature/ownership/reasons/community sections.
- MiniMax H3: real promptbox in the hero. Enqueues an H3 generation via
/v1/omni_gen/generate/video, polls /v1/jobs/job/{token}, and plays the
result inline; logged-out visitors get an inline email/password signup
or login gate and the typed prompt runs on success. Aspect ratio,
resolution, duration, and sound controls; keyframe uploads are left to
the full app. Google SSO is not offered (no OAuth provider in this app).
- Creator spotlight: reel triptych, credits marquee, feed grid, craft
cards, ProfilePage JSON-LD.
Shared: lib/use-platform.ts (OS detection + download-initiated flag) and
components/download/download-modal.tsx extracted from the download page;
api.ts gains login, signup, generateVideo, getVideoJob; ruler roster
reordered so campaign sections precede the reused landing ids; sitemap
lists the four routes.
Restores the Vite pricing table's live behaviour on the Next site without
pulling the Nx @storyteller/api lib into this standalone app:
- lib/api.ts: minimal browser client for the endpoints pricing needs
(session, active subscriptions, signup checkout, subscription checkout,
switch plan, manage-plan portal, credits pack checkout, web referral
log). Same paths, bodies, and envelopes as the shared lib; cookies plus
the signed-session header fallback. Host via NEXT_PUBLIC_API_HOST.
- lib/referral.ts: landing-context capture (?u=, ?r=, landing URL,
referrer) to apex-domain cookies + localStorage, mounted site-wide by
components/landing-context.tsx, which also logs the referral once per
browser session (the old main.tsx bootstrap).
- lib/use-account.ts: one shared session + ArtCraft plan fetch per page
load for every consumer.
- Plan grid: logged out -> Stripe signup checkout with attribution; logged
in without a plan -> subscription checkout; with a plan -> portal plan
switch. "Your plan" tab and disabled CTA on the current tier, "Switch
to X" labels, Manage plan portal link, inline error line.
- Credits cell: logged-in visitors get the one-time credit pack modal
(Stripe checkout); logged-out visitors are sent to the app to sign in.
Server HTML still renders the logged-out state, so static output, SEO,
and every other page are unchanged.
The page-top section on interior pages (Support, Tutorials, News, …) was
running the ordinary anchor-space flip, whose progress at scroll 0 is
(12% of vh + 200px − ~110px) / 200px — so on shorter viewports the 01
heading sat partially flipped, or hidden, instead of leading the stack.
The first non-hero section is now pinned like the hero: flipP = detachP =
1 from the first frame, no queue home, no rail ride. Every page now opens
with its 01 section stacked at the top and 02+ queued below.
- Ruler: every interior page header now carries a section id (pricing,
download, tutorials, news, faq, support, press-kit, beta) registered in
RULER_SECTIONS ahead of the interior ids, so the heading stack starts
with the page's 01 section at the top instead of first appearing
mid-page. The pricing section wraps the promo strip so it begins at the
very first pixel. Roster order is documented as load-bearing (anchors
must increase with index).
- Ruler: capability gate tightened to hover-capable fine pointers at
1024px+ and never on a mobile/tablet user agent.
- Pricing: dropped the "See plans" jump button; the "20% off · ends soon"
badge moved into the plan toolbar next to the cadence toggle.
Reworks /pricing on top of the ported instrument layout so the plan table
pops the way the original did:
- Per-plan color identity restored (green Basic, purple Pro, orange Max,
blue Enterprise) via `.plan-*` tokens with light/dark ink variants: solid
color index tab, color wash pooling under it, plan-colored checks and
CTAs, and a 2px frame on the Most popular / Best value tiers.
- Conversion elements: full-width accent promo strip above the header,
benefit-led headline ("Every model. One studio. Yours forever.") with a
"See plans" jump CTA, 20% off pill and crossed-out anchor on every card,
per-plan yearly savings in dollars, taglines, "2 months free" nudge on
the cadence toggle, arrow CTAs, and a trust strip (cancel anytime, Stripe
checkout, credit refunds, open source) under the grid.
Ports the interior marketing pages into artcraft-website-next, rebuilt in
the landing's instrument language (SectionShell rails + ticks, mono HUD
eyebrows, hairline gap-px cell grids, Archivo display headings with one
serif-italic contrast word, theme tokens for light/dark) instead of the old
dark-only Truchet/glow treatment.
Pages
- /pricing: plan grid (Basic/Pro/Max + Enterprise) with yearly/monthly
TabSelector, 20% promo anchor pricing, highlighted plans invert their
index row, credit-pack and footnote cells. ?ref=sd2fakeyou keeps the
Seedance early-access header + reel. Checkout hands off to the webapp.
- /faq and /faq/[slug]: guide grid + article, FAQPage/Article JSON-LD.
- /news and /news/[slug]: post list + article, blog images resolved
against the media host.
- /tutorials and /tutorials/[slug]: category filter grid, click-to-load
YouTube via LiteYouTube, frontmatter aliases 308 to the canonical slug.
- /support, /download (client-side OS detection, requirements, quick
start, post-download signup modal), /press-kit (asset cells + video
modal), /beta (Google Form signup with honeypot).
Platform (Vite -> Next)
- Markdown content copied into src/content and read from disk in server
code (lib/content.ts) with generateStaticParams, replacing
import.meta.glob; markdown renderer ported to lib/markdown.ts and styled
by token-based .article-content rules in globals.css.
- react-router Links/useParams/useSearchParams -> next/link, awaited
params/searchParams, generateMetadata; react-device-detect -> a
post-hydration user-agent hook; @storyteller/* lib imports replaced by
local data modules (pricing-data, download-links, press-kit-data).
- Removed the legacy-route redirects to the Vite site from next.config
(only the old Stripe return paths still redirect, now to the webapp);
sitemap lists every page and article; ruler roster gains the interior
section ids; Discord/Windows brand icons added.