"use client"; import Image from "next/image"; import { type CSSProperties, Fragment } from "react"; import { trackEmailClick, trackSocialClick } from "@/lib/analytics"; import { CONTACT_EMAIL, LINKEDIN_URL } from "@/lib/site-navigation"; import { HOME_SUBJECT } from "@/lib/whatsapp"; import { textLinkDark } from "./button-styles"; import ClientStrip, { type ClientLink } from "./ClientStrip"; import HeroField from "./cinematic/HeroField"; import { CONTACT_FORM_HASH } from "./contact-subject"; import { HERO_CTA_ID } from "./FloatingWhatsApp"; import HeroWork from "./HeroWork"; import HoverPrefetchLink from "./HoverPrefetchLink"; import { HERO_CAPTIONS } from "./hero-captions"; import WhatsAppLink from "./WhatsAppLink"; import { WhatsAppMark } from "./WhatsAppMark"; const SOCIAL_LINKS = [ { href: LINKEDIN_URL, label: "LinkedIn", onClick: () => trackSocialClick({ network: "linkedin" }), }, { href: `mailto:${CONTACT_EMAIL}`, label: "Email", onClick: () => trackEmailClick({ placement: "hero" }), }, ]; /** * Números reais, calculados em app/page.tsx (nada digitado à mão): os anos vêm de public/portfolio-data.json * e aparecem na mesma linha de "Já entregue para" (ClientStrip). */ export type HeroStats = { years?: number; }; /** O destaque em limão fica num trecho curto: "sob medida" (palavras 3 e 4). */ const ACCENT = new Set([3, 4]); type TitleWord = { word: string; key: string; index: number }; /** * Título em palavras para a entrada em cascata; o texto segue inteiro para leitores de tela e buscadores. As palavras * do destaque seguidas viram um trecho só: elas nunca se separam numa quebra de linha, e o bloco do marcador as cobre * de uma vez. */ const TITLE = "Sites e sistemas sob medida para o jeito que a sua empresa trabalha." .split(" ") .reduce<{ key: string; accent: boolean; words: TitleWord[] }[]>( (runs, word, index) => { const accent = ACCENT.has(index); // a mesma palavra se repete ("e"), então a posição entra na chave const entry = { word, key: `${word}-${index}`, index }; const last = runs.at(-1); if (accent && last?.accent) last.words.push(entry); else runs.push({ key: entry.key, accent, words: [entry] }); return runs; }, [], ); function TitleWords({ words, accent, }: { words: TitleWord[]; accent: boolean; }) { return words.map(({ word, key, index }, position) => ( {position > 0 && " "} {word} )); } export default function Hero({ stats, clients, }: { stats?: HeroStats; clients?: ClientLink[]; }) { return (
); }