{"product_id":"men-s-compression-rashguard-ss-sandstone-arch","title":"Men’s Compression Rashguard SS - Uruguay","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\u003eProduct Description ; Premium Italian Fabrics\u003c\/title\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\u003eFully Customizable\u003c\/div\u003e\n      \u003cdiv class=\"meta-row\" data-anim=\"right\"\u003e\n        \u003cspan\u003eSKU · PRO-RG-01\u003c\/span\u003e\n        \u003cspan\u003ePro Series\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"kicker\" data-anim=\"left\"\u003ePro Lycra · Compression Series\u003c\/div\u003e\n    \u003ch1 data-anim=\"reveal\"\u003ePro Lycra Compression\u003cbr\u003e\u003cspan class=\"accent\"\u003eRashguard\u003c\/span\u003e\n\u003c\/h1\u003e\n    \u003cp class=\"product-full-title\" data-anim=\"rise\"\u003eMen’s Compression Rashguard SS - Sandstone Arch\u003c\/p\u003e\n    \u003cp class=\"subline\" data-anim=\"blur\"\u003e\u003cstrong\u003eCustom armor-grade rashguard.\u003c\/strong\u003e Italian 4-way stretch knit at \u003cstrong\u003e220 g\/m²\u003c\/strong\u003e ; print your \u003cstrong\u003elogo, numbers and sponsors\u003c\/strong\u003e on a denser-than-standard fabric with high resistance to abrasion. From \u003cstrong\u003e1 piece to full team kits\u003c\/strong\u003e ; second-skin compression for surfers, swimmers and watermen who don't compromise.\u003c\/p\u003e\n    \u003cdiv class=\"feature-tabs\" data-anim-stagger=\"60\"\u003e\n      \u003cspan data-anim=\"rise\"\u003e✎ Custom Print\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:\/\/infernobeachwear.com\/pages\/configurator?design=a908494e791870176de90bcc0813aba2\" 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        Edit 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        Create a New 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\"\u003eVolume \u003cspan class=\"em\" style=\"padding: 2px 50px 0px 0px\"\u003ediscounts\u003c\/span\u003e\n\u003c\/h3\u003e\n          \u003cp class=\"pricing-sub\"\u003eDrag the slider · the more you order, the more you save\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\"\u003eQuantity\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)\"\u003epcs\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% OFF\u003c\/div\u003e\n          \u003cspan class=\"save\" id=\"save-line\" style=\"color: rgb(0, 0, 0)\"\u003ePick 2+ pcs to start saving\u003c\/span\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"readout-price\"\u003e\n          \u003cdiv class=\"label\"\u003eYour price\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)\"\u003eTotal: \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 pc\u003c\/div\u003e\n          \u003cdiv class=\"disc zero\"\u003e0%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | money }} ea\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 pcs\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−5%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.95 | money }} ea\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 pcs\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−15%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.85 | money }} ea\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 pcs\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−25%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.75 | money }} ea\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 pcs\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−35%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.65 | money }} ea\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 pcs\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−45%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.55 | money }} ea\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 pcs\u003c\/div\u003e\n          \u003cdiv class=\"disc\"\u003e−50%\u003c\/div\u003e\n          \u003cdiv class=\"price-each\"\u003e{{ product.price | times: 0.50 | money }} ea\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+ pieces\u003c\/div\u003e\n          \u003ch4\u003eNeed a full team kit? \u003cem\u003eLet's talk.\u003c\/em\u003e\n\u003c\/h4\u003e\n          \u003cp\u003eCustom pricing for clubs, teams and events with 50+ pieces. We'll quote you within 24 hours.\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          Request a quote\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⚓ Bulk inquiry · 50+ pieces\u003c\/div\u003e\n            \u003ch3 id=\"quote-modal-title\"\u003eGet your \u003cem\u003ecustom quote.\u003c\/em\u003e\n\u003c\/h3\u003e\n            \u003cp\u003eTell us about your team and we'll get back within 24h with pricing and lead time.\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 Compression Rashguard SS - Sandstone Arch\"\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\"\u003eClub \/ Company name \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\"\u003ePlease enter your club or company name\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\"\u003eCountry \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\"\u003eRequired\u003c\/div\u003e\n                \u003c\/div\u003e\n                \u003cdiv class=\"quote-field\"\u003e\n                  \u003clabel for=\"qf-vat\"\u003eVAT number \u003cspan class=\"opt\"\u003e(if any)\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\"\u003eQuantity \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\"\u003eMust be 50 or more\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\"\u003eValid email required\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\"\u003eNotes \u003cspan class=\"opt\"\u003e(optional — tell us about your team, custom design, deadline, etc.)\u003c\/span\u003e\u003c\/label\u003e\n                  \u003ctextarea id=\"qf-notes\" name=\"contact[Notes]\" rows=\"4\" autocomplete=\"off\" placeholder=\"e.g. 80 compression tops for our triathlon 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\"\u003eWebsite (leave empty — 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                Send request\n              \u003c\/button\u003e\n              \u003cdiv class=\"quote-modal-footnote\"\u003eWe'll reply within 24h to the email you provide. Backup contact: \u003cstrong\u003ecustominferno@gmail.com\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      Premium Italian Fabrics\n    \u003c\/div\u003e\n    \u003ch2 data-anim=\"reveal\"\u003eEngineered for the\u003cbr\u003e\u003cspan class=\"ital\"\u003ewater.\u003c\/span\u003e Cut for the sun.\u003c\/h2\u003e\n    \u003cp data-anim=\"blur\"\u003eBuilt with SITIP Technical Textiles ; a Bergamo mill weaving performance threads since 1956. Every meter of fabric is finished to survive saltwater, sunlight and a thousand wash cycles.\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\"\u003eTested in the Mediterranean\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+ · Water Resistant\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        New Fabric\n        \u003cstrong\u003eSITIP · MONICA\u003c\/strong\u003e\n      \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 ; TECHNOLOGY\u003c\/div\u003e\n      \u003ch2 data-anim=\"reveal\"\u003eTwo finishes.\u003cbr\u003eOne ocean.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eTwo proprietary SITIP treatments work together ; one repels what the water throws at you, the other shields you from what the sun sends down.\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◐ Water Repellent System\u003c\/div\u003e\n      \u003ch3\u003eAcquazero\u003c\/h3\u003e\n      \u003cp class=\"tagline\"\u003eWater beads off. Salt slides off. Stains never settle.\u003c\/p\u003e\n      \u003cul class=\"tech-features\"\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e💧\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eFluorine-free water repellent\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e🌿\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003ePFOA-free \u0026amp; eco-friendly chemistry\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e🧼\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eWash-resistant ; performance lasts\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e💨\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eBreathable with a soft hand-feel\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☀ Sun Protection System\u003c\/div\u003e\n      \u003ch3\u003eEclipse\u003c\/h3\u003e\n      \u003cp class=\"tagline\"\u003eA built-in shadow you wear. Cool to the touch, opaque under glare.\u003c\/p\u003e\n      \u003cul class=\"tech-features\"\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e☀️\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eUPF 50+ certified UV protection\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e👁️\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eNo see-through, even when wet\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e❄️\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eCool-feeling yarn technology\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e🎯\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eTailored fit, fully breathable\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\"\u003eHow it moves\u003cbr\u003ewith you.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eFrom the first paddle-out to the last sunset walk ; fabric behaviour you can feel from minute one.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003csection class=\"perf-strip\" data-anim=\"rise-lg\"\u003e\n    \u003ch3 data-anim=\"reveal\"\u003eBuilt for movement\u003c\/h3\u003e\n    \u003cp class=\"sub\" data-anim=\"fade\"\u003eFour-direction performance · all-day wear\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\u003eCompression Fit\u003c\/h4\u003e\n        \u003cp\u003eHugs like a second skin for muscle support and zero distraction in the line-up.\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\u003eTotal freedom of movement ; every paddle, twist and pop-up unrestricted.\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\u003eQuick-Dry\u003c\/h4\u003e\n        \u003cp\u003eMoisture is pushed to the surface and gone ; comfortable from sea to sand.\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\u003eStays smooth wash after wash. No fuzz, no pills, no premature aging.\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 ; CUSTOMIZE\u003c\/div\u003e\n      \u003ch2 data-anim=\"reveal\"\u003eMake it\u003cbr\u003eyours.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eA custom rashguard built around your team. Print your logo, numbers and sponsors on a denser-than-standard 220 g\/m² Italian lycra ; team-ready from a single piece.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003csection class=\"custom-strip\" data-anim=\"rise-lg\"\u003e\n    \u003ch3 data-anim=\"reveal\"\u003eCustom rashguard, your way\u003c\/h3\u003e\n    \u003cp class=\"sub\" data-anim=\"fade\"\u003eLogo · Numbers · Sponsors · Team colours\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\u003ePrint your logo\u003c\/h4\u003e\n        \u003cp\u003eSublimation print across the chest, sleeves and back. Photo-grade detail on a custom lycra rashguard that won't crack, peel or fade.\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\u003eNumbers \u0026amp; names\u003c\/h4\u003e\n        \u003cp\u003eRoster ready. Add player numbers, names or sponsor blocks ; perfect for surf clubs, watersports teams and event squads.\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\u003eFrom 1 piece\u003c\/h4\u003e\n        \u003cp\u003eNo minimum order on a personalized rashguard. One-off custom prints all the way up to mixed-size team kits of 50+ ; bulk discounts apply automatically.\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\u003eCut, sewn and printed in Italy on a 220 gsm Italian knit. The same fabric your team trains and competes in ; no compromise on the custom build.\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 ; USE CASES\u003c\/div\u003e\n      \u003ch2 data-anim=\"reveal\"\u003eWear it like\u003cbr\u003earmor.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eA \u003cstrong\u003edenser, heavier knit\u003c\/strong\u003e than a standard rashguard. Built to actively shield you from sun, wind, abrasions and impacts ; while the compression cut keeps everything streamlined.\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\u003eArmor-grade compression\u003c\/div\u003e\n\n      \u003cdiv class=\"fit-headline\"\u003e\n        \u003ch3\u003eSecond-skin \u003cspan class=\"em\"\u003earmor.\u003c\/span\u003e\n\u003c\/h3\u003e\n        \u003cp class=\"compare-lead\"\u003eA \u003cstrong\u003ethicker, denser\u003c\/strong\u003e Italian knit than a regular rashguard ; built to protect, not just to cover. Compression cut hugs the muscles ; size up if you want a relaxed feel.\u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"fit-mark\"\u003e\n        \u003cspan\u003eHeavier knit\u003c\/span\u003e\n        \u003cspan\u003eAthletic sizing\u003c\/span\u003e\n        \u003cspan\u003eActive protection\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\u003eLong \u003cspan class=\"ital\"\u003epaddle-outs\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eCompression\u003c\/b\u003e supports shoulders, dense knit shields ribs from board rash.\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eSurfing\u003c\/span\u003e\u003cspan\u003eSUP\u003c\/span\u003e\u003cspan\u003eBodyboard\u003c\/span\u003e\u003cspan\u003eCoastal rowing\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 \/ Swim\u003c\/div\u003e\n        \u003ch4\u003eOpen \u003cspan class=\"ital\"\u003ewater\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eHydrodynamic\u003c\/b\u003e \u0026amp; opaque ; less drag, faster strokes.\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eOpen-water swim\u003c\/span\u003e\u003cspan\u003eTriathlon\u003c\/span\u003e\u003cspan\u003eCoastal rowing\u003c\/span\u003e\u003cspan\u003eLap swim\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 \/ Layer\u003c\/div\u003e\n        \u003ch4\u003eUnder a \u003cspan class=\"ital\"\u003ewetsuit\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eSlips on smooth\u003c\/b\u003e ; prevents chafe, adds thermal layer.\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eWetsuit base\u003c\/span\u003e\u003cspan\u003eSpring suit\u003c\/span\u003e\u003cspan\u003eCold water\u003c\/span\u003e\u003cspan\u003eTechnical drysuit\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 \/ Sun\u003c\/div\u003e\n        \u003ch4\u003eAll-day \u003cspan class=\"ital\"\u003eUV\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eUPF 50+ Eclipse\u003c\/b\u003e ; blocks 98% UVA \/ UVB, even on reflected glare.\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eTropical\u003c\/span\u003e\u003cspan\u003eSailing\u003c\/span\u003e\u003cspan\u003eKayak\u003c\/span\u003e\u003cspan\u003eBoat days\u003c\/span\u003e\u003cspan\u003eFishing\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 \/ Watersports\u003c\/div\u003e\n        \u003ch4\u003eSpeed \u0026amp; \u003cspan class=\"ital\"\u003espray\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eHolds firm\u003c\/b\u003e under harness pressure, blocks wind chill at speed.\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\u003eWater-ski\u003c\/span\u003e\u003cspan\u003eJet ski\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 \/ Dive\u003c\/div\u003e\n        \u003ch4\u003eSnorkel \u0026amp; \u003cspan class=\"ital\"\u003efreedive\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eDense knit\u003c\/b\u003e ; warmth on long swims, barrier vs jellyfish \u0026amp; rocks.\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eSnorkeling\u003c\/span\u003e\u003cspan\u003eFreediving\u003c\/span\u003e\u003cspan\u003eSpearfishing\u003c\/span\u003e\u003cspan\u003eCoasteering\u003c\/span\u003e\u003cspan\u003eSeabob\u003c\/span\u003e\u003cspan\u003eScuba base layer\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 ; STANDARDS\u003c\/div\u003e\n      \u003ch2 data-anim=\"reveal\"\u003eMade honestly.\u003cbr\u003eMade in Italy.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eIndependently audited from yarn to finished garment. Nothing claimed without proof.\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\"\u003eOrigin \u0026amp; certifications\u003c\/h3\u003e\n      \u003cdiv class=\"stamp\" data-anim=\"right\"\u003eVerified · Audited · Traceable\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 · SITIP mill\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 · Class 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\"\u003eApproved supply chain\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\"\u003eLow-impact dyes \u0026amp; finishes\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\"\u003eQuestions,\u003cbr\u003eanswered.\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\u003eCan I print my own logo on the rashguard?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eEven better; you can \u003cstrong\u003ebuild your rashguard from scratch\u003c\/strong\u003e with our advanced \u003cstrong\u003e3D configurator\u003c\/strong\u003e. Change colours, add your logo, write your name, place sponsors, mix patterns; everything is previewed live in 3D. Need ideas? Our \u003cstrong\u003eAI Designer\u003c\/strong\u003e generates custom artwork from a simple text prompt. Total creative freedom; no design skills required.\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eWhat's the minimum order for a custom team kit?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003e\n\u003cstrong\u003eOne piece.\u003c\/strong\u003e There is no minimum. Order a single personalized rashguard or a full team kit of 50+ ; bulk discounts apply automatically from 3 pieces upwards.\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eHow long does a custom order take?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eProduction usually takes \u003cstrong\u003e2 to 3 weeks\u003c\/strong\u003e from checkout, plus shipping. Check the cart page for the exact production time on your current order.\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eWhat size should I choose?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eNo need to worry; the \u003cstrong\u003esize chart will be suggested directly during the configuration step\u003c\/strong\u003e, with measurements tailored to the compression fit of this model.\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eIs the fabric really UPF 50+?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eYes. The Eclipse finish is rated \u003cstrong\u003eUPF 50+\u003c\/strong\u003e, blocking 98% of UVA\/UVB radiation. Tested and certified to UV Standard 801. The protection is woven into the yarn ; it doesn't wash out.\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eCan I wear it for sports other than surfing?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eWe recommend this model for \u003cstrong\u003eall water-contact sports\u003c\/strong\u003e; surfing, SUP, kitesurfing, swimming, freediving, snorkeling, sailing, wakeboarding and watercraft riding. The denser 220 g\/m² knit makes it ideal whenever you're in or on the water.\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eWhere is it made?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003e\n\u003cstrong\u003eEntirely produced in Italy\u003c\/strong\u003e, in our technical apparel manufacturing facility in \u003cstrong\u003eParma\u003c\/strong\u003e. Fabric is woven by SITIP in Bergamo, then cut, sewn, printed and finished in-house by our team.\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eHow do I care for it?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eRinse 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. Treated right, it will outlast three standard rashguards.\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\": \"Pro Lycra Compression Rashguard\",\n    \"description\": \"Custom armor-grade rashguard. Italian 4-way stretch knit at 220 g\/m² with Acquazero water-repellent finish and Eclipse UPF 50+ sun protection. Custom printable from 1 piece. Made in Italy.\",\n    \"category\": \"Sportswear \/ Watersports\",\n    \"brand\": { \"@type\": \"Brand\", \"name\": \"Inferno Beachwear\" },\n    \"material\": \"Italian Lycra · SITIP · Acquazero · 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 compression fit of this model.\"\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\u003ePremium Italian Fabrics\u003c\/span\u003e\n      \u003cspan\u003ePowered by SITIP\u003c\/span\u003e\n      \u003cspan\u003eAcquazero Water Repellent\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\u003ePremium Italian Fabrics\u003c\/span\u003e\n      \u003cspan\u003ePowered by SITIP\u003c\/span\u003e\n      \u003cspan\u003eAcquazero Water Repellent\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":58363901641091,"sku":"PRO-SS-XS","price":74.2,"currency_code":"USD","in_stock":true},{"title":"S","offer_id":58363901673859,"sku":"PRO-SS-S","price":74.2,"currency_code":"USD","in_stock":true},{"title":"M","offer_id":58363901706627,"sku":"PRO-SS-M","price":74.2,"currency_code":"USD","in_stock":true},{"title":"L","offer_id":58363901739395,"sku":"PRO-SS-L","price":74.2,"currency_code":"USD","in_stock":true},{"title":"XL","offer_id":58363901772163,"sku":"PRO-SS-XL","price":74.2,"currency_code":"USD","in_stock":true},{"title":"XXL","offer_id":58363901804931,"sku":"PRO-SS-XXL","price":74.2,"currency_code":"USD","in_stock":true},{"title":"XXXL","offer_id":58363901837699,"sku":"PRO-SS-XXXL","price":74.2,"currency_code":"USD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0988\/4323\/0595\/files\/fb0c6d8c82613d7d01036ed04a79b9ab.jpg?v=1782824440","url":"https:\/\/infernobeachwear.com\/it\/products\/men-s-compression-rashguard-ss-sandstone-arch","provider":"Inferno Beachwear","version":"1.0","type":"link"}