Communitygithub.com

Kargatharaakash/landing-page-skill

Rebuild a premium framed fintech landing page with a photographic hero, editorial card grids, lime-on-olive visual language, smooth in-view reveals, interactive calculator, accordion, testimonial, articles, CTA, and footer.

What is landing-page-skill?

landing-page-skill is a Cursor agent skill that rebuild a premium framed fintech landing page with a photographic hero, editorial card grids, lime-on-olive visual language, smooth in-view reveals, interactive calculator, accordion, testimonial, articles, CTA, and footer.

Works with~Claude Code~Codex CLI✓Cursor
npx skills add Kargatharaakash/landing-page-skill

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Solv Framed Fintech Landing Page — Rebuild Skill

1. Design philosophy

Build the page as a polished product demo placed inside a softly rounded “browserless canvas,” not as an edge-to-edge corporate website. The contrast comes from three systems working together:

  1. Editorial restraint: large grotesk headlines, short copy, generous empty space, and few colors.
  2. Product tactility: pill controls, inset mini-interfaces, live numbers, sliders, accordions, and dashboard fragments.
  3. Soft cinematic motion: content does not bounce or fly. It resolves from blur, low opacity, and modest vertical displacement with an ease-out curve, then remains still.

The page should feel calm at rest and responsive during interaction. Motion is a hierarchy tool, not decoration.


2. What is directly observed vs inferred

Directly observed

  • A 22.38-second, 60 fps desktop capture at 2272×1440.
  • A fixed photographic forest background surrounding a rounded page shell.
  • White, olive, acid-lime, pale blue, pale lavender, gray, and photographic surfaces.
  • Hero load choreography with blur + fade + vertical translation.
  • Smooth vertical scrolling with a narrow lime scroll thumb at the right edge of the page shell.
  • Section reveals that use blur clearing, opacity, and short upward motion.
  • A horizontal logo rail.
  • A live calculator with a square range thumb and real-time funding estimate.
  • An accordion that swaps the open answer with animated height and plus/minus icons.
  • A testimonial image with quote copy and pagination dots.
  • Three article cards, a centered CTA section, and a dark inset footer.
  • No obvious scroll-jacking or pinned horizontal sequence.

High-confidence inference

  • Framer Motion, GSAP ScrollTrigger, or a similar intersection-driven reveal system.
  • A Lenis-like smooth-scrolling layer or very smooth trackpad/browser scrolling.
  • A duplicated CSS marquee for the logo rail.
  • A single modern grotesk family; likely in the Suisse/Neue Haas/Aeonik neighborhood. Exact font identity is not recoverable from the capture alone.
  • Tablet/mobile behavior is not shown. The responsive rules below are implementation requirements designed to preserve the desktop quality.

3. Visual system

3.1 Color tokens

These values are sampled or visually reconstructed from the capture. Use them as the canonical implementation palette.

:root {
  /* Core */
  --ink: #273000;          /* sampled dark olive; FAQ/footer/text */
  --ink-strong: #1f2700;   /* deeper olive for high-contrast controls */
  --acid: #ddff5a;         /* sampled calculator/accent lime */
  --acid-soft: #efffb0;    /* CTA glow / subtle highlighted fields */
  --paper: #ffffff;
  --paper-warm: #fbfbf7;

  /* Supporting cards */
  --sky: #cfe7e9;          /* sampled pale blue */
  --lavender: #d9def8;     /* sampled pale lavender */
  --mist: #efeee9;         /* chips, logo statement pill */
  --line: rgba(39, 48, 0, 0.14);
  --line-on-dark: rgba(221, 255, 90, 0.16);

  /* Text */
  --text-primary: #273000;
  --text-secondary: #74756d;
  --text-on-dark: #ddff5a;
  --white-muted: rgba(255, 255, 255, 0.72);

  /* Hero glass */
  --glass-dark: rgba(48, 43, 39, 0.48);
  --glass-light: rgba(255, 255, 255, 0.82);
  --hero-scrim: linear-gradient(
    180deg,
    rgba(20, 24, 10, 0) 42%,
    rgba(20, 24, 10, 0.24) 68%,
    rgba(20, 24, 10, 0.72) 100%
  );
}

Color usage rules

  • Use --paper for roughly 65–75% of the page surface.
  • Use --ink for one large section and the footer, not for every card.
  • Reserve --acid for primary calls to action, the calculator, FAQ typography, the custom scroll thumb, and small status chips.
  • Do not use more than one pale supporting color in a small component. A card is white, blue, lavender, lime, olive, or photographic—not a multi-color gradient.
  • Avoid pure black for text and controls. The olive-black is an important part of the original character.
  • The forest photo behind the shell should remain muted enough that the page shell is always dominant. Add a subtle cyan/cream wash if necessary.

3.2 Typography

Typeface

The capture uses a neutral neo-grotesk with compact spacing and soft geometry. Use this stack:

font-family: "Suisse Intl", "Neue Haas Grotesk Text", "Inter", "Helvetica Neue", Arial, sans-serif;

For an open-source implementation, use Inter Tight for display and Inter for body. Do not introduce a serif or monospaced secondary family.

Weight system

  • Display: 400–500. The large type is not heavy.
  • Section heading: 400–500.
  • Body: 400.
  • Emphasis inside body: 600.
  • Buttons/nav: 500–600.
  • Large numeric readout: 500.

Desktop type scale

