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
Use it
Free to use · credit appreciated1 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.
<!-- Design Lounge Nº 120 · "Light fintech landing with tilting card" · www.designlounge.live -->
# Light fintech landing with tilting card
> **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
… 168 more lines. Copy or download for the full brief. Loading the source…Brief
208 linesBuild 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
- 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.
- 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). - 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.
- Pointer leaves the stage: the card eases back to its resting pose over 500ms (expo out) and the float resumes.
- 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". - Focus the email field: the pill-shaped signup gets a cobalt border plus a 4px
--accent-softhalo. Submitting does nothing (demo). - 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.stagewithperspective: 1100px..stage::beforeholds 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)..statsfour-column grid with left hairlines between items..rows> twosection.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
| Role | Family | Size | Weight | Line-height | Tracking | Case |
|---|---|---|---|---|---|---|
| Hero h1 | Instrument Serif | 92px | 400 | 0.94 | −0.025em | sentence; italic cobalt emphasis |
| Section h2 | Instrument Serif | 56px | 400 | 1.0 | −0.02em | sentence; one italic word |
| CTA h2 | Instrument Serif | 72px | 400 | 1.0 | −0.02em | sentence, white |
| Testimonial | Instrument Serif | 48px | 400 | 1.12 | −0.015em | sentence, curly quotes |
| Stat value | Instrument Serif | 52px | 400 | 1 | −0.02em | numerals |
| Logo | Instrument Serif | 28px | 400 | 1 | −0.01em | — |
| Lede | Hanken Grotesk | 19px | 400 | 1.5 | 0 | sentence |
| Body | Hanken Grotesk | 16–17px | 400 | 1.55 | 0 | sentence |
| Kicker | Hanken Grotesk | 13px | 600 | 1 | +0.14em | UPPERCASE cobalt |
| Card number | Hanken Grotesk | 19px | 500 | 1 | +0.16em | tabular numerals |
| Card meta | Hanken Grotesk | 11–12px | 400 | 1.3 | +0.06–0.14em | UPPERCASE |
Motion
| Element | Trigger | Property | From → To | Duration | Easing |
|---|---|---|---|---|---|
| Card | idle | translate | 0 → −10px, alternate | 6s loop | --ease |
Chips .f1 / .f2 | idle | translate | 0 → −8px, alternate | 5s / 5.5s (+0.8s delay) | --ease |
| Card | pointermove on stage | rotateX / rotateY | pointer-mapped, ±11° / ±14° | 80ms | linear (tracking) |
Glare ::before | pointermove | radial-gradient centre | follows pointer % | 80ms | linear |
| Card | pointerleave | transform | → resting pose | 500ms | --ease-out |
| Card | swatch click | background, color | finish A → B | 500ms | --ease |
| Buttons | hover / active | background; scale | → hover colour; 1 → .98 | 160ms | --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:
--inkfill, 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-withinfor its border and halo instead. - Swatch selected:
box-shadow: 0 0 0 2px var(--ink)(2px page-coloured border inside keeps a gap); unselected0 0 0 1px var(--line-2). - Live tilt:
.stage.liveswaps the card’s transition to 80ms linear and removes the float animation. - Amounts: outgoing in
--inkwith a true minus (U+2212); incoming--poswith a plus.
Accessibility
- The card is a
divwitharia-label="Quire business card"; its number and chip arearia-hiddenso screen readers don’t read a fake PAN. - Swatches are
<button aria-pressed>with names (Graphite, Cobalt, Bone) insiderole="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-2on--bg6.6:1;--ink-3(3.3:1) is used only for 13px fine print and placeholders. Pair it with--ink-2if 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 (
orderreset); 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
- Tags
Studied
StripeLet one big moving thing carry the colour. Keep the words light and the cards real.
All sourcesOn the shelves