// Group VIDA'S Digital Studios — landing components (v2: purple/black, modern sans) const { useState, useEffect, useRef } = React; // ---------- Primitives ---------- // Realistic Lisbon scene placeholder — SVG-composed skyline/landmark illustrations // No photos available; we compose stylised scene illustrations with purple duotone. const LisbonScene = ({ kind = "tejo", label, ratio = "16/9" }) => { const scenes = { // River Tejo + 25 de Abril bridge silhouette tejo: ( {/* sun */} {/* far hills */} {/* bridge towers */} {/* bridge cables */} {/* bridge deck */} {/* water */} {/* water reflections */} {[150, 160, 170, 180, 190, 200, 210].map((y, i) => ( ))} ), // Alfama rooftops alfama: ( {/* rooftops layered */} {[...Array(30)].map((_, i) => { const x = i * 14; const h = 40 + (i % 7) * 12; const y = 225 - h; return ( {/* roof triangle */} {/* windows */} {h > 60 && } {h > 80 && } ); })} {/* church spire */} ), // Eléctrico 28 tram on cobbled street tram: ( {/* buildings left */} {/* buildings right */} {/* windows glow */} {[[20,70],[20,110],[60,90],[60,140],[120,100],[120,150],[240,90],[240,140],[320,80],[320,130],[360,100]].map(([x,y],i)=>( ))} {/* street */} {/* tram rails */} {/* tram body */} {/* tram number */} 28 {/* pole */} ), // Aerial / drone shot over Baixa aerial: ( {/* grid streets */} {[0,1,2,3,4,5,6,7].map(i => ( ))} {[0,1,2,3,4,5,6,7,8,9,10].map(i => ( ))} {/* blocks */} {[...Array(40)].map((_, i) => { const x = 22 + (i % 10) * 36; const y = 32 + Math.floor(i / 10) * 26; return ; })} {/* drone reticle */} ), // Praça do Comércio arch praca: ( {/* arch */} {/* columns */} {/* top statue */} {/* ground */} {/* wings */} {[...Array(8)].map((_,i)=>)} {[...Array(8)].map((_,i)=>)} ), // Cais (dock) with boats cais: ( {/* far skyline */} {/* water */} {[...Array(12)].map((_,i) => ( ))} {/* boat silhouettes */} ), }; return (
{scenes[kind] || scenes.tejo} {label && (
{label}
)} {/* corner ticks */} {[["top","left"],["top","right"],["bottom","right"]].map(([v,h],i)=>(
))}
); }; // Logo mark — real brand logo const Logo = ({ size = 36 }) => ( Group VIDA'S ); const MonoLabel = ({ children, color }) => ( {children} ); // ---------- Nav ---------- const Nav = ({ onCta }) => { const [scrolled, setScrolled] = useState(false); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 40); window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); const links = [["serviços","services"],["trabalho","work"],["consultoria","consultoria"],["2026","stats"],["contacto","contact"]]; return ( ); }; // ---------- Hero ---------- // Animated purple orb + particles const HeroVisual = () => { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); let w, h, raf; const resize = () => { const r = canvas.getBoundingClientRect(); canvas.width = r.width * devicePixelRatio; canvas.height = r.height * devicePixelRatio; w = r.width; h = r.height; ctx.setTransform(devicePixelRatio,0,0,devicePixelRatio,0,0); }; resize(); window.addEventListener("resize", resize); const particles = Array.from({length: 60}, () => ({ x: Math.random()*1, y: Math.random()*1, vx: (Math.random()-0.5)*0.0004, vy: (Math.random()-0.5)*0.0004, r: Math.random()*1.6+0.4, })); let t = 0; const draw = () => { t += 0.005; ctx.clearRect(0,0,w,h); // orb glow const cx = w*0.55, cy = h*0.5; const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, Math.min(w,h)*0.55); grad.addColorStop(0, "rgba(138, 58, 208, 0.55)"); grad.addColorStop(0.4, "rgba(92, 30, 160, 0.25)"); grad.addColorStop(1, "rgba(10, 4, 21, 0)"); ctx.fillStyle = grad; ctx.fillRect(0,0,w,h); // concentric rings for (let i=0; i<6; i++) { const r = 40 + i*28 + Math.sin(t+i)*4; ctx.beginPath(); ctx.arc(cx, cy, r, 0, Math.PI*2); ctx.strokeStyle = `rgba(198, 240, 60, ${0.22 - i*0.03})`; ctx.lineWidth = 0.6; ctx.stroke(); } // rotating dashed ring ctx.save(); ctx.translate(cx, cy); ctx.rotate(t*2); ctx.beginPath(); ctx.arc(0,0, 110, 0, Math.PI*2); ctx.setLineDash([4, 10]); ctx.strokeStyle = "rgba(198,240,60,0.6)"; ctx.lineWidth = 1; ctx.stroke(); ctx.restore(); ctx.save(); ctx.translate(cx, cy); ctx.rotate(-t*1.3); ctx.beginPath(); ctx.arc(0,0, 170, 0, Math.PI*2); ctx.setLineDash([2, 18]); ctx.strokeStyle = "rgba(138,58,208,0.7)"; ctx.lineWidth = 1; ctx.stroke(); ctx.restore(); // particles particles.forEach(p => { p.x += p.vx; p.y += p.vy; if (p.x < 0 || p.x > 1) p.vx *= -1; if (p.y < 0 || p.y > 1) p.vy *= -1; ctx.beginPath(); ctx.arc(p.x*w, p.y*h, p.r, 0, Math.PI*2); ctx.fillStyle = `rgba(198,240,60,${0.2 + p.r*0.2})`; ctx.fill(); }); raf = requestAnimationFrame(draw); }; draw(); return () => { cancelAnimationFrame(raf); window.removeEventListener("resize", resize); }; }, []); return (
); }; const Hero = () => { const words = ["visíveis", "desejadas", "rentáveis"]; const [w, setW] = useState(0); useEffect(() => { const id = setInterval(() => setW(x => (x+1) % words.length), 2200); return () => clearInterval(id); }, []); return (
Estúdio · Portugal Continental · 2024 — 2026

Negócios locais
tornam-se marcas
{words[w]}.

Produção audiovisual, captação aérea com drone e gestão de presença digital para empresas locais e mediadores imobiliários em Portugal. Um estúdio. Três operações: Produção · Distribuição · Visibilidade.

{/* scroll indicator */}
↓ SCROLL 001 / 006
); }; // ---------- Marquee ---------- const Marquee = () => { const items = ["VÍDEO INSTITUCIONAL", "DRONE 4K", "GOOGLE BUSINESS", "LANDING PAGES", "META ADS", "VÍDEO TOUR IMOBILIÁRIO", "FOTOGRAFIA AÉREA", "STORYTELLING", "RETAINERS MENSAIS", "CONSULTORIA DIGITAL"]; return (
{[...items, ...items, ...items].map((it, i) => ( {it} ))}
); }; // ---------- Services ---------- const services = [ { num: "01", title: "Audiovisual Comercial", scene: "alfama", sceneLabel: "Alfama, Lisboa", short: "Vídeos que vendem percepção.", detail: "Institucionais, promocionais, storytelling de marca e conteúdo nativo para redes sociais. Direção criativa própria — do briefing ao entregável final.", items: ["Vídeos institucionais", "Promocionais", "Storytelling", "Reels & Shorts"], }, { num: "02", title: "Drone & Captação Aérea", scene: "aerial", sceneLabel: "Baixa · vista aérea", short: "Perspectiva que o concorrente não tem.", detail: "Fotografia e vídeo aéreo comercial, vídeos imobiliários, inspeções visuais e mapeamento. Equipamento certificado ANAC, operação com seguro.", items: ["Fotografia aérea 4K", "Vídeo imobiliário", "Inspeções visuais", "Mapeamento"], }, { num: "03", title: "Presença Digital Local", scene: "tram", sceneLabel: "Chiado · eléctrico 28", short: "Visibilidade onde o cliente procura.", detail: "Google Business otimizado, landing pages que convertem, funis simples de aquisição e conteúdo estratégico pensado para mercado local.", items: ["Google Business", "Landing pages", "Funis de aquisição", "Conteúdo SEO local"], }, { num: "04", title: "Imobiliário", scene: "tejo", sceneLabel: "Tejo · 25 de Abril", short: "Anúncios que fecham visitas.", detail: "Vídeo tour de imóveis, fotografia profissional, vídeos de impacto para anúncios e branding visual para mediadores. Vendemos o imóvel antes da visita.", items: ["Vídeo tour", "Fotografia profissional", "Anúncios de impacto", "Branding mediadores"], }, ]; const ServiceRow = ({ s, open, onToggle }) => (