:root {
  --fs-hero: clamp(3.75rem, 4.35vw, 5.15rem);       /* ~60–82px */
  --fs-section-xl: clamp(3rem, 3.4vw, 4.25rem);    /* ~48–68px */
  --fs-section: clamp(2.5rem, 2.8vw, 3.65rem);     /* ~40–58px */
  --fs-card-title: clamp(2rem, 2.2vw, 3rem);       /* ~32–48px */
  --fs-quote: clamp(1.75rem, 2vw, 2.75rem);        /* ~28–44px */
  --fs-body-lg: 1.25rem;                           /* 20px */
  --fs-body: 1rem;                                 /* 16px */
  --fs-small: 0.875rem;                            /* 14px */
}

Line-height and tracking

  • Hero/large headings: line-height: 0.96–1.02, letter-spacing: -0.045em.
  • Section headings: line-height: 0.98–1.05, letter-spacing: -0.04em.
  • Card titles: line-height: 1.0–1.08, letter-spacing: -0.035em.
  • Body: line-height: 1.42–1.55, letter-spacing: -0.01em.
  • Buttons/nav: line-height: 1, letter-spacing: -0.01em.
  • Large currency values: letter-spacing: -0.055em; use tabular numbers.
.numeric {
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -0.055em;
}

Line-length rules

  • Hero body: 42–54 characters.
  • Section body: 48–64 characters.
  • FAQ answer: 62–76 characters.
  • Do not let a display heading exceed 14–18 words or more than three lines on mobile.

3.3 Spacing and grid rhythm

Use a 4px base, with most visible spacing in multiples of 8.

:root {
  --space-1: 0.25rem;  /* 4 */
  --space-2: 0.5rem;   /* 8 */
  --space-3: 0.75rem;  /* 12 */
  --space-4: 1rem;     /* 16 */
  --space-5: 1.5rem;   /* 24 */
  --space-6: 2rem;     /* 32 */
  --space-7: 3rem;     /* 48 */
  --space-8: 4rem;     /* 64 */
  --space-9: 6rem;     /* 96 */
  --space-10: 8rem;    /* 128 */
}

Desktop shell measurements

From the 2272×1440 capture:

  • Page shell width: approximately 90vw.
  • Horizontal outer margin: approximately 5vw.
  • Top/bottom visible outer margin: approximately 3–3.5vh.
  • Shell corner radius: 28–32px.
  • Internal section padding: 56–64px left/right.
  • Large vertical section padding: 96–144px.
  • Gap between major cards: 20–28px.
  • Thin separators: 1px at 12–16% opacity.

Grid

Use a 12-column grid inside the shell.

.section-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: clamp(1rem, 1.4vw, 1.75rem);
}

Composition ratios:

  • Hero content: left 6–7 columns; floating dashboard card: right 3 columns.
  • Product overview: copy 5 columns; visual modules 6–7 columns.
  • Feature trio: approximately 3 / 3 / 4.5 columns, with the photographic card widest.
  • Calculator: 5.5 / 5.5 columns with a generous center gap.
  • FAQ: 5 / 7 columns.
  • Articles: equal 4-column cards.
  • Footer: brand block 4 columns; navigation/contact/location/languages fill the remainder.

3.4 Radius conventions

:root {
  --radius-shell: 2rem;      /* 32px */
  --radius-section: 1.5rem;  /* 24px */
  --radius-card: 1.25rem;    /* 20px */
  --radius-ui: 1rem;         /* 16px */
  --radius-chip: 999px;
}

Rules:

  • Outer page shell: 28–32px.
  • Large media and section cards: 20–24px.
  • Mini dashboard cards: 14–18px.
  • Buttons, tags, segmented nav, and statement chips: full pill.
  • Avoid mixing many arbitrary radii. Use these five values only.

3.5 Shadow and elevation

The original relies more on contrast and blur than obvious shadows.

:root {
  --shadow-shell: 0 24px 70px rgba(26, 34, 12, 0.18);
  --shadow-float: 0 18px 50px rgba(25, 31, 8, 0.18);
  --shadow-ui: 0 8px 24px rgba(25, 31, 8, 0.10);
}
  • Page shell gets one large, soft shadow.
  • Floating hero dashboard gets a medium soft shadow.
  • Most feature cards have no shadow; use border or color separation.
  • Never use sharp black shadows or multiple stacked shadows.

4. Layout architecture

4.1 Global canvas

The forest background stays fixed while the rounded content shell scrolls.

html {
  background: #b9d9d8;
}

body {
  margin: 0;
  color: var(--text-primary);
  background:
    linear-gradient(90deg, rgba(174, 219, 224, 0.34), rgba(250, 249, 218, 0.34)),
    url('/images/forest-background.avif') center / cover fixed;
}

.page-shell {
  width: min(90vw, 132rem);
  margin: 3.25vh auto;
  border-radius: var(--radius-shell);
  overflow: clip;
  background: var(--paper);
  box-shadow: var(--shadow-shell);
  position: relative;
}

Do not put a heavy border around the shell. The contrast against the background is sufficient.

4.2 Section order

  1. Hero / navigation
  2. Customer statement chip + looping logo rail
  3. Product overview — headline/copy left, two product-story cards right
  4. Growth capital feature trio
  5. Transparent fee calculator
  6. FAQ accordion
  7. Testimonial media/carousel
  8. Latest articles
  9. Financing expert CTA
  10. Dark inset footer

