7a30bc08b9
Tutti i testi della landing (hero, launch, card con prezzi, nota validità e FAQ)
passano ora dal sistema di content-tag `promo.*`, editabili inline e da pannello.
Il numero WhatsApp è centralizzato nel tag globale `global.whatsapp`: le risposte
FAQ usano il segnaposto {{whatsapp}}, sostituito a runtime, così si aggiorna in un
punto solo. Struttura delle 4 card e link di acquisto bsport restano nel codice.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
193 lines
9.8 KiB
Plaintext
193 lines
9.8 KiB
Plaintext
---
|
||
import Base from '../layouts/Base.astro';
|
||
import T from '../components/content/T.astro';
|
||
import { t, resolveContent } from '../lib/content';
|
||
// Landing promo/lancio integrata nel sito (header e footer del sito, non standalone).
|
||
// I bottoni "Acquista" portano al gestionale bsport: l'utente crea l'account,
|
||
// inserisce i dati e paga via Stripe dentro la piattaforma. Link centralizzato qui:
|
||
// quando avremo gli ID membership per singolo prodotto basterà mappare BSPORT_URL card per card.
|
||
const BSPORT_URL = 'https://backoffice.bsport.io/login/signup?membership=3428';
|
||
export const prerender = false;
|
||
|
||
// I testi sono editabili dal pannello contenuti (tag `promo.*`). Qui resta solo la
|
||
// struttura: quante card, quante feature ciascuna e quale è "in evidenza".
|
||
const cards = [
|
||
{ id: 1, features: 4, featured: false },
|
||
{ id: 2, features: 4, featured: true },
|
||
{ id: 3, features: 3, featured: false },
|
||
{ id: 4, features: 3, featured: false },
|
||
];
|
||
const faqs = [1, 2, 3, 4, 5, 6];
|
||
// Numero WhatsApp centralizzato: le risposte FAQ contengono il segnaposto {{whatsapp}}
|
||
// che qui viene sostituito col valore del tag globale, così si aggiorna in un punto solo.
|
||
const wa = t('global.whatsapp');
|
||
---
|
||
<Base title="Promo ed eventi — InsanityLab" description="Edizione apertura: pacchetti a 5 incontri per One to One, Small Group, Reformer e Holistic Class. Acquisto online, pagamento sicuro via Stripe.">
|
||
<div class="lp">
|
||
<div class="page">
|
||
|
||
<section class="hero">
|
||
<T tag="promo.hero.badge" as="div" class="badge" />
|
||
<T tag="promo.hero.title1" as="h1" />
|
||
<T tag="promo.hero.accent" as="p" class="accent" />
|
||
<T tag="promo.hero.title2" as="h1" />
|
||
<T tag="promo.hero.desc" as="p" class="desc" />
|
||
<a class="btn-sand" href="#proposte"><T tag="promo.hero.cta" as="span" /></a>
|
||
</section>
|
||
|
||
<section class="launch">
|
||
<T tag="promo.launch.badge" as="div" class="badge" />
|
||
<T tag="promo.launch.title" as="h1" />
|
||
<T tag="promo.launch.accent" as="p" class="accent" />
|
||
<T tag="promo.launch.desc" as="p" class="desc" />
|
||
</section>
|
||
|
||
<section class="why5">
|
||
<T tag="promo.why5.text" as="p" />
|
||
</section>
|
||
|
||
<section class="cards-wrap" id="proposte">
|
||
<div class="cards">
|
||
{cards.map((c) => (
|
||
<div class:list={['card', c.featured && 'featured']}>
|
||
{c.featured && <T tag={`promo.card.${c.id}.badge`} as="div" class="featured-badge" />}
|
||
<T tag={`promo.card.${c.id}.eyebrow`} as="div" class="eyebrow" />
|
||
<T tag={`promo.card.${c.id}.title`} as="div" class="title" />
|
||
<div class="price-row">
|
||
<T tag={`promo.card.${c.id}.price`} as="div" class="price" />
|
||
<T tag={`promo.card.${c.id}.price-old`} as="div" class="price-old" />
|
||
</div>
|
||
<T tag={`promo.card.${c.id}.unit`} as="div" class="unit" />
|
||
<ul>
|
||
{Array.from({ length: c.features }, (_, i) => i + 1).map((m) => (
|
||
<T tag={`promo.card.${c.id}.feature.${m}`} as="li" />
|
||
))}
|
||
</ul>
|
||
<a class="buy" href={BSPORT_URL} target="_blank" rel="noopener"><T tag="promo.buy-label" as="span" /></a>
|
||
</div>
|
||
))}
|
||
</div>
|
||
<T tag="promo.validity-note" as="p" class="validity-note" />
|
||
</section>
|
||
|
||
<section class="faq-wrap">
|
||
<T tag="promo.faq.title" as="h1" />
|
||
{faqs.map((n) => {
|
||
const a = resolveContent(`promo.faq.${n}.a`);
|
||
return (
|
||
<div class="faq-block">
|
||
<div class="faq-q"><T tag={`promo.faq.${n}.q`} as="p" /><div class="faq-toggle">+</div></div>
|
||
<p class:list={['faq-a', a.classes]} data-tag={`promo.faq.${n}.a`} data-guid={a.guid || undefined} set:html={a.value.replaceAll('{{whatsapp}}', wa)} />
|
||
</div>
|
||
);
|
||
})}
|
||
</section>
|
||
|
||
</div>
|
||
</div>
|
||
</Base>
|
||
|
||
<script>
|
||
// Accordion FAQ: click (o Invio/Spazio) sul quesito apre/chiude la risposta.
|
||
document.querySelectorAll('.lp .faq-block .faq-q').forEach((q) => {
|
||
const block = q.closest('.faq-block');
|
||
const toggle = q.querySelector('.faq-toggle');
|
||
q.setAttribute('role', 'button');
|
||
q.setAttribute('tabindex', '0');
|
||
q.setAttribute('aria-expanded', 'false');
|
||
const set = (open: boolean) => {
|
||
block?.classList.toggle('is-open', open);
|
||
q.setAttribute('aria-expanded', String(open));
|
||
if (toggle) toggle.textContent = open ? '−' : '+';
|
||
};
|
||
q.addEventListener('click', () => set(!block?.classList.contains('is-open')));
|
||
q.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); set(!block?.classList.contains('is-open')); }
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<style>
|
||
.lp { background: #ECE7DC; }
|
||
.lp .page { max-width: 1000px; margin: 0 auto; background: #FFFFFF; font-family: 'Inter', system-ui, Arial, sans-serif; }
|
||
|
||
/* HERO */
|
||
.lp .hero { background: #2D2D2D; padding: 72px 64px 84px; }
|
||
.lp .badge {
|
||
display: inline-block; padding: 7px 16px; border: 0.5px solid rgba(196,168,130,0.5);
|
||
border-radius: 999px; margin-bottom: 24px; font-size: 11px; letter-spacing: 0.08em;
|
||
color: #C4A882; font-weight: 500; text-transform: uppercase;
|
||
}
|
||
.lp .hero h1 { margin: 0; font-size: 44px; line-height: 1.2; font-weight: 700; color: #FFFFFF; }
|
||
.lp .hero .accent { margin: 4px 0; font-size: 38px; line-height: 1.3; font-style: italic; color: #C4A882; font-family: Georgia, serif; }
|
||
.lp .hero p.desc { margin: 28px 0 32px; font-size: 16px; line-height: 1.7; color: #B8B6AE; max-width: 480px; }
|
||
.lp .btn-sand {
|
||
display: inline-block; background: #C4A882; color: #2C2C2A; border: none; padding: 15px 30px;
|
||
border-radius: 999px; font-size: 13px; font-weight: 700; letter-spacing: 0.04em; cursor: pointer;
|
||
text-decoration: none;
|
||
}
|
||
|
||
/* LAUNCH */
|
||
.lp .launch { background: #F2ECE1; padding: 72px 64px; }
|
||
.lp .launch .badge { border-color: rgba(140,107,55,0.35); color: #8A6E3F; }
|
||
.lp .launch h1 { margin: 0; font-size: 40px; line-height: 1.25; font-weight: 700; color: #2D2D2D; }
|
||
.lp .launch .accent { margin: 8px 0 28px; font-size: 30px; line-height: 1.35; font-style: italic; color: #8A6E3F; font-family: Georgia, serif; }
|
||
.lp .launch p.desc { margin: 0; font-size: 16px; line-height: 1.7; color: #5C564A; max-width: 540px; }
|
||
|
||
/* PERCHE 5 */
|
||
.lp .why5 { padding: 48px 64px 8px; }
|
||
.lp .why5 p { margin: 0; font-size: 18px; line-height: 1.7; font-style: italic; color: #2D2D2D; font-family: Georgia, serif; max-width: 620px; }
|
||
|
||
/* CARDS */
|
||
.lp .cards-wrap { padding: 32px 64px 72px; }
|
||
.lp .cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
|
||
.lp .card { background: #FAF8F3; border: 0.5px solid #E3DCCB; border-radius: 14px; padding: 26px; position: relative; }
|
||
.lp .card.featured { border: 2px solid #2D2D2D; }
|
||
.lp .featured-badge {
|
||
position: absolute; top: -12px; left: 50%; transform: translateX(-50%); background: #2D2D2D;
|
||
color: #FFFFFF; font-size: 11px; padding: 4px 14px; border-radius: 999px; white-space: nowrap; font-weight: 500;
|
||
}
|
||
.lp .card .eyebrow { font-size: 11px; letter-spacing: 0.08em; color: #8A8980; margin: 0 0 4px; text-transform: uppercase; font-weight: 700; }
|
||
.lp .card .title { font-size: 19px; font-weight: 700; color: #2D2D2D; margin: 0 0 14px; }
|
||
.lp .card .price-row { display: flex; align-items: baseline; gap: 10px; margin: 0 0 2px; }
|
||
.lp .card .price { font-size: 26px; font-weight: 700; color: #2D2D2D; margin: 0; }
|
||
.lp .card .price-old { font-size: 15px; color: #ADABA1; text-decoration: line-through; font-weight: 400; }
|
||
.lp .card .unit { font-size: 12px; color: #8A8980; margin: 0 0 18px; }
|
||
.lp .card ul { list-style: none; padding: 0; margin: 0 0 20px; display: flex; flex-direction: column; gap: 9px; }
|
||
.lp .card li { font-size: 13.5px; line-height: 1.5; color: #5C564A; display: flex; gap: 8px; }
|
||
.lp .card li::before { content: "—"; color: #C4A882; font-weight: 700; flex-shrink: 0; }
|
||
.lp .card .buy {
|
||
display: block; width: 100%; box-sizing: border-box; text-align: center; text-decoration: none;
|
||
background: #2D2D2D; color: #FFFFFF; border: none; padding: 13px; border-radius: 999px;
|
||
font-size: 12px; font-weight: 700; letter-spacing: 0.03em; cursor: pointer;
|
||
}
|
||
.lp .card.featured .buy { background: #C4A882; color: #2C2C2A; }
|
||
|
||
.lp .validity-note { text-align: center; font-size: 12px; color: #8A8980; margin: 22px 0 0; }
|
||
|
||
/* FAQ */
|
||
.lp .faq-wrap { padding: 72px 64px; }
|
||
.lp .faq-wrap h1 { margin: 0 0 40px; font-size: 34px; line-height: 1.25; font-weight: 700; color: #2D2D2D; max-width: 480px; }
|
||
.lp .faq-block { border-top: 0.5px solid #E3DCCB; padding: 22px 0; }
|
||
.lp .faq-block:last-child { border-bottom: 0.5px solid #E3DCCB; }
|
||
.lp .faq-q { display: flex; justify-content: space-between; align-items: center; gap: 24px; cursor: pointer; }
|
||
.lp .faq-q p { margin: 0; font-size: 16px; font-weight: 500; color: #2D2D2D; }
|
||
.lp .faq-q:focus-visible { outline: 2px solid #8A6E3F; outline-offset: 4px; }
|
||
.lp .faq-toggle {
|
||
width: 30px; height: 30px; border-radius: 50%; border: 0.5px solid #C9C3B4; display: flex;
|
||
align-items: center; justify-content: center; flex-shrink: 0; font-size: 16px; color: #2D2D2D;
|
||
transition: background .2s ease, color .2s ease, border-color .2s ease;
|
||
}
|
||
.lp .faq-block.is-open .faq-toggle { background: #2D2D2D; color: #FFFFFF; border-color: #2D2D2D; }
|
||
.lp .faq-a { display: none; margin: 14px 0 0; font-size: 14.5px; line-height: 1.7; color: #8A8980; max-width: 620px; }
|
||
.lp .faq-block.is-open .faq-a { display: block; }
|
||
.lp .faq-a .hl { color: #8A6E3F; }
|
||
|
||
@media (max-width: 700px) {
|
||
.lp .hero, .lp .launch, .lp .why5, .lp .cards-wrap, .lp .faq-wrap { padding-left: 28px; padding-right: 28px; }
|
||
.lp .cards { grid-template-columns: 1fr; }
|
||
.lp .hero h1 { font-size: 32px; }
|
||
.lp .launch h1 { font-size: 28px; }
|
||
}
|
||
</style>
|