{s.detail}

    {s.items.map(it => (
  • {it}
  • ))}
); const Services = () => { const [openIdx, setOpenIdx] = useState(0); return (
§ 01

Quatro pilares. Uma operação.

O mercado separa videomaker, marketing e drone em silos. Nós juntamos os três — produção, distribuição e visibilidade — num só estúdio.

{services.map((s, i) => ( setOpenIdx(openIdx === i ? -1 : i)}/> ))}
); }; // ---------- Consultoria (phased roadmap) ---------- const phases = [ { n: "FASE 01", dur: "30 MIN · GRATUITO", t: "Diagnóstico digital", d: "Sessão inicial por videochamada. Mapeamos a presença atual — Google Business, redes sociais, website, concorrência local. Saem um relatório visual e três hipóteses de ganho imediato.", bullets: ["Auditoria de visibilidade", "Análise de concorrentes locais", "Identificação de 3 oportunidades prioritárias"], scene: "praca", sceneLabel: "Praça do Comércio", }, { n: "FASE 02", dur: "SEMANA 1", t: "Plano editorial & estratégia", d: "Desenhamos um calendário de produção mensal alinhado ao funil do negócio: atração, autoridade e conversão. Definimos formatos, tom e pilares de conteúdo específicos para o segmento.", bullets: ["Calendário editorial 90 dias", "Pilares de conteúdo & narrativa", "Métricas de sucesso acordadas"], scene: "alfama", sceneLabel: "Alfama", }, { n: "FASE 03", dur: "2 – 3 DIAS", t: "Produção no terreno", d: "Dias de captação com equipa completa: vídeo, drone e fotografia na mesma sessão. Optimizamos deslocações e logística para extrair volume útil de conteúdo para 30 a 60 dias.", bullets: ["Vídeo multicâmara", "Captação aérea ANAC", "Fotografia editorial & still"], scene: "tram", sceneLabel: "Chiado", }, { n: "FASE 04", dur: "CONTÍNUO", t: "Distribuição & tráfego", d: "Publicação calendarizada, optimização do perfil Google Business, SEO local, e — quando o plano inclui — gestão de anúncios Meta e Google para o bairro ou cidade onde o negócio está.", bullets: ["Publicação multicanal", "Google Business contínuo", "Meta Ads geolocalizado"], scene: "aerial", sceneLabel: "Vista aérea · Baixa", }, { n: "FASE 05", dur: "MENSAL", t: "Relatório & iteração", d: "Revisão mensal: alcance, contactos gerados, custo por lead, evolução face ao mês anterior. Iteramos sobre dados, nunca sobre achismo. Ajustamos formatos, horários e foco geográfico.", bullets: ["Painel de métricas", "Revisão estratégica mensal", "Iteração com base em dados"], scene: "cais", sceneLabel: "Cais do Sodré", }, ]; const Consultoria = () => { const [active, setActive] = useState(0); return (
§ 02