4.3 Hero composition

  • Height: min(92svh, 82rem) on desktop; minimum 760px.
  • Full-bleed image inside the shell.
  • Top nav floats over the image.
  • Copy is anchored bottom-left.
  • Product/dashboard card is anchored bottom-right.
  • Add a dark bottom scrim for legibility and a very subtle warm overlay over the photo.
.hero {
  min-height: min(92svh, 82rem);
  position: relative;
  isolation: isolate;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--hero-scrim);
  z-index: -1;
}

4.4 Navigation

Desktop consists of three independent clusters:

  • Left: a translucent dark pill containing 3 links.
  • Center: white logo.
  • Right: a dark translucent account pill plus a separate circular menu button.

Use backdrop-filter: blur(14px) and a semi-transparent surface. Keep nav height 58–64px.

At widths below 900px:

  • Hide the left link pill.
  • Keep the centered logo.
  • Keep one primary action and menu icon.
  • Ensure the logo remains optically centered, not mathematically shifted by unequal side controls.

4.5 Logo rail

  • White section.
  • Centered statement chip above logos.
  • Logos in a horizontally clipped rail with duplicated content.
  • Logo size should be visually normalized, not set to identical raw widths.
  • Use grayscale/olive treatment and lower opacity for selected marks.

4.6 Product overview

  • Large two-line headline on the left.
  • Two pill buttons directly below.
  • Two short paragraphs; the first few words in each paragraph are semibold.
  • Right side uses two differently colored cards, offset vertically to create asymmetry.
  • The dark card is narrower/taller than the pale-blue card and contains mini product UI.

4.7 Growth feature trio

  • Section heading spans most of the row, with a small outlined “Learn more” pill aligned right.
  • Three cards:
    1. Soft green photographic/gradient card with inset white UI.
    2. Lavender card with a balance-summary panel.
    3. Wide photographic card with large white headline and bottom copy overlay.
  • Cards share height and radius, but not width.

4.8 Calculator

  • White section with large whitespace above and below.
  • Left: heading, 2–3 line description, dark pill CTA.
  • Right: acid-lime card with header, divider, currency value, range control, divider, funding estimate.
  • The calculator card is approximately square and should not become wider than 650px.

4.9 FAQ

  • Full-width dark olive section.
  • Left column: lime title and summary.
  • Right column: four accordion rows.
  • One answer is open at a time.
  • Row separator lines are extremely subtle.
  • Plus turns to minus without rotating the entire icon container.

4.10 Testimonial

  • Full-width photographic card directly below the FAQ.
  • Large portrait/video still.
  • Blurred foreground at the bottom of the image is part of the photography, not an interface blur.
  • Quote and attribution sit over a darker lower-left gradient.
  • Two small pagination dots/buttons at bottom-right.
  • Treat as a carousel structurally, even though only one slide transition is visible in the recording.

4.11 Articles

  • White section with title on left and small “Show all” action on right.
  • Three equal cards.
  • Each card uses a 16:9 or slightly taller image with a dark bottom gradient and white article title.
  • Titles are short and anchored bottom-left.

4.12 CTA

  • Centered content in a tall section.
  • Background transitions from white at the top to very pale lime at the bottom.
  • Heading: two lines, max-width around 520–620px.
  • Small expert avatar cluster and dark primary pill.
  • Keep approximately 120–180px top and bottom breathing room.

4.13 Footer

  • CTA background continues behind the footer.
  • Footer itself is an inset dark-olive rounded rectangle with 24–32px outer margin.
  • Brand top-left, navigation top-right, contact/location/languages lower area, social circles bottom-left.
  • The footer should feel like a compact dashboard panel, not a traditional edge-to-edge legal footer.

5. Responsive behavior

The capture does not show responsive states. Implement the following to preserve intent.

5.1 Breakpoints

// tailwind.config.ts
screens: {
  sm: '640px',
  md: '768px',
  lg: '1024px',
  xl: '1280px',
  '2xl': '1536px',
}

5.2 Desktop ≥ 1200px

  • Keep the 90vw shell and all multi-column compositions.
  • Use 56–64px internal horizontal padding.
  • Hero copy and dashboard card may overlap the image freely.

5.3 Tablet 768–1199px

  • Shell width: calc(100vw - 32px); radius 24px.
  • Section padding: 32–40px.
  • Product overview becomes 5/7 or stacked if copy is crowded.
  • Feature trio becomes a 2-column grid, with photographic card spanning both columns.
  • Calculator remains 2 columns until about 900px, then stacks.
  • FAQ stacks title above accordion.

5.4 Mobile < 768px

  • Remove the external-photo “picture frame” effect or reduce it to 8px margins; use a 20px shell radius.
  • Hero height: 82–90svh; position copy above the dashboard card rather than overlapping it.
  • Hero headline: clamp(2.75rem, 12vw, 4.25rem).
  • Hide left nav links; retain logo, one action, and menu.
  • All content grids stack to one column.
  • Feature cards use aspect-ratio: 4 / 5 or a minimum height of 430px.
  • Article cards become a horizontal snap rail only when three full cards would become excessively long.
  • Calculator card uses full width; range track must be at least 44px high as an interaction target.
  • Disable background-attachment fixed on iOS and use a solid/gradient body background.
  • Keep motion distances below 28px and blur below 8px on mobile.

