feat(landing): M2/M5/M6/M7 editorial moments — sage & cream - #721
Conversation
…ll primitives Builds the shared First Light landing scaffold (docs/LANDING_ENTRY_WORLD_DESIGN.md) every downstream lane composes on: palette + 3-grade glass grammar, Lenis scroll root, scroll-progress/pinned-scrub/masked-reveal primitives, and nine M1–M9 moment stubs wired into a coherent draft page. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CHFRrZkRsAHWTwvxhySkfe
…ily (Nick 2026-07-02) Repoints --fl-pine -> #2E3A2C (sage-ink) and --fl-green -> #5C6E58 (sage-deep) so in-flight lane work recolors automatically, and adds first-class --fl-cream/--fl-cream-high/--fl-sage-mist/--fl-sage/ --fl-sage-deep/--fl-sage-ink tokens (+ rgb twins) per the SAGE & CREAM amendment in docs/LANDING_ENTRY_WORLD_DESIGN.md. Kelly #16A34A is demoted to product-only (real screenshots + M5 signal-card replica) — never on landing/auth chrome. Updates CONTRACTS.md's palette section to the v2 table, the pine->sage-ink / kelly->sage-deep read-mapping, and the daylight-mood sentence. Swept the foundation's shared files (fonts.ts, lib/, scroll/*, index.ts, page.tsx) for hardcoded #143527/#16A34A: none found, nothing to move. One hardcoded #143527 remains in moments/M3ProductCinema.tsx (the landing-cinema lane's owned stub, out of this lane's ownership) — left in place for that lane to pick up when it replaces the stub. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RVnwXMnsgREVfjpGSAJPvT
…o feat/entry-world-editorial
Inherited sage-recolored partial work from the second builder (killed mid-build) already satisfied the amendment's letter and spirit — M2's ledger, M5's signal-card replica, M6's player vignettes, and M7's honesty band were all built against the sage/cream tokens with correct reduced-motion handling. This pass closes the remaining gaps: - M5's confidence-bar fill animated `width` (layout reflow every frame); switched to a GPU-safe `scaleX` transform (transform-origin left) per the transform/opacity-only motion rule — visually identical, cheaper. - M2/M6/M7 fell back to the generic warm-neutral Tailwind scale for secondary/body text and one eyebrow, breaking from M5's own precedent (rgba(--fl-sage-ink-rgb, n)) in the same PR. Recolored all instances to sage-ink tints and sage-deep eyebrows so the four moments read as one system. Visual proof frames deferred — this session is browser-free (machine stability); frames will be captured in a later pass.
|
PR title or description contains an excluded keyword. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (3)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR Summary by QodoFirst Light landing scaffold + sage/cream moments with Lenis + motion primitives
AI Description
Diagram
High-Level Assessment
Files changed (21)
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 95e5ba94e5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const y = useTransform( | ||
| progress, | ||
| [start, enterEnd, exitStart, end], | ||
| ['28%', '0%', '0%', '-28%'], |
There was a problem hiding this comment.
Keep the final cinema panel centered
When PinnedScrub renders the reduced-motion branch it passes progress = 1, and the opacity mapping keeps the last screen visible at that value. This '-28%' end translation still applies to that visible last screen, so reduced-motion users see the Decision Room panel shifted upward instead of the documented final landed frame; the same off-center state appears at the bottom of the scrub. Special-case the last panel's end transform to stay at 0% or stop keeping it visible while it exits.
Useful? React with 👍 / 👎.
Code Review by Qodo
Context used✅ Compliance rules (platform):
93 rules 1. Dev-only routes type import
|
| <m.div | ||
| ref={cardRef} | ||
| initial={{ opacity: 0, y: 20 }} | ||
| whileInView={{ opacity: 1, y: 0 }} | ||
| viewport={{ once: true, margin: '-15%' }} | ||
| transition={reduced ? { duration: 0 } : { duration: 0.6, ease: [0.16, 1, 0.3, 1] }} | ||
| className="fl-glass-2 relative z-10 mx-auto mt-12 max-w-xl overflow-hidden rounded-2xl" | ||
| > |
There was a problem hiding this comment.
1. fl-glass-2 missing required utilities 📘 Rule violation ⚙ Maintainability
New glass-effect elements use the custom fl-glass-2 class without including the required utility set (bg-white/70, backdrop-blur-xl, border-white/20, rounded-2xl). This violates the standardized glass-effect class requirement and can lead to inconsistent styling across the codebase.
Agent Prompt
## Issue description
Glass-effect elements must include the standardized Tailwind utility set. The new landing components use `fl-glass-2` but do not include the required utilities in their `className`.
## Issue Context
Compliance requires glass-effect elements to include **all** of: `bg-white/70`, `backdrop-blur-xl`, `border-white/20`, `rounded-2xl`.
## Fix Focus Areas
- src/components/marketing/first-light/moments/M5Intelligence.tsx[67-74]
- src/components/marketing/first-light/moments/M4TwoFields.tsx[72-80]
- src/components/marketing/first-light/moments/M6ForThePlayer.tsx[64-82]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| /* ── Sage & cream — first-class tokens (2026-07-02 respec) ──────────── */ | ||
| /* Cream field — alias of --fl-ecru, same value, first-class name. */ | ||
| --fl-cream: #f5f1e6; | ||
| --fl-cream-rgb: 245, 241, 230; | ||
| /* Cream high — glass highlights, replaces white. */ |
There was a problem hiding this comment.
2. --fl-cream not #fffefa 📘 Rule violation ⚙ Maintainability
The new --fl-cream token is defined as #f5f1e6, but the compliance requirement specifies the designated cream background token must be #FFFEFA. This breaks the single source-of-truth requirement for the cream background color.
Agent Prompt
## Issue description
The cream background token does not match the required value.
## Issue Context
Compliance requires that the designated cream background token/variable be defined once and have the exact value `#FFFEFA`.
## Fix Focus Areas
- src/components/marketing/first-light/first-light.css[62-66]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| /// <reference types="next" /> | ||
| /// <reference types="next/image-types/global" /> | ||
| import "./.next/types/routes.d.ts"; | ||
| import "./.next/dev/types/routes.d.ts"; |
There was a problem hiding this comment.
3. Dev-only routes type import 🐞 Bug ☼ Reliability
next-env.d.ts imports ./.next/dev/types/routes.d.ts, a generated dev artifact that won’t exist in clean checkouts and may not exist after next build, causing tsc --noEmit (used by `npm run typecheck`) to fail.
Agent Prompt
## Issue description
`next-env.d.ts` currently imports a generated file under `./.next/dev/types/`.
Because `.next/` is ignored and not guaranteed to exist (and build output paths differ between dev and build), this import can break `npm run typecheck` in CI/fresh checkouts.
## Issue Context
- The repo’s `typecheck` script is `tsc --noEmit` (no implicit Next build step).
- `.next/` is gitignored, so the imported file is not present reliably.
## Fix Focus Areas
- next-env.d.ts[1-6]
- tsconfig.json[58-65]
- package.json[6-36]
- .gitignore[19-22]
## Suggested fix
- Remove the `import "./.next/dev/types/routes.d.ts";` line from `next-env.d.ts`.
- If typed routes are still desired, include them via `tsconfig.json` patterns that do **not** hard-fail when `.next/` is missing (e.g., include `.next/**/types/**/*.d.ts`), or ensure CI generates `.next` types before `tsc` runs (explicit pre-step).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| const SCREENS: CinemaScreen[] = [ | ||
| { | ||
| label: 'Command Center', | ||
| caption: 'Roster, calendar, and tasks — the whole program, one screen.', | ||
| tint: 'linear-gradient(155deg, #1c4632 0%, #143527 100%)', | ||
| }, |
There was a problem hiding this comment.
4. Hardcoded retired palette colors 🐞 Bug ⚙ Maintainability
Multiple First Light moments hardcode retired pine/kelly colors (e.g. #143527, rgba(20,53,39,...), rgba(22,163,74,...)) and use Tailwind primary-* greens on landing CTAs, bypassing the new --fl-* token contract and reintroducing off-spec greens.
Agent Prompt
## Issue description
Several newly-added First Light moments bypass the palette contract by hardcoding old pine/kelly values and/or using Tailwind `primary-*` greens for landing chrome.
This defeats the “repointed aliases + token-only” approach and makes future palette adjustments non-global.
## Issue Context
`CONTRACTS.md` explicitly states:
- kelly (`#16A34A`) is product-only; landing/auth chrome should not use it.
- never hardcode `#143527` / `#16A34A`; always use the token vars.
## Fix Focus Areas
- src/components/marketing/first-light/moments/M3ProductCinema.tsx[34-50]
- src/components/marketing/first-light/moments/M1Hero.tsx[29-31]
- src/components/marketing/first-light/moments/M1Hero.tsx[82-86]
- src/components/marketing/first-light/moments/M4TwoFields.tsx[30-45]
- src/components/marketing/first-light/moments/M8FinalCTA.tsx[20-22]
- src/components/marketing/first-light/moments/M8FinalCTA.tsx[44-48]
- src/components/marketing/first-light/moments/M9Footer.tsx[31-37]
## Suggested fix
- Replace hardcoded pine hex/rgba in gradients with token-based equivalents, e.g. `rgba(var(--fl-sage-ink-rgb), …)` / `var(--fl-sage-ink)` / `var(--fl-sage-mist)` / `var(--fl-cream-high)`.
- Replace `hover:bg-primary-500` on landing CTAs with a First Light token-based hover (e.g. a slightly adjusted `--fl-sage-deep`-based value), so hover states don’t jump back to brand kelly greens.
- Replace footer `rgba(22,163,74,...)` glow with a token (likely `--fl-sage-deep-rgb` or brass) to keep the footer in the sage/cream system.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| className={cn('relative overflow-hidden px-6 py-28 sm:py-36', className)} | ||
| style={photoLayerStyle({ src: '/marketing/first-light/photos/mist.jpg', fallbackGradient: MIST_FALLBACK_GRADIENT })} | ||
| > | ||
| <div className="fl-grain" aria-hidden="true" /> |
There was a problem hiding this comment.
5. Duplicate grain overlay mounts 🐞 Bug ➹ Performance
.fl-grain is a fixed full-bleed overlay intended to be mounted once per page, but M8 adds another instance on top of the ones already mounted in M1 and M3, increasing compositing/paint work unnecessarily.
Agent Prompt
## Issue description
Multiple moments render `<div className="fl-grain" />`, but `.fl-grain` is `position: fixed` and the contract says to mount it once per page.
## Issue Context
- `.fl-grain` is a fixed, full-bleed overlay with `mix-blend-mode: overlay`.
- `CONTRACTS.md` calls out “Mount once per page”.
## Fix Focus Areas
- src/components/marketing/first-light/CONTRACTS.md[78-80]
- src/components/marketing/first-light/first-light.css[89-98]
- src/components/marketing/first-light/moments/M1Hero.tsx[48-55]
- src/components/marketing/first-light/moments/M3ProductCinema.tsx[52-56]
- src/components/marketing/first-light/moments/M8FinalCTA.tsx[24-30]
- src/app/page.tsx[57-69]
## Suggested fix
- Render a single `<div className="fl-grain" aria-hidden="true" />` at the landing page root (e.g. in `src/app/page.tsx` inside `LenisRoot` but outside individual moments), and remove per-moment instances in M1/M3/M8.
- Verify z-index layering remains correct after de-duplication.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Each ledger line's rule had origin-left set but never animated. Now it draws in via whileInView (scaleX 0 -> 1, once, -15% margin), staggered per line, instant under reduced motion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fz1ajgmqcEp1yPEzjnXgY5
… glow, specular/shadow tokens, lit cards, gradient ring, underline wipe (Amendment 2)
…o feat/entry-world-editorial
|
🤖 Mission Control — PR summary What it changes: Landing editorial moments M2/M5/M6/M7 in the "First Light" sage & cream language (e.g. M2 ledger rules that draw in on scroll). +2,253 / −10 across 25 files — additive presentation, stacked on Risk / areas: Public landing surface only. Scroll/whileInView animations + editorial layout; no data or auth surface. Reviewers should watch:
Posted automatically by the Helm Mission Control sweep · read-only triage, no changes made. |
… lit cards, gradient-ring signal card (Amendment 2) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fz1ajgmqcEp1yPEzjnXgY5
…ext (Nick) .fl-card, .fl-light-pool, and .fl-aurora's brightest blob were flat cream-high fills; demoted to cream (or a cream-high-to-cream top edge on .fl-card) so nothing larger than the 1px specular lip renders near-white.
…e-art (Amendment 3) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fz1ajgmqcEp1yPEzjnXgY5
…o feat/entry-world-editorial
…d glint, brand weave (Amendment 3) Merges feat/entry-world-foundation (brand/HelmMark+HelmRosette+SportGlyph, §D2 no-white utilities) and rebuilds M2/M5/M6/M7 per Amendment 3 §A.2/§B.3/ §C.2/§D: M2 breaks into a serif-left/ledger-right editorial split with a rosette eyebrow; M5 goes off-axis with the signal card right-of-center and the honesty line as a left margin-note; M6 becomes a 6-col bento with a dominant readiness tile (div-based sparkline, no chart lib) and per-tile sport glyphs; M7 goes left-weighted with the founder line + refusals on the left and a tabular-nums stat ledger on the right, carrying the page's one animated-gold moment (a single glint sweep on the founder-line brass rule). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fz1ajgmqcEp1yPEzjnXgY5
LAYOUT BRIEF
This lane's history (context for reviewers)
This lane was killed twice. On resume: preserved the second builder's uncommitted sage-era work as
wip: sage partial work (builder killed mid-build), then audited it against the AMENDED spec line-by-line. That inherited work was already strong — correctly recolored to sage/cream, correct reduced-motion pattern (useReducedMotion+transition={reduced ? {duration:0} : {...}}), correct MaskedReveal/AnimatedNumber usage. This PR's diff is the remaining fix-up on top of that inheritance:width(0%→82%), which forces layout reflow every frame. Switched to a GPU-safescaleXtransform (transform-origin: left) per the transform/opacity-only motion rule — pixel-identical result, compositor-only cost.text-warm-500/600) instead of the sage-ink tokens the palette table calls out ("sage-ink — dark bands + ALL body/display ink"). M5, built in the same PR, had already established the correct pattern (rgba(var(--fl-sage-ink-rgb), n)for secondary/tinted text,var(--fl-sage-deep)for eyebrows) — recolored the other three moments to match so all four read as one system.Owned files (per CONTRACTS.md)
src/components/marketing/first-light/moments/M2Clarity.tsxsrc/components/marketing/first-light/moments/M5Intelligence.tsxsrc/components/marketing/first-light/moments/M6ForThePlayer.tsxsrc/components/marketing/first-light/moments/M7Honesty.tsxDesign-bar checklist
#143527/#16A34A; kelly appears ONLY inside M5's signal-card replica (product content, per amendment)font-annual) for UI/numerals — no Inter/system-sans, no italic accent wordsfl-glass-2inset glass, never a stark white rectangle[0.16,1,0.3,1]throughout;useReducedMotion()+ prop-onlytransition={reduced ? {duration:0}: {...}}on every revealwhileInView,once: true) — no PinnedScrub/scrub-linking in this lane, sections stay calm per the brieffl-glass-*layers per viewport in every sectionGate results
npx tsc --noEmit→ 0 errorsnpx eslint <4 changed files>→ 0 errors, 0 warnings (exit 0)Visual proof frames deferred — this session is browser-free (machine stability); frames will be captured in a later pass.