Consultoria fase a fase.

Um processo claro, executado mês a mês. Começa com um diagnóstico gratuito e evolui até um sistema recorrente de aquisição — sem projeto único, sem surpresas.

{/* phase list */}
{phases.map((p, i) => ( ))}
{/* active detail */}
{phases[active].n}

{phases[active].t}

{phases[active].d}

    {phases[active].bullets.map(b => (
  • {b}
  • ))}
{/* CTA within consultoria */}
PRÓXIMO PASSO
Fase 01 — diagnóstico gratuito, 30 minutos.
Marcar agora
); }; // ---------- Portfolio ---------- const portfolio = [ { title: "Restaurante à beira-rio", segment: "local", scene: "tejo", meta: "VÍDEO + STILLS · 00:48", location: "Doca de Santo Amaro" }, { title: "Empreendimento residencial", segment: "imobiliário", scene: "aerial", meta: "DRONE + TOUR · 02:04", location: "Parque das Nações" }, { title: "Clínica boutique", segment: "local", scene: "alfama", meta: "BRANDING + FOTOGRAFIA", location: "Príncipe Real" }, { title: "Apartamento de charme", segment: "imobiliário", scene: "tram", meta: "VÍDEO TOUR · 01:12", location: "Bairro Alto" }, { title: "Ginásio urbano", segment: "local", scene: "praca", meta: "REEL MENSAL + ADS", location: "Baixa-Chiado" }, { title: "Villa com vista", segment: "imobiliário", scene: "cais", meta: "AERIAL + CAMPANHA", location: "Cascais" }, ]; const Portfolio = () => { const [filter, setFilter] = useState("tudo"); const filters = ["tudo", "imobiliário", "local"]; const shown = portfolio.filter(p => filter === "tudo" || p.segment === filter); return (
§ 03