6. Motion system

6.1 Motion principles

  1. Animate only opacity, transform, clip-path, and small-radius blur.
  2. Use ease-out for entrances; do not use symmetric ease-in-out for content reveals.
  3. Stagger sibling items by 60–120ms.
  4. Use motion once as the content enters. Do not replay every time the user scrolls past the same section.
  5. No bouncy spring on large surfaces. Springs are acceptable only for tiny controls.
  6. Preserve native scrolling semantics. Smooth scrolling may soften wheel input, but must not hijack anchors or keyboard navigation.

6.2 Canonical curves

export const easeOutExpo = [0.22, 1, 0.36, 1] as const;
export const easeOutQuart = [0.25, 1, 0.5, 1] as const;
export const easeSoft = [0.33, 1, 0.68, 1] as const;

Recommended durations:

  • Hero title: 700ms.
  • Body/CTA: 560–650ms.
  • Large card: 720–850ms.
  • Section title: 650–750ms.
  • Card grid: 700–850ms with 90–120ms stagger.
  • Accordion height: 360–480ms.
  • Numeric interpolation: 850–1200ms.
  • Hover: 180–260ms.

6.3 Recording timeline and choreography

Timings are approximate to ±0.10s because the source is a screen recording with human scrolling.

Capture timeEventRebuild rule
0.00–0.28sHero image/nav already visible; content held backRender image/nav immediately to avoid blank first paint
0.28–0.55sFloating dashboard and hero heading begin resolving from blur/low opacityStart card at 280ms; heading at 340ms
0.42–0.72sHeading resolves; body and CTA follow70–90ms child stagger
0.68–1.00sMini chart bars animate inScale X from left; 70ms row stagger
~2.55sScroll reaches customer logo railNative/smoothed scroll, no snap
3.15–3.85sProduct overview title, copy, and visual cards revealIn-view at 20–25% viewport; blur 12px → 0, y 32px → 0
4.75–5.35sGrowth heading and 3 cards revealHeading first, shells next, internal UI last
6.70–7.25sCalculator section entersLeft copy and lime card reveal in parallel with 90ms offset
7.00–8.15sRevenue auto-increments and estimate appearsInterpolate numeric value; reveal estimate after 65% completion
8.15–9.35sUser drags range input back and forthImmediate value updates; no easing during drag
10.45–11.05sFAQ resolves from strong blurSingle section reveal; no per-line over-animation
11.0–12.6sAccordion items opened in sequenceCross-swap open panel using layout animation; plus/minus state updates immediately
12.8–13.5sTestimonial image scrolls into viewMedia reveals with y 28px and opacity only
14.8–15.35sAttribution and quote resolve over imageText stagger 70ms; blur 8px → 0
16.0–16.55sArticle heading/cards reveal3-card stagger around 100ms
16.9–17.55sExpert CTA resolvesCentered title, avatars, button; 80ms stagger
17.8–18.55sFooter entersWhole footer y 32px → 0; internal columns 70ms stagger
19.3–22.3sRapid reverse scroll to heroDo not animate exits; content remains stable during reverse scroll

6.4 Reusable reveal component — Framer Motion

'use client';

import { motion, type Variants } from 'framer-motion';
import { ReactNode } from 'react';

const easeOutExpo = [0.22, 1, 0.36, 1] as const;

const variants: Variants = {
  hidden: {
    opacity: 0,
    y: 34,
    filter: 'blur(12px)',
  },
  visible: {
    opacity: 1,
    y: 0,
    filter: 'blur(0px)',
    transition: {
      duration: 0.72,
      ease: easeOutExpo,
    },
  },
};

export function Reveal({
  children,
  delay = 0,
  amount = 0.22,
  className,
}: {
  children: ReactNode;
  delay?: number;
  amount?: number;
  className?: string;
}) {
  return (
    <motion.div
      className={className}
      variants={variants}
      initial="hidden"
      whileInView="visible"
      viewport={{ once: true, amount }}
      transition={{ delay }}
    >
      {children}
    </motion.div>
  );
}

For large text, avoid blur above 12px. For mobile, switch to 6–8px.

6.5 Staggered section container

const section = {
  hidden: {},
  visible: {
    transition: {
      staggerChildren: 0.095,
      delayChildren: 0.04,
    },
  },
};

const child = {
  hidden: { opacity: 0, y: 30, filter: 'blur(10px)' },
  visible: {
    opacity: 1,
    y: 0,
    filter: 'blur(0px)',
    transition: { duration: 0.72, ease: easeOutExpo },
  },
};

<motion.section
  variants={section}
  initial="hidden"
  whileInView="visible"
  viewport={{ once: true, amount: 0.2 }}
>
  <motion.h2 variants={child}>Access the growth capital you need, fast</motion.h2>
  <motion.div variants={child}>Card one</motion.div>
  <motion.div variants={child}>Card two</motion.div>
  <motion.div variants={child}>Card three</motion.div>
</motion.section>

6.6 Hero load choreography

const heroContainer = {
  hidden: {},
  visible: {
    transition: {
      delayChildren: 0.28,
      staggerChildren: 0.075,
    },
  },
};

const heroCopy = {
  hidden: { opacity: 0, y: 40, filter: 'blur(16px)' },
  visible: {
    opacity: 1,
    y: 0,
    filter: 'blur(0px)',
    transition: { duration: 0.72, ease: easeOutExpo },
  },
};

