PageSourceSearch

https://www.verbumradio.com/vetrina-prodotti.html

html verbumradio.com collected 2026-10-01 15:03:58 UTC 32,259 bytes, 548 lines download raw bytes

1<!DOCTYPE html>
2<html lang="it">
3<head>
4  <meta charset="UTF-8">
5  <meta name="viewport" content="width=device-width, initial-scale=1">
6  <title>Vetrina Prodotti e Servizi — VerbumRadio</title>
7  <meta name="description" content="Prodotti, servizi e piani VerbumRadio per Radio Streaming e Video Streaming: apparati, servizi aggiuntivi e abbonamenti per parrocchie, santuari e comunità.">
8  <link rel="canonical" href="https://www.verbumradio.com/vetrina-prodotti.html">
9  <meta name="robots" content="index, follow">
10  <meta property="og:type" content="website">
11  <meta property="og:site_name" content="VerbumRadio">
12  <meta property="og:locale" content="it_IT">
13  <meta property="og:title" content="Prodotti, Servizi e Piani — Radio e Video streaming | VerbumRadio">
14  <meta property="og:description" content="Apparati, servizi e piani per trasmettere in diretta streaming la Santa Messa: soluzioni radio e video per parrocchie e santuari.">
15  <meta property="og:url" content="https://www.verbumradio.com/vetrina-prodotti.html">
16  <meta property="og:image" content="https://www.verbumradio.com/immagini/og-verbumradio.jpg">
17  <meta name="twitter:card" content="summary_large_image">
18  <meta name="twitter:title" content="Prodotti, Servizi e Piani — Radio e Video streaming | VerbumRadio">
19  <meta name="twitter:description" content="Apparati, servizi e piani per trasmettere in diretta streaming la Santa Messa: soluzioni radio e video per parrocchie e santuari.">
20  <meta name="twitter:image" content="https://www.verbumradio.com/immagini/og-verbumradio.jpg">
21  
21<script type="application/ld+json">
22  {
23    "@context":"https://schema.org",
24    "@type":"Service",
25    "serviceType":"Radio e video streaming per parrocchie e santuari",
26    "name":"Prodotti, servizi e piani VerbumRadio",
27    "provider":{"@type":"Organization","name":"VerbumRadio","alternateName":"A.D.V. Telecommunications","url":"https://www.verbumradio.com/","telephone":"+39 02 9517056","email":"[email protected]","address":{"@type":"PostalAddress","addressLocality":"Gorgonzola","addressRegion":"MI","addressCountry":"IT"}},
28    "areaServed":"IT",
29    "description":"Apparati, servizi aggiuntivi e piani di abbonamento per trasmettere in diretta streaming le celebrazioni: radio e video streaming.",
30    "url":"https://www.verbumradio.com/vetrina-prodotti.html"
31  }
32  </script>
32
33  <link rel="preconnect" href="https://fonts.googleapis.com">
34  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
35  <link href="https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
36  <style>
37  :root{
38    --terra:#8a4020; --terra-dk:#6b3018; --terra-lt:#f5e8df; --terra-xlt:#fdf2ec; --terra-soft:#c98352;
39    --blu:#185FA5; --blu-dk:#124a82;
40    --brown:#2d2416; --brown-md:#5a4a38; --brown-lt:#8a7560; --brown-xlt:#c5b8a8;
41    --cream:#faf8f5; --cream-2:#f3ede4; --line:#e7ddd0;
42    --green:#4a7c59;
43  }
44  *{box-sizing:border-box;margin:0;padding:0}
45  body{font-family:'Inter',system-ui,-apple-system,'Segoe UI',sans-serif;color:var(--brown);background:var(--cream);line-height:1.6;overflow-x:hidden}
46  a{color:inherit}
47  img{max-width:100%;display:block}
48  .wrap{max-width:1120px;margin:0 auto;padding:0 20px}
49
50  /* Barra superiore */
51  .topbar{position:sticky;top:0;z-index:20;background:rgba(45,36,22,.96);backdrop-filter:blur(6px);color:#fff;
52    border-bottom:1px solid rgba(255,255,255,.08)}
53  .topbar .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;padding-top:14px;padding-bottom:14px}
54  .brand{font-family:'Lora',Georgia,serif;font-size:22px;font-weight:700;color:#fff;text-decoration:none;white-space:nowrap}
55  .brand span{color:var(--terra-soft)}
56  .top-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:flex-end}
57  .top-actions a{font-size:13.5px;text-decoration:none;color:#e9dfd4;padding:7px 12px;border-radius:999px;transition:.15s}
58  .top-actions a:hover{background:rgba(255,255,255,.10);color:#fff}
59  .wa{display:inline-flex;align-items:center;gap:7px;background:#25d366;color:#fff !important;font-weight:700;
60    box-shadow:0 8px 20px -10px rgba(37,211,102,.9)}
61  .wa:hover{background:#1eb457 !important}
62  .wa svg{width:17px;height:17px;fill:currentColor;flex-shrink:0}
63
64  /* Intestazione pagina */
65  .page-hero{background:linear-gradient(180deg,var(--terra-xlt),var(--cream));border-bottom:1px solid var(--line)}
66  .page-hero .wrap{padding-top:46px;padding-bottom:38px}
67  .eyebrow{font-size:12.5px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--terra-dk)}
68  h1{font-family:'Lora',Georgia,serif;font-size:clamp(30px,4.4vw,46px);line-height:1.1;color:var(--terra-dk);margin:8px 0 12px}
69  .page-hero p{max-width:60ch;color:var(--brown-md);font-size:16.5px}
70  /* Due banner affiancati, ciascuno linka alla propria sezione */
71  .banner-row{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:28px}
72  .banner{display:block;border-radius:16px;overflow:hidden;border:1px solid var(--line);background:#fff;
73    box-shadow:0 18px 44px -30px rgba(45,36,22,.6);transition:transform .16s ease, box-shadow .16s ease}
74  .banner:hover{transform:translateY(-3px);box-shadow:0 26px 54px -28px rgba(45,36,22,.7)}
75  .banner:focus-visible{outline:2px solid var(--terra);outline-offset:3px}
76  .banner img{width:100%;height:auto;display:block}
77  @media(max-width:640px){.banner-row{grid-template-columns:1fr;gap:16px}}
78
79  /* Sezione categoria */
80  .cat{padding:52px 0;scroll-margin-top:74px}
81  .cat + .cat{border-top:1px solid var(--line)}
82  .cat.video{background:var(--cream-2)}
83  /* Titolo della sezione (la si raggiunge cliccando il banner in cima) */
84  .cat-title{margin-bottom:6px;text-align:center}
85  .cat-title .eyebrow{color:var(--terra-dk)}
86  .cat.video .cat-title .eyebrow{color:var(--blu-dk)}
87  .cat-title h2{font-family:'Lora',serif;font-size:clamp(26px,3.4vw,36px);color:var(--terra-dk);margin-top:6px;line-height:1.15}
88  .cat.video .cat-title h2{color:var(--blu-dk)}
89  /* Riquadro-spiegazione: cosa significa avviare il servizio */
90  .cat-intro{background:var(--terra-xlt);border:1px solid var(--terra-lt);border-left:5px solid var(--terra);
91    border-radius:14px;padding:18px 22px;margin:14px 0 30px}
92  .cat.video .cat-intro{background:#eef4fb;border-color:#d6e4f3;border-left-color:var(--blu)}
93  .cat-intro .lead{font-family:'Lora',serif;font-size:clamp(18px,2.2vw,22px);font-weight:600;color:var(--terra-dk);line-height:1.35}
94  .cat.video .cat-intro .lead{color:var(--blu-dk)}
95  .cat-intro p.more{color:var(--brown-md);font-size:15.5px;margin-top:8px}
96  .cat-intro strong{color:var(--terra-dk)}
97  .cat.video .cat-intro strong{color:var(--blu-dk)}
98  .vh{position:absolute !important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
99
100  /* Sotto-blocchi Prodotti / Servizi / Piani */
101  .sub{margin-top:34px}
102  .sub-title{display:flex;align-items:center;justify-content:center;gap:14px;margin-bottom:16px}
103  .sub-title::before{content:"";flex:1;height:1px;background:var(--line)}
104  .sub-title h3{font-family:'Lora',serif;font-size:clamp(22px,2.4vw,26px);color:var(--brown);white-space:nowrap}
105  .sub-title .count{font-size:13px;color:var(--brown-lt);white-space:nowrap}
106  .sub-title .rule{flex:1;height:1px;background:var(--line)}
107
108  /* Card prodotto: immagine + descrizione a fianco */
109  .items{display:grid;gap:16px}
110  .pcard{display:grid;grid-template-columns:200px 1fr;gap:20px;background:#fff;border:1px solid var(--line);
111    border-radius:16px;padding:16px;box-shadow:0 14px 34px -28px rgba(45,36,22,.55)}
112  .pcard .thumb{border-radius:12px;overflow:hidden;background:var(--cream-2);aspect-ratio:4/3;display:flex;align-items:center;justify-content:center}
113  .pcard .thumb img{width:100%;height:100%;object-fit:cover}
114  .pcard .thumb.ph{color:var(--brown-xlt);font-size:13px;font-style:italic}
115  .pcard .body{align-self:center}
116  .pcard .name{font-family:'Lora',serif;font-size:19px;color:var(--brown);margin-bottom:4px}
117  .pcard .desc{color:var(--brown-md);font-size:14.5px;margin-top:6px}
118  .badge-pop{display:inline-block;background:var(--terra);color:#fff;font-size:11px;font-weight:700;padding:2px 9px;border-radius:999px;margin-left:8px;vertical-align:middle}
119  .price{display:inline-block;font-weight:700;color:var(--terra-dk);font-size:18px}
120  .cat.video .price{color:var(--blu-dk)}
121  .price .u{font-size:12.5px;font-weight:600;color:var(--brown-lt)}
122  .feats{list-style:none;margin:10px 0 0;display:flex;flex-wrap:wrap;gap:6px 14px}
123  .feats li{position:relative;padding-left:16px;font-size:13px;color:var(--brown-md)}
124  .feats li::before{content:"";position:absolute;
124left:0;top:7px;width:7px;height:7px;border-radius:50%;background:var(--green)}
125  /* Link acquisto (solo se il prodotto è attivo nell'e-commerce) */
126  .buy{margin-top:14px}
127  .buy-btn{display:inline-flex;align-items:center;gap:8px;background:var(--terra);color:#fff;text-decoration:none;
128    font-weight:700;font-size:14px;padding:10px 18px;border-radius:999px;transition:transform .15s ease,background .15s ease;
129    box-shadow:0 10px 22px -12px rgba(138,64,32,.85)}
130  .buy-btn:hover{background:var(--terra-dk);transform:translateY(-1px)}
131  .buy-btn:focus-visible{outline:2px solid var(--terra-dk);outline-offset:2px}
132  .cat.video .buy-btn{background:var(--blu);box-shadow:0 10px 22px -12px rgba(24,95,165,.85)}
133  .cat.video .buy-btn:hover{background:var(--blu-dk)}
134  .soldout{display:inline-block;margin-top:12px;font-size:13px;color:var(--brown-lt);background:var(--cream-2);
135    border:1px solid var(--line);border-radius:999px;padding:5px 13px}
136  /* Link "Come funziona la radio" in fondo ai servizi radio */
137  .svc-more{margin-top:16px}
138  .how-link{display:inline-flex;align-items:center;gap:8px;font-weight:700;font-size:14.5px;color:var(--terra-dk);
139    text-decoration:none;border:1.5px solid var(--terra-lt);background:var(--terra-xlt);border-radius:999px;padding:9px 18px;transition:.15s}
140  .how-link:hover{border-color:var(--terra);transform:translateY(-1px)}
141  .how-link span{transition:transform .15s}
142  .how-link:hover span{transform:translateX(3px)}
143
144  /* Card servizio (più compatta) */
145  .scard{display:grid;grid-template-columns:96px 1fr auto;gap:16px;align-items:center;background:#fff;border:1px solid var(--line);
146    border-radius:14px;padding:14px 16px}
147  .scard .thumb{width:96px;height:72px;border-radius:10px;overflow:hidden;background:var(--cream-2);display:flex;align-items:center;justify-content:center}
148  .scard .thumb img{width:100%;height:100%;object-fit:cover}
149  .scard.noimg{grid-template-columns:1fr auto}
150  .scard .name{font-weight:700;font-size:16px;color:var(--brown)}
151  .scard .desc{color:var(--brown-md);font-size:14px;margin-top:2px}
152  .scard .plans-tag{display:inline-block;margin-top:6px;font-size:11.5px;color:var(--brown-lt);background:var(--cream-2);border:1px solid var(--line);border-radius:999px;padding:2px 10px}
153  .scard .sprice{text-align:right;white-space:nowrap}
154  .scard .sprice .p{font-weight:700;color:var(--terra-dk);font-size:16px}
155  .cat.video .scard .sprice .p{color:var(--blu-dk)}
156  .scard .sprice small{display:block;color:var(--brown-lt);font-size:11.5px}
157
158  /* Piani */
159  .plans{display:grid;grid-template-columns:1fr 1fr;gap:18px}
160  .plan{display:flex;flex-direction:column;background:#fff;border:1px solid var(--line);border-radius:18px;overflow:hidden;
161    box-shadow:0 18px 44px -32px rgba(45,36,22,.6)}
162  .plan .pimg{aspect-ratio:16/9;background:var(--cream-2);overflow:hidden}
163  .plan .pimg img{width:100%;height:100%;object-fit:cover}
164  .plan .pin{padding:18px 20px 20px;display:flex;flex-direction:column;flex:1}
165  .plan .pname{font-family:'Lora',serif;font-size:20px;color:var(--terra-dk)}
166  .cat.video .plan .pname{color:var(--blu-dk)}
167  .plan .pdesc{color:var(--brown-md);font-size:14.5px;margin:8px 0 14px}
168  .plan .pprice{font-size:26px;font-weight:700;color:var(--brown);margin-top:auto}
169  .plan .pprice .u{font-size:14px;font-weight:600;color:var(--brown-lt)}
170  .plan .pcta{margin-top:14px}
171  .plan .pcta a{display:inline-flex;align-items:center;gap:8px;background:#25d366;color:#fff;text-decoration:none;font-weight:700;
172    font-size:14px;padding:10px 16px;border-radius:999px;transition:.15s;box-shadow:0 8px 20px -10px rgba(37,211,102,.9)}
173  .plan .pcta a:hover{background:#1eb457;transform:translateY(-1px)}
174  .plan .pcta a svg{width:17px;height:17px;fill:currentColor}
175
176  .empty-note{background:#fff;border:1px dashed var(--line);border-radius:14px;padding:20px;color:var(--brown-lt);font-size:14.5px;text-align:center}
177  .loading{color:var(--brown-lt);font-size:15px;padding:8px 0}
178
179  footer{background:var(--brown);color:#e9dfd4;margin-top:0;padding:34px 0}
180  footer .wrap{text-align:center;font-size:13.5px;line-height:1.7}
181  footer .brand{font-size:20px}
182  footer a{color:var(--terra-soft);text-decoration:none}
183
184  @media(max-width:820px){
185    .plans{grid-template-columns:1fr}
186  }
187  @media(max-width:560px){
188    .pcard{grid-template-columns:1fr}
189    .pcard .thumb{aspect-ratio:16/9}
190    .scard{grid-template-columns:1fr;text-align:left}
191    .scard .thumb{width:100%;height:150px}
192    .scard .sprice{text-align:left}
193  }
194  @media(prefers-reduced-motion:reduce){*{transition:none !important}}
195
196  /* Modalità "embed": quando la pagina è inclusa in un iframe (es. nella landing),
197     nasconde barra, intestazione testuale e footer, lasciando i banner e i contenuti. */
198  html.is-embed body{background:transparent}
199  html.is-embed .topbar, html.is-embed footer{display:none}
200  html.is-embed .page-hero{background:none;border-bottom:none}
201  html.is-embed .page-hero .eyebrow, html.is-embed .page-hero h1, html.is-embed .page-hero p{display:none}
202  html.is-embed .page-hero .wrap{padding-top:18px;padding-bottom:0}
203  </style>
204  <link rel="stylesheet" href="theme.php?css">
205  
205<script>
206  /* Modalità embed (iframe): attiva la classe e comunica l'altezza al contenitore per l'auto-resize. */
207  (function(){
208    try{
209      var p=new URLSearchParams(location.search);
210      if(p.get('embed')!=='1') return;
211      document.documentElement.classList.add('is-embed');
212      function postH(){ try{ parent.postMessage({vetrinaHeight: Math.ceil(document.body.getBoundingClientRect().height)}, '*'); }catch(e){} }
213      window.addEventListener('load', postH);
214      window.addEventListener('resize', postH);
215      document.addEventListener('DOMContentLoaded', function(){
216        postH();
217        if('ResizeObserver' in window){ try{ new ResizeObserver(postH).observe(document.body); }catch(e){} }
218        var n=0, t=setInterval(function(){ postH(); if(++n>20) clearInterval(t); }, 500); // rete di sicurezza mentre i dati si caricano
219      });
220    }catch(e){}
221  })();
222  </script>
222
223</head>
224<body>
225
226  <div class="topbar">
227    <div class="wrap">
228      <a class="brand" href="index.html">Verbum<span>Radio</span></a>
229      <div class="top-actions">
230        <a href="index.html">Home</a>
231        <a href="ecommerce-verbumradio/landing.html">Shop &amp; servizi</a>
232        <a class="wa" href="https://wa.me/393355990528?text=Salve%2C%20vorrei%20informazioni%20su%20prodotti%20e%20servizi%20VerbumRadio." target="_blank" rel="noopener">
233          <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M17.5 14.4c-.3-.15-1.7-.85-2-.95-.25-.1-.45-.15-.6.15-.2.3-.7.95-.85 1.1-.15.2-.3.2-.6.05-.3-.15-1.25-.45-2.4-1.5-.9-.8-1.5-1.75-1.65-2.05-.15-.3 0-.45.15-.6.15-.15.3-.35.45-.55.15-.15.2-.3.3-.5.1-.2.05-.35-.05-.5-.1-.15-.6-1.5-.85-2.05-.2-.5-.45-.45-.6-.45h-.5c-.2 0-.5.05-.75.35-.25.3-1 .95-1 2.35s1.05 2.75 1.2 2.9c.15.2 2.05 3.15 5 4.4.7.3 1.25.5 1.65.6.7.2 1.3.2 1.8.1.55-.1 1.7-.7 1.95-1.35.25-.65.25-1.2.15-1.35-.1-.15-.3-.2-.6-.35zM12 2a10 10 0 0 0-8.6 15.1L2 22l5-1.3A10 10 0 1 0 12 2z"></path></svg>
234          Chiedi informazioni
235        </a>
236      </div>
237    </div>
238  </div>
239
240  <header class="page-hero">
241    <div class="wrap">
242      <div class="eyebrow">Vetrina VerbumRadio</div>
243      <h1>Prodotti e Servizi</h1>
244      <p>Tutto ciò che serve per portare la vita della vostra comunità online: apparati, servizi aggiuntivi e piani di abbonamento, per la <strong>Radio Streaming</strong> e il <strong>Video Streaming</strong>.</p>
245      <div class="banner-row">
246        <a class="banner" href="#radio" id="radioBanner" aria-label="Vai alla sezione Radio Streaming"></a>
247        <a class="banner" href="#video" id="videoBanner" aria-label="Vai alla sezione Video Streaming"></a>
248      </div>
249    </div>
250  </header>
251
252  <!-- ═══════════ RADIO ═══════════ -->
253  <section class="cat radio" id="radio">
254    <div class="wrap">
255      <div class="cat-title">
256        <span class="eyebrow">Prodotti e Servizi</span>
257        <h2>Radio Streaming</h2>
258      </div>
259
260      <div class="cat-intro" id="radioIntro">
261        <p class="lead" id="radioIntroLead">Avviare la vostra Radio Streaming significa dare voce alla comunità, ogni giorno, 24 ore su 24.</p>
262        <p class="more" id="radioIntroText">Le Sante Messe, il Rosario, gli avvisi e la musica raggiungono i fedeli <strong>ovunque si trovino</strong> — a casa, in auto, al lavoro — dal sito della parrocchia, dallo smartphone, dagli altoparlanti vocali e persino dalla Smart-TV. Una presenza semplice da gestire, che tiene tutti uniti.</p>
263      </div>
264
265      <div class="sub">
266        <div class="sub-title"><h3>Piani</h3><span class="rule"></span></div>
267        <div class="plans" id="radioPlans"></div>
268      </div>
269
270      <div class="sub">
271        <div class="sub-title"><h3>Prodotti</h3><span class="count" id="radioProdCount"></span><span class="rule"></span></div>
272        <div class="items" id="radioProducts"><div class="loading">Caricamento prodotti…</div></div>
273      </div>
274
275      <div class="sub">
276        <div class="sub-title"><h3>Servizi</h3><span class="count" id="radioSvcCount"></span><span class="rule"></span></div>
277        <div class="items" id="radioServices"></div>
278        <div class="svc-more">
279          <a class="how-link" href="info-radio.html" target="_blank" rel="noopener">Come funziona la radio <span aria-hidden="true">→</span></a>
280        </div>
281      </div>
282    </div>
283  </section>
284
285  <!-- ═══════════ VIDEO ═══════════ -->
286  <section class="cat video" id="video">
287    <div class="wrap">
288      <div class="cat-title">
289        <span class="eyebrow">Prodotti e Servizi</span>
290        <h2>Video Streaming</h2>
291      </div>
292
293      <div class="cat-intro" id="videoIntro">
294        <p class="lead" id="videoIntroLead">Avviare il vostro Video Streaming significa aprire le porte della chiesa a chi non può essere presente.</p>
295        <p class="more" id="videoIntroText">Le celebrazioni vanno <strong>in diretta e in alta definizione</strong> su qualsiasi Smart-TV, sul sito della parrocchia, sui social e su computer, tablet e smartphone. Gli anziani, i malati e i lontani tornano a vivere la liturgia con voi, <strong>come se fossero lì</strong>.</p>
296      </div>
297
298      <div class="sub">
299        <div class="sub-title"><h3>Piani</h3><span class="rule"></span></div>
300        <div class="plans" id="videoPlans"></div>
301      </div>
302
303      <div class="sub">
304        <div class="sub-title"><h3>Prodotti</h3><span class="count" id="videoProdCount"></span><span class="rule"></span></div>
305        <div class="items" id="videoProducts"><div class="loading">Caricamento prodotti…</div></div>
306      </div>
307
308      <div class="sub">
309        <div class="sub-title"><h3>Servizi</h3><span class="count" id="videoSvcCount"></span><span class="rule"></span></div>
310        <div class="items" id="videoServices"></div>
311      </div>
312    </div>
313  </section>
314
315  <footer>
316    <div class="wrap">
317      <a href="index.html" class="brand">Verbum<span style="color:var(--terra-soft)">Radio</span></a>
318      <p style="margin-top:8px">A.D.V. Telecommunications di Bogino Maurizio — P.IVA 10557300158<br>
319      [email protected] · Tel. 02 9517056 · 335 5990528</p>
320      <p style="margin-top:10px"><a href="ecommerce-verbumradio/landing.html">Vai allo shop e ai servizi →</a></p>
321    </div>
322  </footer>
323
324<script>
325(function(){
326  "use strict";
327  // I dati e le immagini stanno nella cartella dell'e-commerce (stessa fonte dello shop).
328  var INV_BASE = 'ecommerce-verbumradio/';
329  var TEL = '393355990528';
330
331  function esc(s){ return String(s==null?'':s).replace(/[&<>"]/g,function(c){return c==='&'?'&amp;':c==='<'?'&lt;':c==='>'?'&gt;':'&quot;';}); }
332
333  // Risolve un path immagine: URL assoluto → invariato; relativo → dentro la cartella e-commerce.
334  function img(u){
335    u=(u||'').trim(); if(!u) return '';
336    if(/^(https?:)?\/\//i.test(u) || u.indexOf('data:')===0) return u;
337    if(u.charAt(0)==='/') return u;
338    return INV_BASE + u.replace(/^\.\//,'');
339  }
340  // Formatta un prezzo in euro; ritorna '' se vuoto/non valido.
341  function eur(v){
342    if(v===''||v==null) return '';
343    var n=Number(v); if(isNaN(n)) return '';
344    var neg=n<0; n=Math.abs(n);
345    var intPart=Math.floor(n).toString().replace(/\B(?=(\d{3})+(?!\d))/g,'.'); // migliaia col punto
346    var cents=Math.round(n*100)%100, dec = cents ? (','+(cents<10?'0'+cents:cents)) : '';
347    return '€'+(neg?'-':'')+intPart+dec;
348  }
349  function waHref(msg){ return 'https://wa.me/'+TEL+'?text='+encodeURIComponent(msg); }
350  var WA_SVG='<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M17.5 14.4c-.3-.15-1.7-.85-2-.95-.25-.1-.45-.15-.6.15-.2.3-.7.95-.85 1.1-.15.2-.3.2-.6.05-.3-.15-1.25-.45-2.4-1.5-.9-.8-1.5-1.75-1.65-2.05-.15-.3 0-.45.15-.6.15-.15.3-.35.45-.55.15-.15.2-.3.3-.5.1-.2.05-.35-.05-.5-.1-.15-.6-1.5-.85-2.05-.2-.5-.45-.45-.6-.45h-.5c-.2 0-.5.05-.75.35-.25.3-1 .95-1 2.35s1.05 2.75 1.2 2.9c.15.2 2.05 3.15 5 4.4.7.3 1.25.5 1.65.6.7.2 1.3.2 1.8.1.55-.1 1.7-.7 1.95-1.35.25-.65.25-1.2.15-1.35-.1-.15-.3-.2-.6-.35zM12 2a10 10 0 0 0-8.6 15.1L2 22l5-1.3A10 10 0 1 0 12 2z"></path></svg>';
351
352  var LABEL={radio:'Radio Streaming', video:'Video Streaming'};
353  var BANNER_ALT={radio:'Radio Live Streaming', video:'Video Live Streaming'};
354  // Fallback del banner se l'admin non ha impostato l'immagine "tipo servizio"
355  var BANNER_FALLBACK={radio:INV_BASE+'immagini/svc-radio.jpg', video:INV_BASE+'immagini/svc-video.jpg'};
356  // Pagina di acquisto (il negozio-wizard dell'e-commerce)
357  var SHOP_URL=INV_BASE+'verbumradio-shop.html';
358  var MESI=['gennaio','febbraio','marzo','aprile','maggio','giugno','luglio','agosto','settembre','ottobre','novembre','dicembre'];
359  function fmtDate(s){ if(!s) return ''; var d=new Date(s); if(isNaN(d.getTime())) return esc(s); return d.getDate()+' '+MESI[d.getMonth()]+' '+d.getFullYear(); }
360
361  function productCard(p, cat, catActive){
362    var im=img(p.imageUrl);
363    var feats=(p.feats||'').split('\n').map(function(s){return s.trim();}).filter(Boolean);
364    var price=eur(p.price);
365    var stock=Number(p.stock||0);
366    var active=!!catActive && stock>=1;   // attivo nell'e-commerce = categoria abilitata e disponibile
367    var buy;
368    if(active){
369      buy='<div class="buy"><a class="buy-btn" href="'+esc(SHOP_URL)+'">Acquista <span aria-hidden="true">&rarr;</span></a></div>';
370    } else if(stock<1){
371      buy='<div class="buy"><span class="soldout">'+(p.availFrom?'Disponibile dal '+esc(fmtDate(p.availFrom)):'Non disponibile online')+'</span></div>';
372    } else { buy=''; }  // categoria non attiva: solo catalogo, nessun link
373    return '<div class="pcard">'+
374      (im?'<div class="thumb"><img src="'+esc(im)+'" alt="'+esc(p.name||'')+'" loading="lazy" onerror="this.parentNode.classList.add(\'ph\');this.remove();this.parentNode.textContent=\'immagine non disponibile\'"></div>'
375         :'<div class="thumb ph">nessuna foto</div>')+
376      '<div class="body">'+
377        '<div class="name">'+esc(p.name||'Prodotto')+(p.popular?'<span class="badge-pop">Consigliato</span>':'')+'</div>'+
378        (price?'<span class="price">'+price+'</span>':'')+
379        (p.desc?'<div class="desc">'+esc(p.desc)+'</div>':'')+
380        (feats.length?'<ul class="feats">'+feats.map(function(f){return '<li>'+esc(f)+'</li>';}).join('')+'</ul>':'')+
381        buy+
382      '</div>'+
383    '</div>';
384  }
385
386  function serviceCard(s, cat){
387    var im=img(s.imageUrl);
388    var single=(s.pricingModel==='single');
389    var p1=Number(s.priceP1||0), p2=Number(s.priceP2||0);
390    var priceHtml='';
391    if(single){ if(p1) priceHtml='<div class="p">'+eur(p1)+'</div>'; }
392    else{
393      if(p1||p2){
394        priceHtml='<div class="p">'+eur(p1||p2)+'</div>';
395        if(p1&&p2&&p1!==p2) priceHtml='<div class="p">'+eur(p1)+'</div><small>con apparato</small>'+
396                                      '<div class="p" style="margin-top:6px">'+eur(p2)+'</div><small>da solo</small>';
397      }
398    }
399    var plansArr=Array.isArray(s.availableInPlans)?s.availableInPlans:[];
400    var plansTag = plansArr.length ? '<span class="plans-tag">Disponibile nei piani: '+plansArr.map(function(x){return esc(x.charAt(0).toUpperCase()+x.slice(1));}).join(', ')+'</span>' : '';
401    var noimg = im ? '' : ' noimg';
402    return '<div class="scard'+noimg+'">'+
403      (im?'<div class="thumb"><img src="'+esc(im)+'" alt="'+esc(s.name||'')+'" loading="lazy" onerror="this.closest(\'.scard\').classList.add(\'noimg\');this.closest(\'.thumb\').remove()"></div>':'')+
404      '<div class="info"><div class="name">'+esc(s.name||'Servizio')+'</div>'+
405        (s.desc?'<div class="desc">'+esc(s.desc)+'</div>':'')+
406        (s.note?'<div class="desc" style="font-size:13px;color:var(--brown-lt)">'+esc(s.note)+'</div>':'')+
407        plansTag+
408      '</div>'+
409      '<div class="sprice">'+(priceHtml||'<small>su richiesta</small>')+'</div>'+
410    '</div>';
411  }
412
413  function planCard(pl, cat){
414    var im=img(pl.img);
415    var price=eur(pl.price);
416    var msg='Salve, vorrei informazioni sul piano '+(pl.name||'')+' ('+LABEL[cat]+') di VerbumRadio.';
417    return '<div class="plan">'+
418      (im?'<div class="pimg"><img src="'+esc(im)+'" alt="'+esc(pl.name||'')+'" loading="lazy" onerror="this.closest(\'.pimg\').remove()"></div>':'')+
419      '<div class="pin">'+
420        '<div class="pname">'+esc(pl.name||'Piano')+'</div>'+
421        (pl.desc?'<div class="pdesc">'+esc(pl.desc)+'</div>':'<div class="pdesc"></div>')+
422        '<div class="pprice">'+(price?price+' <span class="u">/ mese</span>':'<span class="u">Prezzo su richiesta</span>')+'</div>'+
423        '<div class="pcta"><a href="'+esc(waHref(msg))+'" target="_blank" rel="noopener">'+WA_SVG+' Chiedi informazioni</a></div>'+
424      '</div>'+
425    '</div>';
426  }
427
428  function fillCategory(cat, data){
429    // Banner in cima alla pagina (link alla sezione). Immagine gestita dall'admin
430    // (svcRadioImg/svcVideoImg); se assente, fallback a immagini/svc-<cat>.jpg.
431    var banner=document.getElementById(cat+'Banner');
432    var bim=img(data.svc.img) || BANNER_FALLBACK[cat];
433    banner.innerHTML='<img src="'+esc(bim)+'" alt="'+esc(BANNER_ALT[cat])+'" '+
434      'onerror="if(this.src.indexOf(\''+BANNER_FALLBACK[cat]+'\')<0){this.src=\''+BANNER_FALLBACK[cat]+'\';}else{this.closest(\'.banner\').style.display=\'none\';}">';
435
436    // Prodotti
437    var pc=document.getElementById(cat+'Products');
438    if(data.products.length){ pc.innerHTML=data.products.map(function(p){return productCard(p,cat,data.catActive);}).join(''); }
439    else { pc.innerHTML='<div class="empty-note">Nessun prodotto disponibile al momento. Scrivici per una soluzione su misura.<
439/div>'; }
440    document.getElementById(cat+'ProdCount').textContent = data.products.length ? '('+data.products.length+')' : '';
441
442    // Servizi
443    var sc=document.getElementById(cat+'Services');
444    if(data.services.length){ sc.innerHTML=data.services.map(function(s){return serviceCard(s,cat);}).join(''); }
445    else { sc.innerHTML='<div class="empty-note">Nessun servizio aggiuntivo per questa categoria al momento.</div>'; }
446    document.getElementById(cat+'SvcCount').textContent = data.services.length ? '('+data.services.length+')' : '';
447
448    // Piani
449    var plc=document.getElementById(cat+'Plans');
450    var plans=data.plans.filter(function(pl){ return (pl.name && String(pl.name).trim()) || pl.price!=='' ; });
451    if(plans.length){ plc.innerHTML=plans.map(function(pl){return planCard(pl,cat);}).join(''); }
452    else { plc.innerHTML='<div class="empty-note">I piani per questa categoria saranno pubblicati a breve.</div>'; }
453  }
454
455  function num(o,k){ return (o&&o[k]!==undefined&&o[k]!=='')?o[k]:''; }
456
457  (async function(){
458    var IMGS={}, P={}, SET={}, PRODUCTS=[], SERVICES=[];
459
460    // 1) config-manifest.json (immagini/prezzi di base)
461    try{
462      var r1=await fetch(INV_BASE+'config-manifest.json?v='+Date.now(),{cache:'no-store'});
463      if(r1.ok){ var c=await r1.json();
464        if(c.imgs   && typeof c.imgs==='object')   IMGS=c.imgs;
465        if(c.prices && typeof c.prices==='object') P=c.prices;
466      }
467    }catch(e){}
468
469    // 2) inventory pubblico (prodotti + servizi + settings piani/servizi)
470    try{
471      var r2=await fetch(INV_BASE+'inventory.php?action=get_public&v='+Date.now(),{cache:'no-store'});
472      if(r2.ok){ var inv=await r2.json();
473        if(inv && inv.ok){
474          PRODUCTS=Array.isArray(inv.products)?inv.products:[];
475          SERVICES=Array.isArray(inv.services)?inv.services:[];
476          SET=inv.settings||{};
477          Object.keys(SET).forEach(function(k){ if(SET[k]!==undefined && SET[k]!=='') P[k]=SET[k]; });
478        }
479      }
480    }catch(e){}
481
482    var svc={
483      radio:{ desc: num(SET,'svcRadioDesc'), img: num(SET,'svcRadioImg') || num(IMGS,'svcRadio') },
484      video:{ desc: num(SET,'svcVideoDesc'), img: num(SET,'svcVideoImg') || num(IMGS,'svcVideo') }
485    };
486    var plans={
487      radio:[
488        {name:num(P,'planLite')||'Lite', desc:num(P,'planLiteDesc'), img:num(P,'planLiteImg'), price:num(P,'radioLite')},
489        {name:num(P,'planTop')||'Top',   desc:num(P,'planTopDesc'),  img:num(P,'planTopImg'),  price:num(P,'radioTop')}
490      ],
491      video:[
492        {name:num(P,'planVideoLite')||'Video Lite', desc:num(P,'planVideoLiteDesc'), img:num(P,'planVideoLiteImg'), price:num(P,'videoLite')},
493        {name:num(P,'planVideoTop')||'Video Top',   desc:num(P,'planVideoTopDesc'),  img:num(P,'planVideoTopImg'),  price:num(P,'videoTop')}
494      ]
495    };
496
497    function byCatProducts(cat){
498      return PRODUCTS.filter(function(p){ return p.category===cat; })
499                     .sort(function(a,b){ return Number(a.price||0)-Number(b.price||0); });
500    }
501    function byCatServices(cat){
502      return SERVICES.filter(function(s){
503        return Array.isArray(s.appliesTo) ? s.appliesTo.indexOf(cat)>=0 : (cat==='radio');
504      });
505    }
506
507    // Categoria "attiva" nell'e-commerce, con le stesse regole del negozio:
508    // radio abilitata salvo esplicito false; video abilitata solo se esplicitamente true.
509    var enabled={ radio:(P.radioEnabled!==false), video:(P.videoEnabled===true) };
510
511    ['radio','video'].forEach(function(cat){
512      fillCategory(cat,{
513        svc: svc[cat],
514        products: byCatProducts(cat),
515        services: byCatServices(cat),
516        plans: plans[cat],
517        catActive: enabled[cat]
518      });
519    });
520  })();
521})();
522</script>
vendor: 1 bytes, line 522
522
523<script>
524/* Testi introduttivi editabili: se salvati in vetrina-intro.json (via vetrina-intro.php),
525   sovrascrivono i testi predefiniti qui sopra. Supporta **grassetto** e a-capo.
526   Se non c'è nulla di salvato (o il file non è raggiungibile), restano i testi predefiniti. */
527(function(){
528  function fmt(s){
529    s=String(s==null?'':s).replace(/[&<>"]/g,function(c){return c==='&'?'&amp;':c==='<'?'&lt;':c==='>'?'&gt;':'&quot;';});
530    return s.replace(/\*\*([^*]+)\*\*/g,'<strong>$1</strong>').replace(/\r?\n/g,'<br>');
531  }
532  fetch('vetrina-intro.php?action=get&v='+Date.now(),{cache:'no-store'})
533    .then(function(r){ return r.ok ? r.json() : null; })
534    .then(function(d){
535      if(!d || !d.ok || !d.intro) return;
536      ['radio','video'].forEach(function(cat){
537        var it=d.intro[cat]; if(!it) return;
538        var l=document.getElementById(cat+'IntroLead');
539        var t=document.getElementById(cat+'IntroText');
540        if(l && it.lead && String(it.lead).trim()) l.innerHTML=fmt(it.lead);
541        if(t && it.text && String(it.text).trim()) t.innerHTML=fmt(it.text);
542      });
543    })
544    .catch(function(){});
545})();
546</script>
546
547</body>
548</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.