Trabalho selecionado

{filters.map(f => ( ))}
{shown.map((p, i) => { const span = i % 5 === 0 ? 4 : i % 5 === 1 ? 2 : i % 5 === 2 ? 3 : i % 5 === 3 ? 3 : 2; return (
{ const img = e.currentTarget.querySelector(".ph"); if (img) img.style.transform = "scale(1.02)"; }} onMouseLeave={e => { const img = e.currentTarget.querySelector(".ph"); if (img) img.style.transform = "scale(1)"; }} >
= 4 ? "21/9" : span === 3 ? "4/3" : "3/4"}/>
{p.title}
{p.segment}
{p.meta}
); })}
); }; // ---------- Stats 2026 ---------- const Stats2026 = () => { const stats = [ { big: "87%", label: "dos portugueses pesquisam um negócio online antes de o visitar", src: "Marktest Digital" }, { big: "6h 42m", label: "tempo médio diário de utilização de internet em Portugal em 2026", src: "We Are Social PT" }, { big: "72%", label: "dos consumidores locais confiam mais em empresas com vídeo", src: "Wyzowl 2026" }, { big: "+184%", label: "crescimento do consumo de vídeo vertical em Portugal (2024 → 2026)", src: "Meta for Business" }, { big: "3.2×", label: "mais pedidos de contacto em perfis Google Business com fotos profissionais", src: "Google Business Insights" }, { big: "8 seg", label: "é o tempo médio de atenção de um visitante num anúncio imobiliário", src: "Idealista Labs" }, ]; // animated bars return (
{/* faint grid bg */}
§ 04

Portugal digital 2026.

LIVE · ATUALIZADO Q1 2026
{/* main chart strip */}
Consumo de vídeo em Portugal · 2022 → 2026 (índice)
{/* grid */} {[0,1,2,3,4].map(i => ( ))} {/* bars */} {[ ["2022", 45], ["2023", 62], ["2024", 84], ["2025", 118], ["2026", 160], ].map(([y, v], i) => { const x = 40 + i * 155; const h = (v/180) * 140; return ( +{v}% {y} ); })} {/* trend line */} {[75,230,385,540,695].map((x, i) => )}
{/* stat tiles */}
{stats.map((s, i) => (
{s.big}
{s.label}
Fonte · {s.src}
))}
); }; // ---------- Contact ---------- const Contact = () => { const [form, setForm] = useState({ nome: "", empresa: "", email: "", segmento: "local", mensagem: "" }); const [sent, setSent] = useState(false); const [errors, setErrors] = useState({}); const submit = (e) => { e.preventDefault(); const errs = {}; if (!form.nome.trim()) errs.nome = "obrigatório"; if (!form.email.includes("@")) errs.email = "email inválido"; if (!form.mensagem.trim()) errs.mensagem = "obrigatório"; setErrors(errs); if (Object.keys(errs).length === 0) setSent(true); }; const field = (key, label, type = "text") => ( ); return (
§ 05 · contacto

Vamos construir
a sua visibilidade.

{[ ["WhatsApp direto", "+351 933 137 204", "https://wa.me/351933137204"], ["Email", "group.vidas@gmail.com", "mailto:group.vidas@gmail.com"], ["Instagram", "@groupvidas.negocios", "https://instagram.com/groupvidas.negocios"], ["Operação", "Portugal Continental · Rubens Ruan, gestor", null], ].map(([l, v, h]) => (
{l}
{h ? {v} :
{v}
}
))}
{sent ? (
✓ pedido recebido
Obrigado, {form.nome.split(" ")[0]}.

Respondemos em 24h úteis. Entretanto, pode adiantar por WhatsApp.

) : (
{field("nome", "Nome")} {field("empresa", "Empresa (opcional)")} {field("email", "Email", "email")}