const dashboard = {
  hidden: { opacity: 0, y: 72, scale: 0.965, filter: 'blur(12px)' },
  visible: {
    opacity: 1,
    y: 0,
    scale: 1,
    filter: 'blur(0px)',
    transition: { delay: 0.02, duration: 0.8, ease: easeOutExpo },
  },
};

<motion.div variants={heroContainer} initial="hidden" animate="visible">
  <motion.h1 variants={heroCopy}>Build for fast moving business</motion.h1>
  <motion.p variants={heroCopy}>AI-first ERP powering next-gen finance & accounting.</motion.p>
  <motion.a variants={heroCopy}>Get started →</motion.a>
  <motion.div variants={dashboard}>…</motion.div>
</motion.div>

Hero background load

  • Do not fade the hero photograph from black.
  • Preload it and render it on first paint.
  • A tiny scale(1.015) → 1 over 1.2s is acceptable, but the recording does not require it.

6.7 Mini chart bars

const bars = [0.52, 0.78, 0.91, 0.66];

<div className="grid grid-cols-4 items-end gap-3">
  {bars.map((value, i) => (
    <motion.div
      key={i}
      className="origin-left rounded-sm bg-[var(--ink)] h-3"
      initial={{ scaleX: 0, opacity: 0 }}
      animate={{ scaleX: value, opacity: 1 }}
      transition={{
        delay: 0.68 + i * 0.075,
        duration: 0.5,
        ease: easeOutExpo,
      }}
    />
  ))}
</div>

Do not bounce the bars. They should feel like data populating, not a game animation.

6.8 Logo marquee

.logo-marquee {
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.logo-track {
  display: flex;
  width: max-content;
  gap: clamp(3rem, 5vw, 7rem);
  animation: logo-marquee 24s linear infinite;
  will-change: transform;
}
.logo-marquee:hover .logo-track,
.logo-marquee:focus-within .logo-track {
  animation-play-state: paused;
}
@keyframes logo-marquee {
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .logo-track { animation: none; flex-wrap: wrap; justify-content: center; }
}

Duplicate the exact logo list once; calculate track width so -50% is seamless.

6.9 Calculator count-up and slider

The recording shows an initial programmed count-up, followed by direct user dragging. Separate those behaviors.

'use client';

import { animate, motion, useMotionValue, useTransform } from 'framer-motion';
import { useEffect, useState } from 'react';

const money = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 2,
});

export function FundingCalculator() {
  const [revenue, setRevenue] = useState(0);
  const animatedRevenue = useMotionValue(0);
  const displayRevenue = useTransform(animatedRevenue, value => money.format(value));

  useEffect(() => {
    const controls = animate(animatedRevenue, 1544.52, {
      duration: 1.05,
      ease: [0.22, 1, 0.36, 1],
      onUpdate: latest => setRevenue(latest),
    });
    return controls.stop;
  }, [animatedRevenue]);

  const low = Math.round(revenue * 97) * 1000;
  const high = Math.round(revenue * 194) * 1000;

  return (
    <div className="rounded-[24px] bg-[var(--acid)] p-8 md:p-10">
      <h3 className="text-2xl">Calculations</h3>
      <div className="my-5 h-px bg-[var(--ink)]/15" />

      <label htmlFor="monthly-revenue" className="block text-lg">
        Your Monthly revenue
      </label>
      <motion.output className="numeric block text-5xl md:text-7xl font-medium">
        {displayRevenue}
      </motion.output>

      <input
        id="monthly-revenue"
        type="range"
        min="0"
        max="7000"
        step="0.01"
        value={revenue}
        onChange={event => {
          animatedRevenue.stop();
          const next = Number(event.currentTarget.value);
          animatedRevenue.set(next);
          setRevenue(next);
        }}
        className="funding-range"
        aria-describedby="funding-estimate"
      />

      <div className="my-7 h-px bg-[var(--ink)]/15" />
      <p>Your funding estimate</p>
      <output id="funding-estimate" aria-live="polite" className="numeric text-3xl md:text-5xl">
        ${low.toLocaleString()} – ${high.toLocaleString()}
      </output>
    </div>
  );
}
.funding-range {
  appearance: none;
  width: 100%;
  height: 44px;
  background: transparent;
  cursor: pointer;
}
.funding-range::-webkit-slider-runnable-track {
  height: 12px;
  background: color-mix(in srgb, var(--ink) 18%, transparent);
}
.funding-range::-webkit-slider-thumb {
  appearance: none;
  width: 28px;
  height: 40px;
  margin-top: -14px;
  border: 0;
  border-radius: 0; /* observed square thumb */
  background: var(--ink);
  box-shadow: none;
}
.funding-range:focus-visible::-webkit-slider-thumb {
  outline: 3px solid #fff;
  outline-offset: 3px;
}

During drag, values update synchronously. Do not spring or debounce the number.

6.10 FAQ accordion

'use client';

import { AnimatePresence, motion } from 'framer-motion';
import { useId, useState } from 'react';

const items = [
  {
    q: 'Who is eligible to apply for funding?',
    a: 'Any business with consistent revenue and a track record of sales is eligible to apply…',
  },
  {
    q: 'How quickly can I access the funds?',
    a: 'Once approved, funds are typically deposited within 24 hours.',
  },
  {
    q: 'Do I need to provide collateral or give up equity?',
    a: 'No. Our funding is non-dilutive and unsecured—you never give up equity.',
  },
  {
    q: 'Will applying affect my credit score?',
    a: 'Applying has no impact on your personal credit score…',
  },
];

