Initial commit: sito NexStudio (Astro) con Cloudflare, CMS cookie e contenuti legali

- Home: hero, prodotti, servizi, stack, FAQ, CTA con form contatti inline (glossy) e particelle
- Header nero, menu con scroll-spy e alone su voce attiva, CTA Chattiamo (pre-chat)
- Pagine: privacy, cookie, GDPR, terms, about, codice etico, modello organizzativo, dove siamo, news
- Cookie consent first-party, chat gate, stampe-friendly su SubpageLayout
- Footer: Sezioni con Contattaci, Azienda con Dove siamo senza link per ora
- .gitignore: aggiunto .wrangler/ per stato locale Cloudflare

Made-with: Cursor
This commit is contained in:
Javaxman
2026-04-22 13:07:40 +02:00
commit 16c380dfda
64 changed files with 25028 additions and 0 deletions

56
src/scripts/nx-nav-spy.ts Normal file
View File

@ -0,0 +1,56 @@
/**
* Home: evidenzia in bianco il link del menu che corrisponde alla sezione in vista.
*/
const SECTION_IDS = ['prodotti', 'servizi', 'stack', 'faq', 'contatti'] as const;
const HEADER_OFFSET = 88;
function getActiveSectionId(): string | null {
const y = window.scrollY + HEADER_OFFSET;
let active: string | null = null;
for (const id of SECTION_IDS) {
const el = document.getElementById(id);
if (!el) continue;
if (el.offsetTop <= y) active = id;
}
return active;
}
function applyActive(): void {
const active = getActiveSectionId();
document.querySelectorAll<HTMLAnchorElement>('a[data-section]').forEach((a) => {
const id = a.dataset.section;
const on = Boolean(id && id === active);
a.dataset.navActive = on ? 'true' : 'false';
if (on) a.setAttribute('aria-current', 'true');
else a.removeAttribute('aria-current');
});
}
let scheduled = false;
function onScroll(): void {
if (scheduled) return;
scheduled = true;
requestAnimationFrame(() => {
scheduled = false;
applyActive();
});
}
function bind(): void {
const path = window.location.pathname;
if (path !== '/' && path !== '/index.html') return;
applyActive();
window.addEventListener('scroll', onScroll, { passive: true });
window.addEventListener('resize', onScroll, { passive: true });
window.addEventListener('hashchange', applyActive);
window.addEventListener('load', applyActive);
}
if (typeof document !== 'undefined') {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', bind, { once: true });
} else {
bind();
}
}