{"product_id":"men-s-comfort-fit-rashguard-ss-morning-mist","title":"Comfort Fit Rashguard Uomo Manica Corta - KAIZEN","description":"\u003cbody\u003e\n\n\n\u003cmeta charset=\"UTF-8\"\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n\u003ctitle\u003eComfort Fit Rashguard ; Tessuti italiani premium\u003c\/title\u003e\n\u003cmeta name=\"description\" content=\"Comfort Fit Rashguard — relaxed-fit 220 g\/m² Italian knit by SITIP with raglan sleeve. Acquazero water repellent, Eclipse UPF 50+, 4-way stretch. Custom team kits for surf, swim, watersports and beach lifestyle. Made in Italy.\"\u003e\n\u003cmeta name=\"keywords\" content=\"comfort fit rashguard, relaxed rashguard, custom rashguard, raglan rashguard, SITIP italian knit, Acquazero water repellent, Eclipse UPF 50+, 4-way stretch rashguard, surf rashguard, watersports rashguard, made in Italy\"\u003e\n\u003clink rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\"\u003e\n\u003clink rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin\u003e\n\u003clink href=\"https:\/\/fonts.googleapis.com\/css2?family=Archivo:wght@400;500;600;700;800;900\u0026amp;family=Archivo+Narrow:wght@400;500;600;700\u0026amp;family=JetBrains+Mono:wght@400;500;600\u0026amp;display=swap\" rel=\"stylesheet\"\u003e\n\u003cstyle\u003e\n  :root {\n    --ink: #0a1f2c;\n    --ink-soft: #143246;\n    --paper: #ffffff;\n    --paper-warm: #f4efe6;\n    --foam: #ffffff;\n    --ocean: #0066a2;\n    --ocean-deep: #00466e;\n    --aqua: #1fb6c1;\n    --sun: #f5b13d;\n    --coral: #ff5e3a;\n    --sand: #d9c8a5;\n    --line: rgba(10, 31, 44, 0.14);\n  }\n  * { box-sizing: border-box; }\n  html, body {\n    margin: 0;\n    padding: 0;\n    background: var(--paper);\n    color: var(--ink);\n    font-family: 'Archivo', sans-serif;\n    -webkit-font-smoothing: antialiased;\n  }\n  .product-desc {\n    max-width: 1100px;\n    margin: 0 auto;\n    padding: 24px 20px 80px;\n  }\n\n  \/* ============ PRODUCT TITLE BLOCK ============ *\/\n  .product-title {\n    position: relative;\n    padding: 28px 8px 56px;\n    margin-bottom: 8px;\n    border-bottom: 1px solid var(--line);\n    overflow: hidden;\n  }\n  .product-title .top-row {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    gap: 16px;\n    margin-bottom: 28px;\n    flex-wrap: wrap;\n  }\n  .product-title .pill {\n    display: inline-flex;\n    align-items: center;\n    gap: 10px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.22em;\n    text-transform: uppercase;\n    color: var(--ocean-deep);\n    background: rgba(0, 102, 162, 0.08);\n    border: 1px solid rgba(0, 102, 162, 0.25);\n    padding: 8px 14px;\n    border-radius: 100px;\n  }\n  .product-title .pill .pulse {\n    width: 7px; height: 7px;\n    border-radius: 50%;\n    background: var(--coral);\n    box-shadow: 0 0 0 4px rgba(255, 94, 58, 0.18);\n    animation: pulse 1.6s ease-in-out infinite;\n  }\n  @keyframes pulse {\n    0%, 100% { transform: scale(1); opacity: 1; }\n    50% { transform: scale(1.25); opacity: 0.7; }\n  }\n  .product-title .meta-row {\n    display: flex;\n    gap: 18px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.16em;\n    text-transform: uppercase;\n    color: var(--ink-soft);\n    flex-wrap: wrap;\n  }\n  .product-title .meta-row span {\n    display: inline-flex;\n    align-items: center;\n    gap: 8px;\n  }\n  .product-title .meta-row span + span::before { display: none; }\n  .product-title .kicker {\n    display: inline-flex;\n    align-items: center;\n    gap: 12px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 12px;\n    letter-spacing: 0.2em;\n    color: var(--ocean);\n    text-transform: uppercase;\n    margin-bottom: 14px;\n  }\n  .product-title .kicker::before {\n    content: \"\";\n    width: 36px;\n    height: 1.5px;\n    background: var(--ocean);\n  }\n  .product-title h1 {\n    font-family: 'Archivo Narrow', sans-serif;\n    font-weight: 700;\n    font-size: clamp(44px, 7vw, 92px);\n    line-height: 0.92;\n    letter-spacing: -0.025em;\n    text-transform: uppercase;\n    margin: 0 0 8px;\n    text-wrap: balance;\n    color: var(--ink);\n  }\n  .product-title h1 .accent {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-style: italic;\n    background: linear-gradient(110deg, var(--ocean-deep) 0%, var(--ocean) 45%, var(--aqua) 100%);\n    -webkit-background-clip: text;\n    background-clip: text;\n    color: transparent;\n    letter-spacing: -0.04em;\n    padding-right: 0.12em;\n    display: inline-block;\n  }\n  .product-title .product-full-title {\n    position: relative;\n    margin: 18px 0 0;\n    padding-inline-start: 24px;\n    font-family: 'Archivo', sans-serif;\n    font-size: clamp(14px, 1.4vw, 18px);\n    line-height: 1.45;\n    letter-spacing: -0.005em;\n    color: var(--ocean-deep);\n    font-weight: 500;\n    font-style: italic;\n    max-width: 640px;\n    text-wrap: balance;\n  }\n  .product-title .product-full-title::before {\n    content: \"\";\n    position: absolute;\n    inset-block-start: 0.65em;\n    inset-inline-start: 0;\n    width: 14px;\n    height: 2px;\n    background: linear-gradient(90deg, var(--ocean-deep), var(--aqua));\n    border-radius: 2px;\n  }\n  .product-title .subline {\n    font-size: 17px;\n    line-height: 1.55;\n    color: var(--ink-soft);\n    max-width: 640px;\n    margin: 22px 0 0;\n  }\n  .product-title .subline strong {\n    color: var(--ink);\n    font-weight: 700;\n  }\n  .product-title .feature-tabs {\n    display: flex;\n    gap: 8px;\n    margin-top: 28px;\n    flex-wrap: wrap;\n  }\n  .product-title .feature-tabs span {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.14em;\n    text-transform: uppercase;\n    padding: 8px 14px;\n    border: 1px solid var(--line);\n    border-radius: 100px;\n    color: var(--ink-soft);\n    background: var(--paper-warm);\n  }\n\n  \/* ============ DESIGN CTAS ============ *\/\n  .liquid-tag { display: none; }\n  .design-ctas {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n    gap: 12px;\n    margin-top: 32px;\n    position: relative;\n  }\n  .design-ctas::before {\n    content: \"\/\/ Customize this product\";\n    position: absolute;\n    top: -22px;\n    left: 0;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    color: var(--ocean);\n    opacity: 0.7;\n  }\n  .cta-btn {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 12px;\n    width: 100%;\n    padding: 18px 24px;\n    text-decoration: none;\n    font-family: 'Archivo', sans-serif;\n    font-weight: 700;\n    font-size: 14px;\n    letter-spacing: 0.08em;\n    text-transform: uppercase;\n    border-radius: 14px;\n    border: 1.5px solid transparent;\n    transition: transform 0.25s ease, box-shadow 0.25s ease, background 0.25s ease, color 0.25s ease, border-color 0.25s ease;\n    cursor: pointer;\n    position: relative;\n    overflow: hidden;\n  }\n  .cta-btn svg {\n    flex-shrink: 0;\n    transition: transform 0.25s ease, stroke 0.25s ease;\n  }\n  .cta-btn:hover {\n    transform: translateY(-2px);\n  }\n  .cta-btn:hover svg {\n    transform: rotate(-8deg) scale(1.05);\n  }\n\n  \/* Primary — Edit Design (ocean gradient + attention motion) *\/\n  .cta-btn--primary {\n    background: linear-gradient(135deg, var(--ocean-deep) 0%, var(--ocean) 50%, var(--aqua) 100%);\n    color: var(--foam);\n    box-shadow: 0 6px 20px rgba(0, 70, 110, 0.22);\n    position: relative;\n    animation: pdw-cta-pulse 2.6s ease-in-out infinite;\n  }\n  \/* Soft halo behind the button — pulses gently *\/\n  .cta-btn--primary::before {\n    content: \"\";\n    position: absolute;\n    inset: -2px;\n    border-radius: 16px;\n    background: linear-gradient(135deg, var(--ocean), var(--aqua));\n    z-index: -1;\n    opacity: 0.5;\n    filter: blur(8px);\n    animation: pdw-cta-glow 2.6s ease-in-out infinite;\n  }\n  \/* Repeating shine sweep — draws the eye without changing the color *\/\n  .cta-btn--primary::after {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background: linear-gradient(120deg, transparent 35%, rgba(255,255,255,0.4) 50%, transparent 65%);\n    transform: translateX(-100%);\n    animation: pdw-cta-shine 3.2s ease-in-out infinite;\n    pointer-events: none;\n  }\n  \/* Animated arrow hint that nudges right *\/\n  .cta-btn--primary .nudge {\n    display: inline-block;\n    animation: pdw-cta-nudge 1.6s ease-in-out infinite;\n  }\n  .cta-btn--primary:hover {\n    transform: translateY(-3px);\n    box-shadow: 0 14px 32px rgba(0, 70, 110, 0.42);\n    animation-play-state: paused;\n  }\n  .cta-btn--primary:hover::before { animation-play-state: paused; opacity: 0.85; }\n  @keyframes pdw-cta-pulse {\n    0%, 100% { box-shadow: 0 6px 20px rgba(0, 70, 110, 0.22); }\n    50% { box-shadow: 0 8px 28px rgba(31, 182, 193, 0.55), 0 0 0 6px rgba(31, 182, 193, 0.12); }\n  }\n  @keyframes pdw-cta-glow {\n    0%, 100% { opacity: 0.35; }\n    50% { opacity: 0.7; }\n  }\n  @keyframes pdw-cta-shine {\n    0%, 55%, 100% { transform: translateX(-100%); }\n    80% { transform: translateX(100%); }\n  }\n  @keyframes pdw-cta-nudge {\n    0%, 100% { transform: translateX(0); }\n    50% { transform: translateX(4px); }\n  }\n\n  \/* Secondary — Create New Design (outlined → filled on hover) *\/\n  .cta-btn--secondary {\n    background: var(--foam);\n    border-color: var(--ocean-deep);\n    color: var(--ocean-deep);\n  }\n  .cta-btn--secondary svg { stroke: var(--ocean-deep); }\n  .cta-btn--secondary:hover {\n    background: linear-gradient(135deg, var(--ocean-deep) 0%, var(--ocean) 50%, var(--aqua) 100%);\n    border-color: transparent;\n    color: var(--foam);\n    box-shadow: 0 10px 28px rgba(0, 70, 110, 0.28);\n  }\n  .cta-btn--secondary:hover svg { stroke: var(--foam); }\n\n  @media (max-width: 640px) {\n    .design-ctas { grid-template-columns: 1fr; }\n  }\n\n  \/* ============ PRICING TABLE ============ *\/\n  .pricing {\n    margin-top: 36px;\n    background: linear-gradient(180deg, #fff 0%, var(--paper-warm) 100%);\n    border: 1px solid var(--line);\n    border-radius: 20px;\n    padding: 28px 28px 24px;\n    position: relative;\n    overflow: hidden;\n  }\n  .pricing::before {\n    content: \"\/\/ Volume pricing\";\n    position: absolute;\n    top: 16px;\n    right: 22px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    color: var(--ocean);\n    opacity: 0.6;\n  }\n  .pricing-head {\n    display: flex;\n    align-items: end;\n    justify-content: space-between;\n    gap: 20px;\n    margin-bottom: 22px;\n    flex-wrap: wrap;\n  }\n  .pricing-title {\n    font-family: 'Archivo Narrow', sans-serif;\n    text-transform: uppercase;\n    font-size: 24px;\n    font-weight: 700;\n    letter-spacing: -0.01em;\n    margin: 0;\n    line-height: 1;\n  }\n  .pricing-title .em {\n    font-family: 'Archivo', sans-serif;\n    font-style: italic;\n    font-weight: 900;\n    background: linear-gradient(110deg, var(--ocean-deep), var(--aqua));\n    -webkit-background-clip: text;\n    background-clip: text;\n    color: transparent;\n  }\n  .pricing-sub {\n    font-size: 12px;\n    color: var(--ink-soft);\n    font-family: 'JetBrains Mono', monospace;\n    letter-spacing: 0.1em;\n    text-transform: uppercase;\n    margin: 6px 0 0;\n  }\n\n  \/* Live readout *\/\n  .pricing-readout {\n    background: var(--ink);\n    color: var(--foam);\n    border-radius: 16px;\n    padding: 22px 26px;\n    display: grid;\n    grid-template-columns: auto 1fr auto;\n    gap: 24px;\n    align-items: center;\n    margin-bottom: 22px;\n    position: relative;\n    overflow: hidden;\n  }\n  .pricing-readout::after {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background: radial-gradient(ellipse 400px 120px at 0% 100%, rgba(31,182,193,0.25), transparent);\n    pointer-events: none;\n  }\n  .readout-qty {\n    display: flex;\n    flex-direction: column;\n    gap: 4px;\n    position: relative;\n    z-index: 1;\n  }\n  .readout-qty .label {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    color: var(--aqua);\n  }\n  .readout-qty .value {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-style: italic;\n    font-size: 48px;\n    line-height: 0.9;\n    letter-spacing: -0.04em;\n  }\n  .readout-qty .value small {\n    font-size: 14px;\n    font-style: normal;\n    font-weight: 600;\n    letter-spacing: 0.05em;\n    color: rgba(255,255,255,0.55);\n    margin-left: 6px;\n  }\n  .readout-discount {\n    text-align: center;\n    position: relative;\n    z-index: 1;\n  }\n  .readout-discount .badge {\n    display: inline-flex;\n    align-items: center;\n    gap: 6px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.18em;\n    text-transform: uppercase;\n    background: rgba(255, 94, 58, 0.18);\n    border: 1px solid rgba(255, 94, 58, 0.4);\n    color: #ffb89e;\n    padding: 6px 14px;\n    border-radius: 100px;\n    transition: all 0.3s ease;\n  }\n  .readout-discount .badge.zero {\n    background: rgba(255,255,255,0.08);\n    border-color: rgba(255,255,255,0.2);\n    color: rgba(255,255,255,0.55);\n  }\n  .readout-discount .save {\n    display: block;\n    font-size: 11px;\n    color: rgba(255,255,255,0.55);\n    margin-top: 8px;\n    font-family: 'JetBrains Mono', monospace;\n    letter-spacing: 0.08em;\n  }\n  .readout-discount .save b {\n    color: var(--sun);\n    font-weight: 600;\n  }\n  .readout-price {\n    text-align: right;\n    position: relative;\n    z-index: 1;\n  }\n  .readout-price .label {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    color: var(--aqua);\n    margin-bottom: 4px;\n  }\n  .readout-price .unit {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-size: 36px;\n    letter-spacing: -0.03em;\n    line-height: 1;\n  }\n  .readout-price .unit .strike {\n    font-size: 16px;\n    color: rgba(255,255,255,0.4);\n    text-decoration: line-through;\n    font-weight: 600;\n    margin-right: 8px;\n    vertical-align: middle;\n  }\n  .readout-price .total {\n    font-size: 12px;\n    color: rgba(255,255,255,0.7);\n    font-family: 'JetBrains Mono', monospace;\n    letter-spacing: 0.05em;\n    margin-top: 6px;\n  }\n  .readout-price .total b {\n    color: var(--foam);\n    font-weight: 700;\n  }\n\n  \/* Quantity slider *\/\n  .qty-slider-wrap {\n    margin: 0 0 24px;\n  }\n  .qty-slider {\n    -webkit-appearance: none;\n    appearance: none;\n    width: 100%;\n    height: 8px;\n    border-radius: 100px;\n    background: var(--paper-warm);\n    border: 1px solid var(--line);\n    outline: none;\n  }\n  .qty-slider::-webkit-slider-thumb {\n    -webkit-appearance: none;\n    appearance: none;\n    width: 32px;\n    height: 32px;\n    border-radius: 50%;\n    background: linear-gradient(135deg, var(--ocean-deep), var(--aqua));\n    border: 3px solid var(--foam);\n    box-shadow: 0 4px 12px rgba(0, 70, 110, 0.35);\n    cursor: pointer;\n    transition: transform 0.2s ease;\n  }\n  .qty-slider::-webkit-slider-thumb:hover {\n    transform: scale(1.15);\n  }\n  .qty-slider::-moz-range-thumb {\n    width: 32px;\n    height: 32px;\n    border-radius: 50%;\n    background: linear-gradient(135deg, var(--ocean-deep), var(--aqua));\n    border: 3px solid var(--foam);\n    box-shadow: 0 4px 12px rgba(0, 70, 110, 0.35);\n    cursor: pointer;\n  }\n  .qty-ticks {\n    position: relative;\n    height: 14px;\n    margin-top: 10px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.1em;\n    color: var(--ink-soft);\n  }\n  .qty-ticks span {\n    position: absolute;\n    top: 0;\n    transform: translateX(-50%);\n    white-space: nowrap;\n  }\n\n  \/* Tier table — auto-fit lets the grid reflow based on the actual\n     available width (no media\/container queries needed). In a 1100px\n     description it stays 7 columns; in a 400px sidebar it wraps to 3. *\/\n  .tier-grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));\n    gap: 6px;\n  }\n  .tier {\n    background: var(--foam);\n    border: 1.5px solid var(--line);\n    border-radius: 12px;\n    padding: 14px 10px;\n    text-align: center;\n    transition: all 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);\n    cursor: pointer;\n    position: relative;\n  }\n  .tier:hover {\n    border-color: var(--aqua);\n    transform: translateY(-2px);\n  }\n  .tier.active {\n    background: linear-gradient(160deg, var(--ocean-deep), var(--ocean));\n    border-color: var(--ocean-deep);\n    color: var(--foam);\n    transform: translateY(-3px);\n    box-shadow: 0 10px 24px rgba(0, 70, 110, 0.3);\n  }\n  .tier .qty {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.12em;\n    text-transform: uppercase;\n    color: var(--ink-soft);\n    margin-bottom: 6px;\n  }\n  .tier.active .qty { color: rgba(255,255,255,0.7); }\n  .tier .disc {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-style: italic;\n    font-size: 24px;\n    letter-spacing: -0.03em;\n    line-height: 1;\n    color: var(--ocean-deep);\n  }\n  .tier.active .disc { color: var(--sun); }\n  .tier .disc.zero { color: var(--ink-soft); opacity: 0.5; }\n  .tier .price-each {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    color: var(--ocean);\n    margin-top: 4px;\n    letter-spacing: 0.05em;\n  }\n  .tier.active .price-each { color: var(--aqua); }\n\n  \/* Bulk inquiry banner (qty 50+) *\/\n  .bulk-inquiry {\n    margin-top: 14px;\n    padding: 22px 24px;\n    border-radius: 14px;\n    background: linear-gradient(135deg, var(--ocean-deep), var(--ocean));\n    color: var(--foam);\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    gap: 18px;\n    flex-wrap: wrap;\n    box-shadow: 0 14px 32px rgba(0, 50, 77, 0.28);\n    overflow: hidden;\n    position: relative;\n    opacity: 0;\n    transform: translateY(8px);\n    pointer-events: none;\n    max-height: 0;\n    margin-top: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    transition: opacity 0.4s ease, transform 0.4s ease, max-height 0.45s ease, margin-top 0.45s ease, padding 0.45s ease;\n  }\n  .bulk-inquiry.show {\n    opacity: 1;\n    transform: translateY(0);\n    pointer-events: auto;\n    max-height: 240px;\n    margin-top: 14px;\n    padding-top: 22px;\n    padding-bottom: 22px;\n  }\n  .bulk-inquiry::before {\n    content: \"\";\n    position: absolute;\n    top: -40%;\n    right: -10%;\n    width: 280px;\n    height: 280px;\n    background: radial-gradient(circle, rgba(31,182,193,0.35), transparent 70%);\n    pointer-events: none;\n  }\n  .bulk-inquiry-text { position: relative; flex: 1 1 320px; }\n  .bulk-inquiry-eyebrow {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.18em;\n    color: var(--sun);\n    text-transform: uppercase;\n    margin-bottom: 8px;\n  }\n  .bulk-inquiry h4 {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-size: 22px;\n    line-height: 1.15;\n    letter-spacing: -0.02em;\n    margin: 0 0 6px;\n  }\n  .bulk-inquiry h4 em {\n    font-style: italic;\n    color: var(--aqua);\n  }\n  .bulk-inquiry p {\n    font-size: 14px;\n    line-height: 1.5;\n    color: rgba(255,255,255,0.82);\n    margin: 0;\n  }\n  .bulk-inquiry-cta {\n    position: relative;\n    display: inline-flex;\n    align-items: center;\n    gap: 10px;\n    padding: 14px 22px;\n    background: var(--sun);\n    color: var(--ocean-deep);\n    text-decoration: none;\n    border-radius: 999px;\n    font-family: 'Archivo', sans-serif;\n    font-weight: 800;\n    font-size: 14px;\n    letter-spacing: 0.04em;\n    text-transform: uppercase;\n    transition: transform 0.2s ease, box-shadow 0.2s ease;\n    flex-shrink: 0;\n  }\n  .bulk-inquiry-cta:hover {\n    transform: translateY(-2px);\n    box-shadow: 0 10px 24px rgba(255, 200, 87, 0.4);\n  }\n  .bulk-inquiry-cta svg { width: 16px; height: 16px; }\n\n  \/* Quote request modal *\/\n  .quote-modal-overlay {\n    position: fixed;\n    inset: 0;\n    background: rgba(0, 30, 50, 0.6);\n    backdrop-filter: blur(6px);\n    -webkit-backdrop-filter: blur(6px);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    z-index: 99999;\n    padding: 20px;\n    opacity: 0;\n    pointer-events: none;\n    transition: opacity 0.25s ease;\n  }\n  .quote-modal-overlay.show {\n    opacity: 1;\n    pointer-events: auto;\n  }\n  .quote-modal {\n    position: relative;\n    background: #ffffff;\n    border-radius: 18px;\n    width: 100%;\n    max-width: 520px;\n    \/* iOS Safari: 92dvh follows the dynamic viewport (excludes the URL bar\n       when it appears), preventing the modal from being clipped on phones.\n       Falls back to 92vh on browsers without dvh support. *\/\n    max-height: 92vh;\n    max-height: 92dvh;\n    overflow-y: auto;\n    \/* Prevent scroll chaining: when the modal reaches its top\/bottom edge,\n       the scroll DOES NOT propagate to the page below. Critical on iOS to\n       avoid the bouncing\/locked feeling. *\/\n    overscroll-behavior: contain;\n    \/* Smooth touch-scrolling on older iOS (deprecated but harmless on new). *\/\n    -webkit-overflow-scrolling: touch;\n    box-shadow: 0 30px 80px rgba(0, 30, 50, 0.4);\n    transform: translateY(20px) scale(0.96);\n    transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);\n  }\n  .quote-modal-overlay.show .quote-modal { transform: translateY(0) scale(1); }\n  .quote-modal-header {\n    padding: 28px 32px 18px;\n    background: linear-gradient(135deg, var(--ocean-deep), var(--ocean));\n    color: var(--foam);\n    border-radius: 18px 18px 0 0;\n    position: relative;\n    overflow: hidden;\n  }\n  .quote-modal-header::before {\n    content: \"\";\n    position: absolute;\n    top: -50%;\n    right: -20%;\n    width: 220px;\n    height: 220px;\n    background: radial-gradient(circle, rgba(31,182,193,0.4), transparent 70%);\n    pointer-events: none;\n  }\n  .quote-modal-eyebrow {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.18em;\n    text-transform: uppercase;\n    color: var(--sun);\n    margin-bottom: 6px;\n    position: relative;\n  }\n  .quote-modal-header h3 {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-size: 24px;\n    line-height: 1.15;\n    letter-spacing: -0.02em;\n    margin: 0 0 6px;\n    position: relative;\n  }\n  .quote-modal-header h3 em { font-style: italic; color: var(--aqua); }\n  .quote-modal-header p {\n    font-size: 13px;\n    line-height: 1.5;\n    color: rgba(255,255,255,0.78);\n    margin: 0;\n    position: relative;\n  }\n  .quote-modal-close {\n    position: absolute;\n    top: 16px;\n    right: 16px;\n    \/* Visible button stays compact 32x32 so it doesn't get clipped by the\n       header's rounded top-right corner (border-radius 18px + overflow:hidden).\n       The ::before pseudo-element extends the clickable hit-area to 44x44\n       outside the visible button — invisible, but catches taps. *\/\n    width: 32px;\n    height: 32px;\n    border-radius: 50%;\n    background: rgba(255,255,255,0.15);\n    border: none;\n    color: #fff;\n    cursor: pointer;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 20px;\n    line-height: 1;\n    transition: background 0.2s ease, transform 0.2s ease;\n    z-index: 2;\n  }\n  \/* Invisible hit-area extender: takes the clickable area from 32x32 visible\n     to ~44x44 effective, without affecting the visual size. *\/\n  .quote-modal-close::before {\n    content: \"\";\n    position: absolute;\n    inset: -6px;\n    border-radius: 50%;\n  }\n  .quote-modal-close:hover { background: rgba(255,255,255,0.28); transform: rotate(90deg); }\n  .quote-modal-body {\n    padding: 24px 32px 32px;\n  }\n  .quote-form-row {\n    display: grid;\n    gap: 16px;\n    margin-bottom: 14px;\n  }\n  .quote-form-row.two { grid-template-columns: 1fr 1fr; }\n  @media (max-width: 480px) {\n    .quote-form-row.two { grid-template-columns: 1fr; }\n    .quote-modal-header { padding: 22px 22px 16px; }\n    .quote-modal-body { padding: 20px 22px 26px; }\n  }\n  .quote-field { display: flex; flex-direction: column; gap: 6px; }\n  .quote-field label {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.15em;\n    text-transform: uppercase;\n    color: var(--ink-soft);\n    font-weight: 600;\n  }\n  .quote-field label .req { color: var(--coral); }\n  .quote-field label .opt {\n    color: var(--ink-soft);\n    opacity: 0.6;\n    font-size: 9px;\n    margin-left: 4px;\n    text-transform: none;\n    letter-spacing: 0.05em;\n  }\n  .quote-field input,\n  .quote-field select,\n  .quote-field textarea {\n    font-family: 'Archivo', sans-serif;\n    font-size: 14px;\n    color: var(--ink);\n    background: var(--foam);\n    border: 1.5px solid var(--line);\n    border-radius: 10px;\n    padding: 11px 14px;\n    outline: none;\n    transition: border-color 0.2s ease, background 0.2s ease;\n    width: 100%;\n    box-sizing: border-box;\n  }\n  .quote-field input:focus,\n  .quote-field select:focus,\n  .quote-field textarea:focus {\n    border-color: var(--ocean);\n    background: #fff;\n  }\n  \/* iOS Safari triggers auto-zoom on text\/textarea inputs whose font-size\n     is below 16px. With body in position:fixed (our scroll lock), that\n     zoom gets stuck and the virtual keyboard fails to open — only\n     type=\"number\" and type=\"email\" remain functional. Force 16px on\n     mobile to disable the auto-zoom. *\/\n  @media (max-width: 640px) {\n    .quote-field input,\n    .quote-field select,\n    .quote-field textarea {\n      font-size: 16px;\n    }\n  }\n  .quote-field input.invalid,\n  .quote-field select.invalid {\n    border-color: var(--coral);\n    background: #fff5f3;\n  }\n  .quote-field-error {\n    color: var(--coral);\n    font-size: 11px;\n    font-family: 'JetBrains Mono', monospace;\n    margin-top: 2px;\n    display: none;\n  }\n  .quote-field-error.show { display: block; }\n\n  \/* Honeypot anti-spam: hidden off-screen for humans, but still in the DOM\n     and submitted by naive bots that auto-fill every visible input. We\n     avoid display:none \/ visibility:hidden because some bots skip those. *\/\n  .quote-honeypot {\n    position: absolute;\n    left: -10000px;\n    top: auto;\n    width: 1px;\n    height: 1px;\n    overflow: hidden;\n  }\n  .quote-modal-submit {\n    width: 100%;\n    margin-top: 8px;\n    padding: 16px 22px;\n    background: linear-gradient(135deg, var(--ocean-deep), var(--ocean));\n    color: var(--foam);\n    border: none;\n    border-radius: 12px;\n    font-family: 'Archivo', sans-serif;\n    font-weight: 800;\n    font-size: 15px;\n    letter-spacing: 0.04em;\n    text-transform: uppercase;\n    cursor: pointer;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 10px;\n    transition: transform 0.2s ease, box-shadow 0.2s ease;\n  }\n  .quote-modal-submit:hover {\n    transform: translateY(-1px);\n    box-shadow: 0 12px 28px rgba(0, 70, 110, 0.35);\n  }\n  .quote-modal-submit svg { width: 16px; height: 16px; }\n  .quote-modal-footnote {\n    text-align: center;\n    font-size: 11px;\n    color: var(--ink-soft);\n    margin-top: 14px;\n  }\n  .quote-success {\n    text-align: center;\n    padding: 40px 20px;\n  }\n  .quote-success .check {\n    width: 64px;\n    height: 64px;\n    border-radius: 50%;\n    background: linear-gradient(135deg, #22c55e, #16a34a);\n    color: #fff;\n    margin: 0 auto 18px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 32px;\n    font-weight: 700;\n  }\n  .quote-success h4 {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-size: 22px;\n    margin: 0 0 8px;\n    color: var(--ink);\n  }\n  .quote-success p {\n    font-size: 14px;\n    color: var(--ink-soft);\n    margin: 0 auto;\n    max-width: 36ch;\n    line-height: 1.5;\n  }\n\n  @media (max-width: 720px) {\n    .pricing-readout { grid-template-columns: 1fr; gap: 16px; text-align: left; }\n    .readout-discount, .readout-price { text-align: left; }\n    .tier-grid { grid-template-columns: repeat(2, 1fr); }\n    .bulk-inquiry { padding: 18px 16px; }\n    .bulk-inquiry h4 { font-size: 18px; }\n    .pricing::before { display: none; }\n  }\n\n  \/* ============ HERO BANNER ============ *\/\n  .hero {\n    position: relative;\n    border-radius: 28px;\n    overflow: hidden;\n    background: linear-gradient(160deg, var(--ocean-deep) 0%, var(--ocean) 45%, var(--aqua) 100%);\n    color: var(--foam);\n    padding: 64px 48px 72px;\n    isolation: isolate;\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n    gap: 40px;\n    align-items: center;\n  }\n  .hero-text { position: relative; z-index: 2; }\n  .hero-visual {\n    position: relative;\n    z-index: 1;\n    aspect-ratio: 1 \/ 1;\n    width: 100%;\n    max-width: 460px;\n    justify-self: end;\n    border-radius: 24px;\n    overflow: hidden;\n    background:\n      radial-gradient(ellipse at 30% 20%, rgba(255,255,255,0.35), transparent 55%),\n      linear-gradient(150deg, rgba(255,255,255,0.18), rgba(255,255,255,0.04));\n    border: 1px solid rgba(255,255,255,0.22);\n    box-shadow: 0 30px 60px -20px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.18);\n    backdrop-filter: blur(4px);\n  }\n  .hero-visual svg.honeycomb,\n  .hero-visual img.honeycomb {\n    position: absolute;\n    inset: 0;\n    width: 100%;\n    height: 100%;\n    display: block;\n    object-fit: cover;\n  }\n  .hero-visual .hc-label {\n    position: absolute;\n    left: 18px; bottom: 18px;\n    z-index: 3;\n    display: inline-flex; flex-direction: column; gap: 4px;\n    padding: 10px 14px;\n    background: rgba(255,255,255,0.92);\n    color: var(--ink);\n    border-radius: 12px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.18em;\n    text-transform: uppercase;\n    box-shadow: 0 8px 24px -8px rgba(0,0,0,0.3);\n  }\n  .hero-visual .hc-label strong {\n    font-family: 'Archivo Narrow', sans-serif;\n    font-size: 18px;\n    letter-spacing: -0.01em;\n    text-transform: none;\n    font-weight: 800;\n    color: var(--ocean-deep);\n  }\n  .hero-visual .hc-feather {\n    position: absolute;\n    right: 16px; top: 16px;\n    z-index: 3;\n    display: inline-flex; align-items: center; gap: 6px;\n    padding: 6px 12px;\n    background: rgba(255,255,255,0.18);\n    border: 1px solid rgba(255,255,255,0.4);\n    color: #fff;\n    border-radius: 100px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    backdrop-filter: blur(6px);\n  }\n  .hero-visual .hc-feather::before { content: \"\"; width: 5px; height: 5px; background: var(--sun); border-radius: 50%; box-shadow: 0 0 0 3px rgba(245,177,61,0.4); }\n  @keyframes hc-breathe { 0%,100% { opacity: 0.7; } 50% { opacity: 1; } }\n  .hero-visual svg.honeycomb .cell-a { animation: hc-breathe 5s ease-in-out infinite; }\n  .hero-visual svg.honeycomb .cell-b { animation: hc-breathe 5s ease-in-out infinite; animation-delay: -1.6s; }\n  .hero-visual svg.honeycomb .cell-c { animation: hc-breathe 5s ease-in-out infinite; animation-delay: -3.2s; }\n  .hero::before {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background:\n      radial-gradient(circle at 85% 20%, rgba(245, 177, 61, 0.35), transparent 45%),\n      radial-gradient(circle at 10% 90%, rgba(255, 255, 255, 0.18), transparent 50%);\n    z-index: -1;\n  }\n  .hero svg.waves {\n    position: absolute;\n    left: 0; right: 0; bottom: -2px;\n    width: 100%;\n    height: 110px;\n    z-index: 0;\n  }\n  .hero-eyebrow {\n    display: inline-flex;\n    align-items: center;\n    gap: 10px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.22em;\n    text-transform: uppercase;\n    background: rgba(255,255,255,0.14);\n    border: 1px solid rgba(255,255,255,0.3);\n    padding: 8px 14px;\n    border-radius: 100px;\n    backdrop-filter: blur(6px);\n  }\n  .hero-eyebrow .dot {\n    width: 6px; height: 6px;\n    background: var(--sun);\n    border-radius: 50%;\n    box-shadow: 0 0 0 4px rgba(245,177,61,0.3);\n  }\n  .hero h2 {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-size: clamp(40px, 6vw, 76px);\n    line-height: 0.95;\n    letter-spacing: -0.03em;\n    margin: 22px 0 18px;\n    text-wrap: balance;\n  }\n  .hero h2 .ital {\n    font-style: italic;\n    font-weight: 800;\n    color: var(--sun);\n  }\n  .hero p {\n    font-size: 17px;\n    line-height: 1.5;\n    max-width: 540px;\n    opacity: 0.92;\n    margin: 0;\n  }\n  .hero-meta {\n    display: flex;\n    gap: 24px;\n    margin-top: 36px;\n    flex-wrap: wrap;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 12px;\n    letter-spacing: 0.08em;\n    text-transform: uppercase;\n  }\n  .hero-meta span {\n    display: flex; align-items: center; gap: 8px;\n  }\n  .hero-meta span::before {\n    content: \"\";\n    width: 8px; height: 8px;\n    border: 1.5px solid var(--sun);\n    transform: rotate(45deg);\n  }\n\n  \/* ============ SECTION HEAD ============ *\/\n  .section-head {\n    margin: 72px 0 28px;\n    display: flex;\n    align-items: end;\n    justify-content: space-between;\n    gap: 24px;\n    flex-wrap: wrap;\n  }\n  .section-head .num {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 12px;\n    color: var(--ocean);\n    letter-spacing: 0.2em;\n  }\n  .section-head h2 {\n    font-family: 'Archivo Narrow', sans-serif;\n    font-weight: 700;\n    font-size: clamp(34px, 4.5vw, 54px);\n    line-height: 0.95;\n    letter-spacing: -0.02em;\n    margin: 6px 0 0;\n    text-transform: uppercase;\n  }\n  .section-head .lede {\n    max-width: 360px;\n    font-size: 14px;\n    line-height: 1.5;\n    color: var(--ink-soft);\n  }\n\n  \/* ============ TECHNOLOGY CARDS (Microsense \u0026 Native) ============ *\/\n  .tech-grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));\n    gap: 20px;\n  }\n  .tech-card {\n    position: relative;\n    border-radius: 24px;\n    padding: 36px 32px 32px;\n    overflow: hidden;\n    color: var(--foam);\n    isolation: isolate;\n    min-height: 460px;\n    display: flex;\n    flex-direction: column;\n  }\n  .tech-card.acquazero {\n    background:\n      radial-gradient(ellipse 600px 400px at 80% 10%, rgba(31,182,193,0.7), transparent),\n      linear-gradient(160deg, var(--ocean-deep), var(--ocean));\n  }\n  .tech-card.eclipse {\n    background:\n      radial-gradient(ellipse 500px 400px at 90% 90%, rgba(245,177,61,0.55), transparent),\n      linear-gradient(160deg, var(--ink), var(--ink-soft));\n  }\n  .tech-card .badge {\n    display: inline-flex;\n    align-items: center;\n    gap: 8px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    background: rgba(255,255,255,0.15);\n    border: 1px solid rgba(255,255,255,0.3);\n    padding: 6px 12px;\n    border-radius: 100px;\n    align-self: flex-start;\n  }\n  .tech-card h3 {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-style: italic;\n    font-size: 64px;\n    line-height: 0.9;\n    letter-spacing: -0.04em;\n    margin: 22px 0 6px;\n  }\n  .tech-card .tagline {\n    font-size: 15px;\n    opacity: 0.85;\n    margin: 0 0 28px;\n    max-width: 280px;\n    line-height: 1.4;\n  }\n  .tech-features {\n    list-style: none;\n    padding: 0;\n    margin: auto 0 0;\n    display: grid;\n    gap: 12px;\n  }\n  .tech-features li {\n    display: flex;\n    align-items: center;\n    gap: 14px;\n    padding: 12px 14px;\n    background: rgba(255,255,255,0.08);\n    border: 1px solid rgba(255,255,255,0.14);\n    border-radius: 14px;\n    backdrop-filter: blur(8px);\n    transition: transform 0.3s ease, background 0.3s ease;\n  }\n  .tech-features li:hover {\n    transform: translateX(4px);\n    background: rgba(255,255,255,0.14);\n  }\n  .tech-features .ico {\n    width: 38px; height: 38px;\n    flex-shrink: 0;\n    border-radius: 10px;\n    display: grid;\n    place-items: center;\n    font-size: 18px;\n    background: rgba(255,255,255,0.16);\n  }\n  .tech-card.eclipse .tech-features .ico {\n    background: rgba(245,177,61,0.25);\n  }\n  .tech-features .label {\n    font-size: 14px;\n    font-weight: 600;\n    letter-spacing: 0.01em;\n  }\n\n  \/* Decorative drop \/ sun *\/\n  .tech-card .deco {\n    position: absolute;\n    top: 28px; right: 28px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.18em;\n    opacity: 0.55;\n  }\n  .tech-card .ring {\n    position: absolute;\n    border-radius: 50%;\n    border: 1.5px dashed rgba(255,255,255,0.18);\n    pointer-events: none;\n  }\n  .acquazero .ring-1 { width: 320px; height: 320px; top: -120px; right: -100px; animation: spin 60s linear infinite; }\n  .acquazero .ring-2 { width: 180px; height: 180px; top: -40px; right: -20px; animation: spin 40s linear infinite reverse; }\n  .eclipse .ring-1 { width: 280px; height: 280px; bottom: -100px; right: -80px; animation: spin 70s linear infinite; }\n  .eclipse .feather {\n    position: absolute;\n    width: 86px; height: 150px;\n    top: 18px; right: 26px;\n    pointer-events: none;\n    opacity: 0.92;\n    filter: drop-shadow(0 6px 18px rgba(255,255,255,0.18));\n    transform-origin: 50% 8%;\n    animation: feather-float 7s ease-in-out infinite;\n  }\n  @keyframes spin {\n    to { transform: rotate(360deg); }\n  }\n  @keyframes feather-float {\n    0%, 100% { transform: translate(0, 0) rotate(18deg); }\n    50%      { transform: translate(-6px, -10px) rotate(24deg); }\n  }\n\n  \/* ============ PERFORMANCE STRIP ============ *\/\n  .perf-strip {\n    background: var(--ink);\n    color: var(--foam);\n    border-radius: 24px;\n    padding: 48px 40px;\n    margin-top: 28px;\n    position: relative;\n    overflow: hidden;\n  }\n  .perf-strip::after {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background: radial-gradient(ellipse 800px 200px at 50% 100%, rgba(31,182,193,0.25), transparent);\n    pointer-events: none;\n  }\n  .perf-strip h3 {\n    font-family: 'Archivo Narrow', sans-serif;\n    text-transform: uppercase;\n    letter-spacing: -0.01em;\n    font-size: 32px;\n    font-weight: 700;\n    margin: 0 0 6px;\n  }\n  .perf-strip .sub {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.2em;\n    color: var(--aqua);\n    text-transform: uppercase;\n    margin: 0 0 32px;\n  }\n  .perf-grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n    gap: 16px;\n    position: relative;\n    z-index: 1;\n  }\n  .perf-card {\n    background: rgba(255,255,255,0.04);\n    border: 1px solid rgba(255,255,255,0.1);\n    border-radius: 16px;\n    padding: 22px 20px;\n    transition: all 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);\n    cursor: default;\n  }\n  .perf-card:hover {\n    background: rgba(31,182,193,0.12);\n    border-color: var(--aqua);\n    transform: translateY(-4px);\n  }\n  .perf-card .icon-box {\n    width: 48px; height: 48px;\n    border-radius: 12px;\n    background: linear-gradient(135deg, var(--aqua), var(--ocean));\n    display: grid;\n    place-items: center;\n    font-size: 22px;\n    margin-bottom: 18px;\n  }\n  .perf-card h4 {\n    font-family: 'Archivo', sans-serif;\n    font-size: 17px;\n    font-weight: 800;\n    margin: 0 0 6px;\n    letter-spacing: -0.01em;\n  }\n  .perf-card p {\n    font-size: 13px;\n    line-height: 1.45;\n    color: rgba(255,255,255,0.65);\n    margin: 0;\n  }\n\n  \/* ============ CUSTOM PRINT STRIP ============ *\/\n  .custom-strip {\n    background: linear-gradient(140deg, color-mix(in oklab, var(--ocean-deep) 70%, black) 0%, var(--ocean-deep) 50%, color-mix(in oklab, var(--ocean) 80%, var(--aqua)) 100%);\n    color: var(--foam);\n    border-radius: 28px;\n    padding: 56px 48px;\n    margin-top: 24px;\n    position: relative;\n    overflow: hidden;\n  }\n  .custom-strip::before {\n    content: \"\/\/ 01 → 50+ pieces\";\n    position: absolute;\n    top: 22px; right: 28px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.22em;\n    text-transform: uppercase;\n    color: rgba(255,255,255,0.55);\n  }\n  .custom-strip::after {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background: radial-gradient(900px circle at 110% -10%, rgba(31,182,193,0.28), transparent 55%),\n                radial-gradient(700px circle at -10% 110%, rgba(255,255,255,0.06), transparent 60%);\n    pointer-events: none;\n  }\n  .custom-strip h3 {\n    font-family: 'Archivo Narrow', sans-serif;\n    text-transform: uppercase;\n    font-size: 36px;\n    font-weight: 700;\n    letter-spacing: -0.01em;\n    margin: 0 0 6px;\n    position: relative;\n    z-index: 1;\n  }\n  .custom-strip .sub {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.22em;\n    text-transform: uppercase;\n    color: rgba(255,255,255,0.6);\n    margin: 0 0 32px;\n    position: relative;\n    z-index: 1;\n  }\n  .custom-grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n    gap: 16px;\n    position: relative;\n    z-index: 1;\n  }\n  .custom-card {\n    background: rgba(255,255,255,0.05);\n    border: 1px solid rgba(255,255,255,0.12);\n    border-radius: 18px;\n    padding: 24px 22px;\n    position: relative;\n    overflow: hidden;\n    transition: transform .3s cubic-bezier(.2,.8,.2,1), background .3s, border-color .3s;\n  }\n  .custom-card:hover {\n    background: rgba(31,182,193,0.14);\n    border-color: var(--aqua);\n    transform: translateY(-4px);\n  }\n  .custom-num {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.2em;\n    color: var(--aqua);\n    margin-bottom: 18px;\n  }\n  .custom-card h4 {\n    font-family: 'Archivo', sans-serif;\n    font-size: 17px;\n    font-weight: 700;\n    margin: 0 0 8px;\n    color: var(--foam);\n    letter-spacing: -0.01em;\n  }\n  .custom-card p {\n    font-size: 13px;\n    line-height: 1.5;\n    color: rgba(255,255,255,0.7);\n    margin: 0;\n  }\n\n  \/* ============ USE CASES ============ *\/\n  .usecase { margin-top: 28px; display: flex; flex-direction: column; gap: 20px; }\n  .compare { background: linear-gradient(160deg, var(--paper-warm), #fff); border: 1px solid var(--line); border-radius: 24px; padding: 32px 28px; position: relative; overflow: hidden; }\n  .compare::before { content: \"\/\/ vs · standard sports tee\"; position: absolute; top: 16px; right: 22px; font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--ocean); opacity: 0.6; }\n  .compare h3 { font-family: 'Archivo Narrow', sans-serif; text-transform: uppercase; font-size: 26px; font-weight: 700; margin: 14px 0 6px; line-height: 1; letter-spacing: -0.01em; }\n  .compare h3 .em { font-family: 'Archivo', sans-serif; font-style: italic; font-weight: 900; background: linear-gradient(110deg, var(--ocean-deep), var(--aqua)); -webkit-background-clip: text; background-clip: text; color: transparent; }\n  .compare-lead { font-size: 13px; line-height: 1.55; color: var(--ink-soft); margin: 0 0 22px; }\n  .compare-rows { display: grid; gap: 8px; }\n  .compare-row { display: grid; grid-template-columns: 1fr 1fr; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: #fff; }\n  .compare-row .col { padding: 12px 14px; font-size: 12.5px; line-height: 1.35; display: flex; align-items: center; gap: 10px; }\n  .compare-row .col.lo { color: var(--ink-soft); background: rgba(10, 31, 44, 0.025); }\n  .compare-row .col.hi { color: var(--ink); font-weight: 600; background: linear-gradient(110deg, rgba(31, 182, 193, 0.12), rgba(0, 102, 162, 0.06)); border-left: 1px solid var(--line); }\n  .compare-row .col.hi::before { content: \"\"; width: 12px; height: 12px; border-radius: 50%; background: linear-gradient(135deg, var(--ocean-deep), var(--aqua)); flex-shrink: 0; box-shadow: 0 0 0 3px rgba(31,182,193,0.2); }\n  .compare-row .col.lo::before { content: \"\"; width: 12px; height: 12px; border-radius: 50%; border: 1.5px solid var(--line); flex-shrink: 0; background: #fff; }\n  .compare-row .lab { grid-column: 1 \/ -1; background: var(--ink); color: var(--foam); font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase; padding: 8px 14px; }\n  .compare-pill { display: inline-flex; align-items: center; gap: 8px; font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase; background: var(--ink); color: var(--foam); padding: 6px 12px; border-radius: 100px; }\n  .compare-pill .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--sun); }\n  .compare { display: grid; grid-template-columns: auto 1fr auto; column-gap: 28px; row-gap: 14px; align-items: center; }\n  .compare .compare-pill { grid-column: 1 \/ -1; justify-self: start; }\n  .fit-headline { text-align: left; }\n  .fit-headline h3 { margin: 0 0 8px; font-size: 30px; }\n  .fit-headline .compare-lead { margin: 0; max-width: 60ch; }\n  .fit-mark { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; margin: 0; padding: 0; border-top: none; align-self: center; max-width: 220px; }\n  .fit-mark span { font-family: 'JetBrains Mono', monospace; font-size: 9px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ocean-deep); background: rgba(31, 182, 193, 0.08); padding: 6px 10px; border-radius: 100px; }\n  @media (max-width: 720px) { .compare { grid-template-columns: 1fr; } .fit-headline { text-align: left; } .fit-mark { justify-content: flex-start; max-width: none; } }\n  .usecase-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; align-content: start; }\n  .uc-card { background: #fff; border: 1px solid var(--line); border-radius: 18px; padding: 22px 20px 20px; position: relative; overflow: hidden; transition: transform .3s cubic-bezier(.2,.8,.2,1), border-color .3s ease, box-shadow .3s ease; display: flex; flex-direction: column; gap: 14px; }\n  .uc-card::before { content: \"\"; position: absolute; top: 0; left: 0; width: 4px; height: 100%; background: linear-gradient(180deg, var(--ocean-deep), var(--aqua)); opacity: 0.85; }\n  .uc-card:hover { transform: translateY(-4px); border-color: var(--ocean); box-shadow: 0 14px 30px rgba(0, 70, 110, 0.1); }\n  .uc-card:hover .uc-icon { background: linear-gradient(135deg, var(--ocean-deep), var(--aqua)); color: var(--foam); border-color: transparent; }\n  .uc-icon { width: 56px; height: 56px; border-radius: 14px; border: 1.5px solid var(--line); background: var(--paper-warm); display: grid; place-items: center; color: var(--ocean-deep); transition: all .3s ease; flex-shrink: 0; }\n  .uc-icon svg { width: 28px; height: 28px; stroke: currentColor; stroke-width: 1.6; fill: none; stroke-linecap: round; stroke-linejoin: round; }\n  .uc-num { font-family: 'JetBrains Mono', monospace; font-size: 9px; letter-spacing: 0.22em; color: var(--ocean); display: flex; align-items: center; gap: 8px; text-transform: uppercase; }\n  .uc-num::after { content: \"\"; flex: 1; height: 1px; background: var(--line); }\n  .uc-card h4 { font-family: 'Archivo Narrow', sans-serif; font-weight: 700; text-transform: uppercase; font-size: 20px; line-height: 1; margin: 0; letter-spacing: -0.01em; color: var(--ink); }\n  .uc-card h4 .ital { font-family: 'Archivo', sans-serif; font-style: italic; font-weight: 900; color: var(--ocean); }\n  .uc-benefit { font-size: 12.5px; line-height: 1.4; color: var(--ink-soft); margin: 0; padding: 10px 12px; background: rgba(31, 182, 193, 0.06); border-left: 2px solid var(--aqua); border-radius: 4px; }\n  .uc-benefit b { color: var(--ink); font-weight: 700; }\n  .uc-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: auto; }\n  .uc-tags span { font-family: 'JetBrains Mono', monospace; font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ocean-deep); background: rgba(0, 102, 162, 0.06); border: 1px solid rgba(0, 102, 162, 0.18); padding: 4px 8px; border-radius: 100px; }\n  @media (max-width: 900px) { .usecase-list { grid-template-columns: repeat(3, 1fr); } }\n  @media (max-width: 720px) { .usecase-list { grid-template-columns: 1fr 1fr; } }\n  @media (max-width: 540px) { .usecase-list { grid-template-columns: 1fr; } .compare-row { grid-template-columns: 1fr; } .compare-row .col.hi { border-left: none; border-top: 1px solid var(--line); } }\n\n  \/* ============ CERTIFICATIONS ============ *\/\n  .certs {\n    margin-top: 28px;\n    background: var(--paper-warm);\n    border-radius: 24px;\n    padding: 40px;\n    position: relative;\n    overflow: hidden;\n  }\n  .certs-head {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    margin-bottom: 28px;\n    flex-wrap: wrap;\n    gap: 16px;\n  }\n  .certs h3 {\n    font-family: 'Archivo Narrow', sans-serif;\n    text-transform: uppercase;\n    font-size: 28px;\n    font-weight: 700;\n    margin: 0;\n    letter-spacing: -0.01em;\n  }\n  .certs .stamp {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.2em;\n    color: var(--ocean-deep);\n    text-transform: uppercase;\n    border: 1.5px solid var(--ocean-deep);\n    padding: 6px 12px;\n    border-radius: 100px;\n  }\n  .cert-grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n    gap: 12px;\n  }\n  .cert {\n    background: var(--foam);\n    border: 1px solid var(--line);\n    border-radius: 16px;\n    padding: 22px 20px;\n    display: flex;\n    align-items: center;\n    gap: 14px;\n    transition: all 0.3s ease;\n  }\n  .cert:hover {\n    border-color: var(--ocean);\n    transform: translateY(-2px);\n    box-shadow: 0 8px 24px rgba(0,70,110,0.08);\n  }\n  .cert .glyph {\n    width: 44px; height: 44px;\n    border-radius: 12px;\n    background: var(--paper);\n    display: grid;\n    place-items: center;\n    font-size: 20px;\n    flex-shrink: 0;\n  }\n  .cert .name {\n    font-weight: 700;\n    font-size: 14px;\n    line-height: 1.2;\n    letter-spacing: -0.01em;\n  }\n  .cert .meta {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 9px;\n    letter-spacing: 0.15em;\n    color: var(--ocean);\n    text-transform: uppercase;\n    margin-top: 3px;\n  }\n\n  \/* ============ FAQ ============ *\/\n  .faq {\n    margin-top: 28px;\n    background: var(--paper-warm);\n    border: 1px solid var(--line);\n    border-radius: 24px;\n    padding: 40px 36px;\n    position: relative;\n    overflow: hidden;\n  }\n  .faq::before {\n    content: \"\/\/ frequently asked\";\n    position: absolute;\n    top: 18px; right: 24px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.22em;\n    text-transform: uppercase;\n    color: var(--ocean);\n    opacity: 0.55;\n  }\n  .faq-list {\n    display: flex;\n    flex-direction: column;\n    gap: 0;\n    margin-top: 8px;\n  }\n  .faq-item {\n    border-top: 1px solid var(--line);\n    padding: 0;\n  }\n  .faq-item:last-child { border-bottom: 1px solid var(--line); }\n  .faq-item summary {\n    list-style: none;\n    cursor: pointer;\n    padding: 22px 48px 22px 0;\n    font-family: 'Archivo', sans-serif;\n    font-size: 17px;\n    font-weight: 600;\n    color: var(--ink);\n    letter-spacing: -0.005em;\n    position: relative;\n    transition: color .2s;\n  }\n  .faq-item summary::-webkit-details-marker { display: none; }\n  .faq-item summary::after {\n    content: \"+\";\n    position: absolute;\n    right: 4px; top: 50%;\n    transform: translateY(-50%);\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 22px;\n    color: var(--ocean-deep);\n    font-weight: 400;\n    transition: transform .25s cubic-bezier(.2,.8,.2,1);\n  }\n  .faq-item[open] summary::after { content: \"\\2013\"; }\n  .faq-item summary:hover { color: var(--ocean-deep); }\n  .faq-item .answer {\n    padding: 0 24px 24px 0;\n    font-size: 14.5px;\n    line-height: 1.65;\n    color: #4b5663;\n    max-width: 780px;\n  }\n  .faq-item .answer strong { color: var(--ink); }\n  @media (max-width: 720px) {\n    .faq { padding: 32px 22px; }\n    .faq-item summary { font-size: 15.5px; padding: 20px 40px 20px 0; }\n  }\n\n  \/* ============ CLOSING TICKER ============ *\/\n  .ticker {\n    margin-top: 28px;\n    background: var(--ocean-deep);\n    color: var(--foam);\n    border-radius: 100px;\n    overflow: hidden;\n    position: relative;\n    height: 56px;\n    display: flex;\n    align-items: center;\n  }\n  .ticker-track {\n    display: flex;\n    gap: 48px;\n    white-space: nowrap;\n    animation: ticker-scroll 28s linear infinite;\n    padding-right: 48px;\n  }\n  .ticker-track span {\n    font-family: 'Archivo Narrow', sans-serif;\n    font-weight: 700;\n    font-size: 18px;\n    text-transform: uppercase;\n    letter-spacing: 0.05em;\n    display: flex;\n    align-items: center;\n    gap: 48px;\n  }\n  .ticker-track span::after {\n    content: \"✦\";\n    color: var(--sun);\n  }\n  @keyframes ticker-scroll {\n    to { transform: translateX(-50%); }\n  }\n\n  \/* ============ INTRO ANIMATION ============ *\/\n  @media (prefers-reduced-motion: no-preference) {\n    [data-anim] {\n      opacity: 0;\n      will-change: opacity, transform, filter, clip-path;\n    }\n    [data-anim=\"fade\"]    { transform: translateY(8px); }\n    [data-anim=\"rise\"]    { transform: translateY(28px); }\n    [data-anim=\"rise-lg\"] { transform: translateY(56px); }\n    [data-anim=\"drop\"]    { transform: translateY(-22px); }\n    [data-anim=\"left\"]    { transform: translateX(-32px); }\n    [data-anim=\"right\"]   { transform: translateX(32px); }\n    [data-anim=\"scale\"]   { transform: scale(0.92); }\n    [data-anim=\"zoom\"]    { transform: scale(0.6); filter: blur(8px); }\n    [data-anim=\"reveal\"]  { clip-path: inset(0 100% 0 0); }\n    [data-anim=\"blur\"]    { filter: blur(14px); transform: translateY(12px); }\n\n    [data-anim].in {\n      opacity: 1;\n      transform: none;\n      filter: none;\n      clip-path: inset(0 0 0 0);\n      transition:\n        opacity 0.9s cubic-bezier(0.2, 0.8, 0.2, 1),\n        transform 1s cubic-bezier(0.2, 0.8, 0.2, 1),\n        filter 0.9s ease,\n        clip-path 1.1s cubic-bezier(0.7, 0, 0.3, 1);\n    }\n  }\n\n  \/* ============ TWEAKS — DENSITY ============ *\/\n  \/* Active preset: \"compact\" (tighter, denser). Base vars are inherited by\n     all density-scoped rules below. *\/\n  html { --tw-pad-scale: 1; --tw-radius-scale: 1; --tw-weight-shift: 0; --tw-tracking-add: 0em; --tw-line-shift: 0; }\n  html[data-density=\"compact\"]   { --tw-pad-scale: 0.72; --tw-radius-scale: 0.45; --tw-weight-shift: 100; --tw-tracking-add: -0.005em; --tw-line-shift: -0.06; }\n\n  \/* Apply density to the major surfaces *\/\n  html[data-density] .product-desc { padding: calc(24px * var(--tw-pad-scale)) calc(20px * var(--tw-pad-scale)) calc(80px * var(--tw-pad-scale)); }\n  html[data-density] .hero,\n  html[data-density] .perf-strip,\n  html[data-density] .custom-strip,\n  html[data-density] .certs,\n  html[data-density] .faq,\n  html[data-density] .pricing,\n  html[data-density] .compare,\n  html[data-density] .tech-card,\n  html[data-density] .uc-card,\n  html[data-density] .perf-card,\n  html[data-density] .custom-card,\n  html[data-density] .cert,\n  html[data-density] .pricing-readout,\n  html[data-density] .tier,\n  html[data-density] .bulk-inquiry { border-radius: calc(var(--natural-radius, 20px) * var(--tw-radius-scale)); }\n  \/* assign each surface its natural base radius via custom prop *\/\n  html[data-density] .hero          { --natural-radius: 28px; padding: calc(64px * var(--tw-pad-scale)) calc(48px * var(--tw-pad-scale)) calc(72px * var(--tw-pad-scale)); }\n  html[data-density] .perf-strip    { --natural-radius: 24px; padding: calc(48px * var(--tw-pad-scale)) calc(40px * var(--tw-pad-scale)); }\n  html[data-density] .custom-strip  { --natural-radius: 28px; padding: calc(56px * var(--tw-pad-scale)) calc(48px * var(--tw-pad-scale)); }\n  html[data-density] .certs         { --natural-radius: 24px; padding: calc(40px * var(--tw-pad-scale)); }\n  html[data-density] .faq           { --natural-radius: 24px; padding: calc(40px * var(--tw-pad-scale)) calc(36px * var(--tw-pad-scale)); }\n  html[data-density] .pricing       { --natural-radius: 20px; padding: calc(28px * var(--tw-pad-scale)) calc(28px * var(--tw-pad-scale)) calc(24px * var(--tw-pad-scale)); }\n  html[data-density] .compare       { --natural-radius: 24px; padding: calc(32px * var(--tw-pad-scale)) calc(28px * var(--tw-pad-scale)); }\n  html[data-density] .tech-card     { --natural-radius: 24px; padding: calc(36px * var(--tw-pad-scale)) calc(32px * var(--tw-pad-scale)) calc(32px * var(--tw-pad-scale)); }\n  html[data-density] .uc-card       { --natural-radius: 18px; padding: calc(22px * var(--tw-pad-scale)) calc(20px * var(--tw-pad-scale)) calc(20px * var(--tw-pad-scale)); }\n  html[data-density] .perf-card     { --natural-radius: 16px; padding: calc(22px * var(--tw-pad-scale)) calc(20px * var(--tw-pad-scale)); }\n  html[data-density] .custom-card   { --natural-radius: 18px; padding: calc(24px * var(--tw-pad-scale)) calc(22px * var(--tw-pad-scale)); }\n  html[data-density] .cert          { --natural-radius: 16px; padding: calc(22px * var(--tw-pad-scale)) calc(20px * var(--tw-pad-scale)); }\n  html[data-density] .pricing-readout { --natural-radius: 16px; padding: calc(22px * var(--tw-pad-scale)) calc(26px * var(--tw-pad-scale)); }\n  html[data-density] .bulk-inquiry  { --natural-radius: 14px; }\n  html[data-density] .tier          { --natural-radius: 12px; padding: calc(14px * var(--tw-pad-scale)) calc(10px * var(--tw-pad-scale)); }\n\n  \/* Editorial: lighter weights, looser tracking; Compact: heavier, tighter *\/\n  html[data-density] h1,\n  html[data-density] h2,\n  html[data-density] h3,\n  html[data-density] h4,\n  html[data-density] .pricing-title,\n  html[data-density] .uc-card h4 {\n    font-weight: calc(700 + var(--tw-weight-shift));\n    letter-spacing: calc(-0.02em + var(--tw-tracking-add));\n  }\n  html[data-density=\"compact\"]   .product-title h1 { font-weight: 800; letter-spacing: -0.035em; }\n  html[data-density=\"compact\"]   .hero h2 { font-weight: 900; letter-spacing: -0.045em; }\n\n  \/* Compact thickens borders, sharpens contrast *\/\n  html[data-density=\"compact\"] .pricing,\n  html[data-density=\"compact\"] .compare,\n  html[data-density=\"compact\"] .faq,\n  html[data-density=\"compact\"] .uc-card,\n  html[data-density=\"compact\"] .cert,\n  html[data-density=\"compact\"] .perf-card,\n  html[data-density=\"compact\"] .tier,\n  html[data-density=\"compact\"] .compare-row { border-width: 2px; }\n  html[data-density=\"compact\"] .uc-card::before { width: 6px; }\n\n  \/* ============ TWEAKS — MOTION ============ *\/\n  \/* Active preset: \"riptide\" (everything pulsing). *\/\n  html[data-motion=\"riptide\"] {\n    --tw-spin-mult: 0.18;     \/* rings spin much faster *\/\n    --tw-ticker-mult: 0.35;   \/* ticker much faster *\/\n    --tw-pulse-mult: 0.45;\n  }\n  html[data-motion=\"riptide\"] .acquazero .ring-1 { animation-duration: calc(60s * var(--tw-spin-mult)); }\n  html[data-motion=\"riptide\"] .acquazero .ring-2 { animation-duration: calc(40s * var(--tw-spin-mult)); }\n  html[data-motion=\"riptide\"] .eclipse .ring-1   { animation-duration: calc(70s * var(--tw-spin-mult)); }\n  html[data-motion=\"riptide\"] .ticker-track       { animation-duration: calc(28s * var(--tw-ticker-mult)); }\n  html[data-motion=\"riptide\"] .cta-btn--primary   { animation-duration: calc(2.6s * var(--tw-pulse-mult)); }\n  html[data-motion=\"riptide\"] .cta-btn--primary::before { animation-duration: calc(2.6s * var(--tw-pulse-mult)); }\n  html[data-motion=\"riptide\"] .cta-btn--primary::after  { animation-duration: calc(3.2s * var(--tw-pulse-mult)); }\n  html[data-motion=\"riptide\"] .cta-btn--primary .nudge  { animation-duration: calc(1.6s * var(--tw-pulse-mult)); }\n  html[data-motion=\"riptide\"] .product-title .pill .pulse { animation-duration: 0.8s; }\n  \/* In riptide, add a livelier float to the eclipse feather. *\/\n  html[data-motion=\"riptide\"] .eclipse .feather { animation-duration: 4.5s; }\n  html[data-motion=\"riptide\"] .hero-eyebrow .dot,\n  html[data-motion=\"riptide\"] .pricing-readout::after { animation: tw-glow 2.4s ease-in-out infinite; }\n  @keyframes tw-glow {\n    0%, 100% { opacity: 0.6; }\n    50%      { opacity: 1; }\n  }\n\n  \/* ============ RESPONSIVE ============ *\/\n  @media (max-width: 800px) {\n    .hero { padding: 44px 28px 56px; grid-template-columns: 1fr; gap: 28px; }\n    .hero-visual { max-width: 100%; justify-self: stretch; aspect-ratio: 16 \/ 11; }\n    .tech-grid { grid-template-columns: 1fr; }\n    .perf-grid { grid-template-columns: repeat(2, 1fr); }\n    .cert-grid { grid-template-columns: repeat(2, 1fr); }\n    .custom-grid { grid-template-columns: repeat(2, 1fr); }\n    .custom-strip { padding: 44px 28px; }\n    .custom-strip h3 { font-size: 28px; }\n    .product-desc { padding: 16px 12px 60px; }\n  }\n  @media (max-width: 480px) {\n    .perf-grid, .cert-grid { grid-template-columns: 1fr; }\n    .custom-grid { grid-template-columns: 1fr; }\n    .tech-card h3 { font-size: 48px; }\n  }\n\n  \/* ============ A11Y: respect prefers-reduced-motion ============ *\/\n  \/* Disable all infinite\/looping decorative animations when the user has\n     selected \"reduce motion\" in their OS settings. The brief one-shot\n     intro animations on [data-anim] are already guarded by their own\n     @media (prefers-reduced-motion: no-preference) block above and so\n     do not run at all in this mode. *\/\n  @media (prefers-reduced-motion: reduce) {\n    .acquazero .ring-1,\n    .acquazero .ring-2,\n    .eclipse .ring-1,\n    .eclipse .feather,\n    .ticker-track,\n    .product-title .pill .pulse,\n    .hero-visual svg.honeycomb .cell-a,\n    .hero-visual svg.honeycomb .cell-b,\n    .hero-visual svg.honeycomb .cell-c,\n    .cta-btn--primary,\n    .cta-btn--primary::before,\n    .cta-btn--primary::after,\n    .cta-btn--primary .nudge,\n    .pricing-readout::after,\n    .hero-eyebrow .dot {\n      animation: none !important;\n    }\n  }\n\n  \/* ============ PERF: content-visibility ============ *\/\n  \/* Sections below the initial fold: the browser skips layout\/paint\/style\n     until they scroll near the viewport. contain-intrinsic-size reserves\n     approximate space so the scrollbar doesn't jump. Supported by\n     Chrome\/Edge\/Safari 16+; older browsers ignore both properties safely. *\/\n  .perf-strip,\n  .custom-strip,\n  .usecase,\n  .certs,\n  .faq,\n  .ticker {\n    content-visibility: auto;\n    contain-intrinsic-size: auto 800px;\n  }\n\u003c\/style\u003e\n\n\n\u003cdiv class=\"product-desc\"\u003e\n\n  \u003c!-- ============ PRODUCT TITLE ============ --\u003e\n  \u003cheader class=\"product-title\" style=\"padding: 28px 8px 40px\"\u003e\n    \u003cdiv class=\"top-row\"\u003e\n      \u003cdiv class=\"pill\" data-anim=\"drop\"\u003e\n\u003cspan class=\"pulse\"\u003e\u003c\/span\u003eCompletamente personalizzabile\u003c\/div\u003e\n      \u003cdiv class=\"meta-row\" data-anim=\"right\"\u003e\n        \u003cspan\u003eSKU · COM-RG-01\u003c\/span\u003e\n        \u003cspan\u003eComfort Series\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"kicker\" data-anim=\"left\"\u003eComfort Fit · Relaxed Series\u003c\/div\u003e\n    \u003ch1 data-anim=\"reveal\"\u003eComfort Fit\u003cbr\u003e\u003cspan class=\"accent\"\u003eRashguard\u003c\/span\u003e\n\u003c\/h1\u003e\n    \u003cp class=\"product-full-title\" data-anim=\"rise\"\u003eComfort Fit Rashguard Uomo Manica Corta - Morning Mist\u003c\/p\u003e\n    \u003cp class=\"subline\" data-anim=\"blur\"\u003e\u003cstrong\u003eRashguard relaxed-fit personalizzata. Stessa maglia italiana 4-way stretch da 220 g\/m² e stesse prestazioni SITIP, ma con manica raglan e una silhouette rilassata che cade morbida invece di comprimere. Stampa il tuo logo, i numeri e gli sponsor, dalla singola maglia ai kit completi per la squadra: comfort tutto il giorno per ogni fisico, senza bisogno di una corporatura atletica.\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003c\/p\u003e\n    \u003cdiv class=\"feature-tabs\" data-anim-stagger=\"60\"\u003e\n      \u003cspan data-anim=\"rise\"\u003e✎ Stampa personalizzata\u003c\/span\u003e\n      \u003cspan data-anim=\"rise\"\u003e◐ Acquazero\u003c\/span\u003e\n      \u003cspan data-anim=\"rise\"\u003e☀ Eclipse UPF 50+\u003c\/span\u003e\n      \u003cspan data-anim=\"rise\"\u003e↔ 4-Way Stretch\u003c\/span\u003e\n      \u003cspan data-anim=\"rise\"\u003e🇮🇹 Made in Italy\u003c\/span\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Design CTAs (Shopify Liquid) --\u003e\n    \u003cdiv class=\"design-ctas\" data-anim=\"rise\"\u003e\n      \u003cspan class=\"liquid-tag\"\u003e\u003c\/span\u003e\n      \u003ca href=\"https:\/\/dqavr9-dh.myshopify.com\/pages\/configurator?design=8b747a7c0694d5ebc511c8ea309a3a71\" class=\"cta-btn cta-btn--primary\" style=\"background-size: cover; line-height: 2.3; padding: 22px 24px\"\u003e\n        \u003csvg width=\"18\" height=\"18\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\n          \u003cpath d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"\u003e\u003c\/path\u003e\n        \u003c\/svg\u003e\n        Modifica design \u003cspan class=\"nudge\"\u003e→\u003c\/span\u003e\n      \u003c\/a\u003e\n      \u003cspan class=\"liquid-tag\"\u003e\u003c\/span\u003e\n      \u003ca href=\"https:\/\/infernobeachwear.com\/pages\/configurator\" class=\"cta-btn cta-btn--secondary\"\u003e\n        \u003csvg width=\"18\" height=\"18\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\n          \u003cpath d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"\u003e\u003c\/path\u003e\n        \u003c\/svg\u003e\n        Crea un nuovo design\n      \u003c\/a\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- ============ PRICING TABLE ============ --\u003e\n    \u003cdiv class=\"pricing\" data-anim=\"rise-lg\"\u003e\n      \u003cdiv class=\"pricing-head\"\u003e\n        \u003cdiv\u003e\n          \u003ch3 class=\"pricing-title\"\u003eSconti \u003cspan class=\"em\" style=\"padding: 2px 50px 0px 0px\"\u003equantità\u003c\/span\u003e\n\u003c\/h3\u003e\n          \u003cp class=\"pricing-sub\"\u003eTrascina il cursore · più ordini, più risparmi\u003c\/p\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Live readout --\u003e\n      \u003cdiv class=\"pricing-readout\" style=\"background-color: rgb(255, 255, 255)\"\u003e\n        \u003cdiv class=\"readout-qty\"\u003e\n          \u003cspan class=\"label\"\u003eQuantità\u003c\/span\u003e\n          \u003cspan class=\"value\"\u003e\u003cspan id=\"qty-num\" style=\"color: rgb(245, 177, 61); font-size: 60px\"\u003e2\u003c\/span\u003e\u003csmall style=\"color: rgb(0, 0, 0)\"\u003epz\u003c\/small\u003e\u003c\/span\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"readout-discount\" style=\"color: rgb(0, 0, 0)\"\u003e\n          \u003cdiv class=\"badge zero\" id=\"disc-badge\" style=\"color: rgb(0, 0, 0); font-size: 17px\"\u003e0% di sconto\u003c\/div\u003e\n          \u003cspan class=\"save\" id=\"save-line\" style=\"color: rgb(0, 0, 0)\"\u003eScegli 2+ pz per iniziare a risparmiare\u003c\/span\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"readout-price\"\u003e\n          \u003cdiv class=\"label\"\u003eIl tuo prezzo\u003c\/div\u003e\n          \u003cdiv class=\"unit\"\u003e\n\u003cspan class=\"strike\" id=\"strike-price\" style=\"display: none; color: rgb(0, 0, 0)\"\u003e{{ product.price | money }}\u003c\/span\u003e\u003cspan id=\"unit-price\" style=\"color: rgb(53, 36, 36)\"\u003e{{ product.price | money }}\u003c\/span\u003e\n\u003c\/div\u003e\n          \u003cdiv class=\"total\" style=\"color: rgb(245, 177, 61)\"\u003eTotale: \u003cb style=\"color: rgb(245, 177, 61)\"\u003e\u003cspan id=\"total-price\" style=\"color: rgb(245, 177, 61)\"\u003e{{ product.price | money }}\u003c\/span\u003e\u003c\/b\u003e\n\u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Slider --\u003e\n      \u003cdiv class=\"qty-slider-wrap\"\u003e\n        \u003cinput type=\"range\" min=\"1\" max=\"60\" value=\"1\" class=\"qty-slider\" id=\"qty-slider\" aria-label=\"Quantity\"\u003e\n        \u003cdiv class=\"qty-ticks\"\u003e\n          \u003cspan style=\"left: 14px\"\u003e1\u003c\/span\u003e\n          \u003cspan style=\"left: calc(15.25% + 9.73px)\"\u003e10\u003c\/span\u003e\n          \u003cspan style=\"left: calc(32.20% + 4.98px)\"\u003e20\u003c\/span\u003e\n          \u003cspan style=\"left: calc(49.15% + 0.24px)\"\u003e30\u003c\/span\u003e\n          \u003cspan style=\"left: calc(66.10% - 4.51px)\"\u003e40\u003c\/span\u003e\n          \u003cspan style=\"left: calc(83.05% - 9.25px)\"\u003e50\u003c\/span\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Tiers --\u003e\n      \u003cdiv class=\"tier-grid\" id=\"tier-grid\"\u003e\n        \u003cdiv class=\"tier active\" data-min=\"1\" data-max=\"1\" data-disc=\"0\" style=\"border-color: rgb(138, 82, 82)\"\u003e\n          \u003cdiv class=\"qty\"\u003e1 pz\u003c\/div\u003e\n          \u003cdiv class=\"disc zero\"\u003e0%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | money }} cad.\u003c\/div\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"tier\" data-min=\"2\" data-max=\"2\" data-disc=\"5\"\u003e\n          \u003cdiv class=\"qty\"\u003e2 pz\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−5%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.95 | money }} cad.\u003c\/div\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"tier\" data-min=\"3\" data-max=\"5\" data-disc=\"15\"\u003e\n          \u003cdiv class=\"qty\"\u003e3–5 pz\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−15%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.85 | money }} cad.\u003c\/div\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"tier\" data-min=\"6\" data-max=\"10\" data-disc=\"25\"\u003e\n          \u003cdiv class=\"qty\"\u003e6–10 pz\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−25%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.75 | money }} cad.\u003c\/div\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"tier\" data-min=\"11\" data-max=\"20\" data-disc=\"35\"\u003e\n          \u003cdiv class=\"qty\"\u003e11–20 pz\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−35%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.65 | money }} cad.\u003c\/div\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"tier\" data-min=\"21\" data-max=\"35\" data-disc=\"45\"\u003e\n          \u003cdiv class=\"qty\"\u003e21–35 pz\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−45%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.55 | money }} cad.\u003c\/div\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"tier\" data-min=\"36\" data-max=\"50\" data-disc=\"50\"\u003e\n          \u003cdiv class=\"qty\"\u003e36–50 pz\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−50%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.50 | money }} cad.\u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Bulk inquiry (50+) --\u003e\n      \u003cdiv class=\"bulk-inquiry\" id=\"bulk-inquiry\"\u003e\n        \u003cdiv class=\"bulk-inquiry-text\"\u003e\n          \u003cdiv class=\"bulk-inquiry-eyebrow\"\u003e⚓ 50+ pezzi\u003c\/div\u003e\n          \u003ch4\u003eTi serve un kit completo per la squadra? Parliamone.\n\u003cem\u003e\u003c\/em\u003e\u003c\/h4\u003e\n          \u003cp\u003ePrezzi dedicati per club, squadre ed eventi da 50+ pezzi: ti inviamo un preventivo entro 24 ore.\u003c\/p\u003e\n        \u003c\/div\u003e\n        \u003cbutton type=\"button\" id=\"quote-open-btn\" class=\"bulk-inquiry-cta\"\u003e\n          \u003csvg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\n            \u003cpath d=\"M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z\"\u003e\u003c\/path\u003e\n            \u003cpolyline points=\"22,6 12,13 2,6\"\u003e\u003c\/polyline\u003e\n          \u003c\/svg\u003e\n          Richiedi un preventivo\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Quote request modal --\u003e\n      \u003cdiv class=\"quote-modal-overlay\" id=\"quote-modal-overlay\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"quote-modal-title\" hidden\u003e\n        \u003cdiv class=\"quote-modal\"\u003e\n          \u003cdiv class=\"quote-modal-header\"\u003e\n            \u003cbutton type=\"button\" class=\"quote-modal-close\" id=\"quote-close-btn\" aria-label=\"Close\"\u003e×\u003c\/button\u003e\n            \u003cdiv class=\"quote-modal-eyebrow\"\u003e⚓ Richiesta quantità · 50+ pezzi\u003c\/div\u003e\n            \u003ch3 id=\"quote-modal-title\"\u003eRicevi il tuo preventivo personalizzato.\n\u003cem\u003e\u003c\/em\u003e\u003c\/h3\u003e\n            \u003cp\u003eRaccontaci della tua squadra e ti rispondiamo entro 24h con prezzi e tempi di consegna.\u003c\/p\u003e\n          \u003c\/div\u003e\n          \u003cdiv class=\"quote-modal-body\" id=\"quote-modal-body\"\u003e\n            \u003cform id=\"quote-form\" action=\"\/contact\" method=\"post\" accept-charset=\"UTF-8\" novalidate\u003e\n              \u003cinput type=\"hidden\" name=\"form_type\" value=\"contact\"\u003e\n              \u003cinput type=\"hidden\" name=\"utf8\" value=\"✓\"\u003e\n              \u003cinput type=\"hidden\" name=\"authenticity_token\" id=\"qf-token\" value=\"\"\u003e\n              \u003cinput type=\"hidden\" name=\"return_to\" value=\"\"\u003e\n              \u003cinput type=\"hidden\" name=\"contact[Product]\" value=\"Men’s Comfort Fit Rashguard SS - Morning Mist\"\u003e\n              \u003cinput type=\"hidden\" name=\"contact[Product URL]\" id=\"qf-product-url\" value=\"{{ shop.url | append: product.url }}\"\u003e\n              \u003cinput type=\"hidden\" name=\"contact[subject]\" id=\"qf-subject\" value=\"Bulk quote request from product page\"\u003e\n\n              \u003cdiv class=\"quote-form-row\"\u003e\n                \u003cdiv class=\"quote-field\"\u003e\n                  \u003clabel for=\"qf-club\"\u003eNome club \/ azienda \u003cspan class=\"req\"\u003e*\u003c\/span\u003e\u003c\/label\u003e\n                  \u003cinput type=\"text\" id=\"qf-club\" name=\"contact[name]\" required autocomplete=\"organization\"\u003e\n                  \u003cdiv class=\"quote-field-error\" data-for=\"qf-club\"\u003eInserisci il nome del club o dell’azienda\u003c\/div\u003e\n                \u003c\/div\u003e\n              \u003c\/div\u003e\n\n              \u003cdiv class=\"quote-form-row two\"\u003e\n                \u003cdiv class=\"quote-field\"\u003e\n                  \u003clabel for=\"qf-country\"\u003ePaese \u003cspan class=\"req\"\u003e*\u003c\/span\u003e\u003c\/label\u003e\n                  \u003cinput type=\"text\" id=\"qf-country\" name=\"contact[Country]\" required autocomplete=\"country-name\" placeholder=\"e.g. Italy\"\u003e\n                  \u003cdiv class=\"quote-field-error\" data-for=\"qf-country\"\u003eObbligatorio\u003c\/div\u003e\n                \u003c\/div\u003e\n                \u003cdiv class=\"quote-field\"\u003e\n                  \u003clabel for=\"qf-vat\"\u003ePartita IVA \u003cspan class=\"opt\"\u003e(se presente)\u003c\/span\u003e\u003c\/label\u003e\n                  \u003cinput type=\"text\" id=\"qf-vat\" name=\"contact[VAT]\" autocomplete=\"off\" placeholder=\"IT12345678901\"\u003e\n                \u003c\/div\u003e\n              \u003c\/div\u003e\n\n              \u003cdiv class=\"quote-form-row two\"\u003e\n                \u003cdiv class=\"quote-field\"\u003e\n                  \u003clabel for=\"qf-qty\"\u003eQuantità \u003cspan class=\"req\"\u003e*\u003c\/span\u003e\u003c\/label\u003e\n                  \u003cinput type=\"number\" id=\"qf-qty\" name=\"contact[Quantity]\" min=\"50\" required placeholder=\"e.g. 80\" autocomplete=\"off\" inputmode=\"numeric\"\u003e\n                  \u003cdiv class=\"quote-field-error\" data-for=\"qf-qty\"\u003eDeve essere almeno 50\u003c\/div\u003e\n                \u003c\/div\u003e\n                \u003cdiv class=\"quote-field\"\u003e\n                  \u003clabel for=\"qf-email\"\u003eEmail \u003cspan class=\"req\"\u003e*\u003c\/span\u003e\u003c\/label\u003e\n                  \u003cinput type=\"email\" id=\"qf-email\" name=\"contact[email]\" required autocomplete=\"email\" inputmode=\"email\" placeholder=\"you@club.com\"\u003e\n                  \u003cdiv class=\"quote-field-error\" data-for=\"qf-email\"\u003eÈ richiesta un’email valida\u003c\/div\u003e\n                \u003c\/div\u003e\n              \u003c\/div\u003e\n\n              \u003cdiv class=\"quote-form-row\"\u003e\n                \u003cdiv class=\"quote-field\"\u003e\n                  \u003clabel for=\"qf-notes\"\u003eNote \u003cspan class=\"opt\"\u003e(facoltativo — raccontaci della squadra, del design, delle scadenze, ecc.)\u003c\/span\u003e\u003c\/label\u003e\n                  \u003ctextarea id=\"qf-notes\" name=\"contact[Notes]\" rows=\"4\" autocomplete=\"off\" placeholder=\"e.g. 80 rashguards for our surf club — same logo on all, 6 different sizes mixed, needed by July 15th.\"\u003e\u003c\/textarea\u003e\n                \u003c\/div\u003e\n              \u003c\/div\u003e\n\n              \u003cdiv class=\"quote-honeypot\" aria-hidden=\"true\"\u003e\n                \u003clabel for=\"qf-website\"\u003eSito web (lascia vuoto — anti-spam)\u003c\/label\u003e\n                \u003cinput type=\"text\" id=\"qf-website\" name=\"website\" tabindex=\"-1\" autocomplete=\"off\"\u003e\n              \u003c\/div\u003e\n\n              \u003cbutton type=\"submit\" class=\"quote-modal-submit\"\u003e\n                \u003csvg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\n                  \u003cline x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"\u003e\u003c\/line\u003e\n                  \u003cpolygon points=\"22 2 15 22 11 13 2 9 22 2\"\u003e\u003c\/polygon\u003e\n                \u003c\/svg\u003e\n                Invia richiesta\n              \u003c\/button\u003e\n              \u003cdiv class=\"quote-modal-footnote\"\u003eTi risponderemo entro 24h all’email che ci indichi. Contatto alternativo: custominferno@gmail.com.\u003cstrong\u003e\u003c\/strong\u003e\u003c\/div\u003e\n            \u003c\/form\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003cscript\u003e\n      (function() {\n        \/\/ --- Dynamic base price + currency detection from Shopify ---\n        \/\/ The theme's visible price element is our single source of truth: it\n        \/\/ already reflects the current currency switcher state. We scrape both\n        \/\/ the numeric value AND the currency symbol from its rendered text,\n        \/\/ and re-scrape on every DOM mutation so the volume discount stays in\n        \/\/ sync when the user flips currency.\n        \/\/ Pin the selector to the CURRENT product's ID via Liquid. Horizon\n        \/\/ emits \u003cproduct-price data-product-id=\"\"\u003e,\n        \/\/ so this anchors us to the main product and ignores any unrelated\n        \/\/ \u003cproduct-price\u003e elements (related\/featured\/recommended products)\n        \/\/ that would otherwise be matched by a generic selector.\n        \/\/ If Liquid is not processed, PRODUCT_ID will literally be the\n        \/\/ string \"\", which won't match anything — and the\n        \/\/ unscoped fallbacks below will take over.\n        var PRODUCT_ID = \"\";\n        \/\/ If Liquid was not processed, PRODUCT_ID still contains \"{{\" —\n        \/\/ blank it so we don't generate broken [data-product-id=\"{{ ...\"]\n        \/\/ selectors that wouldn't match anything anyway.\n        if (PRODUCT_ID.indexOf('{') !== -1) PRODUCT_ID = '';\n        var PRICE_SELECTOR = [\n          '[data-product-id=\"' + PRODUCT_ID + '\"] [ref=\"priceContainer\"] .price:not(.compare-at-price)',\n          '[data-product-id=\"' + PRODUCT_ID + '\"] .price:not(.compare-at-price)',\n          '[data-product-id=\"' + PRODUCT_ID + '\"]',\n          \/\/ Unscoped fallbacks (only if data-product-id pinning failed)\n          '.product-details product-price .price:not(.compare-at-price)',\n          '.product-information product-price .price:not(.compare-at-price)',\n          '[data-product-price]',\n          '.price-item--regular',\n          '.product__price'\n        ].join(', ');\n        var themePriceEl = null;\n\n        function parsePriceText(raw) {\n          if (!raw) return null;\n          \/\/ Capture the currency symbol\/code: anything that's not digit\/space\/.,\/-\n          \/\/ Examples we should handle: \"€50.00\", \"$50.00\", \"£50.00\", \"50.00 €\",\n          \/\/ \"USD 50.00\", \"CHF 50,00\", \"kr 50,00\"\n          var symMatch = raw.match(\/[^\\d\\s.,\\-]+(?:\\s*[A-Z]{2,3})?|[A-Z]{2,3}\/);\n          var sym = symMatch ? symMatch[0].trim() : '';\n          \/\/ Normalize number: strip non-numeric except . and ,, drop thousand\n          \/\/ separators, convert decimal comma to dot.\n          var cleaned = raw.replace(\/[^\\d.,]\/g, '');\n          \/\/ If both . and , present, the LAST one is the decimal separator\n          var lastDot = cleaned.lastIndexOf('.');\n          var lastCom = cleaned.lastIndexOf(',');\n          if (lastDot \u003e -1 \u0026\u0026 lastCom \u003e -1) {\n            if (lastCom \u003e lastDot) cleaned = cleaned.replace(\/\\.\/g, '').replace(',', '.');\n            else                   cleaned = cleaned.replace(\/,\/g, '');\n          } else if (lastCom \u003e -1) {\n            \/\/ Only comma — treat as decimal if 1-2 digits after, else thousands\n            var afterCom = cleaned.length - 1 - lastCom;\n            cleaned = afterCom \u003c= 2 ? cleaned.replace(',', '.') : cleaned.replace(\/,\/g, '');\n          }\n          var n = parseFloat(cleaned);\n          if (isNaN(n) || n \u003c= 0) return null;\n          return { value: n, symbol: sym || '' };\n        }\n\n        \/\/ Map a currency CODE (USD, GBP, JPY...) to its localized symbol.\n        \/\/ Intl gives us the right glyph for free — much more reliable than\n        \/\/ scraping the theme's static markup, which often keeps \"€\" hardcoded\n        \/\/ in the Liquid template even after the number gets swapped.\n        var SYMBOL_CACHE = {};\n        function symbolFromCode(code) {\n          if (!code) return null;\n          if (SYMBOL_CACHE[code]) return SYMBOL_CACHE[code];\n          try {\n            var parts = new Intl.NumberFormat('en', { style: 'currency', currency: code }).formatToParts(0);\n            for (var i = 0; i \u003c parts.length; i++) {\n              if (parts[i].type === 'currency') {\n                SYMBOL_CACHE[code] = parts[i].value;\n                return parts[i].value;\n              }\n            }\n          } catch(e) {}\n          SYMBOL_CACHE[code] = code;\n          return code;\n        }\n\n        \/\/ Shopify exposes the currently active currency code globally —\n        \/\/ currency-switcher apps update this synchronously when the user\n        \/\/ picks a new currency, so it's the single source of truth.\n        function activeShopifyCurrency() {\n          try {\n            if (window.Shopify \u0026\u0026 window.Shopify.currency \u0026\u0026 window.Shopify.currency.active) {\n              return window.Shopify.currency.active;\n            }\n          } catch(e) {}\n          return null;\n        }\n\n        function detectFromDOM() {\n          themePriceEl = document.querySelector(PRICE_SELECTOR);\n          var parsed = null;\n          if (themePriceEl) {\n            var raw = themePriceEl.getAttribute('data-product-price')\n                   || themePriceEl.getAttribute('data-price')\n                   || themePriceEl.textContent;\n            parsed = parsePriceText(raw);\n          }\n          \/\/ Override the scraped symbol with Shopify.currency.active when\n          \/\/ it's available — that's the only string that actually tracks the\n          \/\/ currency switcher; theme markup can lag behind.\n          var code = activeShopifyCurrency();\n          if (code \u0026\u0026 parsed) {\n            parsed.symbol = symbolFromCode(code) || parsed.symbol;\n          }\n          \/\/ Do NOT fabricate a value here. If parsed is null, return null\n          \/\/ so the caller falls through to other detection paths.\n          return parsed;\n        }\n\n        function detectInitial() {\n          \/\/ Priority 1: trust the Liquid-rendered initial value in our own\n          \/\/ readout. If the store processes Liquid in product descriptions,\n          \/\/ {{ product.price | money }} has already been replaced with the\n          \/\/ CORRECT product price — that's our single source of truth, and\n          \/\/ it can't be confused with prices of unrelated products on the page.\n          \/\/ If Liquid was not processed, the textContent is \"{{ product.price | money }}\"\n          \/\/ (literal) and parsePriceText returns null, so we fall through.\n          var ownUnit = document.getElementById('unit-price');\n          if (ownUnit) {\n            var ownParsed = parsePriceText(ownUnit.textContent);\n            if (ownParsed \u0026\u0026 ownParsed.value \u003e 0) {\n              \/\/ Override symbol with active Shopify currency when available\n              var code = activeShopifyCurrency();\n              if (code) ownParsed.symbol = symbolFromCode(code) || ownParsed.symbol;\n              return ownParsed;\n            }\n          }\n          \/\/ Priority 2: theme DOM (for stores where Liquid is NOT processed\n          \/\/ in descriptions). detectFromDOM also drives currency switching.\n          var fromDom = detectFromDOM();\n          if (fromDom) return fromDom;\n          try {\n            var sa = window.ShopifyAnalytics;\n            if (sa \u0026\u0026 sa.meta \u0026\u0026 sa.meta.product \u0026\u0026 sa.meta.product.variants \u0026\u0026 sa.meta.product.variants.length) {\n              var v = sa.meta.product.variants[0];\n              if (v \u0026\u0026 typeof v.price === 'number') return { value: v.price \/ 100, symbol: (symbolFromCode(activeShopifyCurrency()) || '') };\n            }\n            if (window.meta \u0026\u0026 window.meta.product \u0026\u0026 window.meta.product.variants \u0026\u0026 window.meta.product.variants.length) {\n              var mv = window.meta.product.variants[0];\n              if (mv \u0026\u0026 typeof mv.price === 'number') return { value: mv.price \/ 100, symbol: (symbolFromCode(activeShopifyCurrency()) || '') };\n            }\n            var jsonEl = document.querySelector('script[type=\"application\/json\"][data-product-json], [id^=\"ProductJson\"]');\n            if (jsonEl) {\n              try {\n                var data = JSON.parse(jsonEl.textContent);\n                if (data) {\n                  if (typeof data.price === 'number') return { value: data.price \/ 100, symbol: (symbolFromCode(activeShopifyCurrency()) || '') };\n                  if (data.variants \u0026\u0026 data.variants[0] \u0026\u0026 data.variants[0].price != null) {\n                    var p = data.variants[0].price;\n                    return { value: (typeof p === 'number' ? p \/ 100 : parseFloat(p)), symbol: (symbolFromCode(activeShopifyCurrency()) || '') };\n                  }\n                }\n              } catch(e) {}\n            }\n          } catch(e) {}\n          \/\/ Last-resort fallback: no detection succeeded. Return 0 (not 50,\n          \/\/ which used to be a confusing \"fake real price\"). The widget\n          \/\/ will visibly read 0,00 so it's obvious detection failed.\n          return { value: 0, symbol: (symbolFromCode(activeShopifyCurrency()) || '') };\n        }\n\n        var initial = detectInitial();\n        var BASE = initial.value;\n        var CURRENCY = initial.symbol;\n\n        var TIERS = [\n          { min: 1, max: 1, disc: 0 },\n          { min: 2, max: 2, disc: 5 },\n          { min: 3, max: 5, disc: 15 },\n          { min: 6, max: 10, disc: 25 },\n          { min: 11, max: 20, disc: 35 },\n          { min: 21, max: 35, disc: 45 },\n          { min: 36, max: 50, disc: 50 }\n        ];\n        var BULK_THRESHOLD = 50;\n        var slider = document.getElementById('qty-slider');\n        var qtyNum = document.getElementById('qty-num');\n        var discBadge = document.getElementById('disc-badge');\n        var saveLine = document.getElementById('save-line');\n        var unitPrice = document.getElementById('unit-price');\n        var totalPrice = document.getElementById('total-price');\n        var strikePrice = document.getElementById('strike-price');\n        var tierEls = document.querySelectorAll('#tier-grid .tier');\n        var bulkBanner = document.getElementById('bulk-inquiry');\n\n        function fmt(n) { return n.toFixed(2); }\n        function money(n) { return CURRENCY + fmt(n); }\n\n        \/\/ The static readout HTML had hardcoded \"€\" prefix spans before\n        \/\/ #unit-price (and a \"€\" text-node before #total-price inside its \u003cb\u003e).\n        \/\/ We blank those out so the symbol now lives in textContent only,\n        \/\/ emitted by money() and refreshable when currency changes.\n        var unitPrefix = unitPrice \u0026\u0026 unitPrice.previousElementSibling;\n        if (unitPrefix \u0026\u0026 unitPrefix.textContent.trim().length \u003c= 3) unitPrefix.textContent = '';\n        if (totalPrice \u0026\u0026 totalPrice.parentNode) {\n          var tp = totalPrice.parentNode;\n          for (var i = 0; i \u003c tp.childNodes.length; i++) {\n            var n = tp.childNodes[i];\n            if (n.nodeType === 3 \u0026\u0026 n.textContent.trim().length \u0026\u0026 n.textContent.trim().length \u003c= 3) n.textContent = '';\n          }\n        }\n\n        function update(qty) {\n          var isBulk = qty \u003e BULK_THRESHOLD;\n          if (bulkBanner) bulkBanner.classList.toggle('show', isBulk);\n\n          if (isBulk) {\n            qtyNum.textContent = '50+';\n            unitPrice.textContent = '—';\n            totalPrice.textContent = 'Quote';\n            discBadge.textContent = '⚓ Custom quote';\n            discBadge.classList.remove('zero');\n            saveLine.innerHTML = 'Bulk pricing on request';\n            strikePrice.style.display = 'none';\n            tierEls.forEach(function(el){ el.classList.remove('active'); });\n            return;\n          }\n\n          var tier = TIERS.find(function(t){ return qty \u003e= t.min \u0026\u0026 qty \u003c= t.max; }) || TIERS[TIERS.length-1];\n          var unit = BASE * (1 - tier.disc\/100);\n          var total = unit * qty;\n          var saved = (BASE - unit) * qty;\n\n          qtyNum.textContent = qty;\n          unitPrice.textContent = money(unit);\n          totalPrice.textContent = money(total);\n\n          if (tier.disc === 0) {\n            discBadge.textContent = '0% off';\n            discBadge.classList.add('zero');\n            saveLine.innerHTML = 'Pick 2+ pcs to start saving';\n            strikePrice.style.display = 'none';\n          } else {\n            discBadge.textContent = '− ' + tier.disc + '% off';\n            discBadge.classList.remove('zero');\n            saveLine.innerHTML = 'You save \u003cb\u003e' + money(saved) + '\u003c\/b\u003e';\n            strikePrice.style.display = '';\n            strikePrice.textContent = money(BASE);\n          }\n\n          tierEls.forEach(function(el) {\n            var min = parseInt(el.getAttribute('data-min'),10);\n            var max = parseInt(el.getAttribute('data-max'),10);\n            el.classList.toggle('active', qty \u003e= min \u0026\u0026 qty \u003c= max);\n          });\n        }\n\n        function refreshTiers() {\n          tierEls.forEach(function(el){\n            var disc = parseInt(el.getAttribute('data-disc'),10) || 0;\n            var label = el.querySelector('.price-each');\n            if (label) label.textContent = money(BASE * (1 - disc\/100)) + ' ea';\n          });\n        }\n\n        slider.addEventListener('input', function(){ update(parseInt(slider.value,10)); });\n        tierEls.forEach(function(el){\n          el.addEventListener('click', function(){\n            var min = parseInt(el.getAttribute('data-min'),10);\n            slider.value = min;\n            update(min);\n          });\n        });\n        refreshTiers();\n        update(1);\n\n        \/\/ --- React to Shopify currency switcher ---\n        \/\/ The theme price element re-renders when the user changes currency.\n        \/\/ Re-scrape its value+symbol on every mutation, then re-run the math\n        \/\/ so tiers, readout and \"save\" line all stay coherent.\n        function onCurrencyMaybeChanged() {\n          var fresh = detectFromDOM();\n          if (!fresh) return;\n          if (fresh.value === BASE \u0026\u0026 fresh.symbol === CURRENCY) return;\n          \/\/ Outlier guard: if the symbol didn't change but the value is\n          \/\/ wildly different from the current BASE (more than 2x larger or\n          \/\/ smaller), that's almost certainly a different product picked\n          \/\/ up by an incorrect selector — reject the update.\n          if (fresh.symbol === CURRENCY \u0026\u0026 BASE \u003e 0) {\n            var ratio = fresh.value \/ BASE;\n            if (ratio \u003c 0.5 || ratio \u003e 2.0) return;\n          }\n          BASE = fresh.value;\n          CURRENCY = fresh.symbol;\n          refreshTiers();\n          update(parseInt(slider.value,10));\n        }\n        \/\/ If detectInitial picked the value from our own readout (Priority 1)\n        \/\/ themePriceEl was never set. Call detectFromDOM purely for the\n        \/\/ side-effect of populating it, so the MutationObserver can watch\n        \/\/ the theme's price element for currency-switch changes.\n        if (!themePriceEl) detectFromDOM();\n        if (themePriceEl \u0026\u0026 window.MutationObserver) {\n          var mo = new MutationObserver(onCurrencyMaybeChanged);\n          mo.observe(themePriceEl, { childList: true, characterData: true, subtree: true, attributes: true, attributeFilter: ['data-product-price','data-price'] });\n        }\n        \/\/ Some currency apps swap the price element wholesale or only fire\n        \/\/ Listen to standard currency-switcher events only. NO polling:\n        \/\/ a setInterval kept overwriting the correct Liquid-rendered price\n        \/\/ with whatever the (potentially wrong) PRICE_SELECTOR found.\n        ['shopify:section:load','currency:change','currency.changed','shopify:cart:update'].forEach(function(ev){\n          document.addEventListener(ev, onCurrencyMaybeChanged);\n        });\n\n        \/\/ ===== Quote request modal =====\n        var qOverlay = document.getElementById('quote-modal-overlay');\n        var qOpenBtn = document.getElementById('quote-open-btn');\n        var qCloseBtn = document.getElementById('quote-close-btn');\n        var qForm = document.getElementById('quote-form')\n          || document.querySelector('#quote-modal-body form');\n        var qBody = document.getElementById('quote-modal-body');\n\n        \/\/ Remember which element was focused before the modal opened, so we\n        \/\/ can restore focus there on close (a11y: keyboard users should not\n        \/\/ be stranded at the page \u003cbody\u003e after closing the modal).\n        var qFocusReturn = null;\n        \/\/ Saved scroll position for iOS-safe body scroll lock.\n        var qSavedScrollY = 0;\n\n        function openQuote() {\n          if (!qOverlay) return;\n          \/\/ Move overlay to \u003cbody\u003e on open to escape any ancestor with\n          \/\/ transform\/filter\/will-change that would trap position:fixed\n          \/\/ (Shopify theme wrappers commonly do this — symptom on mobile:\n          \/\/ the site header stays visible behind the \"fullscreen\" modal).\n          if (qOverlay.parentNode !== document.body) {\n            document.body.appendChild(qOverlay);\n          }\n          qFocusReturn = document.activeElement;\n          qOverlay.hidden = false;\n          \/\/ force reflow then add show class\n          requestAnimationFrame(function(){ qOverlay.classList.add('show'); });\n          \/\/ Pre-fill quantity with current slider value if 50+\n          var qInput = document.getElementById('qf-qty');\n          if (qInput) {\n            var cur = parseInt(slider.value, 10);\n            qInput.value = cur \u003e 50 ? cur : 50;\n          }\n          \/\/ iOS-safe body scroll lock: overflow:hidden alone DOES NOT prevent\n          \/\/ scrolling on iOS Safari. We freeze the body in place with\n          \/\/ position:fixed and remember the scroll position so we can restore\n          \/\/ it on close — the only reliable cross-browser approach.\n          qSavedScrollY = window.scrollY || window.pageYOffset || 0;\n          document.body.style.position = 'fixed';\n          document.body.style.top = (-qSavedScrollY) + 'px';\n          document.body.style.left = '0';\n          document.body.style.right = '0';\n          document.body.style.width = '100%';\n          \/\/ Move focus to the first input inside the modal after the open\n          \/\/ animation has had a moment to start (avoids fighting the visual\n          \/\/ transition or being stolen back by the page).\n          setTimeout(function(){\n            var firstInput = qOverlay.querySelector('input:not([type=\"hidden\"]):not([disabled]):not(.quote-honeypot input), textarea:not([disabled]), select:not([disabled])');\n            if (firstInput) firstInput.focus();\n          }, 60);\n        }\n        function closeQuote() {\n          if (!qOverlay) return;\n          qOverlay.classList.remove('show');\n          setTimeout(function(){\n            qOverlay.hidden = true;\n            \/\/ Undo iOS-safe body scroll lock and restore the user's scroll\n            \/\/ position (which was lost when we switched body to position:fixed).\n            document.body.style.position = '';\n            document.body.style.top = '';\n            document.body.style.left = '';\n            document.body.style.right = '';\n            document.body.style.width = '';\n            window.scrollTo(0, qSavedScrollY);\n            \/\/ Restore focus to whatever opened the modal.\n            if (qFocusReturn \u0026\u0026 typeof qFocusReturn.focus === 'function') {\n              try { qFocusReturn.focus(); } catch(err) {}\n            }\n            qFocusReturn = null;\n          }, 280);\n        }\n        if (qOpenBtn) qOpenBtn.addEventListener('click', openQuote);\n        if (qCloseBtn) qCloseBtn.addEventListener('click', closeQuote);\n        if (qOverlay) qOverlay.addEventListener('click', function(e){\n          if (e.target === qOverlay) closeQuote();\n        });\n        document.addEventListener('keydown', function(e){\n          if (e.key === 'Escape' \u0026\u0026 qOverlay \u0026\u0026 !qOverlay.hidden) closeQuote();\n        });\n\n        \/\/ Focus trap: while the modal is open, keep Tab\/Shift+Tab cycling\n        \/\/ among focusable elements inside the modal — never letting focus\n        \/\/ escape to the page underneath.\n        if (qOverlay) qOverlay.addEventListener('keydown', function(e){\n          if (e.key !== 'Tab' || qOverlay.hidden) return;\n          var focusables = qOverlay.querySelectorAll(\n            'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n          );\n          var visible = Array.prototype.filter.call(focusables, function(el){\n            return el.offsetParent !== null;\n          });\n          if (!visible.length) return;\n          var first = visible[0];\n          var last = visible[visible.length - 1];\n          if (e.shiftKey \u0026\u0026 document.activeElement === first) {\n            e.preventDefault();\n            last.focus();\n          } else if (!e.shiftKey \u0026\u0026 document.activeElement === last) {\n            e.preventDefault();\n            first.focus();\n          }\n        });\n\n        function isValidEmail(s) {\n          return \/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/.test(String(s).trim());\n        }\n\n        \/\/ Escape HTML special chars before interpolating user input into\n        \/\/ innerHTML. Prevents XSS via crafted email addresses (the email\n        \/\/ regex above doesn't block \u003c \u003e \" ' \u0026 by itself).\n        function escapeHtml(s) {\n          return String(s).replace(\/[\u0026\u003c\u003e\"']\/g, function(c){\n            return ({ '\u0026': '\u0026amp;', '\u003c': '\u0026lt;', '\u003e': '\u0026gt;', '\"': '\u0026quot;', \"'\": '\u0026#39;' })[c];\n          });\n        }\n\n        function showError(id, show) {\n          var input = document.getElementById(id);\n          var err = document.querySelector('.quote-field-error[data-for=\"' + id + '\"]');\n          if (input) input.classList.toggle('invalid', !!show);\n          if (err) err.classList.toggle('show', !!show);\n        }\n\n        \/\/ ===== Scrape Shopify's authenticity_token at page load =====\n        \/\/ The token is needed so the native form submit can POST to \/contact.\n        \/\/ We scrape it from any page on the store that DOES render a Liquid\n        \/\/ {% form %} tag (product description HTML doesn't). Best source is\n        \/\/ the current page (same session, same cookie). The token is written\n        \/\/ into the hidden #qf-token BEFORE the user submits.\n        function loadTokenIntoForm(){\n          var qfToken = document.getElementById('qf-token');\n          if (!qfToken) return;\n          \/\/ Scrape only the current page: same session\/cookie, token is\n          \/\/ guaranteed valid if found. Skip the \/pages\/contact and \/ fallbacks\n          \/\/ that previously chained — they downloaded ~400KB of HTML for no\n          \/\/ additional chance of success in practice.\n          fetch(window.location.pathname + window.location.search, {\n            credentials: 'same-origin',\n            headers: { 'Accept': 'text\/html' }\n          })\n            .then(function(r){ return r.ok ? r.text() : Promise.reject(new Error('GET ' + r.status)); })\n            .then(function(html){\n              var m = html.match(\/name=\"authenticity_token\"\\s+value=\"([^\"]+)\"\/);\n              if (m) qfToken.value = m[1];\n              \/* if no match, qfToken stays empty → submit handler falls back to mailto: *\/\n            })\n            .catch(function(){ \/* network error — submit handler falls back to mailto: *\/ });\n        }\n        loadTokenIntoForm();\n\n        \/\/ ===== URL hygiene: strip Shopify contact-form leftover params =====\n        \/\/ When return_to fails to resolve (Liquid not processed in a product\n        \/\/ description), Shopify can redirect back with all the contact[*]\n        \/\/ fields appended to the page URL. Those leftovers then pollute the\n        \/\/ NEXT submission's \"Product URL\" field (auto-perpetuating bug) and\n        \/\/ make the shared page URL ugly. Strip them on load, and use this\n        \/\/ helper any time we copy window.location into a hidden field.\n        function stripContactParams(url) {\n          var u;\n          try { u = new URL(url, window.location.origin); }\n          catch (e) { return url; }\n          var changed = false;\n          var keep = new URLSearchParams();\n          u.searchParams.forEach(function(v, k){\n            if (k.indexOf('contact[') === 0 || k === 'form_type' || k === 'contact_posted') {\n              changed = true;\n              return;\n            }\n            keep.append(k, v);\n          });\n          if (!changed) return url;\n          u.search = keep.toString();\n          return u.toString();\n        }\n        try {\n          var cleanUrl = stripContactParams(window.location.href);\n          if (cleanUrl !== window.location.href) {\n            history.replaceState(null, '', cleanUrl);\n          }\n        } catch (e) {}\n\n        \/\/ ===== Product URL: guarantee a correct value =====\n        \/\/ The Liquid `{{ shop.url | append: product.url }}` SHOULD resolve to\n        \/\/ the full product URL, but some Liquid-in-description apps strip or\n        \/\/ mis-parse complex tags. The browser's window.location.href is\n        \/\/ always the actual product URL the user is viewing (including the\n        \/\/ ?variant=... param), so we override the hidden field with it if\n        \/\/ the Liquid output looks incomplete (missing \"\/products\/\" path).\n        \/\/ Always run through stripContactParams so a polluted URL from a\n        \/\/ previous failed submit can't poison the next one.\n        (function ensureProductUrl(){\n          var el = document.getElementById('qf-product-url');\n          if (!el) return;\n          var liquidValue = (el.value || '').trim();\n          if (liquidValue.indexOf('\/products\/') === -1) {\n            el.value = stripContactParams(window.location.href);\n          } else {\n            el.value = stripContactParams(liquidValue);\n          }\n        })();\n\n        \/\/ ===== return_to: same defensive treatment =====\n        \/\/ If Liquid didn't resolve ``, fall back to the\n        \/\/ current pathname (no query string). Otherwise strip contact[*]\n        \/\/ params so the post-submit redirect lands on a clean URL.\n        (function ensureReturnTo(){\n          if (!qForm) return;\n          var el = qForm.querySelector('input[name=\"return_to\"]');\n          if (!el) return;\n          var v = (el.value || '').trim();\n          if (v.indexOf('\/products\/') === -1) {\n            el.value = window.location.pathname;\n          } else {\n            el.value = stripContactParams(v);\n          }\n        })();\n\n        if (qForm) {\n          qForm.addEventListener('submit', function(e){\n            \/\/ Honeypot check: real humans won't see\/fill the off-screen\n            \/\/ \"website\" field. If it's been filled, silently drop the\n            \/\/ submission and show a fake success — the bot moves on, no\n            \/\/ email is sent.\n            var honeypot = document.getElementById('qf-website');\n            if (honeypot \u0026\u0026 honeypot.value.trim() !== '') {\n              e.preventDefault();\n              if (qBody) {\n                qBody.innerHTML =\n                  '\u003cdiv class=\"quote-success\"\u003e'\n                  + '\u003cdiv class=\"check\"\u003e✓\u003c\/div\u003e'\n                  + '\u003ch4\u003eRequest sent!\u003c\/h4\u003e'\n                  + '\u003cp\u003eWe received your inquiry and will reply within 24 hours.\u003c\/p\u003e'\n                  + '\u003c\/div\u003e';\n              }\n              setTimeout(closeQuote, 4000);\n              return;\n            }\n\n            var club = document.getElementById('qf-club').value.trim();\n            var country = document.getElementById('qf-country').value.trim();\n            var vat = document.getElementById('qf-vat').value.trim();\n            var qty = parseInt(document.getElementById('qf-qty').value, 10);\n            var email = document.getElementById('qf-email').value.trim();\n            var notes = (document.getElementById('qf-notes')?.value || '').trim();\n\n            \/\/ Client-side validation — block native submit only on errors.\n            var ok = true;\n            showError('qf-club', !club); if (!club) ok = false;\n            showError('qf-country', !country); if (!country) ok = false;\n            showError('qf-qty', !(qty \u003e= 50)); if (!(qty \u003e= 50)) ok = false;\n            showError('qf-email', !isValidEmail(email)); if (!isValidEmail(email)) ok = false;\n            if (!ok) { e.preventDefault(); return; }\n\n            \/\/ Resolve product name and compose subject + body for the email.\n            var productName = document.title || 'Custom Inferno product';\n            try {\n              if (window.ShopifyAnalytics \u0026\u0026 window.ShopifyAnalytics.meta \u0026\u0026 window.ShopifyAnalytics.meta.product) {\n                productName = window.ShopifyAnalytics.meta.product.title || productName;\n              }\n            } catch(err) {}\n            var subject = 'Bulk quote request — ' + qty + ' pcs — ' + club;\n            var bodyLines = [\n              'New bulk quote request from the product page.', '',\n              'Product: ' + productName,\n              'Club \/ Company: ' + club,\n              'Country: ' + country,\n              'VAT number: ' + (vat || '—'),\n              'Quantity: ' + qty + ' pieces',\n              'Contact email: ' + email\n            ];\n            if (notes) {\n              bodyLines.push('', 'Notes:', notes);\n            }\n            \/\/ Body string is only used for the mailto: fallback; Shopify\n            \/\/ renders the individual fields (Name, Country, VAT, Quantity,\n            \/\/ Email, Notes, Product, Product URL) in the email itself, so\n            \/\/ we no longer push it into a contact[body] hidden field.\n            var body = bodyLines.join('\\n');\n            var qfSubject = document.getElementById('qf-subject');\n            if (qfSubject) qfSubject.value = subject;\n\n            \/\/ If token wasn't fetched (slow network or theme didn't expose\n            \/\/ it), show an in-modal error instead of falling back to mailto:.\n            \/\/ On iOS, `location.href = 'mailto:'` opens the Mail app — that's\n            \/\/ confusing UX, and the resulting message comes from the user's\n            \/\/ own email client (different from\/template, no Shopify routing).\n            var qfToken = document.getElementById('qf-token');\n            if (!qfToken || !qfToken.value) {\n              e.preventDefault();\n              if (qBody) {\n                qBody.innerHTML =\n                  '\u003cdiv class=\"quote-success\"\u003e'\n                  + '\u003cdiv class=\"check\" style=\"background: linear-gradient(135deg, #ff5e3a, #f5b13d)\"\u003e!\u003c\/div\u003e'\n                  + '\u003ch4\u003eService temporarily unavailable\u003c\/h4\u003e'\n                  + '\u003cp\u003ePlease try again in a few seconds, or email us directly at \u003cstrong\u003ecustominferno@gmail.com\u003c\/strong\u003e.\u003c\/p\u003e'\n                  + '\u003c\/div\u003e';\n              }\n              return;\n            }\n\n            \/\/ Set a localStorage flag with a timestamp BEFORE the native\n            \/\/ submit. localStorage (not sessionStorage) because some browsers\n            \/\/ do not commit sessionStorage in time during a synchronous form\n            \/\/ unload, leaving the flag null on the next page. localStorage\n            \/\/ is committed synchronously and survives the redirect reliably.\n            try {\n              localStorage.setItem('quoteSubmitted', JSON.stringify({\n                email: email,\n                timestamp: Date.now()\n              }));\n            } catch(err) {}\n\n            \/\/ Disable the submit button to prevent double-clicks while the\n            \/\/ native submit is in flight (the browser navigates away in ~1s,\n            \/\/ but a fast double-tap could otherwise trigger two POSTs).\n            var qSubmitBtn = qForm.querySelector('button[type=\"submit\"]');\n            if (qSubmitBtn) qSubmitBtn.disabled = true;\n\n            \/\/ Show pending state — the browser will reload shortly.\n            qBody.innerHTML =\n              '\u003cdiv class=\"quote-success\"\u003e'\n              + '\u003cdiv class=\"check\" style=\"background: linear-gradient(135deg, #1fb6c1, #0066a2)\"\u003e…\u003c\/div\u003e'\n              + '\u003ch4\u003eSending your request…\u003c\/h4\u003e'\n              + '\u003cp\u003eOne moment.\u003c\/p\u003e'\n              + '\u003c\/div\u003e';\n\n            \/\/ No e.preventDefault() — let the browser do the native POST.\n            \/\/ hCaptcha will solve invisibly; Shopify sends the email and\n            \/\/ redirects to the URL declared in `return_to` (the product page).\n            \/\/ When that landing page loads, the IIFE runs again and the\n            \/\/ detectQuoteSubmitted handler picks up the sessionStorage flag.\n          });\n        }\n\n        \/\/ ===== Post-redirect success banner =====\n        \/\/ Triggers on TWO independent signals (either one is enough):\n        \/\/   1. localStorage 'quoteSubmitted' flag set by the submit handler\n        \/\/   2. Shopify's own URL params (contact_posted=true, etc.) that\n        \/\/      Shopify sometimes appends after a successful contact submit\n        \/\/ We run the check on DOMContentLoaded to guarantee qBody\/openQuote\n        \/\/ are defined; if the script already runs late, we run immediately.\n        function detectQuoteSubmitted(){\n          var raw = null;\n          var data = null;\n          try { raw = localStorage.getItem('quoteSubmitted'); } catch(err) {}\n          if (raw) {\n            try { data = JSON.parse(raw); } catch(err) {}\n            \/\/ Always clear the flag (even if invalid) so it never fires twice.\n            try { localStorage.removeItem('quoteSubmitted'); } catch(err) {}\n          }\n          \/\/ Check URL params as a secondary signal (Shopify standard).\n          var params = new URLSearchParams(window.location.search);\n          var shopifyPosted = params.get('contact_posted') === 'true'\n            || params.get('contact[posted]') === 'true'\n            || params.has('contact_form_success');\n          if (shopifyPosted) {\n            \/\/ Strip these params so a refresh doesn't replay the banner.\n            ['contact_posted', 'contact[posted]', 'contact_form_success'].forEach(function(k){\n              params.delete(k);\n            });\n            var cleanUrl = window.location.pathname\n              + (params.toString() ? '?' + params.toString() : '')\n              + window.location.hash;\n            history.replaceState({}, '', cleanUrl);\n          }\n          \/\/ Trigger if EITHER the flag is recent (\u003c 60s) OR Shopify URL signal.\n          var flagFresh = data \u0026\u0026 data.timestamp \u0026\u0026 (Date.now() - data.timestamp \u003c= 60000);\n          if (!flagFresh \u0026\u0026 !shopifyPosted) return;\n          var email = (data \u0026\u0026 data.email) || '';\n          if (qBody) {\n            qBody.innerHTML =\n              '\u003cdiv class=\"quote-success\"\u003e'\n              + '\u003cdiv class=\"check\"\u003e✓\u003c\/div\u003e'\n              + '\u003ch4\u003eRequest sent!\u003c\/h4\u003e'\n              + '\u003cp\u003eWe received your inquiry'\n              + (email ? ' and will reply to \u003cstrong\u003e' + escapeHtml(email) + '\u003c\/strong\u003e' : '')\n              + ' within 24 hours.\u003c\/p\u003e'\n              + '\u003c\/div\u003e';\n          }\n          openQuote();\n          setTimeout(closeQuote, 5500);\n        }\n        if (document.readyState === 'loading') {\n          document.addEventListener('DOMContentLoaded', detectQuoteSubmitted);\n        } else {\n          detectQuoteSubmitted();\n        }\n      })();\n      \u003c\/script\u003e\n    \u003c\/div\u003e\n\n  \u003c\/header\u003e\n\n  \u003c!-- ============ HERO ============ --\u003e\n  \u003csection class=\"hero\" data-anim=\"rise-lg\"\u003e\n    \u003cdiv class=\"hero-text\"\u003e\n    \u003cdiv class=\"hero-eyebrow\" data-anim=\"drop\"\u003e\n      \u003cspan class=\"dot\"\u003e\u003c\/span\u003e\n      Tessuti italiani premium\n    \u003c\/div\u003e\n    \u003ch2 data-anim=\"reveal\"\u003eProgettata per l’\u003cbr\u003e\u003cspan class=\"ital\"\u003eacqua.\u003c\/span\u003e Tagliata per il sole.\u003c\/h2\u003e\n    \u003cp data-anim=\"blur\"\u003eRealizzata con i tessuti tecnici SITIP, l’azienda di Bergamo che tesse filati ad alte prestazioni dal 1956. Ogni metro di tessuto è rifinito per resistere a salsedine, sole e mille lavaggi.\u003c\/p\u003e\n    \u003cdiv class=\"hero-meta\" data-anim-stagger=\"80\"\u003e\n      \u003cspan data-anim=\"rise\"\u003ePowered by SITIP\u003c\/span\u003e\n      \u003cspan data-anim=\"rise\"\u003eMade in Italy\u003c\/span\u003e\n      \u003cspan data-anim=\"rise\"\u003eTestata nel Mediterraneo\u003c\/span\u003e\n    \u003c\/div\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"hero-visual\" data-anim=\"zoom\" aria-label=\"NEW MONICA fabric — UPF 50+ sun protection and water-resistant Italian knit by SITIP\"\u003e\n      \u003cspan class=\"hc-feather\"\u003eUPF 50+ · Idrorepellente\u003c\/span\u003e\n      \u003cimg class=\"honeycomb\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0988\/4323\/0595\/files\/NEW_MONICA_FABRIC_UPF_50_WATER_RESISTANT_a7590067-5f99-481a-a1d3-e1247285a509.png?v=1779367352\" alt=\"NEW MONICA fabric by SITIP — UPF 50+ sun protection and water-resistant Italian performance knit\" decoding=\"async\" fetchpriority=\"high\" width=\"460\" height=\"460\"\u003e\n      \u003cspan class=\"hc-label\"\u003e\n        Nuovo tessuto SITIP · MONICA\n      \u003cstrong\u003e\u003c\/strong\u003e\u003c\/span\u003e\n    \u003c\/div\u003e\n    \u003csvg class=\"waves\" viewbox=\"0 0 1200 110\" preserveaspectratio=\"none\" aria-hidden=\"true\"\u003e\n      \u003cpath d=\"M0,60 C200,100 400,20 600,60 C800,100 1000,20 1200,60 L1200,110 L0,110 Z\" fill=\"rgba(255,255,255,0.08)\"\u003e\u003c\/path\u003e\n      \u003cpath d=\"M0,80 C200,40 400,110 600,80 C800,50 1000,110 1200,80 L1200,110 L0,110 Z\" fill=\"rgba(255,255,255,0.14)\"\u003e\u003c\/path\u003e\n      \u003cpath d=\"M0,100 C300,80 600,120 900,100 C1050,90 1150,105 1200,100 L1200,110 L0,110 Z\" fill=\"#ffffff\"\u003e\u003c\/path\u003e\n    \u003c\/svg\u003e\n  \u003c\/section\u003e\n\n  \u003c!-- ============ TECHNOLOGIES ============ --\u003e\n  \u003cdiv class=\"section-head\"\u003e\n    \u003cdiv\u003e\n      \u003cdiv class=\"num\" data-anim=\"left\"\u003e01 ; TECNOLOGIA\u003c\/div\u003e\n      \u003ch2 data-anim=\"reveal\"\u003eDue finiture.\u003cbr\u003eUn solo oceano.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eDue trattamenti SITIP brevettati lavorano in coppia: uno respinge ciò che ti lancia l’acqua, l’altro ti scherma da ciò che ti manda il sole.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003cdiv class=\"tech-grid\" data-anim-stagger=\"180\"\u003e\n    \u003c!-- Acquazero --\u003e\n    \u003carticle class=\"tech-card acquazero\" data-anim=\"rise-lg\"\u003e\n      \u003cdiv class=\"ring ring-1\"\u003e\u003c\/div\u003e\n      \u003cdiv class=\"ring ring-2\"\u003e\u003c\/div\u003e\n      \u003cdiv class=\"deco\"\u003e\/\/ SITIP·H₂O\u003c\/div\u003e\n      \u003cdiv class=\"badge\"\u003e◐ Sistema idrorepellente\u003c\/div\u003e\n      \u003ch3\u003eAcquazero\u003c\/h3\u003e\n      \u003cp class=\"tagline\"\u003eL’acqua scivola via, il sale scivola via e le macchie non attecchiscono.\u003c\/p\u003e\n      \u003cul class=\"tech-features\"\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e💧\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eIdrorepellente senza fluoro\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e🌿\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eChimica senza PFOA ed eco-friendly\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e🧼\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eResistente ai lavaggi: le prestazioni durano nel tempo\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e💨\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eTraspirante e morbida al tatto\u003c\/div\u003e\n        \u003c\/li\u003e\n      \u003c\/ul\u003e\n    \u003c\/article\u003e\n\n    \u003c!-- NATIVE --\u003e\n    \u003carticle class=\"tech-card eclipse\" data-anim=\"rise-lg\"\u003e\n      \u003csvg class=\"feather\" viewbox=\"0 0 80 140\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\"\u003e\n        \u003cdefs\u003e\n          \u003clineargradient id=\"featherFill\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\"\u003e\n            \u003cstop offset=\"0%\" stop-color=\"#ffffff\" stop-opacity=\"0.95\"\u003e\u003c\/stop\u003e\n            \u003cstop offset=\"60%\" stop-color=\"#ffffff\" stop-opacity=\"0.75\"\u003e\u003c\/stop\u003e\n            \u003cstop offset=\"100%\" stop-color=\"#ffffff\" stop-opacity=\"0.35\"\u003e\u003c\/stop\u003e\n          \u003c\/lineargradient\u003e\n          \u003clineargradient id=\"featherShade\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\"\u003e\n            \u003cstop offset=\"0%\" stop-color=\"#ffffff\" stop-opacity=\"0\"\u003e\u003c\/stop\u003e\n            \u003cstop offset=\"50%\" stop-color=\"#ffffff\" stop-opacity=\"0.22\"\u003e\u003c\/stop\u003e\n            \u003cstop offset=\"100%\" stop-color=\"#ffffff\" stop-opacity=\"0\"\u003e\u003c\/stop\u003e\n          \u003c\/lineargradient\u003e\n        \u003c\/defs\u003e\n        \u003c!-- main plume --\u003e\n        \u003cpath d=\"M 40 6 C 22 22, 12 50, 14 82 C 16 108, 26 128, 38 138 L 42 138 C 54 128, 64 108, 66 82 C 68 50, 58 22, 40 6 Z\" fill=\"url(#featherFill)\"\u003e\u003c\/path\u003e\n        \u003c!-- inner shading --\u003e\n        \u003cpath d=\"M 40 18 C 28 32, 22 56, 24 80 C 26 100, 32 116, 40 124 C 48 116, 54 100, 56 80 C 58 56, 52 32, 40 18 Z\" fill=\"url(#featherShade)\"\u003e\u003c\/path\u003e\n        \u003c!-- rachis (central spine) --\u003e\n        \u003cpath d=\"M 40 8 Q 41 70 40 135\" stroke=\"rgba(255,255,255,0.55)\" stroke-width=\"0.9\" fill=\"none\" stroke-linecap=\"round\"\u003e\u003c\/path\u003e\n        \u003c!-- left barbs --\u003e\n        \u003cg stroke=\"rgba(255,255,255,0.32)\" stroke-width=\"0.6\" fill=\"none\" stroke-linecap=\"round\"\u003e\n          \u003cpath d=\"M 39 24 Q 32 27 22 32\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 39 36 Q 30 41 18 48\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 39 48 Q 28 54 16 62\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 39 60 Q 27 67 15 76\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 39 72 Q 27 78 16 88\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 39 84 Q 28 91 18 100\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 39 96 Q 30 104 22 112\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 39 108 Q 32 116 27 124\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 39 120 Q 35 126 32 132\"\u003e\u003c\/path\u003e\n        \u003c\/g\u003e\n        \u003c!-- right barbs --\u003e\n        \u003cg stroke=\"rgba(255,255,255,0.32)\" stroke-width=\"0.6\" fill=\"none\" stroke-linecap=\"round\"\u003e\n          \u003cpath d=\"M 41 24 Q 48 27 58 32\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 41 36 Q 50 41 62 48\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 41 48 Q 52 54 64 62\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 41 60 Q 53 67 65 76\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 41 72 Q 53 78 64 88\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 41 84 Q 52 91 62 100\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 41 96 Q 50 104 58 112\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 41 108 Q 48 116 53 124\"\u003e\u003c\/path\u003e\n          \u003cpath d=\"M 41 120 Q 45 126 48 132\"\u003e\u003c\/path\u003e\n        \u003c\/g\u003e\n      \u003c\/svg\u003e\n      \u003cdiv class=\"ring ring-1\"\u003e\u003c\/div\u003e\n      \u003cdiv class=\"deco\"\u003e\/\/ SITIP·UV\u003c\/div\u003e\n      \u003cdiv class=\"badge\"\u003e☀ Sistema di protezione solare\u003c\/div\u003e\n      \u003ch3\u003eEclipse\u003c\/h3\u003e\n      \u003cp class=\"tagline\"\u003eUn’ombra che indossi: fresca al tatto e opaca anche in pieno riverbero.\u003c\/p\u003e\n      \u003cul class=\"tech-features\"\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e☀️\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eProtezione UV certificata UPF 50+\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e👁️\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eNon trasparente, nemmeno da bagnata\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e❄️\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eFilato con tecnologia a effetto fresco\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e🎯\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eVestibilità su misura, totalmente traspirante\u003c\/div\u003e\n        \u003c\/li\u003e\n      \u003c\/ul\u003e\n    \u003c\/article\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- ============ PERFORMANCE ============ --\u003e\n  \u003cdiv class=\"section-head\"\u003e\n    \u003cdiv\u003e\n      \u003cdiv class=\"num\" data-anim=\"left\"\u003e02 ; PERFORMANCE\u003c\/div\u003e\n      \u003ch2 data-anim=\"reveal\"\u003eCome si muove\u003cbr\u003econ te.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eDalla prima remata all’ultima passeggiata al tramonto: un tessuto che senti reattivo fin dal primo minuto.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003csection class=\"perf-strip\" data-anim=\"rise-lg\"\u003e\n    \u003ch3 data-anim=\"reveal\"\u003eCostruita per il movimento\u003c\/h3\u003e\n    \u003cp class=\"sub\" data-anim=\"fade\"\u003ePrestazioni in quattro direzioni · comfort tutto il giorno\u003c\/p\u003e\n    \u003cdiv class=\"perf-grid\" data-anim-stagger=\"100\"\u003e\n      \u003cdiv class=\"perf-card\" data-anim=\"zoom\"\u003e\n        \u003cdiv class=\"icon-box\"\u003e💪\u003c\/div\u003e\n        \u003ch4\u003eComfort Fit · Raglan\u003c\/h4\u003e\n        \u003cp\u003eSilhouette rilassata con manica raglan: cade morbida su ogni fisico, senza compressione e senza effetto seconda pelle.\u003c\/p\u003e\n      \u003c\/div\u003e\n      \u003cdiv class=\"perf-card\" data-anim=\"zoom\"\u003e\n        \u003cdiv class=\"icon-box\"\u003e🔄\u003c\/div\u003e\n        \u003ch4\u003e4-Way Stretch\u003c\/h4\u003e\n        \u003cp\u003eTotale libertà di movimento: ogni remata, torsione e pop-up senza il minimo vincolo.\u003c\/p\u003e\n      \u003c\/div\u003e\n      \u003cdiv class=\"perf-card\" data-anim=\"zoom\"\u003e\n        \u003cdiv class=\"icon-box\"\u003e⚡\u003c\/div\u003e\n        \u003ch4\u003eAsciugatura rapida\u003c\/h4\u003e\n        \u003cp\u003eL’umidità viene portata in superficie ed evapora in fretta: comfort dal mare alla sabbia.\u003c\/p\u003e\n      \u003c\/div\u003e\n      \u003cdiv class=\"perf-card\" data-anim=\"zoom\"\u003e\n        \u003cdiv class=\"icon-box\"\u003e✨\u003c\/div\u003e\n        \u003ch4\u003eAnti-pilling\u003c\/h4\u003e\n        \u003cp\u003eResta liscia lavaggio dopo lavaggio: niente pelucchi, niente pallini, niente invecchiamento precoce.\u003c\/p\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/section\u003e\n\n  \u003c!-- ============ CUSTOM PRINT (SEO: custom rashguard, team kits, customizable lycra) ============ --\u003e\n  \u003cdiv class=\"section-head\"\u003e\n    \u003cdiv\u003e\n      \u003cdiv class=\"num\" data-anim=\"left\"\u003e03 ; PERSONALIZZA\u003c\/div\u003e\n      \u003ch2 data-anim=\"reveal\"\u003eRendila\u003cbr\u003etua.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eUna rashguard personalizzata, costruita sulla tua squadra. Stampa logo, numeri e sponsor su una lycra italiana da 220 g\/m², più densa dello standard: pronta per la squadra già dal primo pezzo.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003csection class=\"custom-strip\" data-anim=\"rise-lg\"\u003e\n    \u003ch3 data-anim=\"reveal\"\u003eLa tua rashguard personalizzata, a modo tuo\u003c\/h3\u003e\n    \u003cp class=\"sub\" data-anim=\"fade\"\u003eLogo · Numeri · Sponsor · Colori squadra\u003c\/p\u003e\n    \u003cdiv class=\"custom-grid\" data-anim-stagger=\"100\"\u003e\n      \u003cdiv class=\"custom-card\" data-anim=\"zoom\"\u003e\n        \u003cdiv class=\"custom-num\"\u003e01\u003c\/div\u003e\n        \u003ch4\u003eStampa il tuo logo\u003c\/h4\u003e\n        \u003cp\u003eStampa a sublimazione su petto, maniche e schiena. Dettaglio fotografico su una rashguard in lycra personalizzata che non si crepa, non si screpola e non sbiadisce.\u003c\/p\u003e\n      \u003c\/div\u003e\n      \u003cdiv class=\"custom-card\" data-anim=\"zoom\"\u003e\n        \u003cdiv class=\"custom-num\"\u003e02\u003c\/div\u003e\n        \u003ch4\u003eNumeri e nomi\u003c\/h4\u003e\n        \u003cp\u003ePronta per la rosa: aggiungi numeri di gioco, nomi o blocchi sponsor. Perfetta per surf club, team di sport acquatici e squadre da evento.\u003c\/p\u003e\n      \u003c\/div\u003e\n      \u003cdiv class=\"custom-card\" data-anim=\"zoom\"\u003e\n        \u003cdiv class=\"custom-num\"\u003e03\u003c\/div\u003e\n        \u003ch4\u003eDa 1 pezzo\u003c\/h4\u003e\n        \u003cp\u003eNessun ordine minimo per una rashguard personalizzata: dal pezzo unico fino ai kit squadra con taglie miste da 50+, con gli sconti quantità applicati in automatico.\u003c\/p\u003e\n      \u003c\/div\u003e\n      \u003cdiv class=\"custom-card\" data-anim=\"zoom\"\u003e\n        \u003cdiv class=\"custom-num\"\u003e04\u003c\/div\u003e\n        \u003ch4\u003eMade in Italy\u003c\/h4\u003e\n        \u003cp\u003eTagliata, cucita e stampata in Italia su una maglia italiana da 220 g\/m². Lo stesso tessuto con cui la tua squadra si allena e gareggia: nessun compromesso sulla personalizzazione.\u003c\/p\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/section\u003e\n\n  \u003c!-- ============ USE CASES ============ --\u003e\n  \u003cdiv class=\"section-head\"\u003e\n    \u003cdiv\u003e\n      \u003cdiv class=\"num\" data-anim=\"left\"\u003e04 ; UTILIZZI\u003c\/div\u003e\n      \u003ch2 data-anim=\"reveal\"\u003eIndossala come\u003cbr\u003ela tua t-shirt preferita.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eUna maglia più densa e pesante di una rashguard standard, con la stessa protezione della Pro Lycra, ma tagliata con manica raglan e una silhouette rilassata che si muove con te invece di stringere.\u003cstrong\u003e\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003csection class=\"usecase\"\u003e\n    \u003c!-- Fit ID card --\u003e\n    \u003cdiv class=\"compare\" data-anim=\"rise-lg\"\u003e\n      \u003cdiv class=\"compare-pill\"\u003e\n\u003cspan class=\"dot\"\u003e\u003c\/span\u003eVestibilità comfort rilassata\u003c\/div\u003e\n\n      \u003cdiv class=\"fit-headline\"\u003e\n        \u003ch3\u003eComfort \u003cspan class=\"em\"\u003erilassato.\u003c\/span\u003e\n\u003c\/h3\u003e\n        \u003cp class=\"compare-lead\"\u003eUna maglia italiana più spessa e densa di una rashguard normale, pensata per proteggere e non solo per coprire. Manica raglan e silhouette rilassata: cade morbida su ogni fisico, senza bisogno di essere in forma atletica per indossarla.\u003cstrong\u003e\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"fit-mark\"\u003e\n        \u003cspan\u003eManica raglan\u003c\/span\u003e\n        \u003cspan\u003eSilhouette rilassata\u003c\/span\u003e\n        \u003cspan\u003eOgni fisico\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Use cases grid --\u003e\n    \u003cdiv class=\"usecase-list\" data-anim-stagger=\"100\"\u003e\n      \u003cdiv class=\"uc-card\" data-anim=\"rise\"\u003e\n        \u003cdiv class=\"uc-icon\"\u003e\u003csvg viewbox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003ccircle cx=\"12\" cy=\"8\" r=\"3\"\u003e\u003c\/circle\u003e\u003cpath d=\"M5 21c2-4 5-6 7-6s5 2 7 6\"\u003e\u003c\/path\u003e\u003cpath d=\"M3 14c2-2 4-3 6-3\"\u003e\u003c\/path\u003e\u003cpath d=\"M21 14c-2-2-4-3-6-3\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n        \u003cdiv class=\"uc-num\"\u003e01 \/ Surf\u003c\/div\u003e\n        \u003ch4\u003eLunghe \u003cspan class=\"ital\"\u003eremate\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eLa manica raglan dà totale libertà alle spalle e la maglia densa protegge le costole dallo sfregamento della tavola.\u003c\/b\u003e\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eSurf\u003c\/span\u003e\u003cspan\u003eSUP\u003c\/span\u003e\u003cspan\u003eBodyboard\u003c\/span\u003e\u003cspan\u003eCanottaggio costiero\u003c\/span\u003e\n\u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"uc-card\" data-anim=\"rise\"\u003e\n        \u003cdiv class=\"uc-icon\"\u003e\u003csvg viewbox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003ccircle cx=\"12\" cy=\"12\" r=\"9\"\u003e\u003c\/circle\u003e\u003cpath d=\"M3 12h18\"\u003e\u003c\/path\u003e\u003cpath d=\"M12 3c3 3 3 15 0 18\"\u003e\u003c\/path\u003e\u003cpath d=\"M12 3c-3 3-3 15 0 18\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n        \u003cdiv class=\"uc-num\"\u003e02 \/ Nuoto\u003c\/div\u003e\n        \u003ch4\u003eAcque \u003cspan class=\"ital\"\u003elibere\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eIdrodinamica e opaca: meno attrito nell’acqua e bracciate più veloci.\u003c\/b\u003e\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eNuoto in acque libere\u003c\/span\u003e\u003cspan\u003eTriathlon\u003c\/span\u003e\u003cspan\u003eCanottaggio costiero\u003c\/span\u003e\u003cspan\u003eNuoto in vasca\u003c\/span\u003e\n\u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"uc-card\" data-anim=\"rise\"\u003e\n        \u003cdiv class=\"uc-icon\"\u003e\u003csvg viewbox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003ccircle cx=\"12\" cy=\"12\" r=\"4\"\u003e\u003c\/circle\u003e\u003cpath d=\"M12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M4.9 19.1L7 17M17 7l2.1-2.1\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n        \u003cdiv class=\"uc-num\"\u003e03 \/ Strato\u003c\/div\u003e\n        \u003ch4\u003eSotto la \u003cspan class=\"ital\"\u003emuta\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eSi indossa con scioltezza: previene gli sfregamenti e aggiunge uno strato termico.\u003c\/b\u003e\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eStrato base sotto muta\u003c\/span\u003e\u003cspan\u003eMuta shorty\u003c\/span\u003e\u003cspan\u003eAcqua fredda\u003c\/span\u003e\u003cspan\u003eMuta stagna tecnica\u003c\/span\u003e\n\u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"uc-card\" data-anim=\"rise\"\u003e\n        \u003cdiv class=\"uc-icon\"\u003e\u003csvg viewbox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003cpath d=\"M3 19c2 0 3-2 5-2s3 2 5 2 3-2 5-2 3 2 3 2\"\u003e\u003c\/path\u003e\u003cpath d=\"M3 15c2 0 3-2 5-2s3 2 5 2 3-2 5-2 3 2 3 2\"\u003e\u003c\/path\u003e\u003cpath d=\"M3 11c2 0 3-2 5-2s3 2 5 2 3-2 5-2 3 2 3 2\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n        \u003cdiv class=\"uc-num\"\u003e04 \/ Sole\u003c\/div\u003e\n        \u003ch4\u003eTutto il giorno \u003cspan class=\"ital\"\u003eUV\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eUPF 50+ Eclipse: blocca il 98% di UVA \/ UVB, anche dai riflessi.\u003c\/b\u003e\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eTropici\u003c\/span\u003e\u003cspan\u003eVela\u003c\/span\u003e\u003cspan\u003eKayak\u003c\/span\u003e\u003cspan\u003eGiornate in barca\u003c\/span\u003e\u003cspan\u003ePesca\u003c\/span\u003e\n\u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"uc-card\" data-anim=\"rise\"\u003e\n        \u003cdiv class=\"uc-icon\"\u003e\u003csvg viewbox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003cpath d=\"M4 20l4-8 4 4 4-6 4 10\"\u003e\u003c\/path\u003e\u003ccircle cx=\"12\" cy=\"6\" r=\"2\"\u003e\u003c\/circle\u003e\u003c\/svg\u003e\u003c\/div\u003e\n        \u003cdiv class=\"uc-num\"\u003e05 \/ Sport acquatici\u003c\/div\u003e\n        \u003ch4\u003eVelocità e \u003cspan class=\"ital\"\u003espruzzi\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eResta ben aderente sotto la pressione dell’imbracatura e ti protegge dal freddo del vento alle alte velocità.\u003c\/b\u003e\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eKitesurf\u003c\/span\u003e\u003cspan\u003eWindsurf\u003c\/span\u003e\u003cspan\u003eWing foil\u003c\/span\u003e\u003cspan\u003eWakeboard\u003c\/span\u003e\u003cspan\u003eSci nautico\u003c\/span\u003e\u003cspan\u003eMoto d’acqua\u003c\/span\u003e\u003cspan\u003eFlyboard\u003c\/span\u003e\n\u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"uc-card\" data-anim=\"rise\"\u003e\n        \u003cdiv class=\"uc-icon\"\u003e\u003csvg viewbox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003cpath d=\"M6 22V10l6-6 6 6v12\"\u003e\u003c\/path\u003e\u003cpath d=\"M9 22V14h6v8\"\u003e\u003c\/path\u003e\u003cpath d=\"M2 12h2M20 12h2\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n        \u003cdiv class=\"uc-num\"\u003e06 \/ Immersione\u003c\/div\u003e\n        \u003ch4\u003eSnorkeling e \u003cspan class=\"ital\"\u003eapnea\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eMaglia densa: tiene caldo nelle lunghe nuotate e fa da barriera contro meduse e scogli.\u003c\/b\u003e\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eSnorkeling\u003c\/span\u003e\u003cspan\u003eApnea\u003c\/span\u003e\u003cspan\u003ePesca in apnea\u003c\/span\u003e\u003cspan\u003eCoasteering\u003c\/span\u003e\u003cspan\u003eSeabob\u003c\/span\u003e\u003cspan\u003eStrato base per sub\u003c\/span\u003e\n\u003c\/div\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/section\u003e\n\n  \u003c!-- ============ CERTIFICATIONS ============ --\u003e\n  \u003cdiv class=\"section-head\"\u003e\n    \u003cdiv\u003e\n      \u003cdiv class=\"num\" data-anim=\"left\"\u003e05 ; STANDARD\u003c\/div\u003e\n      \u003ch2 data-anim=\"reveal\"\u003eFatta con onestà.\u003cbr\u003eMade in Italy.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eControllata in modo indipendente, dal filato al capo finito: nessuna dichiarazione senza prove.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003csection class=\"certs\" data-anim=\"rise-lg\"\u003e\n    \u003cdiv class=\"certs-head\"\u003e\n      \u003ch3 data-anim=\"reveal\"\u003eOrigine e certificazioni\u003c\/h3\u003e\n      \u003cdiv class=\"stamp\" data-anim=\"right\"\u003eVerificato · Controllato · Tracciabile\u003c\/div\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"cert-grid\" data-anim-stagger=\"110\"\u003e\n      \u003cdiv class=\"cert\" data-anim=\"rise\"\u003e\n        \u003cdiv class=\"glyph\"\u003e🇮🇹\u003c\/div\u003e\n        \u003cdiv\u003e\n          \u003cdiv class=\"name\"\u003eMade in Italy\u003c\/div\u003e\n          \u003cdiv class=\"meta\"\u003eBergamo · stabilimento SITIP\u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cdiv class=\"cert\" data-anim=\"rise\"\u003e\n        \u003cdiv class=\"glyph\"\u003e✅\u003c\/div\u003e\n        \u003cdiv\u003e\n          \u003cdiv class=\"name\"\u003eOeko-Tex\u003c\/div\u003e\n          \u003cdiv class=\"meta\"\u003eStandard 100 · Classe I\u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cdiv class=\"cert\" data-anim=\"rise\"\u003e\n        \u003cdiv class=\"glyph\"\u003e🔬\u003c\/div\u003e\n        \u003cdiv\u003e\n          \u003cdiv class=\"name\"\u003eBluesign®\u003c\/div\u003e\n          \u003cdiv class=\"meta\"\u003eFiliera approvata\u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cdiv class=\"cert\" data-anim=\"rise\"\u003e\n        \u003cdiv class=\"glyph\"\u003e♻️\u003c\/div\u003e\n        \u003cdiv\u003e\n          \u003cdiv class=\"name\"\u003eEco-friendly\u003c\/div\u003e\n          \u003cdiv class=\"meta\"\u003eTinture e finissaggi a basso impatto\u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/section\u003e\n\n  \u003c!-- ============ FAQ (SEO: FAQPage schema) ============ --\u003e\n  \u003cdiv class=\"section-head\"\u003e\n    \u003cdiv\u003e\n      \u003cdiv class=\"num\" data-anim=\"left\"\u003e06 ; FAQ\u003c\/div\u003e\n      \u003ch2 data-anim=\"reveal\"\u003eDomande,\u003cbr\u003erisposte.\u003c\/h2\u003e\n    \u003c\/div\u003e\n  \u003c\/div\u003e\n\n  \u003csection class=\"faq\" data-anim=\"rise-lg\"\u003e\n    \u003cdiv class=\"faq-list\" data-anim-stagger=\"60\"\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003ePosso stampare il mio logo sulla rashguard?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eAncora meglio: puoi creare la tua rashguard da zero con il nostro configuratore 3D avanzato. Cambia i colori, aggiungi il logo, scrivi il tuo nome, posiziona gli sponsor e combina le fantasie, vedendo tutto in anteprima live in 3D. Servono idee? Il nostro AI Designer genera grafiche personalizzate da una semplice descrizione testuale: massima libertà creativa, senza bisogno di saper disegnare.\u003cstrong\u003e\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eQual è l’ordine minimo per un kit squadra personalizzato?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003e\nBasta un pezzo: non c’è un minimo. Ordina una singola rashguard personalizzata o un kit completo da 50+, con gli sconti quantità che partono in automatico già da 3 pezzi.\u003cstrong\u003e\u003c\/strong\u003e\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eQuanto tempo richiede un ordine personalizzato?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eDi solito la produzione richiede 2-3 settimane dal checkout, più i tempi di spedizione. Controlla la pagina del carrello per il tempo di produzione esatto del tuo ordine.\u003cstrong\u003e\u003c\/strong\u003e\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eChe taglia devo scegliere?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eNessun problema: la guida alle taglie ti verrà suggerita direttamente durante la configurazione, con misure calibrate sulla vestibilità comfort rilassata di questo modello. Non serve essere atleti per indossarla: la silhouette è tagliata per cadere morbida su ogni fisico.\u003cstrong\u003e\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eIl tessuto è davvero UPF 50+?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eSì. La finitura Eclipse è certificata UPF 50+ e blocca il 98% delle radiazioni UVA\/UVB. È testata e certificata secondo lo UV Standard 801, e la protezione è intessuta nel filato: non se ne va con i lavaggi.\u003cstrong\u003e\u003c\/strong\u003e\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003ePosso usarla per sport diversi dal surf?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eConsigliamo questo modello per tutti gli sport a contatto con l’acqua: surf, SUP, kitesurf, nuoto, apnea, snorkeling, vela, wakeboard e guida di mezzi acquatici. La maglia più densa da 220 g\/m² lo rende ideale ogni volta che sei dentro o sopra l’acqua.\u003cstrong\u003e\u003c\/strong\u003e\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eDove è prodotta?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003e\nInteramente prodotta in Italia, nel nostro stabilimento di abbigliamento tecnico a Parma. Il tessuto è realizzato da SITIP a Bergamo, poi tagliato, cucito, stampato e rifinito internamente dal nostro team.\u003cstrong\u003e\u003c\/strong\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eCome si lava?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eSciacquala in acqua dolce dopo ogni sessione. Lavaggio in lavatrice a freddo (30°C) con ciclo delicato, senza ammorbidente e senza asciugatrice. Falla asciugare stesa; va bene anche al sole. Trattata bene, durerà più di tre rashguard standard.\u003c\/div\u003e\n      \u003c\/details\u003e\n    \u003c\/div\u003e\n  \u003c\/section\u003e\n\n  \u003cscript type=\"application\/ld+json\"\u003e\n  {\n    \"@context\": \"https:\/\/schema.org\",\n    \"@type\": \"Product\",\n    \"name\": \"Comfort Fit Rashguard\",\n    \"description\": \"Relaxed-fit 220 g\/m² Italian knit rashguard with raglan sleeve. SITIP Acquazero water repellent and Eclipse UPF 50+ finishes, 4-way stretch. Custom printable from 1 piece for surf, swim, watersports and beach lifestyle. Made in Italy.\",\n    \"category\": \"Sportswear \/ Watersports\",\n    \"brand\": { \"@type\": \"Brand\", \"name\": \"Inferno Beachwear\" },\n    \"material\": \"220 g\/m² Italian knit · SITIP Acquazero · SITIP Eclipse UPF 50+\",\n    \"weight\": { \"@type\": \"QuantitativeValue\", \"value\": 220, \"unitText\": \"g\/m²\" },\n    \"countryOfOrigin\": \"IT\"\n  }\n  \u003c\/script\u003e\n  \u003cscript type=\"application\/ld+json\"\u003e\n  {\n    \"@context\": \"https:\/\/schema.org\",\n    \"@type\": \"FAQPage\",\n    \"mainEntity\": [\n      {\n        \"@type\": \"Question\",\n        \"name\": \"Can I print my own logo on the rashguard?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"Yes. You can build your rashguard from scratch with our advanced 3D configurator: change colours, add your logo, write your name, place sponsors and mix patterns, with a live 3D preview. Our AI Designer also generates custom artwork from a simple text prompt, so total creative freedom is possible with no design skills required.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"What's the minimum order for a custom team kit?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"One piece. There is no minimum order. You can order a single personalized rashguard or a full team kit of 50+ pieces. Bulk discounts apply automatically from 3 pieces upwards.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"How long does a custom order take?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"Production usually takes 2 to 3 weeks from checkout, plus shipping. Check the cart page for the exact production time on your current order.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"What size should I choose?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"The size chart will be suggested directly during the configuration step, with measurements tailored to the relaxed comfort fit of this model. You don't need to be an athlete to wear it.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"Is the fabric really UPF 50+?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"Yes. The Eclipse finish is rated UPF 50+, blocking 98% of UVA\/UVB radiation. Tested and certified to UV Standard 801. The protection is woven into the yarn and does not wash out.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"Can I wear it for sports other than surfing?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"We recommend this model for all water-contact sports: surfing, SUP, kitesurfing, swimming, freediving, snorkeling, sailing, wakeboarding and watercraft riding. The denser 220 g\/m² knit makes it ideal whenever you are in or on the water.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"Where is it made?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"Entirely produced in Italy, in our technical apparel manufacturing facility in Parma. Fabric is woven by SITIP in Bergamo, then cut, sewn, printed and finished in-house by our team.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"How do I care for the rashguard?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"Rinse in fresh water after each session. Machine wash cold (30°C) on a gentle cycle, no fabric softener, no tumble dry. Hang to dry; sun drying is fine.\"\n        }\n      }\n    ]\n  }\n  \u003c\/script\u003e\n\n  \u003c!-- ============ TICKER ============ --\u003e\n  \u003cdiv class=\"ticker\" data-anim=\"reveal\"\u003e\n    \u003cdiv class=\"ticker-track\"\u003e\n      \u003cspan\u003eTessuti italiani premium\u003c\/span\u003e\n      \u003cspan\u003ePowered by SITIP\u003c\/span\u003e\n      \u003cspan\u003eAcquazero Idrorepellente\u003c\/span\u003e\n      \u003cspan\u003eEclipse UPF 50+\u003c\/span\u003e\n      \u003cspan\u003e4-Way Stretch\u003c\/span\u003e\n      \u003cspan\u003eMade in Italy\u003c\/span\u003e\n      \u003cspan\u003eTessuti italiani premium\u003c\/span\u003e\n      \u003cspan\u003ePowered by SITIP\u003c\/span\u003e\n      \u003cspan\u003eAcquazero Idrorepellente\u003c\/span\u003e\n      \u003cspan\u003eEclipse UPF 50+\u003c\/span\u003e\n      \u003cspan\u003e4-Way Stretch\u003c\/span\u003e\n      \u003cspan\u003eMade in Italy\u003c\/span\u003e\n    \u003c\/div\u003e\n  \u003c\/div\u003e\n\n\u003c\/div\u003e\n\u003cscript\u003e\n(function(){\n  var els = Array.from(document.querySelectorAll('.product-desc [data-anim]'));\n  if (!els.length) return;\n  var BASE_STEP = 70;       \/\/ ms between unrelated elements\n  var GROUP_STEP = 60;      \/\/ ms between siblings inside a stagger group (default)\n  var SECTION_GAP = 220;    \/\/ bigger pause when crossing major sections\n  var sectionSelector = '.hero, .section-head, .perf-strip, .certs, .ticker, .product-title, .pricing';\n\n  function findGroup(el) {\n    var p = el.parentElement;\n    while (p \u0026\u0026 p !== document.body) {\n      if (p.hasAttribute('data-anim-stagger')) return p;\n      p = p.parentElement;\n    }\n    return null;\n  }\n  function findSection(el) {\n    return el.closest(sectionSelector);\n  }\n\n  var t = 80; \/\/ initial offset so paint settles\n  var lastSection = null;\n  var seenGroups = new Map();\n\n  els.forEach(function(el, i){\n    var section = findSection(el);\n    if (lastSection \u0026\u0026 section !== lastSection) {\n      t += SECTION_GAP;\n    }\n    lastSection = section;\n\n    var group = findGroup(el);\n    var delay;\n    if (group) {\n      var step = parseInt(group.getAttribute('data-anim-stagger'),10) || GROUP_STEP;\n      if (!seenGroups.has(group)) {\n        seenGroups.set(group, { start: t, step: step, idx: 0 });\n        delay = t;\n        t += step * 1.2; \/\/ group occupies its own band\n      } else {\n        var g = seenGroups.get(group);\n        g.idx++;\n        delay = g.start + g.step * g.idx;\n      }\n    } else {\n      delay = t;\n      t += BASE_STEP;\n    }\n    el.style.transitionDelay = (delay\/1000).toFixed(3) + 's';\n  });\n\n  function play(){\n    requestAnimationFrame(function(){\n      requestAnimationFrame(function(){\n        els.forEach(function(el){ el.classList.add('in'); });\n      });\n    });\n  }\n  if (document.readyState === 'complete' || document.readyState === 'interactive') {\n    play();\n  } else {\n    window.addEventListener('DOMContentLoaded', play);\n  }\n})();\n\u003c\/script\u003e\n\n\u003c!-- Apply density \u0026 motion presets to \u003chtml\u003e on first paint (no flash) --\u003e\n\u003cscript\u003e\n  (function(){\n    var html = document.documentElement;\n    html.setAttribute('data-density', 'compact');\n    html.setAttribute('data-motion', 'riptide');\n  })();\n\u003c\/script\u003e\n\n\u003c\/body\u003e","brand":"Custom Inferno","offers":[{"title":"XS","offer_id":58219445322115,"sku":"COM-SS-XS","price":74.23,"currency_code":"USD","in_stock":true},{"title":"S","offer_id":58219445354883,"sku":"COM-SS-S","price":74.23,"currency_code":"USD","in_stock":true},{"title":"M","offer_id":58219445387651,"sku":"COM-SS-M","price":74.23,"currency_code":"USD","in_stock":true},{"title":"L","offer_id":58219445420419,"sku":"COM-SS-L","price":74.23,"currency_code":"USD","in_stock":true},{"title":"XL","offer_id":58219445453187,"sku":"COM-SS-XL","price":74.23,"currency_code":"USD","in_stock":true},{"title":"XXL","offer_id":58219445485955,"sku":"COM-SS-XXL","price":74.23,"currency_code":"USD","in_stock":true},{"title":"3XL","offer_id":58219445518723,"sku":"COM-SS-3XL","price":74.23,"currency_code":"USD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0988\/4323\/0595\/files\/ccefed9dfa8f3784e2f845cb40dd1788.jpg?v=1781094780","url":"https:\/\/infernobeachwear.com\/it\/products\/men-s-comfort-fit-rashguard-ss-morning-mist","provider":"Inferno Beachwear","version":"1.0","type":"link"}