export function Faq() {
  const [open, setOpen] = useState(0);
  const baseId = useId();

  return (
    <div>
      {items.map((item, index) => {
        const expanded = open === index;
        const panelId = `${baseId}-panel-${index}`;
        return (
          <div key={item.q} className="border-t border-[var(--acid)]/15">
            <button
              type="button"
              className="flex w-full items-center justify-between gap-6 py-6 text-left text-xl md:text-2xl"
              aria-expanded={expanded}
              aria-controls={panelId}
              onClick={() => setOpen(expanded ? -1 : index)}
            >
              <span>{item.q}</span>
              <span aria-hidden className="text-3xl leading-none">
                {expanded ? '−' : '+'}
              </span>
            </button>

            <AnimatePresence initial={false} mode="popLayout">
              {expanded && (
                <motion.div
                  id={panelId}
                  key="answer"
                  initial={{ height: 0, opacity: 0, filter: 'blur(5px)' }}
                  animate={{ height: 'auto', opacity: 1, filter: 'blur(0px)' }}
                  exit={{ height: 0, opacity: 0, filter: 'blur(4px)' }}
                  transition={{ duration: 0.42, ease: [0.25, 1, 0.5, 1] }}
                  className="overflow-hidden"
                >
                  <p className="max-w-3xl pb-7 text-lg text-[var(--acid)]/60">
                    {item.a}
                  </p>
                </motion.div>
              )}
            </AnimatePresence>
          </div>
        );
      })}
    </div>
  );
}

The plus/minus should update at click time. Height and answer opacity may overlap briefly during a rapid switch, matching the recording’s fluid transition.

6.11 Testimonial quote reveal

<motion.div
  className="absolute inset-x-0 bottom-0 p-6 md:p-12"
  initial="hidden"
  whileInView="visible"
  viewport={{ once: true, amount: 0.55 }}
  variants={{
    hidden: {},
    visible: { transition: { staggerChildren: 0.07 } },
  }}
>
  <motion.p variants={child} className="text-sm text-[var(--acid)]">
    Sarah Mitchell, Co. at BrightThreads
  </motion.p>
  <motion.blockquote variants={child} className="mt-3 max-w-5xl text-[var(--acid)] text-3xl md:text-5xl">
    “The funding process was seamless and transparent…”
  </motion.blockquote>
</motion.div>

Do not blur the entire image. Only the text resolves from a small blur; the apparent foreground blur is photographic depth of field.

6.12 Scroll progress thumb

Observed as a narrow acid-lime bar at the shell’s right edge.

'use client';

import { motion, useScroll, useSpring } from 'framer-motion';

export function ScrollProgress() {
  const { scrollYProgress } = useScroll();
  const scaleY = useSpring(scrollYProgress, {
    stiffness: 180,
    damping: 28,
    mass: 0.3,
  });

  return (
    <motion.div
      aria-hidden
      className="fixed right-[5vw] top-[12vh] z-50 h-[16vh] w-1 origin-top rounded-full bg-[var(--acid)]"
      style={{ scaleY }}
    />
  );
}

A true scrollbar thumb moves rather than scales. For closer fidelity, map scroll progress to translateY inside a fixed track. Keep it decorative and do not replace the browser scrollbar for accessibility.


7. Micro-interactions

7.1 Buttons

Observed buttons are pill-shaped, compact, and mostly dark olive or acid lime.

.button {
  min-height: 52px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 0 28px;
  border-radius: 999px;
  font-weight: 600;
  transition:
    transform 220ms cubic-bezier(.22,1,.36,1),
    background-color 220ms ease,
    color 220ms ease,
    box-shadow 220ms ease;
}
.button:hover { transform: translateY(-2px); }
.button:active { transform: translateY(0) scale(0.985); }
.button:focus-visible { outline: 3px solid var(--acid); outline-offset: 3px; }

Recommended states:

  • Acid primary: dark text; hover slightly reduce luminance and lift 2px.
  • Dark primary: acid or white text; hover to --ink-strong.
  • Outlined secondary: 1px olive at 18%; hover fills --mist.
  • Arrow icon: translate 3–4px right on hover, 220ms ease-out.

These hover details are not visibly demonstrated in the recording but match the system and should be implemented.

7.2 Cursor behavior

  • Default OS arrow is visible.
  • Pointer/hand appears on slider and accordion.
  • No custom trailing cursor, magnetic cursor, or cursor inversion is observed.
  • Do not introduce a custom cursor.

7.3 Cards

Recommended hover, where the card is a link:

.link-card {
  overflow: clip;
  transition: transform 320ms cubic-bezier(.22,1,.36,1);
}
.link-card img {
  transition: transform 600ms cubic-bezier(.22,1,.36,1), filter 400ms ease;
}
.link-card:hover { transform: translateY(-4px); }
.link-card:hover img { transform: scale(1.035); }

Keep hover movement subtle. Large 3D tilts would violate the original tone.

7.4 Smooth scrolling

Use native scrolling first. If using Lenis:

  • Duration/easing equivalent: 0.8–1.0s soft interpolation.
  • Keep wheel multiplier near 1.
  • Disable on reduced motion.
  • Sync Framer/GSAP updates on each Lenis RAF.
  • Never block Home/End/PageUp/PageDown, focus scrolling, or hash navigation.

