Evita l'errore runtime su /en e /th che causava pagina vuota o UI rotta nel selettore lingua. Made-with: Cursor
744 lines
30 KiB
Plaintext
744 lines
30 KiB
Plaintext
---
|
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
|
import HeroDataflow from '../components/HeroDataflow.astro';
|
|
import DataflowSpine from '../components/DataflowSpine.astro';
|
|
import ContactFormInline from '../components/ContactFormInline.astro';
|
|
import CardBottomRightTexture from '../components/CardBottomRightTexture.astro';
|
|
import SiteFooter from '../components/SiteFooter.astro';
|
|
import {
|
|
getSiteMeta,
|
|
getNavigation,
|
|
getHero,
|
|
stats,
|
|
getServices,
|
|
getStackSection,
|
|
productsSection,
|
|
getFaq,
|
|
getCta,
|
|
} from '../data/home';
|
|
|
|
const path = Astro.url.pathname;
|
|
const localeMatch = path.match(/^\/(en|th)(\/|$)/);
|
|
const currentLocale = (localeMatch?.[1] ?? 'it') as 'it' | 'en' | 'th';
|
|
const navigation = getNavigation(currentLocale);
|
|
const siteMeta = getSiteMeta(currentLocale);
|
|
const hero = getHero(currentLocale);
|
|
const services = getServices(currentLocale);
|
|
const stackSection = getStackSection(currentLocale);
|
|
const faq = getFaq(currentLocale);
|
|
const cta = getCta(currentLocale);
|
|
const infrastructureCarouselItems = stackSection.infrastructureCarousel.items;
|
|
const pageLabels = {
|
|
it: { focus: 'Focus' },
|
|
en: { focus: 'Focus' },
|
|
th: { focus: 'จุดเน้น' },
|
|
}[currentLocale];
|
|
const localize = (href: string) => {
|
|
if (currentLocale === 'it') return href;
|
|
if (href.startsWith(`/${currentLocale}`)) return href;
|
|
if (href.startsWith('/#')) return `/${currentLocale}${href}`;
|
|
if (href.startsWith('/')) return `/${currentLocale}${href}`;
|
|
return href;
|
|
};
|
|
const langItHref = '/';
|
|
const langEnHref = '/en';
|
|
const langThHref = '/th';
|
|
const langMeta = {
|
|
it: { code: 'IT', label: 'Italiano', flagSrc: '/images/flags/it.svg' },
|
|
en: { code: 'EN', label: 'English', flagSrc: '/images/flags/en.svg' },
|
|
th: { code: 'TH', label: 'ไทย', flagSrc: '/images/flags/th.svg' },
|
|
} as const;
|
|
---
|
|
|
|
<BaseLayout title={siteMeta.title} description={siteMeta.description}>
|
|
<div class="nx-grid-bg relative min-h-screen">
|
|
<canvas
|
|
id="particleCanvas"
|
|
class="nx-particle-layer pointer-events-none"
|
|
aria-hidden="true"></canvas>
|
|
<div
|
|
class="pointer-events-none absolute inset-0 z-[1] bg-[radial-gradient(ellipse_80%_50%_at_50%_-20%,rgba(56,189,248,0.18),transparent)]"
|
|
>
|
|
</div>
|
|
<header
|
|
class="sticky top-0 z-50 border-b border-nx-border/40 bg-black"
|
|
x-data="{ mobile: false }"
|
|
>
|
|
<div
|
|
class="mx-auto flex max-w-6xl items-center justify-between gap-4 px-4 py-3 sm:px-6"
|
|
>
|
|
<a href={localize('/')} class="group no-underline">
|
|
<span
|
|
class="text-2xl font-semibold tracking-tight text-nx-fg group-hover:text-white sm:text-3xl"
|
|
>{navigation.brandName}</span
|
|
>
|
|
</a>
|
|
|
|
<nav
|
|
class="hidden items-center gap-8 text-sm md:flex"
|
|
aria-label={navigation.labels.mainNavAria}
|
|
>
|
|
{navigation.items.map((item) => {
|
|
const sectionId = item.href.includes('#')
|
|
? item.href.split('#').pop()!
|
|
: '';
|
|
return (
|
|
<a
|
|
class="nx-nav-link"
|
|
href={localize(item.href)}
|
|
data-section={sectionId}
|
|
data-nav-active="false"
|
|
>
|
|
{item.label}
|
|
</a>
|
|
);
|
|
})}
|
|
</nav>
|
|
|
|
<div class="flex items-center gap-2 sm:gap-3">
|
|
<details class="relative hidden sm:block" data-lang-dropdown>
|
|
<summary
|
|
class="inline-flex h-10 cursor-pointer list-none items-center gap-2 rounded-lg border border-nx-border/80 bg-nx-bg/50 px-3 text-xs font-medium text-nx-fg transition-colors hover:border-sky-500/35 hover:text-white"
|
|
aria-label={navigation.labels.languageSelectorAria}
|
|
>
|
|
<img src={langMeta[currentLocale].flagSrc} alt="" class="h-3.5 w-5 rounded-[2px] object-cover" loading="lazy" decoding="async" />
|
|
<span>{langMeta[currentLocale].code}</span>
|
|
<svg class="h-3.5 w-3.5 text-nx-muted" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 0 1 1.06.02L10 11.168l3.71-3.938a.75.75 0 1 1 1.08 1.04l-4.25 4.5a.75.75 0 0 1-1.08 0l-4.25-4.5a.75.75 0 0 1 .02-1.06Z" clip-rule="evenodd"></path>
|
|
</svg>
|
|
</summary>
|
|
<div
|
|
class="absolute right-0 top-12 z-50 min-w-44 overflow-hidden rounded-lg border border-nx-border bg-nx-elevated/95 p-1 shadow-xl backdrop-blur"
|
|
role="menu"
|
|
>
|
|
<a
|
|
href={langItHref}
|
|
class:list={[
|
|
'flex items-center justify-between rounded-md px-3 py-2 text-sm text-nx-muted transition-colors hover:bg-white/5 hover:text-nx-fg',
|
|
currentLocale === 'it' && 'bg-white/5 text-nx-fg',
|
|
]}
|
|
aria-current={currentLocale === 'it' ? 'page' : undefined}
|
|
>
|
|
<span class="flex items-center gap-2">
|
|
<img src={langMeta.it.flagSrc} alt="" class="h-3.5 w-5 rounded-[2px] object-cover" loading="lazy" decoding="async" />
|
|
{langMeta.it.label}
|
|
</span>
|
|
<span class="text-xs">{langMeta.it.code}</span>
|
|
</a>
|
|
<a
|
|
href={langEnHref}
|
|
class:list={[
|
|
'flex items-center justify-between rounded-md px-3 py-2 text-sm text-nx-muted transition-colors hover:bg-white/5 hover:text-nx-fg',
|
|
currentLocale === 'en' && 'bg-white/5 text-nx-fg',
|
|
]}
|
|
aria-current={currentLocale === 'en' ? 'page' : undefined}
|
|
>
|
|
<span class="flex items-center gap-2">
|
|
<img src={langMeta.en.flagSrc} alt="" class="h-3.5 w-5 rounded-[2px] object-cover" loading="lazy" decoding="async" />
|
|
{langMeta.en.label}
|
|
</span>
|
|
<span class="text-xs">{langMeta.en.code}</span>
|
|
</a>
|
|
<a
|
|
href={langThHref}
|
|
class:list={[
|
|
'flex items-center justify-between rounded-md px-3 py-2 text-sm text-nx-muted transition-colors hover:bg-white/5 hover:text-nx-fg',
|
|
currentLocale === 'th' && 'bg-white/5 text-nx-fg',
|
|
]}
|
|
aria-current={currentLocale === 'th' ? 'page' : undefined}
|
|
>
|
|
<span class="flex items-center gap-2">
|
|
<img src={langMeta.th.flagSrc} alt="" class="h-3.5 w-5 rounded-[2px] object-cover" loading="lazy" decoding="async" />
|
|
{langMeta.th.label}
|
|
</span>
|
|
<span class="text-xs">{langMeta.th.code}</span>
|
|
</a>
|
|
</div>
|
|
</details>
|
|
<button
|
|
type="button"
|
|
data-nx-chat-open
|
|
class="inline-flex cursor-pointer rounded-lg bg-gradient-to-r from-sky-500 to-violet-500 px-4 py-2 text-sm font-semibold text-white shadow-lg shadow-sky-500/25 hover:brightness-110"
|
|
title={navigation.cta.linkTitle}
|
|
aria-label={navigation.cta.ariaLabel}
|
|
>{navigation.cta.label}</button
|
|
>
|
|
<button
|
|
type="button"
|
|
class="inline-flex h-10 w-10 items-center justify-center rounded-lg border border-nx-border text-nx-fg md:hidden"
|
|
@click="mobile = !mobile"
|
|
:aria-expanded="mobile"
|
|
aria-controls="mobile-nav"
|
|
aria-label={navigation.labels.openMenuAria}
|
|
>
|
|
<svg
|
|
x-show="!mobile"
|
|
class="h-5 w-5"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
x-cloak
|
|
>
|
|
<path d="M4 6h16M4 12h16M4 18h16" stroke-linecap="round"></path>
|
|
</svg>
|
|
<svg
|
|
x-show="mobile"
|
|
class="h-5 w-5"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
x-cloak
|
|
>
|
|
<path d="M6 18L18 6M6 6l12 12" stroke-linecap="round"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div
|
|
id="mobile-nav"
|
|
x-show="mobile"
|
|
x-transition
|
|
x-cloak
|
|
class="border-b border-nx-border bg-black px-4 py-4 md:hidden"
|
|
>
|
|
<nav class="flex flex-col gap-3 text-sm" aria-label={navigation.labels.mobileNavAria}>
|
|
{navigation.items.map((item) => {
|
|
const sectionId = item.href.includes('#')
|
|
? item.href.split('#').pop()!
|
|
: '';
|
|
return (
|
|
<a
|
|
class="nx-nav-link block py-1"
|
|
href={localize(item.href)}
|
|
data-section={sectionId}
|
|
data-nav-active="false"
|
|
@click="mobile = false"
|
|
>
|
|
{item.label}
|
|
</a>
|
|
);
|
|
})}
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="relative z-[1] isolate">
|
|
<DataflowSpine />
|
|
<section
|
|
id="intro"
|
|
class="relative z-10 overflow-hidden px-4 pb-20 pt-16 sm:px-6 sm:pt-24"
|
|
>
|
|
<div class="nx-hero-ambient" aria-hidden="true">
|
|
<div class="nx-hero-ambient__inner">
|
|
<HeroDataflow />
|
|
</div>
|
|
</div>
|
|
<div class="relative z-10 mx-auto max-w-6xl">
|
|
<p
|
|
class="mb-6 inline-flex items-center gap-2.5 rounded-full border border-nx-border bg-nx-surface/60 px-4 py-1.5 text-sm font-medium text-sky-300/90 sm:px-5 sm:py-2"
|
|
>
|
|
<span
|
|
class="h-2 w-2 rounded-full bg-sky-400 shadow-[0_0_10px_#38bdf8]"></span>
|
|
{hero.badge}
|
|
</p>
|
|
<h1
|
|
class="max-w-4xl text-4xl font-semibold leading-[1.1] tracking-tight text-nx-fg sm:text-5xl md:text-6xl"
|
|
>
|
|
{hero.titleBefore}
|
|
<span
|
|
class="bg-gradient-to-r from-sky-300 via-cyan-200 to-violet-400 bg-clip-text text-transparent"
|
|
>{hero.titleHighlight}</span
|
|
>{hero.titleAfter}
|
|
</h1>
|
|
<p
|
|
class="mt-5 max-w-3xl text-lg font-medium leading-relaxed text-sky-100/90 sm:text-xl"
|
|
>
|
|
{hero.subtitle}
|
|
</p>
|
|
<div class="mt-8 max-w-3xl space-y-4 text-base leading-relaxed text-nx-muted sm:text-lg">
|
|
{hero.paragraphs.map((p) => <p>{p}</p>)}
|
|
</div>
|
|
<div class="mt-10 max-w-3xl">
|
|
<h2 class="text-base font-semibold text-nx-fg sm:text-lg">
|
|
{hero.businessUnitsHeading}
|
|
</h2>
|
|
<p class="mt-2 text-sm leading-relaxed text-nx-muted sm:text-base">
|
|
{hero.businessUnitsIntro}
|
|
</p>
|
|
<ul class="mt-5 space-y-4 border-l border-nx-border pl-5">
|
|
{hero.businessUnits.map((u) => (
|
|
<li>
|
|
<span class="font-semibold text-sky-300/95">{u.name}</span>
|
|
<span class="text-nx-muted"> — {u.description}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="relative z-10 px-4 py-6 sm:px-6 sm:py-8">
|
|
<div
|
|
class="nx-stats-card mx-auto max-w-6xl rounded-2xl border border-nx-border bg-gradient-to-b from-nx-elevated/78 to-nx-surface/68 px-6 py-10 ring-1 ring-inset ring-white/[0.06] sm:px-10 sm:py-12"
|
|
>
|
|
<div
|
|
class="grid grid-cols-1 gap-8 sm:grid-cols-3 sm:gap-8 lg:gap-10"
|
|
>
|
|
{stats.items.map((item) => (
|
|
<div>
|
|
<p
|
|
class="text-3xl font-semibold tracking-tight text-nx-fg sm:text-4xl"
|
|
>
|
|
{item.value}
|
|
</p>
|
|
<p class="mt-1 text-sm leading-relaxed text-nx-muted">
|
|
{item.caption}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="prodotti" class="relative z-10 px-4 py-20 sm:px-6">
|
|
<div class="mx-auto max-w-6xl">
|
|
<h2
|
|
class="text-sm font-semibold uppercase tracking-wider text-sky-400/90"
|
|
>
|
|
{productsSection.eyebrow}
|
|
</h2>
|
|
<p
|
|
class="mt-2 text-3xl font-semibold tracking-tight text-nx-fg sm:text-4xl"
|
|
>
|
|
{productsSection.title}
|
|
</p>
|
|
<p class="mt-4 max-w-3xl text-base leading-relaxed text-nx-muted sm:text-lg">
|
|
{productsSection.lead}
|
|
</p>
|
|
|
|
<div class="relative mt-14">
|
|
<div
|
|
class="pointer-events-none absolute -top-28 left-1/2 z-0 h-64 w-[min(96%,60rem)] -translate-x-1/2 rounded-full bg-[radial-gradient(ellipse_at_center,rgba(125,211,252,0.34)_0%,rgba(96,165,250,0.2)_36%,rgba(16,24,40,0)_74%)] blur-3xl"
|
|
aria-hidden="true"
|
|
/>
|
|
<div
|
|
class="pointer-events-none absolute -top-14 left-1/2 z-0 h-40 w-[min(88%,54rem)] -translate-x-1/2 rounded-full bg-[radial-gradient(ellipse_at_center,rgba(186,230,253,0.16)_0%,rgba(16,24,40,0)_70%)] blur-2xl"
|
|
aria-hidden="true"
|
|
/>
|
|
<div
|
|
class="relative z-10 grid gap-8 lg:grid-cols-2 lg:gap-10 lg:items-stretch"
|
|
>
|
|
{productsSection.items.map((product, pi) => (
|
|
<article
|
|
class:list={[
|
|
'relative flex flex-col overflow-hidden rounded-2xl border p-6 -translate-y-1 shadow-2xl shadow-black/30 sm:p-8',
|
|
pi === 0
|
|
? 'border-sky-400/45 bg-gradient-to-b from-sky-950/30 to-nx-surface/30'
|
|
: 'border-emerald-400/40 bg-gradient-to-b from-emerald-950/25 to-nx-surface/30',
|
|
]}
|
|
>
|
|
<div
|
|
class="pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_at_top,rgba(255,255,255,0.12),transparent_62%)]"
|
|
aria-hidden="true"
|
|
/>
|
|
<div class="pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white/35 to-transparent opacity-60" aria-hidden="true"></div>
|
|
<div class="flex flex-wrap items-baseline justify-between gap-2">
|
|
<h3 class="text-2xl font-semibold tracking-tight text-nx-fg">
|
|
{product.name}
|
|
</h3>
|
|
<span
|
|
class:list={[
|
|
'rounded-full px-2.5 py-0.5 text-xs font-medium',
|
|
pi === 0
|
|
? 'bg-sky-500/25 text-sky-200/95'
|
|
: 'bg-emerald-500/25 text-emerald-200/95',
|
|
]}
|
|
>
|
|
{product.badge}
|
|
</span>
|
|
</div>
|
|
<p class="mt-3 text-lg font-medium leading-snug text-nx-fg sm:text-xl">
|
|
{product.tagline}
|
|
</p>
|
|
<p
|
|
class:list={[
|
|
'mt-2 text-sm font-medium',
|
|
pi === 0 ? 'text-sky-200/85' : 'text-emerald-200/85',
|
|
]}
|
|
>
|
|
<span class="text-nx-muted font-normal">{pageLabels.focus} — </span>
|
|
{product.focus}
|
|
</p>
|
|
<p class="mt-5 text-sm leading-relaxed text-nx-muted sm:text-base">
|
|
{product.body}
|
|
</p>
|
|
<ul class="mt-6 space-y-4 border-t border-white/10 pt-6">
|
|
{product.highlights.map((h) => (
|
|
<li>
|
|
<p class="text-sm leading-relaxed sm:text-[15px]">
|
|
<span
|
|
class:list={[
|
|
'font-semibold',
|
|
pi === 0 ? 'text-sky-200/95' : 'text-emerald-200/95',
|
|
]}
|
|
>
|
|
{h.title}
|
|
</span>
|
|
<span class="text-nx-muted">
|
|
<span class="text-nx-muted/60"> — </span>
|
|
{h.text}
|
|
</span>
|
|
</p>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
{'closing' in product && product.closing ? (
|
|
<p class="mt-6 border-t border-white/10 pt-6 text-sm italic leading-relaxed text-nx-muted">
|
|
{product.closing}
|
|
</p>
|
|
) : null}
|
|
</article>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="servizi" class="relative z-10 px-4 py-20 sm:px-6">
|
|
<div class="mx-auto max-w-6xl">
|
|
<h2
|
|
class="text-sm font-semibold uppercase tracking-wider text-sky-400/90"
|
|
>
|
|
{services.eyebrow}
|
|
</h2>
|
|
<p
|
|
class="mt-2 max-w-2xl text-3xl font-semibold tracking-tight text-nx-fg sm:text-4xl"
|
|
>
|
|
{services.title}
|
|
</p>
|
|
<p class="mt-5 max-w-3xl text-base leading-relaxed text-nx-muted sm:text-lg">
|
|
{services.lead}
|
|
</p>
|
|
<div
|
|
class="mt-12 grid gap-4 md:grid-cols-3 md:grid-rows-2 md:gap-5 [&>article]:rounded-2xl [&>article]:border [&>article]:border-nx-border [&>article]:bg-nx-elevated/50 [&>article]:p-6"
|
|
>
|
|
{services.cards.map((card) => {
|
|
const hasGlobe =
|
|
'decoration' in card &&
|
|
card.decoration === 'wireframe-globe';
|
|
return (
|
|
<article
|
|
class:list={[
|
|
card.layout === 'wide' && 'md:col-span-2',
|
|
card.layout === 'tall' && 'md:row-span-2',
|
|
hasGlobe && 'relative overflow-hidden',
|
|
]}
|
|
>
|
|
{hasGlobe && <CardBottomRightTexture />}
|
|
<div class:list={[hasGlobe && 'relative z-10']}>
|
|
<h3 class="text-lg font-semibold text-nx-fg">{card.title}</h3>
|
|
<p class="mt-2 text-sm leading-relaxed text-nx-muted">
|
|
{card.body}
|
|
</p>
|
|
{'callout' in card && card.callout && (
|
|
<div
|
|
class="group relative mt-4 overflow-hidden rounded-xl border border-sky-400/35 bg-gradient-to-br from-sky-500/20 via-slate-900/70 to-violet-950/50 p-4 shadow-[inset_0_1px_0_0_rgba(255,255,255,0.16),0_8px_32px_-6px_rgba(14,165,233,0.18)]"
|
|
>
|
|
<div
|
|
class="pointer-events-none absolute inset-0 bg-gradient-to-b from-white/[0.14] via-white/[0.02] to-transparent"
|
|
aria-hidden="true"
|
|
/>
|
|
<div
|
|
class="pointer-events-none absolute -right-6 -top-12 h-28 w-36 rotate-12 rounded-full bg-gradient-to-br from-cyan-200/30 via-sky-400/15 to-transparent blur-2xl"
|
|
aria-hidden="true"
|
|
/>
|
|
<div
|
|
class="pointer-events-none absolute -bottom-8 -left-4 h-20 w-32 rotate-[-8deg] rounded-full bg-gradient-to-tr from-violet-500/10 to-transparent blur-xl"
|
|
aria-hidden="true"
|
|
/>
|
|
<div class="relative z-10">
|
|
<p class="text-sm font-semibold text-sky-100/95">
|
|
{card.callout.title}
|
|
</p>
|
|
<p class="mt-2 text-sm leading-relaxed text-nx-muted">
|
|
{card.callout.body}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
{'bullets' in card && card.bullets && (
|
|
<ul class="mt-4 space-y-2 text-sm text-sky-300/90">
|
|
{card.bullets.map((b) => (
|
|
<li class="flex gap-2">
|
|
<span class="text-violet-400">▹</span>
|
|
{b}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
</div>
|
|
</article>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section
|
|
id="stack"
|
|
class="relative z-10 overflow-hidden border-t border-nx-border bg-nx-surface/30 px-4 py-20 sm:px-6"
|
|
>
|
|
<div class="mx-auto max-w-6xl">
|
|
<h2
|
|
class="text-sm font-semibold uppercase tracking-wider text-sky-400/90"
|
|
>
|
|
{stackSection.eyebrow}
|
|
</h2>
|
|
<p
|
|
class="mt-2 max-w-3xl text-3xl font-semibold tracking-tight text-nx-fg sm:text-4xl"
|
|
>
|
|
{stackSection.title}
|
|
</p>
|
|
<p class="mt-5 max-w-3xl text-base leading-relaxed text-nx-muted sm:text-lg">
|
|
{stackSection.lead}
|
|
</p>
|
|
|
|
<div
|
|
class="relative z-[1] mt-12 rounded-2xl border border-orange-500/20 bg-gradient-to-br from-orange-950/20 to-nx-elevated/40 p-6 sm:p-8"
|
|
>
|
|
<p class="text-xs font-medium uppercase tracking-wider text-orange-200/90">
|
|
{stackSection.infrastructureHeading}
|
|
</p>
|
|
<div
|
|
class="nx-infra-carousel mt-5"
|
|
role="region"
|
|
aria-label={stackSection.infrastructureCarousel.ariaLabel}
|
|
>
|
|
<div class="nx-infra-carousel__viewport">
|
|
<div class="nx-infra-carousel__track">
|
|
{infrastructureCarouselItems.map((item) => (
|
|
<article class="nx-infra-carousel__item">
|
|
<a
|
|
href={item.href}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
class="group inline-flex h-16 w-[16rem] items-center gap-3 rounded-xl border border-white/10 bg-nx-bg/60 px-4 transition hover:border-orange-400/35"
|
|
>
|
|
<img
|
|
src={item.iconSrc}
|
|
alt={item.iconAlt}
|
|
width={item.label === 'Ecosistema AWS' ? 84 : 40}
|
|
height={item.label === 'Ecosistema AWS' ? 28 : 40}
|
|
class:list={[
|
|
'shrink-0 object-contain',
|
|
item.label === 'Ecosistema AWS' ? 'h-7 w-20' : 'h-9 w-9',
|
|
]}
|
|
loading="lazy"
|
|
decoding="async"
|
|
/>
|
|
<div class="min-w-0">
|
|
<p class="text-sm font-semibold text-nx-fg group-hover:text-orange-100">
|
|
{item.label}
|
|
</p>
|
|
</div>
|
|
</a>
|
|
<p class="mt-2 text-sm leading-relaxed text-nx-muted">
|
|
{item.slogan}
|
|
</p>
|
|
</article>
|
|
))}
|
|
{infrastructureCarouselItems.map((item) => (
|
|
<article class:list={['nx-infra-carousel__item', 'nx-infra-carousel__item--dup']}>
|
|
<a
|
|
href={item.href}
|
|
tabindex="-1"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
aria-hidden="true"
|
|
class="group inline-flex h-16 w-[16rem] items-center gap-3 rounded-xl border border-white/10 bg-nx-bg/60 px-4"
|
|
>
|
|
<img
|
|
src={item.iconSrc}
|
|
alt=""
|
|
width={item.label === 'Ecosistema AWS' ? 84 : 40}
|
|
height={item.label === 'Ecosistema AWS' ? 28 : 40}
|
|
class:list={[
|
|
'shrink-0 object-contain',
|
|
item.label === 'Ecosistema AWS' ? 'h-7 w-20' : 'h-9 w-9',
|
|
]}
|
|
loading="lazy"
|
|
decoding="async"
|
|
/>
|
|
<div class="min-w-0">
|
|
<p class="text-sm font-semibold text-nx-fg">
|
|
{item.label}
|
|
</p>
|
|
</div>
|
|
</a>
|
|
<p class="mt-2 text-sm leading-relaxed text-nx-muted">
|
|
{item.slogan}
|
|
</p>
|
|
</article>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<ul class="relative z-[1] mt-16 space-y-6 sm:mt-20">
|
|
{stackSection.cloudflare.points.map((item) => (
|
|
<li class="border-l-2 border-orange-400/40 pl-5">
|
|
<p class="font-semibold text-orange-100/95">{item.title}</p>
|
|
<p class="mt-1.5 text-sm leading-relaxed text-nx-muted sm:text-[15px]">
|
|
{item.body}
|
|
</p>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
|
|
<div
|
|
class="mt-14 rounded-2xl border border-nx-border bg-nx-elevated/50 p-6 sm:p-8 sm:mt-16"
|
|
>
|
|
<h3 class="text-lg font-semibold text-nx-fg">
|
|
{stackSection.continuity.title}
|
|
</h3>
|
|
<p class="mt-3 text-sm leading-relaxed text-nx-muted sm:text-base">
|
|
{stackSection.continuity.body}
|
|
</p>
|
|
</div>
|
|
|
|
<div class="mt-14 sm:mt-16">
|
|
<h3 class="text-lg font-semibold text-nx-fg">
|
|
{stackSection.whyThisChoice.title}
|
|
</h3>
|
|
<ul class="mt-4 space-y-3 text-sm leading-relaxed text-nx-muted sm:text-[15px]">
|
|
{stackSection.whyThisChoice.points.map((line) => (
|
|
<li class="flex gap-3">
|
|
<span class="mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-sky-400/80" />
|
|
<span>{line}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section
|
|
id="faq"
|
|
class="relative z-10 border-t border-nx-border bg-nx-surface/20 px-4 py-20 sm:px-6"
|
|
x-data="{ q: 0 }"
|
|
>
|
|
<div class="mx-auto max-w-2xl">
|
|
<h2
|
|
class="text-sm font-semibold uppercase tracking-wider text-sky-400/90"
|
|
>
|
|
{faq.eyebrow}
|
|
</h2>
|
|
<p
|
|
class="mt-2 text-3xl font-semibold tracking-tight text-nx-fg sm:text-4xl"
|
|
>
|
|
{faq.title}
|
|
</p>
|
|
|
|
<div class="mt-10 divide-y divide-nx-border rounded-2xl border border-nx-border bg-nx-elevated/30">
|
|
{faq.items.map((item, idx) => {
|
|
const n = idx + 1;
|
|
return (
|
|
<div>
|
|
<button
|
|
type="button"
|
|
class="flex w-full items-center justify-between px-4 py-4 text-left text-sm font-medium text-nx-fg hover:bg-white/5"
|
|
@click={`q = q === ${n} ? 0 : ${n}`}
|
|
:aria-expanded={`q === ${n}`}
|
|
>
|
|
{item.question}
|
|
<span
|
|
class="ml-3 inline-flex shrink-0 text-nx-muted transition-transform duration-200 ease-out"
|
|
:class={`q === ${n} && 'rotate-180'`}
|
|
aria-hidden="true"
|
|
>
|
|
<svg
|
|
class="size-5 sm:size-6"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path d="m6 9 6 6 6-6"></path>
|
|
</svg>
|
|
</span>
|
|
</button>
|
|
<div
|
|
x-show={`q === ${n}`}
|
|
x-transition
|
|
x-cloak
|
|
class="border-t border-nx-border px-4 py-3 text-sm text-nx-muted"
|
|
>
|
|
{item.answer}
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section
|
|
id="contatti"
|
|
class="relative z-10 border-t border-nx-border bg-nx-surface/20 px-4 pt-14 pb-16 sm:px-6 sm:pt-20 sm:pb-20"
|
|
>
|
|
<div class="mx-auto max-w-6xl">
|
|
<h2
|
|
class="text-sm font-semibold uppercase tracking-wider text-sky-400/90"
|
|
>
|
|
{cta.eyebrow}
|
|
</h2>
|
|
<p
|
|
class="mt-2 text-3xl font-semibold leading-snug tracking-tight text-nx-fg sm:text-4xl"
|
|
>
|
|
<span class="block">{cta.titleLine1}</span>
|
|
<span class="mt-1 block text-sky-200 sm:text-sky-100/95"
|
|
>{cta.titleLine2}</span
|
|
>
|
|
</p>
|
|
|
|
<div
|
|
class="mt-8 sm:mt-10"
|
|
>
|
|
<div
|
|
class="nx-cta-card relative mx-auto max-w-6xl overflow-hidden rounded-3xl border border-nx-border bg-gradient-to-br from-sky-500/15 via-nx-elevated to-violet-600/15 px-5 py-5 sm:px-6 sm:py-6"
|
|
>
|
|
<div
|
|
class="relative z-10 flex flex-col gap-6 lg:flex-row lg:items-start lg:gap-10"
|
|
>
|
|
<div
|
|
class="min-w-0 flex-1 lg:max-w-[min(100%,28rem)] xl:max-w-[min(100%,32rem)]"
|
|
>
|
|
<p class="max-w-2xl text-base leading-relaxed text-nx-muted sm:text-lg">
|
|
{cta.body}
|
|
</p>
|
|
</div>
|
|
<div
|
|
class="w-full min-w-0 shrink-0 lg:max-w-md xl:max-w-lg"
|
|
>
|
|
<ContactFormInline />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<SiteFooter />
|
|
</div>
|
|
<script>
|
|
import '../scripts/nx-nav-spy.ts';
|
|
import '../scripts/nx-lang-dropdown.ts';
|
|
</script>
|
|
</BaseLayout>
|