// scenes-portrait.jsx — Terra hero reel, portrait (1080×1920) edition // Relies on globals from scenes.jsx + animations.jsx: // TERRA, SANS, MONO, HUD, Sprite, useTime, clamp, Easing // ───────────────────────── Scene 1P: Cold Open (portrait) ───────────────────── function SceneColdOpenP({ start, end }) { return ( {({ localTime, duration }) => { const logoP = clamp((localTime - 0.4) / 0.9, 0, 1); const logoEased = Easing.easeOutExpo(logoP); const subP = clamp((localTime - 1.6) / 0.7, 0, 1); const exitP = clamp((localTime - 3.5) / 0.5, 0, 1); const exitY = Easing.easeInCubic(exitP) * -30; const exitOp = 1 - exitP; const lineOffset = localTime * 20; return (
{/* Diagonal stripe field */}
{/* Scanning line */}
{/* Main stack */}
{/* Eyebrow */}
— A DIGITAL GROWTH AGENCY —
{/* Wordmark — masked reveal */}
TERRA.
{/* Lime underline */}
{/* Subtitle */}
Your long-term growth partner.
); }} ); } // ───────────────────────── Scene 2P: Manifesto (portrait) ───────────────────── function SceneManifestoP({ start, end }) { return ( {({ localTime, duration }) => { const words = [ { text: 'REAL', sub: 'PEOPLE.', t: 0.2, accent: false }, { text: 'REAL', sub: 'RESULTS.', t: 1.5, accent: false }, { text: 'NO', sub: 'BS.', t: 2.8, accent: true }, ]; const exitP = clamp((localTime - (duration - 0.55)) / 0.5, 0, 1); const exitOp = 1 - exitP; return (
{/* Horizontal guide lines (rotated vertical for portrait) */}
{words.map((w, i) => { const wp = clamp((localTime - w.t) / 0.35, 0, 1); const eased = Easing.easeOutExpo(wp); const slideX = (1 - eased) * -80; return (
0{i + 1}
{w.text}
{w.sub}
); })} {/* Underline + caption */}
We don't win unless you do.
); }} ); } // Local counter helper (mirrors the one in scenes.jsx) function _CounterP({ from, to, suffix = '', prefix = '', duration, t, fixed = 0 }) { const p = clamp(t / duration, 0, 1); const eased = Easing.easeOutExpo(p); const v = from + (to - from) * eased; const display = fixed > 0 ? v.toFixed(fixed) : Math.round(v).toString(); return `${prefix}${display}${suffix}`; } // ───────────────────────── Scene 3P: Stats (portrait) ───────────────────────── function SceneStatsP({ start, end }) { return ( {({ localTime, duration }) => { const stats = [ { label: 'CLIENTS SERVED', from: 0, to: 150, suffix: '+', countDur: 1.9, startAt: 0.4 }, { label: 'AVG. ROI INCREASE', from: 0, to: 3.2, suffix: 'x', fixed: 1, countDur: 1.9, startAt: 0.8 }, { label: 'AI SUPPORT', from: 0, to: 24, suffix: '/7', countDur: 1.9, startAt: 1.2 }, { label: 'CLIENT RETENTION', from: 0, to: 98, suffix: '%', countDur: 1.9, startAt: 1.6 }, ]; const headerP = clamp(localTime / 0.7, 0, 1); const exitP = clamp((localTime - (duration - 0.6)) / 0.5, 0, 1); const globalOp = 1 - exitP; return (
{/* Header */}
THE NUMBERS — RECEIPTS, NOT PROMISES
{/* Stats grid — 2x2 for portrait */}
{stats.map((s, i) => { const localT = Math.max(0, localTime - s.startAt); const appearP = clamp((localTime - (s.startAt - 0.1)) / 0.3, 0, 1); const isRight = i % 2 === 1; const isBottomRow = i >= 2; return (
0{i + 1} / 04
{_CounterP({ from: s.from, to: s.to, suffix: s.suffix, duration: s.countDur, t: localT, fixed: s.fixed || 0, })}
{s.label}
); })}
{/* Bar visualizer */}
{Array.from({ length: 28 }, (_, i) => { const phase = (localTime * 2 + i * 0.15) % (Math.PI * 2); const h = 24 + Math.abs(Math.sin(phase)) * 24; const op = clamp((localTime - 0.4) / 0.8, 0, 1); return (
); })}
); }} ); } // ───────────────────────── Scene 4P: Results (portrait) ─────────────────────── function SceneResultsP({ start, end }) { return ( {({ localTime, duration }) => { const results = [ { metric: '$127K', label: 'TRACKED REVENUE', client: 'SUMMIT ROOFING', detail: 'Cold account → 3.8x ROAS in 90 days' }, { metric: '+340%', label: 'ORGANIC ENQUIRIES', client: 'LUXE SKIN CLINIC', detail: 'Booked 6 weeks out in 90 days' }, { metric: '4.1x', label: 'RETURN ON AD SPEND', client: 'CLEARPATH LAW', detail: '4x consultations, same budget' }, { metric: '−61%', label: 'COST PER LEAD', client: 'LOANBRIDGE FINANCIAL',detail: 'Half the cost, twice the quality' }, { metric: '#1', label: '14 LOCAL KEYWORDS', client: 'NESTFINDER REALTY', detail: 'Organic > paid in 4 months' }, { metric: '0', label: 'MISSED CALLS — EVER', client: 'PRESTIGE HOME SVCS', detail: '15 lost calls/day → 0', hold: true }, ]; const cardDur = 1.15; const lastCardBonus = 0.9; const totalCards = results.length; const regularSpan = (totalCards - 1) * cardDur; let currentIdx, cardLocal, effectiveDur; if (localTime < regularSpan) { currentIdx = Math.floor(localTime / cardDur); cardLocal = localTime - currentIdx * cardDur; effectiveDur = cardDur; } else { currentIdx = totalCards - 1; cardLocal = localTime - regularSpan; effectiveDur = cardDur + lastCardBonus; } currentIdx = clamp(currentIdx, 0, totalCards - 1); const cardP = clamp(cardLocal / effectiveDur, 0, 1); const r = results[currentIdx]; const isLast = currentIdx === totalCards - 1; const pulse = isLast ? (1 + Math.sin(cardLocal * 5) * 0.04) : 1; const headerP = clamp(localTime / 0.5, 0, 1); const exitP = clamp((localTime - (duration - 0.5)) / 0.5, 0, 1); const globalOp = 1 - exitP; return (
{/* Header */}
PROVEN RESULTS
{/* Stacked card — metric on top, client detail below */}
{/* Top: huge metric */}
CASE #{String(currentIdx + 1).padStart(2, '0')} / 0{results.length}{isLast ? ' · FINAL' : ''}
{r.metric}
{r.label}
{/* Bottom: client detail (full width, no left border) */}
CLIENT
{r.client}
{r.detail}
{/* Progress pips */}
{results.map((_, i) => (
))}
); }} ); } // ───────────────────────── Scene 5P: CTA (portrait) ─────────────────────────── function SceneCTAP({ start, end }) { return ( {({ localTime, duration }) => { const p1 = clamp(localTime / 0.7, 0, 1); const p2 = clamp((localTime - 0.7) / 0.8, 0, 1); const p3 = clamp((localTime - 1.8) / 0.7, 0, 1); const p4 = clamp((localTime - 2.8) / 0.7, 0, 1); const p5 = clamp((localTime - 3.9) / 0.6, 0, 1); const pulse = 1 + Math.sin(localTime * 4) * 0.02; return (
{/* Gradient glow */}
{/* Grid */}
{/* Eyebrow */}
→ READY TO GROW?
{/* Headline */}
Let's find out
if we fit.
{/* Subtitle */}
Free strategy call. No commitment. No pressure.
{/* CTA button (full-width) */}
BOOK A FREE CALL
{/* Contact info */}
DMITRIDEFREITAS.COM
BASED IN BARBADOS
{/* Final sign-off logo */}
TERRA.
— WE DON'T WIN UNLESS YOU DO
); }} ); } Object.assign(window, { SceneColdOpenP, SceneManifestoP, SceneStatsP, SceneResultsP, SceneCTAP, });