7.5 Parallax and sticky behavior

  • No strong parallax is observed.
  • No section is visibly pinned.
  • A 4–8% image drift inside large media cards is acceptable, but optional.
  • Do not add scroll-jacked horizontal card rails.

8. Component patterns

8.1 PageShell

Responsibilities:

  • fixed background outside shell
  • rounded clipping
  • shadow
  • decorative scroll thumb
  • semantic <main> inside

8.2 PillNav

Structure:

<nav>
  <div class="nav-pill nav-links">…</div>
  <a class="brand">…</a>
  <div class="nav-actions">
    <div class="nav-pill account-actions">…</div>
    <button class="circle-menu">…</button>
  </div>
</nav>

8.3 StoryCard

Reusable for blue/dark product cards:

type StoryCardProps = {
  tone: 'sky' | 'lavender' | 'acid' | 'ink' | 'image';
  eyebrow?: string;
  title: string;
  body?: string;
  cta?: { label: string; href: string };
  media?: ReactNode;
};

Rules:

  • One visual idea per card.
  • Title is either top-left or bottom-left, not centered.
  • Internal UI panel uses white and 16px radius.
  • Card text should never compete with more than one miniature interface.

8.4 FeatureCardGrid

  • 3 columns on desktop.
  • Shared height.
  • Different widths/tones.
  • Reveal shell first and internal content second.
  • On mobile, stack with consistent 16–20px gaps.

8.5 FundingCalculator

  • Controlled range input.
  • Programmatic introductory animation only once.
  • Immediate response to user input.
  • Output values use tabular numerals.
  • Labels and live region required.

8.6 Accordion

  • Real <button> per question.
  • aria-expanded, aria-controls.
  • Only one item open at a time.
  • Height animation 420ms.
  • Plus/minus symbol remains aligned right.

8.7 TestimonialCarousel

Data model:

type Testimonial = {
  name: string;
  role: string;
  company: string;
  quote: string;
  image: string;
  imageAlt: string;
};
  • Autoplay is optional and should pause on hover/focus.
  • Minimum 6 seconds per slide.
  • Crossfade or 20px horizontal shift; no dramatic full-width swipe.
  • Dots are buttons with accessible labels.

8.8 ArticleCard

  • Entire card is a link.
  • Image, dark gradient, title, optional category/date.
  • Use semantic <article>.
  • Maintain consistent title area height.
  • Hover: 3.5% image scale, 4px card lift.

8.9 ExpertCTA

  • Centered copy.
  • Avatar cluster uses 28–34px circles with -6px overlap.
  • Button follows avatar cluster or sits beside it on desktop.
  • Gradient only in section background; no glowing button shadow.

8.10 InsetFooter

  • Dark olive rounded panel.
  • CSS grid; no absolute positioning except decorative marks.
  • Social buttons: 36–40px circles.
  • All links gain underlines or color shift on keyboard focus.

9. Tailwind foundation

// tailwind.config.ts
import type { Config } from 'tailwindcss';

export default {
  content: ['./app/**/*.{ts,tsx}', './components/**/*.{ts,tsx}'],
  theme: {
    extend: {
      colors: {
        ink: '#273000',
        'ink-strong': '#1f2700',
        acid: '#ddff5a',
        'acid-soft': '#efffb0',
        sky: '#cfe7e9',
        lavender: '#d9def8',
        mist: '#efeee9',
      },
      borderRadius: {
        shell: '2rem',
        section: '1.5rem',
        card: '1.25rem',
        ui: '1rem',
      },
      boxShadow: {
        shell: '0 24px 70px rgba(26, 34, 12, 0.18)',
        float: '0 18px 50px rgba(25, 31, 8, 0.18)',
        ui: '0 8px 24px rgba(25, 31, 8, 0.10)',
      },
      fontFamily: {
        sans: ['Inter', 'Helvetica Neue', 'Arial', 'sans-serif'],
        display: ['Inter Tight', 'Inter', 'Helvetica Neue', 'Arial', 'sans-serif'],
      },
      transitionTimingFunction: {
        'out-expo': 'cubic-bezier(0.22, 1, 0.36, 1)',
      },
    },
  },
  plugins: [],
} satisfies Config;

Reusable section classes:

@layer components {
  .section-pad {
    @apply px-5 py-20 md:px-10 md:py-28 xl:px-16 xl:py-36;
  }
  .display-xl {
    @apply font-display font-medium tracking-[-0.045em] leading-[0.98];
    font-size: clamp(3rem, 3.4vw, 4.25rem);
  }
  .pill {
    @apply inline-flex min-h-12 items-center justify-center rounded-full px-6 font-semibold;
  }
}

10. Performance requirements

10.1 Images

  • Hero: AVIF/WebP with responsive srcset; preload only the desktop-appropriate source.
  • Use fetchpriority="high" for hero only.
  • All below-fold images: lazy load and decode asynchronously.
  • Set width/height or aspect ratio to prevent layout shift.
  • Target hero image ≤ 350KB desktop where possible; individual card images ≤ 180KB.

10.2 Motion

  • Use will-change only while animating, not permanently on every element.
  • Avoid animating filter: blur() on full-viewport images. Blur only text/card groups and keep the radius ≤ 12–16px.
  • Prefer opacity + transform for mobile.
  • Do not animate box-shadow continuously.
  • A single smooth-scroll RAF plus Framer Motion is enough; do not run Lenis, GSAP ScrollSmoother, and native smooth behavior together.

