Design Lounge
Install

Nº 120 of 520

Light fintech landing with tilting card

A warm-paper business banking landing page: serif headline, a CSS debit card that tilts toward the pointer with a moving glare, trust stats, feature rows and a cobalt CTA.

Preview

Open full size
1280 × 800 · 18.6 KB · 241 lines

Use it

Free to use · credit appreciated

1 Once, in your project

npx skills add SusanAcharya/Design-Lounge

2 Then ask

Using the Design Lounge skill, build "Light fintech landing with tilting card" (piece landing-fintech-light) in my stack. Match its brief; restyle it onto my product's theme.

No skill? Paste the brief instead. It carries the numbers, tokens and behaviour.

Brief

208 lines

Build brief for a coding agent. Rebuild this piece in the reader’s stack. If they haven’t said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don’t “improve” them.

What it is

The landing page for Quire, a fictional business-banking product for small companies. Top to bottom: a light nav, a hero with a 92px Instrument Serif headline beside a debit card built entirely in CSS, a four-up trust-stat band, two alternating feature rows with miniature product UI, a centred serif testimonial, a cobalt CTA panel and a compliance footer. The page should feel like a calm, expensive stationery shop, not a crypto app. What makes it worth copying is the card. It sits in 3D on a faint 48px grid, floats gently at rest, and turns to follow the pointer with a soft-light glare that tracks the cursor. Three finish swatches recolour it.

Reference behaviour

  1. Initial state: top of the page. The nav, the “New 4.10% APY” pill, the three-line headline (“Business banking / that keeps the / books for you.” with the italic words in cobalt), the lede, the email signup and the full stat band are visible within 800px.
  2. At rest the card is posed at rotateX(8deg) rotateY(-16deg) rotateZ(-4deg) and floats 10px up and down on a 6s alternate loop. Two white notification chips bob 8px on 5s and 5.5s loops (the second is delayed 0.8s).
  3. Move the pointer over the hero’s right-hand stage: the float pauses and the card tilts toward the pointer. rotateY ranges ±14deg across the stage width and rotateX ±11deg across its height. It follows on an 80ms linear transition, and the glare highlight moves to the pointer position.
  4. Pointer leaves the stage: the card eases back to its resting pose over 500ms (expo out) and the float resumes.
  5. Click a finish swatch (Graphite, Cobalt, Bone): the card gradient and text colour cross-fade over 500ms; the pressed swatch gets a 2px ink ring and aria-pressed="true".
  6. Focus the email field: the pill-shaped signup gets a cobalt border plus a 4px --accent-soft halo. Submitting does nothing (demo).
  7. Scroll: the feature rows alternate copy-left/UI-right, then UI-left/copy-right. The testimonial sits between two hairlines and the CTA panel is a 28px-radius cobalt block with concentric rings in the top-right.

Structure

1280 × 800                                               page height ≈ 2730px
┌────────────────────────────────────────────────────────────────────────┐
│ ◯ Quire   Accounts Cards Tax vault Pricing Customers   Log in [Open an account] │ 72
├───────────────────────────────┬────────────────────────────────────────┤
│ (New) 4.10% APY…              │  ┌ Invoice #1042 paid ┐   48px grid,  │
│ Business banking     92px     │  └────────────────────┘   radial mask │
│ that keeps the                │        ╱▔▔▔▔▔▔▔▔▔▔▔▔▔▔╲  380×240 card │
│ books for you.                │       │ Quire  BUSINESS·DEBIT │ 3D   │
│ lede 19px / 460               │       │ ▣ chip                │      │
│ [ you@company.com  (Get started) ] │  │ 4417 2290 0183 6025   │      │
│ fine print 13px               │        ╲______________________╱      │
│                               │ Finish ● ● ●   ┌ +$1,240 to Tax vault ┐│
├───────────┬───────────┬───────┴───┬────────────────────────────────────┤
│ 48,000    │ $2.1B     │ $5M       │ 4.9          stats: 52px serif     │
└───────────┴───────────┴───────────┴────────────────────────────────────┘
below: feature row (copy | transactions UI) · feature row (vault UI | copy)
       testimonial 48px serif centred · cobalt CTA 72px · footer disclosures
