<html lang="it">
<head>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-KMP9MMS');</script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>SMS-Alert – Catena della Solidarietà</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Platypi:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #ffffff;
--surface: #f4f2ee;
--border: rgba(170,165,155,0.45);
--text: #0b0c0d;
--text-muted: rgba(11,12,13,0.60);
--text-dim: rgba(11,12,13,0.38);
--accent: #e82340;
}
html { scroll-behavior: smooth; overflow-y: auto; }
body {
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
-webkit-font-smoothing: antialiased;
overflow-x: hidden;
}
/* ── Layout ── */
.page {
max-width: 640px;
margin: 0 auto;
padding: 0 24px 0;
position: relative;
}
/* ── Screens ── */
.screen {
display: none;
animation: screenEnter 0.42s cubic-bezier(.25,.8,.25,1) both;
}
.screen.active { display: block; }
.screen.leaving {
display: block;
position: absolute;
top: 0; left: 24px; right: 24px;
animation: screenLeave 0.3s ease forwards;
pointer-events: none;
}
@keyframes screenEnter {
from { opacity: 0; transform: translateY(24px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes screenLeave {
from { opacity: 1; transform: translateY(0); }
to { opacity: 0; transform: translateY(-14px); }
}
/* ── Header shared ── */
.pre-logo {
padding-top: 40px;
margin-bottom: 40px;
}
.pre-logo img {
width: 100%;
max-height: 80px;
object-fit: contain;
object-position: center;
display: block;
}
.pre-logo-sep {
width: 1px;
height: 28px;
background: rgba(11,12,13,0.15);
flex-shrink: 0;
}
.pre-logo-anni {
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
font-size: 11px;
font-weight: 500;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--text-dim);
white-space: nowrap;
}
/* ── Inline disaster word pill ── */
.disaster-pill {
display: inline-block;
color: #000000;
font-style: normal;
font-size: 1em;
font-weight: 700;
min-width: 5em;
text-align: left;
vertical-align: baseline;
transition: opacity 0.5s ease;
}
.disaster-pill.fade { opacity: 0; }
/* ── Typography ── */
.headline {
font-family: 'Platypi', Georgia, serif;
font-size: clamp(30px, 7.5vw, 46px);
font-weight: 300;
line-height: 1.3;
letter-spacing: -0.01em;
color: var(--text);
text-align: center;
margin-bottom: 10px;
}
.subheadline {
font-size: clamp(14px, 3.2vw, 16px);
color: var(--text-muted);
text-align: center;
line-height: 1.55;
max-width: 420px;
margin: 0 auto 28px;
}
/* ── Counter block ── */
.counter-block {
text-align: center;
margin: 0 auto 28px;
}
.counter-number {
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
font-size: clamp(56px, 15vw, 96px);
font-weight: 800;
letter-spacing: -0.03em;
color: var(--text);
line-height: 1;
display: block;
font-variant-numeric: tabular-nums;
transition: color 0.15s ease;
}
@keyframes counterPulse {
0% { color: var(--text); }
20% { color: #e82340; }
100% { color: var(--text); }
}
.counter-pulse {
animation: counterPulse 0.9s ease-out forwards;
}
.counter-label {
font-size: clamp(14px, 3.2vw, 16px);
color: var(--text);
letter-spacing: 0.02em;
line-height: 1.7;
max-width: 380px;
margin: 10px auto 0;
}
/* ── CTA area ── */
.cta-question {
font-size: clamp(14px, 3.2vw, 16px);
color: var(--text-muted);
text-align: center;
margin: 24px auto 10px;
line-height: 1.5;
max-width: 420px;
}
.btn-primary {
display: block;
width: 100%;
max-width: 360px;
margin: 0 auto;
background: var(--accent);
border: none;
border-radius: 48px;
padding: 16px 28px;
color: #fff;
font-size: 16px;
font-weight: 600;
font-family: inherit;
cursor: pointer;
letter-spacing: 0.03em;
text-align: center;
transition: opacity 0.2s ease, transform 0.15s ease;
}
.btn-primary:hover { opacity: 0.86; }
.btn-primary:active { transform: scale(0.97); opacity: 1; }
/* ── Screen 2: Lead capture ── */
#screen-2 .headline {
margin-top: 20px;
}
.lead-sub {
font-size: 14px;
color: var(--text-muted);
text-align: center;
line-height: 1.65;
max-width: 460px;
margin: 0 auto 40px;
}
.input-wrap {
max-width: 360px;
margin: 0 auto 4px;
}
.input-field {
width: 100%;
background: #fff;
border: 1px solid rgba(11,12,13,0.3);
border-radius: 0;
padding: 12px 14px 12px 100px;
color: var(--text);
font-size: 22px;
font-family: inherit;
outline: none;
text-align: left;
transition: border-color 0.25s ease;
-webkit-appearance: none;
}
.input-field::placeholder { color: var(--text-dim); font-size: 20px; }
.input-field:focus { border-color: var(--text); }
.input-field.error {
border-color: #e82340;
animation: shake 0.3s ease;
}
@keyframes shake {
0%,100% { transform: translateX(0); }
25% { transform: translateX(-6px); }
75% { transform: translateX(6px); }
}
.input-error-msg {
font-size: 13px;
color: #e82340;
text-align: center;
margin-top: 8px;
min-height: 18px;
opacity: 0;
transition: opacity 0.25s ease;
}
.input-error-msg.visible { opacity: 1; }
.trust-line {
text-align: center;
font-size: 12px;
color: var(--text-dim);
font-weight: 400;
margin: 14px auto 28px;
letter-spacing: 0.02em;
}
.btn-wrap {
max-width: 360px;
margin: 0 auto;
}
.btn-wrap .btn-primary { max-width: 100%; }
/* ── Inline phone section ── */
#phone-section {
margin-top: 0;
}
.form-headline {
font-family: 'Platypi', Georgia, serif;
font-size: clamp(19px, 4.8vw, 27px);
font-weight: 300;
line-height: 1.3;
text-align: center;
margin-bottom: 28px;
color: var(--text);
}
/* ── Screen 3: Thank you ── */
#screen-3 {
padding-top: 48px;
text-align: center;
}
.check-icon {
width: 72px;
height: 72px;
background: #e82340;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 32px;
animation: popIn 0.4s cubic-bezier(.34,1.56,.64,1) both;
}
@keyframes popIn {
from { transform: scale(0.4); opacity: 0; }
to { transform: scale(1); opacity: 1; }
}
.check-icon svg {
width: 34px;
height: 34px;
}
.check-icon .check-path {
stroke-dasharray: 30;
stroke-dashoffset: 30;
animation: drawCheck 0.5s cubic-bezier(.4,0,.2,1) 0.25s forwards;
}
@keyframes drawCheck {
to { stroke-dashoffset: 0; }
}
#screen-3 .headline {
margin-top: 0;
margin-bottom: 16px;
}
.thanks-sub {
font-size: 15px;
color: var(--text-muted);
line-height: 1.7;
max-width: 420px;
margin: 0 auto;
}
/* ── Footer ── */
.footer-glow {
margin-top: 80px;
text-align: center;
font-size: 12px;
color: var(--text-dim);
letter-spacing: 0.08em;
padding-bottom: 40px;
}
.glow-rule {
width: 60px;
height: 2px;
background: var(--accent);
margin: 0 auto 16px;
opacity: 0.7;
border-radius: 1px;
}
@media (max-width: 400px) {
.page { padding: 0 16px 0; }
}
</style>
</head>
<body>
<noscript><p> height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript></p> <p> <!-- End Google Tag Manager (noscript) --></p> <div class="page"><p> </p> <p> </p> <p> <!-- ══════════ SCREEN 1 ══════════ --></p> <div id="screen-1" class="screen active"><p> </p> <p> </p> <div class="pre-logo"><p> </p></div> <p> </p> <h1 class="headline">In caso di <span class="disaster-pill" id="disaster-word">Terremoti</span><br>ogni minuto conta.</h1> <p> </p> <p class="subheadline">Permetti alla <strong>Catena della Solidarietà</strong> di<br>informarti quando è necessario un aiuto rapido?</p> <p> </p> <div class="counter-block"><p> </p> <p> <span class="counter-number" id="counter-num">0</span></p> <p class="counter-label">sono già iscritti.</p></div> <p> </p> <p class="cta-question">Il tuo numero di cellulare:</p> <p> </p> <div id="phone-section"><p> </p> <div class="input-wrap"><p> </p> <p> <input</p> <p> class="input-field"</p> <p> type="tel"</p> <p> id="phone-input"</p> <p> placeholder="079 123 45 67"</p> <p> inputmode="tel"</p> <p> autocomplete="tel"</p> <p> /></p></div> <p> <input type="text" name="website" id="hp-website" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px;width:1px;height:1px;opacity:0" aria-hidden="true"></p> <p class="input-error-msg" id="phone-error-msg">Inserisci un numero di cellulare svizzero (07X XXX XX XX)</p> <p class="trust-line">Nessuna chiamata · nessuna pubblicità · nessuna condivisione con terzi</p> <p class="trust-line" style="margin-top:4px">Un'azione per l'80° anniversario della Catena della Solidarietà</p> <div class="btn-wrap"><p> </p> <p> <button class="btn-primary" id="btn-submit">Attiva l'avviso SMS</button></p></div> <p> </p></div> <p> </p></div> <p> </p> <p> <!-- ══════════ SCREEN 3 ══════════ --></p> <div id="screen-3" class="screen"><p> </p> <div class="check-icon"><p> </p> <p> <svg viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg"></p> <p> <path class="check-path" d="M7 18L14 25L27 10" stroke="#ffffff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></p> <p> </svg></p></div> <p> </p> <h1 class="headline">Grazie.<br>La tua solidarietà conta.</h1> <p> </p> <p> <p class="thanks-sub"></p> <p> È fantastico che possiamo contare su di te in caso di emergenza.<br><br></p> <p> Quando la Catena della Solidarietà lancia una grande campagna di solidarietà, ti informiamo via SMS.</p> <p> </p></p> <p> </p></div> <p> </p></div> <p> </p> <p><script></p> <p>// ── Disaster word crossfade ────────────────────────────────</p> <p>(function() {</p> <p> const WORDS = ['Terremoti','disastri naturali','frane','tempeste','alluvioni','siccità'];</p> <p> const el = document.getElementById('disaster-word');</p> <p> let idx = 0;</p> <p> </p> <p> setInterval(() => {</p> <p> el.classList.add('fade');</p> <p> setTimeout(() => {</p> <p> idx = (idx + 1) % WORDS.length;</p> <p> el.textContent = WORDS[idx];</p> <p> el.classList.remove('fade');</p> <p> }, 500);</p> <p> }, 3400);</p> <p>})();</p> <p> </p> <p>// ── Counter animation ───────────────────────────────────────</p> <p>(function() {</p> <p> const el = document.getElementById('counter-num');</p> <p> const DURATION = 2200;</p> <p> </p> <p> function easeOut(t) { return 1 - Math.pow(1 - t, 18); }</p> <p> </p> <p> function runAnimation(target) {</p> <p> const TARGET = target;</p> <p> const start = performance.now();</p> <p> </p> <p> function step(ts) {</p> <p> const t = Math.min(1, (ts - start) / DURATION);</p> <p> const val = Math.round(easeOut(t) * TARGET);</p> <p> el.textContent = val.toLocaleString('it-IT');</p> <p> if (t < 1) { requestAnimationFrame(step); } else { startLiveTicker(TARGET); }</p> <p> }</p> <p> requestAnimationFrame(step);</p> <p> </p> <p> function startLiveTicker(count) {</p> <p> revealPhoneSection();</p> <p> let first = true;</p> <p> function tick() {</p> <p> const delay = first ? 400 : 2000 + Math.random() * 13000;</p> <p> first = false;</p> <p> setTimeout(() => {</p> <p> count++;</p> <p> el.textContent = count.toLocaleString('it-IT');</p> <p> el.classList.remove('counter-pulse');</p> <p> void el.offsetWidth;</p> <p> el.classList.add('counter-pulse');</p> <p> setTimeout(() => el.classList.remove('counter-pulse'), 900);</p> <p> tick();</p> <p> }, delay);</p> <p> }</p> <p> tick();</p> <p> }</p> <p> }</p> <p> </p> <p> // Load real count from server; fall back to hardcoded value</p> <p> fetch('api/count.php')</p> <p> .then(r => r.ok ? r.json() : Promise.reject())</p> <p> .then(data => runAnimation(data.count || 24096))</p> <p> .catch(() => runAnimation(24096));</p> <p>})();</p> <p> </p> <p>// ── Screen transitions ──────────────────────────────────────</p> <p>function showScreen(id) {</p> <p> const current = document.querySelector('.screen.active');</p> <p> const next = document.getElementById(id);</p> <p> window.scrollTo({ top: 0, behavior: 'instant' });</p> <p> if (current && current !== next) {</p> <p> current.classList.add('leaving');</p> <p> current.classList.remove('active');</p> <p> setTimeout(() => current.classList.remove('leaving'), 320);</p> <p> setTimeout(() => next.classList.add('active'), 200);</p> <p> } else {</p> <p> next.classList.add('active');</p> <p> }</p> <p>}</p> <p> </p> <p>function revealPhoneSection() {</p> <p> const s = document.getElementById('phone-section');</p> <p> if (s.classList.contains('visible')) return;</p> <p> s.classList.add('visible');</p> <p> setTimeout(() => s.scrollIntoView({ behavior: 'smooth', block: 'nearest' }), 200);</p> <p>}</p> <p> </p> <p>// ── UTM-Parameter aus URL ────────────────────────────────────</p> <p>function getUtm() {</p> <p> const p = new URLSearchParams(location.search);</p> <p> const utm = {};</p> <p> ['utm_source','utm_medium','utm_campaign'].forEach(k => {</p> <p> const v = p.get(k);</p> <p> if (v) utm[k] = v.slice(0, 100);</p> <p> });</p> <p> return utm;</p> <p>}</p> <p> </p> <p>// ── Telefonnummer-Format ────────────────────────────────────</p> <p>function formatPhoneInput(e) {</p> <p> const input = e.target;</p> <p> const isPlus = input.value.startsWith('+');</p> <p> const digits = input.value.replace(/\D/g, '');</p> <p> let f = '';</p> <p> if (isPlus) {</p> <p> if (digits.length <= 2) f = '+' + digits;</p> <p> else if (digits.length <= 4) f = '+' + digits.slice(0,2) + ' ' + digits.slice(2);</p> <p> else if (digits.length <= 7) f = '+' + digits.slice(0,2) + ' ' + digits.slice(2,4) + ' ' + digits.slice(4);</p> <p> else if (digits.length <= 9) f = '+' + digits.slice(0,2) + ' ' + digits.slice(2,4) + ' ' + digits.slice(4,7) + ' ' + digits.slice(7);</p> <p> else f = '+' + digits.slice(0,2) + ' ' + digits.slice(2,4) + ' ' + digits.slice(4,7) + ' ' + digits.slice(7,9) + ' ' + digits.slice(9,11);</p> <p> } else {</p> <p> if (digits.length <= 3) f = digits;</p> <p> else if (digits.length <= 6) f = digits.slice(0,3) + ' ' + digits.slice(3);</p> <p> else if (digits.length <= 8) f = digits.slice(0,3) + ' ' + digits.slice(3,6) + ' ' + digits.slice(6);</p> <p> else f = digits.slice(0,3) + ' ' + digits.slice(3,6) + ' ' + digits.slice(6,8) + ' ' + digits.slice(8,10);</p> <p> }</p> <p> input.value = f;</p> <p>}</p> <p> </p> <p>// ── Phone submit ──────────────────────────────────────────</p> <p>const phoneInput = document.getElementById('phone-input');</p> <p>const btnSubmit = document.getElementById('btn-submit');</p> <p>const phoneErrorMsg = document.getElementById('phone-error-msg');</p> <p> </p> <p>phoneInput.addEventListener('input', formatPhoneInput);</p> <p> </p> <p>function submitPhone() {</p> <p> const val = phoneInput.value.trim().replace(/\s/g, '');</p> <p> // Validation: Swiss phone numbers only</p> <p> if (!/^(\+41|07)\d{7,9}$/.test(val)) {</p> <p> phoneInput.classList.add('error');</p> <p> phoneErrorMsg.classList.add('visible');</p> <p> setTimeout(() => { phoneInput.classList.remove('error'); phoneErrorMsg.classList.remove('visible'); }, 3000);</p> <p> return;</p> <p> }</p> <p> try { localStorage.setItem('glueckskette_phone', val); } catch(e) {}</p> <p> // Send to server: subscribe.php</p> <p> fetch('/alert/api/subscribe.php', {</p> <p> method: 'POST',</p> <p> headers: { 'Content-Type': 'application/json' },</p> <p> body: JSON.stringify({ phone: val, lang: 'IT', source: 'c-i', hp: document.getElementById('hp-website').value, ...getUtm() })</p> <p> }).then(() => {</p> <p> // Success: show thank you screen</p> <p> showScreen('screen-3');</p> <p> }).catch(err => {</p> <p> console.error('Errore:', err);</p> <p> // On error: still show thank you to avoid blocking user</p> <p> showScreen('screen-3');</p> <p> });</p> <p>}</p> <p> </p> <p>btnSubmit.addEventListener('click', submitPhone);</p> <p>phoneInput.addEventListener('keydown', e => { if (e.key === 'Enter') submitPhone(); });</p> <p></script></p> <p></body></p> <p></html></p> </body>