10.3 React

  • Keep static sections server-rendered.
  • Isolate client components to nav menu, calculator, FAQ, testimonial carousel, and scroll progress.
  • Avoid rerendering the full page during slider movement.
  • Memoize formatted values if calculations become complex.

11. Accessibility requirements

  • Respect prefers-reduced-motion and switch reveal duration to near-zero or simple 150ms opacity.
  • Provide visible focus rings on all controls.
  • Maintain at least 4.5:1 contrast for body copy.
  • Do not rely on acid-lime text over white; use dark olive on lime or lime on dark olive.
  • Nav has a descriptive label; mobile menu button has aria-expanded.
  • Range input has a visible label and keyboard support.
  • Funding estimate uses aria-live="polite" but avoid announcing every tiny drag step; debounce screen-reader announcements by 200–300ms while keeping visual updates immediate.
  • FAQ uses semantic buttons and controlled regions.
  • Testimonial dots are buttons with labels such as “Show testimonial 2 of 3.”
  • Article cards need meaningful image alt text or empty alt when decorative.
  • Disable autoplay motion when the carousel has focus or when reduced motion is set.

Reduced-motion CSS:

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    scroll-behavior: auto !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

In Framer Motion, read useReducedMotion() and substitute { opacity: 0 } → { opacity: 1 } with no translation or blur.


12. Improvements beyond the original

12.1 Performance

  • The capture uses visible blur reveals on large text and card groups. Keep them, but cap desktop blur at 12px and mobile at 8px. Larger blur is expensive and creates muddy anti-aliasing.
  • Do not use a full-page backdrop filter. Restrict backdrop blur to the nav pills.
  • Replace a JS logo carousel with a CSS duplicated marquee unless logos are interactive.
  • Precompute calculator formulas and update with a controlled range; avoid rendering animation libraries on every input tick.

12.2 Accessibility

  • Preserve the decorative lime progress indicator but leave the native scrollbar available.
  • The square range thumb is visually distinctive but needs a larger invisible hit area and clear focus outline.
  • Accordion answers in the capture use low-contrast olive/lime. Increase answer opacity to at least 68–72% while preserving hierarchy.
  • Pause marquee/carousel on hover and focus.

12.3 Easing quality

  • Use cubic-bezier(0.22, 1, 0.36, 1) instead of generic ease for reveals.
  • Avoid spring physics for section entrances. It would make the page feel less editorial.
  • Use a 90–100ms stagger for cards; longer than 150ms feels theatrical and slows scanning.

12.4 Mobile behavior

  • Do not keep the desktop floating dashboard card overlapping the hero copy. Stack it below the CTA with 24px gap.
  • Replace the fixed forest background with a lightweight gradient or static cropped image on mobile.
  • Keep all CTA buttons at least 48px tall.
  • Convert the 3-card article grid to a snap rail only when it shortens the page meaningfully; otherwise stack.

12.5 Content clarity

  • The source combines finance, ERP, banking, and venture debt language. In a real rebuild, establish one primary product story and ensure each card reinforces it.
  • Keep the visually rich cards, but reduce copy duplication between hero, product overview, and growth section.

13. Build checklist

Visual

  • Fixed forest/cyan background surrounds a 90vw rounded white shell.
  • Dark olive and acid lime match #273000 and #ddff5a.
  • Display type is regular/medium grotesk with tight negative tracking.
  • Section spacing is generous and consistent.
  • Card radii use only the defined scale.
  • Shadows are broad and low contrast.

Layout

  • Hero has overlay nav, bottom-left copy, bottom-right dashboard.
  • Logo statement chip sits above a clipped marquee.
  • Product overview uses a 5/7 split.
  • Feature trio uses unequal widths with a wide photographic card.
  • Calculator and FAQ preserve desktop split layouts.
  • CTA and inset footer finish the page.

Motion

  • Hero begins after ~280ms, not instantly.
  • Copy reveals via opacity + y + blur; no bounce.
  • Dashboard card enters separately and chart bars populate after it.
  • In-view reveals run once.
  • Sibling stagger is 60–120ms.
  • Calculator count-up lasts roughly 1 second and drag updates immediately.
  • Accordion height transition lasts roughly 420ms.
  • Reverse scrolling shows stable content; no exit animations.

Quality

  • Reduced motion is implemented.
  • Focus states are visible.
  • Slider and accordion are keyboard operable.
  • Images are responsive and dimensioned.
  • No full-screen filter animation or continuous expensive effects.
  • Mobile removes awkward overlap and fixed-background cost.

14. Final reproduction rule

When generating a new landing page from this skill without the source video, preserve the following signature:

A rounded, framed white canvas floats over a quiet nature background. A photographic hero carries translucent pill navigation, a low-left editorial headline, and a floating product card. White space dominates the page, interrupted by olive and acid-lime sections, pastel product cards, and a live calculator. Every major element resolves once from slight blur and upward motion using an ease-out-expo curve. Interaction is direct and tactile; spectacle is restrained.

If a proposed design adds neon gradients, heavy glassmorphism, 3D tilt, elastic springs, scroll-jacked scenes, or dense dashboard chrome, reject it. Those choices are outside this visual and motion system.

Related Skills