hero grid 1.05fr 1fr, gap 24 · stage 540px tall · gutter 72px
  • <nav aria-label="Main">: logo (serif wordmark with a 18px ring mark), links, two pill buttons.
  • <header class="hero">: left column (.pill, h1, .lede, form.signup, .fine); right column .stage with perspective: 1100px.
  • .stage::before holds the grid and white bloom, masked to fade at its edges. Chips and swatches sit above it unmasked.
  • .card[aria-label]: .top (wordmark + tier), .chipc (EMV chip from gradients and two pseudo-element hairlines), .num, .bot (holder name, expiry, two overlapping circles).
  • .stats four-column grid with left hairlines between items.
  • .rows > two section.row; .row.rev .copy { order: 2 } swaps sides.
  • section.quote > blockquote + .who; section.cta; <footer>.

Tokens

:root {
  /* surfaces */
  --bg: #f5f3ee;          /* warm paper page */
  --surface: #fffdfa;     /* cards, chips, inputs */
  --surface-2: #ece9e1;   /* tags, meter tracks, ghost hover */
  --line: #e0dcd2;
  --line-2: #cbc6ba;
  /* text */
  --ink: #15171c;
  --ink-2: #575a62;
  --ink-3: #8b8d93;
  /* accent */
  --accent: #2f4bff;      /* cobalt */
  --accent-2: #2238d6;    /* hover */
  --accent-soft: #e3e7ff; /* focus halo, icon tiles */
  --pos: #1f7a4d;         /* incoming money */
  /* card finish (swapped by JS) */
  --card-a: #2a2c31;  --card-b: #15161a;  --card-ink: #e9e6df;
  /* type */
  --serif: "Instrument Serif", Georgia, serif;
  --sans: "Hanken Grotesk", system-ui, sans-serif;
  /* layout */
  --gutter: 72px;
  --r: 12px;  --r-lg: 20px;  --r-card: 18px;  --r-panel: 28px;
  /* elevation */
  --shadow-card: 0 40px 60px -30px rgba(21,23,28,.45), 0 12px 24px -12px rgba(21,23,28,.25);
  --shadow-chip: 0 10px 30px -12px rgba(21,23,28,.25);
  /* motion */
  --t-fast: 160ms;
  --t-tilt: 500ms;
  --t-follow: 80ms;
  --float: 6s;
  --ease: cubic-bezier(.2, .7, .2, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
}

Finishes: Graphite #2a2c31 → #15161a / ink #e9e6df; Cobalt #4560ff → #1c2fc4 / ink #f3f4ff; Bone #efe9dc → #d6cfbf / ink #2a2c31.

Typography

RoleFamilySizeWeightLine-heightTrackingCase
Hero h1Instrument Serif92px4000.94−0.025emsentence; italic cobalt emphasis
Section h2Instrument Serif56px4001.0−0.02emsentence; one italic word
CTA h2Instrument Serif72px4001.0−0.02emsentence, white
TestimonialInstrument Serif48px4001.12−0.015emsentence, curly quotes
Stat valueInstrument Serif52px4001−0.02emnumerals
LogoInstrument Serif28px4001−0.01em—
LedeHanken Grotesk19px4001.50sentence
BodyHanken Grotesk16–17px4001.550sentence
KickerHanken Grotesk13px6001+0.14emUPPERCASE cobalt
Card numberHanken Grotesk19px5001+0.16emtabular numerals
Card metaHanken Grotesk11–12px4001.3+0.06–0.14emUPPERCASE

Motion

ElementTriggerPropertyFrom → ToDurationEasing
Cardidletranslate0 → −10px, alternate6s loop--ease
Chips .f1 / .f2idletranslate0 → −8px, alternate5s / 5.5s (+0.8s delay)--ease
Cardpointermove on stagerotateX / rotateYpointer-mapped, ±11° / ±14°80mslinear (tracking)
Glare ::beforepointermoveradial-gradient centrefollows pointer %80mslinear
Cardpointerleavetransform→ resting pose500ms--ease-out
Cardswatch clickbackground, colorfinish A → B500ms--ease
Buttonshover / activebackground; scale→ hover colour; 1 → .98160ms--ease

Reduced motion: no float, no bob, and pointer tracking is not attached; the card stays in its resting pose. Swatches still work (1ms).

States

  • Primary dark button: --ink fill, hover #2b2e36. Cobalt button: hover --accent-2. Ghost: hover --surface-2.
  • Active (pressed): scale(.98).
  • Focus-visible: 2px cobalt outline, 3px offset, 8px radius. The signup uses :focus-within for its border and halo instead.
  • Swatch selected: box-shadow: 0 0 0 2px var(--ink) (2px page-coloured border inside keeps a gap); unselected 0 0 0 1px var(--line-2).
  • Live tilt: .stage.live swaps the card’s transition to 80ms linear and removes the float animation.
  • Amounts: outgoing in --ink with a true minus (U+2212); incoming --pos with a plus.

Accessibility

  • The card is a div with aria-label="Quire business card"; its number and chip are aria-hidden so screen readers don’t read a fake PAN.
  • Swatches are <button aria-pressed> with names (Graphite, Cobalt, Bone) inside role="group" aria-label="Card finish".
  • Email input has a visually hidden <label>; the submit is a real <button type="submit">.
  • Tilt is pointer-only decoration; nothing depends on it.
  • Contrast: --ink-2 on --bg 6.6:1; --ink-3 (3.3:1) is used only for 13px fine print and placeholders. Pair it with --ink-2 if your audit requires 4.5:1. White on cobalt 6.9:1.

Responsive rules

  • ≥ 1280: as specified.
  • 1024–1279: h1 76px; stage 460px tall; card 330×208; stats stay 4-up.
  • 768–1023: hero stacks, stage below the copy at 420px; stats 2×2; feature rows stack with the UI below the copy (order reset); CTA single column.
  • < 640: gutter 20px; nav collapses to logo + “Open an account”; h1 52px; card 300×190 with tilt disabled (no hover on touch); testimonial 30px; CTA h2 44px with 32px padding.

Acceptance checklist

  • The headline is three lines at 1280 with “keeps the books” italic and #2f4bff.
  • The full stat band is visible above 800px.
  • The card is 380×240 with an 18px radius, built only from CSS (no images), including the EMV chip.
  • At rest the card floats 10px on a 6s loop; while hovered the float stops.
  • Pointer tilt maps to at most ±14° Y and ±11° X, and the glare follows the pointer.
  • On pointer leave the card returns to rotateX(8deg) rotateY(-16deg) rotateZ(-4deg) over 500ms.
  • The three swatches recolour the card and update aria-pressed.
  • The grid behind the card fades out at its edges while chips and swatches stay fully opaque.
  • The signup shows a cobalt border and 4px soft halo on focus.
  • Feature rows alternate sides; vault meters render as 6px bars.
  • The footer carries a “not a bank” disclosure.
  • With reduced motion nothing moves, but every section is complete.

Implementation notes

Tilt from pointer position. Map the pointer’s position within the stage to custom properties and let CSS do the transform:

stage.addEventListener('pointermove', e => {
  const r = stage.getBoundingClientRect();
  const x = (e.clientX - r.left) / r.width, y = (e.clientY - r.top) / r.height;
  stage.classList.add('live');
  card.style.setProperty('--ry', ((x - .5) * 28).toFixed(2) + 'deg');
  card.style.setProperty('--rx', ((.5 - y) * 22).toFixed(2) + 'deg');
  card.style.setProperty('--gx', x * 100 + '%');
  card.style.setProperty('--gy', y * 100 + '%');
});
stage.addEventListener('pointerleave', () => {
  stage.classList.remove('live');
  ['--rx', '--ry', '--gx', '--gy'].forEach(p => card.style.removeProperty(p));
});

Two transition speeds on one element. The resting pose eases slowly; live tracking must be nearly instant or the card feels laggy:

.card { transform: rotateX(var(--rx)) rotateY(var(--ry)) rotateZ(-4deg);
        transition: transform 500ms var(--ease-out);
        animation: float 6s var(--ease) infinite alternate; }
.stage.live .card { transition: transform 80ms linear; animation: none; }
@keyframes float { to { translate: 0 -10px; } }

Use the individual translate property for the float so it composes with transform instead of overwriting the tilt.

Glare and brushed texture are two pseudo-elements: a pointer-centred radial gradient in mix-blend-mode: soft-light, and a 115° repeating stripe at 3.5% white.

.card::before { content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: radial-gradient(circle at var(--gx) var(--gy), rgba(255,255,255,.28), transparent 45%);
  mix-blend-mode: soft-light; }

Common mistakes: masking the whole stage, which also fades the chips and swatches (mask a ::before instead); forgetting transform-style: preserve-3d so the translateZ on the number and chip has no parallax; using a straight quote " in the 48px testimonial.

Details

Palette
Type
Instrument Serif · Hanken Grotesk
Motion
Subtle motion
Build
One session
Designed bySusan AcharyaKathmandu

Studied

Stripe

Let one big moving thing carry the colour. Keep the words light and the cards real.

All sources