Usa questo codice React e rendilo funzionante import { useEffect, useRef, useState } from “react”; import * as THREE from “three”; // ── DATA ────────────────────────────────────────────────────────────── const SERVICES = [ { icon: “⚡”, title: “ATOMO FIBRA”, desc: “Pura fibra ottica fino a casa”, specs: “↓ 1 Gbps · ↑ 300 Mbps”, badge: “da €23,95/mese”, accent: “#00e5ff” }, { icon: “📡”, title: “ATOMO RURAL”, desc: “FWA proprietaria per aree rurali”, specs: “↓ 100 Mbps · ↑ 20 Mbps”, badge: “da €29,95/mese”, accent: “#4dffb4” }, { icon: “🏢”, title: “BUSINESS”, desc: “Connettività senza compromessi”, specs: “↓ 2.5 Gbps · ↑ 1 Gbps”, badge: “SLA dedicato”, accent: “#ffd166” }, { icon: “☁️”, title: “CENTRALINO CLOUD”, desc: “VoIP e Centralino InCloud”, specs: “Scalabile · Affidabile”, badge: “Per la tua azienda”, accent: “#ff6b9d” }, { icon: “🔗”, title: “CORPORATE”, desc: “Dark Fiber & IP Transit”, specs: “Layer 2 · Housing · Cloud”, badge: “Su misura”, accent: “#a78bfa” }, { icon: “🏛️”, title: “WHOLESALE | PA”, desc: “Partner Open Fiber certificato”, specs: “Sicilia e tutta Italia”, badge: “Pubblica Amministrazione”, accent: “#fb923c” }, ]; const STATS = [ { end: 2.5, decimals: 1, unit: “Gbps”, label: “Download FIBRA PLUS” }, { end: 1, decimals: 0, unit: “Gbps”, label: “Upload FIBRA PLUS” }, { end: 365, decimals: 0, unit: “gg”, label: “Assistenza dedicata” }, { end: 2010,decimals: 0, unit: “”, label: “Anno di fondazione” }, ]; const TOWNS = [ “Borgetto”,“Partinico”,“Terrasini”,“Balestrate”,“Trappeto”, “Carini”,“Alcamo”,“Castellammare”,“Villagrazia di Carini”, “Torretta”,“Isola delle Femmine”,“Cinisi”,“Montelepre”, “Giardinello”,“Sagana”,“San Vito Lo Capo”, ]; // ── UTILS ───────────────────────────────────────────────────────────── const loadScript = (src) => new Promise((res) => { if (document.querySelector(`script[src="${src}"]`)) return res(); const s = document.createElement(“script”); s.src = src; s.onload = res; document.head.appendChild(s); }); // ── CORNER ACCENT ───────────────────────────────────────────────────── const corners = { topLeft: { top:-1, left:-1, borderWidth:“1px 0 0 1px” }, topRight: { top:-1, right:-1, borderWidth:“1px 1px 0 0” }, bottomLeft: { bottom:-1, left:-1, borderWidth:“0 0 1px 1px” }, bottomRight: { bottom:-1, right:-1, borderWidth:“0 1px 1px 0” }, }; const CornerAccents = ({ color = “#00e5ff” }) => Object.entries(corners).map(([k, v]) => ( <div key={k} style={{ position:“absolute”, width:18, height:18, borderColor:color, borderStyle:“solid”, opacity:0.5, …v }} /> )); // ── MAIN COMPONENT ───────────────────────────────────────────────────── export default function AtomoNetworksCinematic() { const canvasRef = useRef(null); const [countersActive, setCountersActive] = useState(false); const [counts, setCounts] = useState([0, 0, 0, 0]); // ── THREE.JS SCENE ────────────────────────────────────────────────── useEffect(() => { const W = window.innerWidth, H = window.innerHeight; ``` const renderer = new THREE.WebGLRenderer({ canvas: canvasRef.current, antialias: true }); renderer.setSize(W, H); renderer.setPixelRatio(Math.min(devicePixelRatio, 2)); renderer.setClearColor(0x020c1a); const scene = new THREE.Scene(); scene.fog = new THREE.FogExp2(0x020c1a, 0.016); const camera = new THREE.PerspectiveCamera(55, W / H, 0.1, 200); camera.position.set(0, 0, 10); // — Nodes — const nodeGeo = new THREE.SphereGeometry(0.07, 8, 8); const nodeCount = 70; const nodePos = []; const nodeMeshes = []; for (let i = 0; i < nodeCount; i++) { const p = new THREE.Vector3( (Math.random() - 0.5) * 30, (Math.random() - 0.5) * 20, (Math.random() - 0.5) * 14 ); nodePos.push(p); const mat = new THREE.MeshBasicMaterial({ color: Math.random() > 0.5 ? 0x00e5ff : 0x1b7fd6, transparent: true, opacity: 0.8, }); const m = new THREE.Mesh(nodeGeo, mat); m.position.copy(p); scene.add(m); nodeMeshes.push(m); } // — Edges — for (let i = 0; i < nodeCount; i++) { for (let j = i + 1; j < nodeCount; j++) { const d = nodePos[i].distanceTo(nodePos[j]); if (d < 7) { const geo = new THREE.BufferGeometry().setFromPoints([nodePos[i], nodePos[j]]); const hue = 0.54 + Math.random() * 0.08; const col = new THREE.Color().setHSL(hue, 1, 0.55); const mat = new THREE.LineBasicMaterial({ color: col, transparent: true, opacity: (1 - d / 7) * 0.35 }); scene.add(new THREE.Line(geo, mat)); } } } // — Particle field — const PC = 5000; const pp = new Float32Array(PC * 3); const pc = new Float32Array(PC * 3); for (let i = 0; i < PC; i++) { pp[i*3] = (Math.random()-0.5)*55; pp[i*3+1] = (Math.random()-0.5)*42; pp[i*3+2] = (Math.random()-0.5)*28; const r = Math.random(); if (r < 0.55) { pc[i*3]=0.1; pc[i*3+1]=0.55; pc[i*3+2]=1.0; } else if (r < 0.82) { pc[i*3]=0; pc[i*3+1]=0.9; pc[i*3+2]=1.0; } else { pc[i*3]=0.3; pc[i*3+1]=1.0; pc[i*3+2]=0.7; } } const pGeo = new THREE.BufferGeometry(); pGeo.setAttribute("position", new THREE.BufferAttribute(pp, 3)); pGeo.setAttribute("color", new THREE.BufferAttribute(pc, 3)); const pMat = new THREE.PointsMaterial({ size: 0.045, vertexColors: true, transparent: true, opacity: 0.6, blending: THREE.AdditiveBlending, depthWrite: false, }); const particles = new THREE.Points(pGeo, pMat); scene.add(particles); // — Scroll tracking — let scrollY = 0, smoothScroll = 0; const onScroll = () => { scrollY = window.scrollY; }; window.addEventListener("scroll", onScroll, { passive: true }); // — Render loop — let raf; const clock = new THREE.Clock(); const render = () => { raf = requestAnimationFrame(render); const t = clock.getElapsedTime(); smoothScroll += (scrollY - smoothScroll) * 0.045; const sp = smoothScroll / Math.max(document.documentElement.scrollHeight - innerHeight, 1); // Cinematic camera dolly camera.position.z = 10 - sp * 5; camera.position.y = -sp * 2.5; camera.lookAt(0, -sp * 1.5, 0); // Particle drift particles.rotation.y = t * 0.022 + sp * 0.7; particles.rotation.x = Math.sin(t * 0.012) * 0.06; // Node pulse nodeMeshes.forEach((m, i) => { const pulse = Math.sin(t * 1.5 + i * 0.38) * 0.5 + 0.5; m.material.opacity = 0.35 + pulse * 0.6; const sc = 0.75 + pulse * 0.5; m.scale.set(sc, sc, sc); }); renderer.render(scene, camera); }; render(); // — Resize — const onResize = () => { const w = innerWidth, h = innerHeight; camera.aspect = w / h; camera.updateProjectionMatrix(); renderer.setSize(w, h); }; window.addEventListener("resize", onResize); // — GSAP + ScrollTrigger — loadScript("https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js") .then(() => loadScript("https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js")) .then(() => { const { gsap, ScrollTrigger } = window; gsap.registerPlugin(ScrollTrigger); // Hero entrance gsap.from("#hero-eye", { opacity:0, scale:0.4, duration:1.2, ease:"back.out(2)", delay:0.2 }); gsap.from("#hero-title", { opacity:0, y:80, duration:1.5, ease:"power4.out", delay:0.5 }); gsap.from("#hero-sub", { opacity:0, y:40, duration:1.2, ease:"power3.out", delay:1.0 }); gsap.from("#hero-cta", { opacity:0, y:30, duration:1.0, ease:"power3.out", delay:1.4 }); // Parallax: hero content moves up on scroll gsap.to("#hero-content", { y: -220, ease:"none", scrollTrigger: { trigger:"#hero-section", start:"top top", end:"bottom top", scrub:1.5 }, }); // Section reveals document.querySelectorAll(".reveal").forEach((el) => { gsap.from(el, { opacity:0, y:80, duration:1.15, ease:"power3.out", scrollTrigger: { trigger:el, start:"top 78%", toggleActions:"play none none reverse" }, }); }); // Service cards stagger gsap.from(".svc-card", { opacity:0, y:60, scale:0.85, duration:0.75, ease:"back.out(1.6)", stagger:0.09, scrollTrigger: { trigger:"#services-section", start:"top 72%" }, }); // Town pills stagger gsap.from(".town-pill", { opacity:0, scale:0.6, duration:0.38, stagger:0.045, ease:"back.out(2)", scrollTrigger: { trigger:"#territory-section", start:"top 72%" }, }); // Stats counter trigger ScrollTrigger.create({ trigger:"#stats-section", start:"top 65%", onEnter: () => setCountersActive(true), }); // Depth parallax layers document.querySelectorAll(".parallax-bg").forEach((el) => { const speed = parseFloat(el.dataset.speed || "0.3"); gsap.to(el, { y: () => (parseFloat(el.dataset.dist || "80")) * speed, ease:"none", scrollTrigger: { trigger:el.parentElement, start:"top bottom", end:"bottom top", scrub:true }, }); }); }); return () => { cancelAnimationFrame(raf); window.removeEventListener("scroll", onScroll); window.removeEventListener("resize", onResize); renderer.dispose(); }; ``` }, []); // ── COUNTER ANIMATION ─────────────────────────────────────────────── useEffect(() => { if (!countersActive) return; STATS.forEach((stat, i) => { const dur = 2400; const start = performance.now(); const tick = (now) => { const p = Math.min((now - start) / dur, 1); const ease = 1 - Math.pow(1 - p, 3); setCounts((prev) => { const n=[…prev]; n[i]=ease*stat.end; return n; }); if (p < 1) requestAnimationFrame(tick); }; setTimeout(() => requestAnimationFrame(tick), i * 190); }); }, [countersActive]); const fmt = (val, stat) => stat.decimals === 0 ? Math.round(val).toLocaleString(“it-IT”) : val.toFixed(stat.decimals); // ── RENDER ────────────────────────────────────────────────────────── return ( <div style={{ background:”#020c1a”, color:”#e8f0ff”, fontFamily:”‘DM Sans’,system-ui,sans-serif”, overflowX:“hidden”, position:“relative” }}> ``` {/* ── Global CSS ── */} <style>{` @import url('https://fonts.googleapis.com/css2?family=Rajdhani:wght@300;500;600;700&family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;1,9..40,300&display=swap'); *,*::before,*::after{box-sizing:border-box;margin:0;padding:0;} @keyframes orbit { from{transform:rotate(0deg) translateX(30px) rotate(0deg);} to{transform:rotate(360deg) translateX(30px) rotate(-360deg);} } @keyframes orbit2 { from{transform:rotate(90deg) translateX(22px) rotate(-90deg);} to{transform:rotate(450deg) translateX(22px) rotate(-450deg);} } @keyframes glow-pulse { 0%,100%{box-shadow:0 0 22px #00e5ff33,0 0 70px #00e5ff0d;} 50%{box-shadow:0 0 44px #00e5ff55,0 0 120px #00e5ff18;} } @keyframes data-flow { 0%{background-position:0% 50%;} 50%{background-position:100% 50%;} 100%{background-position:0% 50%;} } @keyframes bounce-y { 0%,100%{transform:translateX(-50%) translateY(0);} 50%{transform:translateX(-50%) translateY(12px);} } @keyframes line-grow { from{scaleY:0;} to{scaleY:1;} } @keyframes scan { 0%{transform:translateY(-100%);} 100%{transform:translateY(100vh);} } .svc-card{transition:transform 0.3s ease,box-shadow 0.3s ease;} .svc-card:hover{transform:translateY(-8px) scale(1.025)!important;} .town-pill{transition:transform 0.2s ease,background 0.2s ease;cursor:default;} .town-pill:hover{transform:scale(1.06);} a{text-decoration:none;} `}</style> {/* ── THREE.JS canvas (fixed bg) ── */} <canvas ref={canvasRef} style={{ position:"fixed", inset:0, zIndex:0, width:"100%", height:"100%" }} /> {/* Vignette overlay */} <div style={{ position:"fixed", inset:0, zIndex:1, pointerEvents:"none", background:"radial-gradient(ellipse 75% 75% at 50% 40%, transparent 25%, rgba(2,12,26,0.6) 100%)", }}/> {/* Scan line (ambiance) */} <div style={{ position:"fixed", top:0, left:0, width:"100%", height:"2px", zIndex:2, background:"linear-gradient(90deg, transparent, rgba(0,229,255,0.07), transparent)", animation:"scan 8s linear infinite", pointerEvents:"none", }}/> {/* ════════════════ CONTENT ════════════════ */} <div style={{ position:"relative", zIndex:3 }}> {/* ════ HERO ════ */} <section id="hero-section" style={{ height:"100vh", display:"flex", flexDirection:"column", alignItems:"center", justifyContent:"center", textAlign:"center", padding:"0 24px", position:"relative" }}> <div id="hero-content"> {/* Animated atom icon */} <div id="hero-eye" style={{ marginBottom:36, display:"inline-flex", alignItems:"center", justifyContent:"center", position:"relative", width:80, height:80 }}> <div style={{ width:80, height:80, borderRadius:"50%", border:"1px solid rgba(0,229,255,0.35)", animation:"glow-pulse 3s ease-in-out infinite", display:"flex", alignItems:"center", justifyContent:"center", background:"radial-gradient(circle, rgba(0,229,255,0.06), transparent)", }}> <span style={{ fontSize:32, filter:"drop-shadow(0 0 8px #00e5ff)" }}>⚛</span> </div> <div style={{ position:"absolute", width:9, height:9, borderRadius:"50%", background:"#00e5ff", boxShadow:"0 0 12px #00e5ff", animation:"orbit 3.5s linear infinite" }}/> <div style={{ position:"absolute", width:6, height:6, borderRadius:"50%", background:"#4dffb4", boxShadow:"0 0 8px #4dffb4", animation:"orbit2 2.2s linear infinite" }}/> </div> {/* Eyebrow */} <p style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:12, letterSpacing:"0.55em", color:"#00e5ff", textTransform:"uppercase", marginBottom:20 }}> Borgetto · Palermo · Sicilia · Est. 2010 </p> {/* Title */} <h1 id="hero-title" style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:"clamp(48px,9.5vw,108px)", fontWeight:700, letterSpacing:"0.04em", lineHeight:0.92, background:"linear-gradient(120deg,#ffffff 0%,#7dd3fc 35%,#00e5ff 65%,#4dffb4 100%)", WebkitBackgroundClip:"text", WebkitTextFillColor:"transparent", backgroundClip:"text", backgroundSize:"200% 100%", animation:"data-flow 7s ease infinite", marginBottom:22, }}> ATOMO<br/>NETWORKS </h1> <p id="hero-sub" style={{ fontFamily:"'DM Sans',sans-serif", fontSize:"clamp(15px,2vw,20px)", color:"rgba(200,220,255,0.65)", lineHeight:1.65, maxWidth:460, margin:"0 auto 48px", letterSpacing:"0.01em", }}> La vera Fibra Ottica per privati e aziende. <br/>Veloce · Efficiente · Sicura. </p> <div id="hero-cta" style={{ display:"flex", gap:14, justifyContent:"center", flexWrap:"wrap" }}> <a href="https://atomonetworks.com/verifica-copertura-internet/" target="_blank" rel="noreferrer" style={{ padding:"14px 34px", background:"linear-gradient(135deg,#00e5ff,#1b7fd6)", color:"#020c1a", fontFamily:"'Rajdhani',sans-serif", fontWeight:700, fontSize:15, letterSpacing:"0.14em", textTransform:"uppercase", clipPath:"polygon(12px 0%,100% 0%,calc(100% - 12px) 100%,0% 100%)", boxShadow:"0 0 40px rgba(0,229,255,0.25)", }}> ⚡ Verifica Copertura </a> <a href="https://atomonetworks.com/" target="_blank" rel="noreferrer" style={{ padding:"13px 30px", background:"transparent", border:"1px solid rgba(0,229,255,0.45)", color:"#00e5ff", fontFamily:"'Rajdhani',sans-serif", fontWeight:600, fontSize:15, letterSpacing:"0.12em", textTransform:"uppercase", clipPath:"polygon(12px 0%,100% 0%,calc(100% - 12px) 100%,0% 100%)", }}> Scopri di più → </a> </div> </div> {/* Scroll indicator */} <div style={{ position:"absolute", bottom:32, left:"50%", animation:"bounce-y 2.5s ease-in-out infinite", display:"flex", flexDirection:"column", alignItems:"center", gap:8 }}> <div style={{ width:1, height:52, background:"linear-gradient(to bottom,rgba(0,229,255,0.7),transparent)" }}/> <span style={{ fontSize:10, letterSpacing:"0.35em", color:"rgba(0,229,255,0.4)", textTransform:"uppercase", fontFamily:"'Rajdhani',sans-serif" }}>scroll</span> </div> </section> {/* ════ MANIFESTO ════ */} <section style={{ minHeight:"55vh", display:"flex", alignItems:"center", padding:"100px 24px", position:"relative" }}> <div className="parallax-bg" data-speed="0.25" data-dist="60" style={{ position:"absolute", inset:0, background:"radial-gradient(ellipse 60% 50% at 30% 60%,rgba(27,127,214,0.06),transparent)", pointerEvents:"none" }}/> <div className="reveal" style={{ maxWidth:900, margin:"0 auto", textAlign:"center", padding:"64px 48px", background:"rgba(255,255,255,0.025)", border:"1px solid rgba(0,229,255,0.1)", backdropFilter:"blur(24px)", position:"relative" }}> <CornerAccents/> <p style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:11, letterSpacing:"0.55em", color:"#00e5ff", textTransform:"uppercase", marginBottom:28 }}>La nostra missione</p> <h2 style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:"clamp(30px,5vw,58px)", fontWeight:700, lineHeight:1.15, color:"#fff", marginBottom:28 }}> Connessione per{" "} <span style={{ background:"linear-gradient(90deg,#00e5ff,#4dffb4)", WebkitBackgroundClip:"text", WebkitTextFillColor:"transparent", backgroundClip:"text" }}> passione </span> </h2> <p style={{ fontFamily:"'DM Sans',sans-serif", fontSize:"clamp(14px,1.7vw,18px)", color:"rgba(200,220,255,0.6)", lineHeight:1.85, maxWidth:660, margin:"0 auto 40px" }}> Dal 2010, Atomo Networks porta la vera fibra ottica nelle case e nelle aziende della Sicilia occidentale. Certificati ISO 9001:2015, offriamo assistenza dedicata 365 giorni l'anno con un team giovane, altamente qualificato e ambizioso. </p> <div style={{ display:"inline-flex", alignItems:"center", gap:10, padding:"9px 22px", border:"1px solid rgba(255,209,102,0.4)", background:"rgba(255,209,102,0.05)" }}> <span style={{ fontSize:18 }}>🏅</span> <span style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:13, letterSpacing:"0.22em", color:"#ffd166", textTransform:"uppercase" }}>Certificazione ISO 9001:2015</span> </div> </div> </section> {/* ════ STATS ════ */} <section id="stats-section" style={{ padding:"80px 24px" }}> <div className="reveal" style={{ maxWidth:1100, margin:"0 auto" }}> <p style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:11, letterSpacing:"0.55em", color:"#00e5ff", textTransform:"uppercase", textAlign:"center", marginBottom:64 }}> I numeri di Atomo </p> <div style={{ display:"grid", gridTemplateColumns:"repeat(auto-fit,minmax(220px,1fr))", gap:2 }}> {STATS.map((stat, i) => ( <div key={i} style={{ padding:"44px 24px", textAlign:"center", background:"rgba(255,255,255,0.025)", border:"1px solid rgba(0,229,255,0.08)", position:"relative", overflow:"hidden" }}> <div style={{ position:"absolute", inset:0, background:`radial-gradient(ellipse 80% 60% at 50% 0%,rgba(0,229,255,${i===0?"0.06":"0.03"}),transparent)`, pointerEvents:"none" }}/> <div style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:"clamp(46px,7vw,76px)", fontWeight:700, lineHeight:1, background:"linear-gradient(135deg,#fff,#00e5ff)", WebkitBackgroundClip:"text", WebkitTextFillColor:"transparent", backgroundClip:"text" }}> {fmt(counts[i], stat)} </div> {stat.unit && ( <div style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:17, letterSpacing:"0.2em", color:"#00e5ff", textTransform:"uppercase", marginTop:4, marginBottom:10 }}>{stat.unit}</div> )} <div style={{ fontFamily:"'DM Sans',sans-serif", fontSize:13, color:"rgba(180,200,230,0.5)", letterSpacing:"0.04em", marginTop: stat.unit ? 0 : 14 }}>{stat.label}</div> </div> ))} </div> </div> </section> {/* ════ SERVICES ════ */} <section id="services-section" style={{ padding:"100px 24px", position:"relative" }}> <div className="parallax-bg" data-speed="0.2" data-dist="80" style={{ position:"absolute", inset:0, background:"radial-gradient(ellipse 50% 60% at 70% 50%,rgba(27,127,214,0.05),transparent)", pointerEvents:"none" }}/> <div style={{ maxWidth:1200, margin:"0 auto", position:"relative" }}> <div className="reveal" style={{ textAlign:"center", marginBottom:70 }}> <p style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:11, letterSpacing:"0.55em", color:"#00e5ff", textTransform:"uppercase", marginBottom:20 }}>I nostri servizi</p> <h2 style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:"clamp(32px,5vw,60px)", fontWeight:700, color:"#fff" }}> Ogni esigenza,<br/> <span style={{ background:"linear-gradient(90deg,#1b7fd6,#00e5ff,#4dffb4)", WebkitBackgroundClip:"text", WebkitTextFillColor:"transparent", backgroundClip:"text" }}> una soluzione Atomo </span> </h2> </div> <div style={{ display:"grid", gridTemplateColumns:"repeat(auto-fit,minmax(310px,1fr))", gap:16 }}> {SERVICES.map((svc, i) => ( <div key={i} className="svc-card" style={{ padding:"38px 30px", background:"rgba(255,255,255,0.03)", border:`1px solid ${svc.accent}22`, backdropFilter:"blur(12px)", position:"relative", overflow:"hidden" }}> {/* Glow spot */} <div style={{ position:"absolute", top:-20, right:-20, width:130, height:130, background:`radial-gradient(circle,${svc.accent}18,transparent 70%)`, borderRadius:"50%", pointerEvents:"none" }}/> {/* Top accent line */} <div style={{ position:"absolute", top:0, left:0, right:0, height:2, background:`linear-gradient(90deg,transparent,${svc.accent}66,transparent)` }}/> <span style={{ fontSize:34, display:"block", marginBottom:20, filter:`drop-shadow(0 0 10px ${svc.accent}66)` }}>{svc.icon}</span> <h3 style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:20, fontWeight:700, letterSpacing:"0.1em", color:svc.accent, textTransform:"uppercase", marginBottom:12 }}>{svc.title}</h3> <p style={{ fontFamily:"'DM Sans',sans-serif", fontSize:15, color:"rgba(200,220,255,0.78)", marginBottom:12, lineHeight:1.55 }}>{svc.desc}</p> <p style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:12, letterSpacing:"0.2em", color:"rgba(180,200,230,0.4)", textTransform:"uppercase", marginBottom:20 }}>{svc.specs}</p> <div style={{ display:"inline-block", padding:"6px 16px", background:`${svc.accent}18`, border:`1px solid ${svc.accent}44`, fontFamily:"'Rajdhani',sans-serif", fontSize:13, color:svc.accent, letterSpacing:"0.1em", textTransform:"uppercase" }}> {svc.badge} </div> </div> ))} </div> </div> </section> {/* ════ TERRITORY ════ */} <section id="territory-section" style={{ padding:"100px 24px" }}> <div style={{ maxWidth:1000, margin:"0 auto" }}> <div className="reveal" style={{ textAlign:"center", marginBottom:60 }}> <p style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:11, letterSpacing:"0.55em", color:"#00e5ff", textTransform:"uppercase", marginBottom:20 }}>Copertura del territorio</p> <h2 style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:"clamp(28px,4.5vw,52px)", fontWeight:700, color:"#fff", marginBottom:20 }}> Radicati nella<br/> <span style={{ background:"linear-gradient(90deg,#00e5ff,#4dffb4)", WebkitBackgroundClip:"text", WebkitTextFillColor:"transparent", backgroundClip:"text" }}> Sicilia occidentale </span> </h2> <p style={{ fontFamily:"'DM Sans',sans-serif", fontSize:"clamp(14px,1.7vw,17px)", color:"rgba(180,200,230,0.55)", maxWidth:520, margin:"0 auto", lineHeight:1.8 }}> Dalla sede di Borgetto, portiamo la connessione ultrabroadband in tutto il territorio palermitano e trapanese. Partner Open Fiber su tutta la Sicilia e Italia. </p> </div> <div style={{ display:"flex", flexWrap:"wrap", gap:10, justifyContent:"center" }}> {TOWNS.map((town, i) => ( <div key={i} className="town-pill" style={{ padding:"9px 20px", background: town==="Borgetto" ? "rgba(0,229,255,0.1)" : "rgba(255,255,255,0.04)", border:`1px solid ${town==="Borgetto" ? "rgba(0,229,255,0.5)" : "rgba(255,255,255,0.1)"}`, fontFamily:"'Rajdhani',sans-serif", fontSize:14, letterSpacing:"0.12em", color: town==="Borgetto" ? "#00e5ff" : "rgba(200,220,255,0.65)", textTransform:"uppercase", }}> {town==="Borgetto" ? "📍 " : ""}{town} </div> ))} </div> </div> </section> {/* ════ CTA ════ */} <section style={{ padding:"130px 24px", textAlign:"center", position:"relative" }}> <div style={{ position:"absolute", top:"50%", left:"50%", transform:"translate(-50%,-50%)", width:"65vw", height:"65vw", maxWidth:750, maxHeight:750, background:"radial-gradient(circle,rgba(27,127,214,0.07),transparent 70%)", borderRadius:"50%", pointerEvents:"none" }}/> <div style={{ position:"absolute", top:"50%", left:"50%", transform:"translate(-50%,-50%)", width:"35vw", height:"35vw", maxWidth:400, maxHeight:400, background:"radial-gradient(circle,rgba(0,229,255,0.05),transparent 70%)", borderRadius:"50%", pointerEvents:"none" }}/> <div className="reveal" style={{ position:"relative" }}> <p style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:11, letterSpacing:"0.55em", color:"#00e5ff", textTransform:"uppercase", marginBottom:28 }}>Inizia subito</p> <h2 style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:"clamp(36px,7.5vw,88px)", fontWeight:700, lineHeight:1.0, marginBottom:28, background:"linear-gradient(120deg,#fff 0%,#7dd3fc 45%,#00e5ff 100%)", WebkitBackgroundClip:"text", WebkitTextFillColor:"transparent", backgroundClip:"text", }}> Pronto a navigare<br/>alla massima potenza? </h2> <p style={{ fontFamily:"'DM Sans',sans-serif", fontSize:"clamp(14px,1.8vw,18px)", color:"rgba(180,200,230,0.55)", marginBottom:52, maxWidth:500, margin:"0 auto 52px", lineHeight:1.75 }}> Installazione inclusa, Router WiFi 6 incluso, assistenza 365 giorni l'anno. Scopri se sei coperto dalla nostra rete. </p> <a href="https://atomonetworks.com/verifica-copertura-internet/" target="_blank" rel="noreferrer" style={{ display:"inline-block", padding:"17px 44px", background:"linear-gradient(135deg,#00e5ff,#1b7fd6)", color:"#020c1a", fontFamily:"'Rajdhani',sans-serif", fontWeight:700, fontSize:18, letterSpacing:"0.14em", textTransform:"uppercase", clipPath:"polygon(14px 0%,100% 0%,calc(100% - 14px) 100%,0% 100%)", boxShadow:"0 0 60px rgba(0,229,255,0.3)", marginBottom:64, }}> ⚡ Verifica Copertura </a> {/* Contact grid */} <div style={{ display:"flex", gap:40, justifyContent:"center", flexWrap:"wrap", marginTop:8 }}> {[ { label:"Telefono", value:"091 748 10 23" }, { label:"WhatsApp", value:"388 721 54 47" }, { label:"Email", value:"info@atomonetworks.com" }, { label:"Sede", value:"Via Corsitti 17, Borgetto (PA)" }, ].map((c, i) => ( <div key={i} style={{ textAlign:"center" }}> <div style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:10, letterSpacing:"0.45em", color:"#00e5ff", textTransform:"uppercase", marginBottom:6 }}>{c.label}</div> <div style={{ fontFamily:"'DM Sans',sans-serif", fontSize:14, color:"rgba(200,220,255,0.75)" }}>{c.value}</div> </div> ))} </div> </div> </section> {/* ════ FOOTER ════ */} <footer style={{ borderTop:"1px solid rgba(0,229,255,0.07)", padding:"32px 24px", textAlign:"center" }}> <p style={{ fontFamily:"'Rajdhani',sans-serif", fontSize:11, letterSpacing:"0.28em", color:"rgba(120,160,200,0.35)", textTransform:"uppercase" }}> © 2025 Atomo Networks S.r.l. · P.IVA 06009080828 · Via Corsitti 17, 90042 Borgetto (PA) · Connessione per passione </p> </footer> </div>{/* /content */} </div> ``` ); }
Now I'll create the component and page. The original code has some syntax issues (using … instead of ... for spread operators) that I need to fix:
Ho reso funzionante il codice React per la landing page di Atomo Networks. Le modifiche principali che ho fatto:
"use client" - Necessario per Next.js App Router poiché il componente usa hooks (useEffect, useState, useRef) e browser APIs… (carattere Unicode ellipsis) con ... (tre punti)l'anno con l'anno per evitare errori JSXLa pagina ora mostra una landing page cinematografica con:
Puoi vedere la preview direttamente nel pannello a destra di v0.
Per ottenere un link pubblico online, clicca il pulsante "Publish" in alto a destra. Questo deployerà il progetto su Vercel e ti fornirà un URL pubblico (tipo nome-progetto.vercel.app).