{"product_id":"ultralight-technical-t-shirt-reef-quarter","title":"Ultralight Technical T-Shirt - Japan","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\u003eThe Beach Shirt ; Ultralight Honeycomb Jersey for Beach Volley \u0026amp; Beach Sports\u003c\/title\u003e\n\u003cmeta name=\"description\" content=\"The Beach Shirt — ultralight 95 g\/m² honeycomb-knit jersey by SITIP. Recycled NATIVE yarn, MICROSENSE soft-touch finish, breathable as a sea breeze. Custom team kits for beach volley, beach tennis, footvolley and beach sports. Made in Italy.\"\u003e\n\u003cmeta name=\"keywords\" content=\"beach volley jersey, beach tennis shirt, ultralight sports shirt, breathable beach shirt, honeycomb knit jersey, recycled polyester sportswear, custom beach volley kit, SITIP NATIVE LINDA, MICROSENSE, beach sports apparel, made in Italy\"\u003e\n\u003clink rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\"\u003e\n\u003clink rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin\u003e\n\u003clink href=\"https:\/\/fonts.googleapis.com\/css2?family=Archivo:wght@400;500;600;700;800;900\u0026amp;family=Archivo+Narrow:wght@400;500;600;700\u0026amp;family=JetBrains+Mono:wght@400;500;600\u0026amp;display=swap\" rel=\"stylesheet\"\u003e\n\u003cstyle\u003e\n  :root {\n    --ink: #0a1f2c;\n    --ink-soft: #143246;\n    --paper: #ffffff;\n    --paper-warm: #f4efe6;\n    --foam: #ffffff;\n    --ocean: #0066a2;\n    --ocean-deep: #00466e;\n    --aqua: #1fb6c1;\n    --sun: #f5b13d;\n    --coral: #ff5e3a;\n    --sand: #d9c8a5;\n    --line: rgba(10, 31, 44, 0.14);\n  }\n  * { box-sizing: border-box; }\n  html, body {\n    margin: 0;\n    padding: 0;\n    background: var(--paper);\n    color: var(--ink);\n    font-family: 'Archivo', sans-serif;\n    -webkit-font-smoothing: antialiased;\n  }\n  .product-desc {\n    max-width: 1100px;\n    margin: 0 auto;\n    padding: 24px 20px 80px;\n  }\n\n  \/* ============ PRODUCT TITLE BLOCK ============ *\/\n  .product-title {\n    position: relative;\n    padding: 28px 8px 56px;\n    margin-bottom: 8px;\n    border-bottom: 1px solid var(--line);\n    overflow: hidden;\n  }\n  .product-title .top-row {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    gap: 16px;\n    margin-bottom: 28px;\n    flex-wrap: wrap;\n  }\n  .product-title .pill {\n    display: inline-flex;\n    align-items: center;\n    gap: 10px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.22em;\n    text-transform: uppercase;\n    color: var(--ocean-deep);\n    background: rgba(0, 102, 162, 0.08);\n    border: 1px solid rgba(0, 102, 162, 0.25);\n    padding: 8px 14px;\n    border-radius: 100px;\n  }\n  .product-title .pill .pulse {\n    width: 7px; height: 7px;\n    border-radius: 50%;\n    background: var(--coral);\n    box-shadow: 0 0 0 4px rgba(255, 94, 58, 0.18);\n    animation: pulse 1.6s ease-in-out infinite;\n  }\n  @keyframes pulse {\n    0%, 100% { transform: scale(1); opacity: 1; }\n    50% { transform: scale(1.25); opacity: 0.7; }\n  }\n  .product-title .meta-row {\n    display: flex;\n    gap: 18px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.16em;\n    text-transform: uppercase;\n    color: var(--ink-soft);\n    flex-wrap: wrap;\n  }\n  .product-title .meta-row span {\n    display: inline-flex;\n    align-items: center;\n    gap: 8px;\n  }\n  .product-title .meta-row span + span::before { display: none; }\n  .product-title .kicker {\n    display: inline-flex;\n    align-items: center;\n    gap: 12px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 12px;\n    letter-spacing: 0.2em;\n    color: var(--ocean);\n    text-transform: uppercase;\n    margin-bottom: 14px;\n  }\n  .product-title .kicker::before {\n    content: \"\";\n    width: 36px;\n    height: 1.5px;\n    background: var(--ocean);\n  }\n  .product-title h1 {\n    font-family: 'Archivo Narrow', sans-serif;\n    font-weight: 700;\n    font-size: clamp(44px, 7vw, 92px);\n    line-height: 0.92;\n    letter-spacing: -0.025em;\n    text-transform: uppercase;\n    margin: 0 0 8px;\n    text-wrap: balance;\n    color: var(--ink);\n  }\n  .product-title h1 .accent {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-style: italic;\n    background: linear-gradient(110deg, var(--ocean-deep) 0%, var(--ocean) 45%, var(--aqua) 100%);\n    -webkit-background-clip: text;\n    background-clip: text;\n    color: transparent;\n    letter-spacing: -0.04em;\n    padding-right: 0.12em;\n    display: inline-block;\n  }\n  .product-title .product-full-title {\n    position: relative;\n    margin: 18px 0 0;\n    padding-inline-start: 24px;\n    font-family: 'Archivo', sans-serif;\n    font-size: clamp(14px, 1.4vw, 18px);\n    line-height: 1.45;\n    letter-spacing: -0.005em;\n    color: var(--ocean-deep);\n    font-weight: 500;\n    font-style: italic;\n    max-width: 640px;\n    text-wrap: balance;\n  }\n  .product-title .product-full-title::before {\n    content: \"\";\n    position: absolute;\n    inset-block-start: 0.65em;\n    inset-inline-start: 0;\n    width: 14px;\n    height: 2px;\n    background: linear-gradient(90deg, var(--ocean-deep), var(--aqua));\n    border-radius: 2px;\n  }\n  .product-title .subline {\n    font-size: 17px;\n    line-height: 1.55;\n    color: var(--ink-soft);\n    max-width: 640px;\n    margin: 22px 0 0;\n  }\n  .product-title .subline strong {\n    color: var(--ink);\n    font-weight: 700;\n  }\n  .product-title .feature-tabs {\n    display: flex;\n    gap: 8px;\n    margin-top: 28px;\n    flex-wrap: wrap;\n  }\n  .product-title .feature-tabs span {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.14em;\n    text-transform: uppercase;\n    padding: 8px 14px;\n    border: 1px solid var(--line);\n    border-radius: 100px;\n    color: var(--ink-soft);\n    background: var(--paper-warm);\n  }\n\n  \/* ============ DESIGN CTAS ============ *\/\n  .liquid-tag { display: none; }\n  .design-ctas {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n    gap: 12px;\n    margin-top: 32px;\n    position: relative;\n  }\n  .design-ctas::before {\n    content: \"\/\/ Customize this product\";\n    position: absolute;\n    top: -22px;\n    left: 0;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    color: var(--ocean);\n    opacity: 0.7;\n  }\n  .cta-btn {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 12px;\n    width: 100%;\n    padding: 18px 24px;\n    text-decoration: none;\n    font-family: 'Archivo', sans-serif;\n    font-weight: 700;\n    font-size: 14px;\n    letter-spacing: 0.08em;\n    text-transform: uppercase;\n    border-radius: 14px;\n    border: 1.5px solid transparent;\n    transition: transform 0.25s ease, box-shadow 0.25s ease, background 0.25s ease, color 0.25s ease, border-color 0.25s ease;\n    cursor: pointer;\n    position: relative;\n    overflow: hidden;\n  }\n  .cta-btn svg {\n    flex-shrink: 0;\n    transition: transform 0.25s ease, stroke 0.25s ease;\n  }\n  .cta-btn:hover {\n    transform: translateY(-2px);\n  }\n  .cta-btn:hover svg {\n    transform: rotate(-8deg) scale(1.05);\n  }\n\n  \/* Primary — Edit Design (ocean gradient + attention motion) *\/\n  .cta-btn--primary {\n    background: linear-gradient(135deg, var(--ocean-deep) 0%, var(--ocean) 50%, var(--aqua) 100%);\n    color: var(--foam);\n    box-shadow: 0 6px 20px rgba(0, 70, 110, 0.22);\n    position: relative;\n    animation: pdw-cta-pulse 2.6s ease-in-out infinite;\n  }\n  \/* Soft halo behind the button — pulses gently *\/\n  .cta-btn--primary::before {\n    content: \"\";\n    position: absolute;\n    inset: -2px;\n    border-radius: 16px;\n    background: linear-gradient(135deg, var(--ocean), var(--aqua));\n    z-index: -1;\n    opacity: 0.5;\n    filter: blur(8px);\n    animation: pdw-cta-glow 2.6s ease-in-out infinite;\n  }\n  \/* Repeating shine sweep — draws the eye without changing the color *\/\n  .cta-btn--primary::after {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background: linear-gradient(120deg, transparent 35%, rgba(255,255,255,0.4) 50%, transparent 65%);\n    transform: translateX(-100%);\n    animation: pdw-cta-shine 3.2s ease-in-out infinite;\n    pointer-events: none;\n  }\n  \/* Animated arrow hint that nudges right *\/\n  .cta-btn--primary .nudge {\n    display: inline-block;\n    animation: pdw-cta-nudge 1.6s ease-in-out infinite;\n  }\n  .cta-btn--primary:hover {\n    transform: translateY(-3px);\n    box-shadow: 0 14px 32px rgba(0, 70, 110, 0.42);\n    animation-play-state: paused;\n  }\n  .cta-btn--primary:hover::before { animation-play-state: paused; opacity: 0.85; }\n  @keyframes pdw-cta-pulse {\n    0%, 100% { box-shadow: 0 6px 20px rgba(0, 70, 110, 0.22); }\n    50% { box-shadow: 0 8px 28px rgba(31, 182, 193, 0.55), 0 0 0 6px rgba(31, 182, 193, 0.12); }\n  }\n  @keyframes pdw-cta-glow {\n    0%, 100% { opacity: 0.35; }\n    50% { opacity: 0.7; }\n  }\n  @keyframes pdw-cta-shine {\n    0%, 55%, 100% { transform: translateX(-100%); }\n    80% { transform: translateX(100%); }\n  }\n  @keyframes pdw-cta-nudge {\n    0%, 100% { transform: translateX(0); }\n    50% { transform: translateX(4px); }\n  }\n\n  \/* Secondary — Create New Design (outlined → filled on hover) *\/\n  .cta-btn--secondary {\n    background: var(--foam);\n    border-color: var(--ocean-deep);\n    color: var(--ocean-deep);\n  }\n  .cta-btn--secondary svg { stroke: var(--ocean-deep); }\n  .cta-btn--secondary:hover {\n    background: linear-gradient(135deg, var(--ocean-deep) 0%, var(--ocean) 50%, var(--aqua) 100%);\n    border-color: transparent;\n    color: var(--foam);\n    box-shadow: 0 10px 28px rgba(0, 70, 110, 0.28);\n  }\n  .cta-btn--secondary:hover svg { stroke: var(--foam); }\n\n  @media (max-width: 640px) {\n    .design-ctas { grid-template-columns: 1fr; }\n  }\n\n  \/* ============ PRICING TABLE ============ *\/\n  .pricing {\n    margin-top: 36px;\n    background: linear-gradient(180deg, #fff 0%, var(--paper-warm) 100%);\n    border: 1px solid var(--line);\n    border-radius: 20px;\n    padding: 28px 28px 24px;\n    position: relative;\n    overflow: hidden;\n  }\n  .pricing::before {\n    content: \"\/\/ Volume pricing\";\n    position: absolute;\n    top: 16px;\n    right: 22px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    color: var(--ocean);\n    opacity: 0.6;\n  }\n  .pricing-head {\n    display: flex;\n    align-items: end;\n    justify-content: space-between;\n    gap: 20px;\n    margin-bottom: 22px;\n    flex-wrap: wrap;\n  }\n  .pricing-title {\n    font-family: 'Archivo Narrow', sans-serif;\n    text-transform: uppercase;\n    font-size: 24px;\n    font-weight: 700;\n    letter-spacing: -0.01em;\n    margin: 0;\n    line-height: 1;\n  }\n  .pricing-title .em {\n    font-family: 'Archivo', sans-serif;\n    font-style: italic;\n    font-weight: 900;\n    background: linear-gradient(110deg, var(--ocean-deep), var(--aqua));\n    -webkit-background-clip: text;\n    background-clip: text;\n    color: transparent;\n  }\n  .pricing-sub {\n    font-size: 12px;\n    color: var(--ink-soft);\n    font-family: 'JetBrains Mono', monospace;\n    letter-spacing: 0.1em;\n    text-transform: uppercase;\n    margin: 6px 0 0;\n  }\n\n  \/* Live readout *\/\n  .pricing-readout {\n    background: var(--ink);\n    color: var(--foam);\n    border-radius: 16px;\n    padding: 22px 26px;\n    display: grid;\n    grid-template-columns: auto 1fr auto;\n    gap: 24px;\n    align-items: center;\n    margin-bottom: 22px;\n    position: relative;\n    overflow: hidden;\n  }\n  .pricing-readout::after {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background: radial-gradient(ellipse 400px 120px at 0% 100%, rgba(31,182,193,0.25), transparent);\n    pointer-events: none;\n  }\n  .readout-qty {\n    display: flex;\n    flex-direction: column;\n    gap: 4px;\n    position: relative;\n    z-index: 1;\n  }\n  .readout-qty .label {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    color: var(--aqua);\n  }\n  .readout-qty .value {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-style: italic;\n    font-size: 48px;\n    line-height: 0.9;\n    letter-spacing: -0.04em;\n  }\n  .readout-qty .value small {\n    font-size: 14px;\n    font-style: normal;\n    font-weight: 600;\n    letter-spacing: 0.05em;\n    color: rgba(255,255,255,0.55);\n    margin-left: 6px;\n  }\n  .readout-discount {\n    text-align: center;\n    position: relative;\n    z-index: 1;\n  }\n  .readout-discount .badge {\n    display: inline-flex;\n    align-items: center;\n    gap: 6px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.18em;\n    text-transform: uppercase;\n    background: rgba(255, 94, 58, 0.18);\n    border: 1px solid rgba(255, 94, 58, 0.4);\n    color: #ffb89e;\n    padding: 6px 14px;\n    border-radius: 100px;\n    transition: all 0.3s ease;\n  }\n  .readout-discount .badge.zero {\n    background: rgba(255,255,255,0.08);\n    border-color: rgba(255,255,255,0.2);\n    color: rgba(255,255,255,0.55);\n  }\n  .readout-discount .save {\n    display: block;\n    font-size: 11px;\n    color: rgba(255,255,255,0.55);\n    margin-top: 8px;\n    font-family: 'JetBrains Mono', monospace;\n    letter-spacing: 0.08em;\n  }\n  .readout-discount .save b {\n    color: var(--sun);\n    font-weight: 600;\n  }\n  .readout-price {\n    text-align: right;\n    position: relative;\n    z-index: 1;\n  }\n  .readout-price .label {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    color: var(--aqua);\n    margin-bottom: 4px;\n  }\n  .readout-price .unit {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-size: 36px;\n    letter-spacing: -0.03em;\n    line-height: 1;\n  }\n  .readout-price .unit .strike {\n    font-size: 16px;\n    color: rgba(255,255,255,0.4);\n    text-decoration: line-through;\n    font-weight: 600;\n    margin-right: 8px;\n    vertical-align: middle;\n  }\n  .readout-price .total {\n    font-size: 12px;\n    color: rgba(255,255,255,0.7);\n    font-family: 'JetBrains Mono', monospace;\n    letter-spacing: 0.05em;\n    margin-top: 6px;\n  }\n  .readout-price .total b {\n    color: var(--foam);\n    font-weight: 700;\n  }\n\n  \/* Quantity slider *\/\n  .qty-slider-wrap {\n    margin: 0 0 24px;\n  }\n  .qty-slider {\n    -webkit-appearance: none;\n    appearance: none;\n    width: 100%;\n    height: 8px;\n    border-radius: 100px;\n    background: var(--paper-warm);\n    border: 1px solid var(--line);\n    outline: none;\n  }\n  .qty-slider::-webkit-slider-thumb {\n    -webkit-appearance: none;\n    appearance: none;\n    width: 32px;\n    height: 32px;\n    border-radius: 50%;\n    background: linear-gradient(135deg, var(--ocean-deep), var(--aqua));\n    border: 3px solid var(--foam);\n    box-shadow: 0 4px 12px rgba(0, 70, 110, 0.35);\n    cursor: pointer;\n    transition: transform 0.2s ease;\n  }\n  .qty-slider::-webkit-slider-thumb:hover {\n    transform: scale(1.15);\n  }\n  .qty-slider::-moz-range-thumb {\n    width: 32px;\n    height: 32px;\n    border-radius: 50%;\n    background: linear-gradient(135deg, var(--ocean-deep), var(--aqua));\n    border: 3px solid var(--foam);\n    box-shadow: 0 4px 12px rgba(0, 70, 110, 0.35);\n    cursor: pointer;\n  }\n  .qty-ticks {\n    position: relative;\n    height: 14px;\n    margin-top: 10px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.1em;\n    color: var(--ink-soft);\n  }\n  .qty-ticks span {\n    position: absolute;\n    top: 0;\n    transform: translateX(-50%);\n    white-space: nowrap;\n  }\n\n  \/* Tier table — auto-fit lets the grid reflow based on the actual\n     available width (no media\/container queries needed). In a 1100px\n     description it stays 7 columns; in a 400px sidebar it wraps to 3. *\/\n  .tier-grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));\n    gap: 6px;\n  }\n  .tier {\n    background: var(--foam);\n    border: 1.5px solid var(--line);\n    border-radius: 12px;\n    padding: 14px 10px;\n    text-align: center;\n    transition: all 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);\n    cursor: pointer;\n    position: relative;\n  }\n  .tier:hover {\n    border-color: var(--aqua);\n    transform: translateY(-2px);\n  }\n  .tier.active {\n    background: linear-gradient(160deg, var(--ocean-deep), var(--ocean));\n    border-color: var(--ocean-deep);\n    color: var(--foam);\n    transform: translateY(-3px);\n    box-shadow: 0 10px 24px rgba(0, 70, 110, 0.3);\n  }\n  .tier .qty {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.12em;\n    text-transform: uppercase;\n    color: var(--ink-soft);\n    margin-bottom: 6px;\n  }\n  .tier.active .qty { color: rgba(255,255,255,0.7); }\n  .tier .disc {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-style: italic;\n    font-size: 24px;\n    letter-spacing: -0.03em;\n    line-height: 1;\n    color: var(--ocean-deep);\n  }\n  .tier.active .disc { color: var(--sun); }\n  .tier .disc.zero { color: var(--ink-soft); opacity: 0.5; }\n  .tier .price-each {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    color: var(--ocean);\n    margin-top: 4px;\n    letter-spacing: 0.05em;\n  }\n  .tier.active .price-each { color: var(--aqua); }\n\n  \/* Bulk inquiry banner (qty 50+) *\/\n  .bulk-inquiry {\n    margin-top: 14px;\n    padding: 22px 24px;\n    border-radius: 14px;\n    background: linear-gradient(135deg, var(--ocean-deep), var(--ocean));\n    color: var(--foam);\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    gap: 18px;\n    flex-wrap: wrap;\n    box-shadow: 0 14px 32px rgba(0, 50, 77, 0.28);\n    overflow: hidden;\n    position: relative;\n    opacity: 0;\n    transform: translateY(8px);\n    pointer-events: none;\n    max-height: 0;\n    margin-top: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    transition: opacity 0.4s ease, transform 0.4s ease, max-height 0.45s ease, margin-top 0.45s ease, padding 0.45s ease;\n  }\n  .bulk-inquiry.show {\n    opacity: 1;\n    transform: translateY(0);\n    pointer-events: auto;\n    max-height: 240px;\n    margin-top: 14px;\n    padding-top: 22px;\n    padding-bottom: 22px;\n  }\n  .bulk-inquiry::before {\n    content: \"\";\n    position: absolute;\n    top: -40%;\n    right: -10%;\n    width: 280px;\n    height: 280px;\n    background: radial-gradient(circle, rgba(31,182,193,0.35), transparent 70%);\n    pointer-events: none;\n  }\n  .bulk-inquiry-text { position: relative; flex: 1 1 320px; }\n  .bulk-inquiry-eyebrow {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.18em;\n    color: var(--sun);\n    text-transform: uppercase;\n    margin-bottom: 8px;\n  }\n  .bulk-inquiry h4 {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-size: 22px;\n    line-height: 1.15;\n    letter-spacing: -0.02em;\n    margin: 0 0 6px;\n  }\n  .bulk-inquiry h4 em {\n    font-style: italic;\n    color: var(--aqua);\n  }\n  .bulk-inquiry p {\n    font-size: 14px;\n    line-height: 1.5;\n    color: rgba(255,255,255,0.82);\n    margin: 0;\n  }\n  .bulk-inquiry-cta {\n    position: relative;\n    display: inline-flex;\n    align-items: center;\n    gap: 10px;\n    padding: 14px 22px;\n    background: var(--sun);\n    color: var(--ocean-deep);\n    text-decoration: none;\n    border-radius: 999px;\n    font-family: 'Archivo', sans-serif;\n    font-weight: 800;\n    font-size: 14px;\n    letter-spacing: 0.04em;\n    text-transform: uppercase;\n    transition: transform 0.2s ease, box-shadow 0.2s ease;\n    flex-shrink: 0;\n  }\n  .bulk-inquiry-cta:hover {\n    transform: translateY(-2px);\n    box-shadow: 0 10px 24px rgba(255, 200, 87, 0.4);\n  }\n  .bulk-inquiry-cta svg { width: 16px; height: 16px; }\n\n  \/* Quote request modal *\/\n  .quote-modal-overlay {\n    position: fixed;\n    inset: 0;\n    background: rgba(0, 30, 50, 0.6);\n    backdrop-filter: blur(6px);\n    -webkit-backdrop-filter: blur(6px);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    z-index: 99999;\n    padding: 20px;\n    opacity: 0;\n    pointer-events: none;\n    transition: opacity 0.25s ease;\n  }\n  .quote-modal-overlay.show {\n    opacity: 1;\n    pointer-events: auto;\n  }\n  .quote-modal {\n    position: relative;\n    background: #ffffff;\n    border-radius: 18px;\n    width: 100%;\n    max-width: 520px;\n    \/* iOS Safari: 92dvh follows the dynamic viewport (excludes the URL bar\n       when it appears), preventing the modal from being clipped on phones.\n       Falls back to 92vh on browsers without dvh support. *\/\n    max-height: 92vh;\n    max-height: 92dvh;\n    overflow-y: auto;\n    \/* Prevent scroll chaining: when the modal reaches its top\/bottom edge,\n       the scroll DOES NOT propagate to the page below. Critical on iOS to\n       avoid the bouncing\/locked feeling. *\/\n    overscroll-behavior: contain;\n    \/* Smooth touch-scrolling on older iOS (deprecated but harmless on new). *\/\n    -webkit-overflow-scrolling: touch;\n    box-shadow: 0 30px 80px rgba(0, 30, 50, 0.4);\n    transform: translateY(20px) scale(0.96);\n    transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);\n  }\n  .quote-modal-overlay.show .quote-modal { transform: translateY(0) scale(1); }\n  .quote-modal-header {\n    padding: 28px 32px 18px;\n    background: linear-gradient(135deg, var(--ocean-deep), var(--ocean));\n    color: var(--foam);\n    border-radius: 18px 18px 0 0;\n    position: relative;\n    overflow: hidden;\n  }\n  .quote-modal-header::before {\n    content: \"\";\n    position: absolute;\n    top: -50%;\n    right: -20%;\n    width: 220px;\n    height: 220px;\n    background: radial-gradient(circle, rgba(31,182,193,0.4), transparent 70%);\n    pointer-events: none;\n  }\n  .quote-modal-eyebrow {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.18em;\n    text-transform: uppercase;\n    color: var(--sun);\n    margin-bottom: 6px;\n    position: relative;\n  }\n  .quote-modal-header h3 {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-size: 24px;\n    line-height: 1.15;\n    letter-spacing: -0.02em;\n    margin: 0 0 6px;\n    position: relative;\n  }\n  .quote-modal-header h3 em { font-style: italic; color: var(--aqua); }\n  .quote-modal-header p {\n    font-size: 13px;\n    line-height: 1.5;\n    color: rgba(255,255,255,0.78);\n    margin: 0;\n    position: relative;\n  }\n  .quote-modal-close {\n    position: absolute;\n    top: 16px;\n    right: 16px;\n    \/* Visible button stays compact 32x32 so it doesn't get clipped by the\n       header's rounded top-right corner (border-radius 18px + overflow:hidden).\n       The ::before pseudo-element extends the clickable hit-area to 44x44\n       outside the visible button — invisible, but catches taps. *\/\n    width: 32px;\n    height: 32px;\n    border-radius: 50%;\n    background: rgba(255,255,255,0.15);\n    border: none;\n    color: #fff;\n    cursor: pointer;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 20px;\n    line-height: 1;\n    transition: background 0.2s ease, transform 0.2s ease;\n    z-index: 2;\n  }\n  \/* Invisible hit-area extender: takes the clickable area from 32x32 visible\n     to ~44x44 effective, without affecting the visual size. *\/\n  .quote-modal-close::before {\n    content: \"\";\n    position: absolute;\n    inset: -6px;\n    border-radius: 50%;\n  }\n  .quote-modal-close:hover { background: rgba(255,255,255,0.28); transform: rotate(90deg); }\n  .quote-modal-body {\n    padding: 24px 32px 32px;\n  }\n  .quote-form-row {\n    display: grid;\n    gap: 16px;\n    margin-bottom: 14px;\n  }\n  .quote-form-row.two { grid-template-columns: 1fr 1fr; }\n  @media (max-width: 480px) {\n    .quote-form-row.two { grid-template-columns: 1fr; }\n    .quote-modal-header { padding: 22px 22px 16px; }\n    .quote-modal-body { padding: 20px 22px 26px; }\n  }\n  .quote-field { display: flex; flex-direction: column; gap: 6px; }\n  .quote-field label {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.15em;\n    text-transform: uppercase;\n    color: var(--ink-soft);\n    font-weight: 600;\n  }\n  .quote-field label .req { color: var(--coral); }\n  .quote-field label .opt {\n    color: var(--ink-soft);\n    opacity: 0.6;\n    font-size: 9px;\n    margin-left: 4px;\n    text-transform: none;\n    letter-spacing: 0.05em;\n  }\n  .quote-field input,\n  .quote-field select,\n  .quote-field textarea {\n    font-family: 'Archivo', sans-serif;\n    font-size: 14px;\n    color: var(--ink);\n    background: var(--foam);\n    border: 1.5px solid var(--line);\n    border-radius: 10px;\n    padding: 11px 14px;\n    outline: none;\n    transition: border-color 0.2s ease, background 0.2s ease;\n    width: 100%;\n    box-sizing: border-box;\n  }\n  .quote-field input:focus,\n  .quote-field select:focus,\n  .quote-field textarea:focus {\n    border-color: var(--ocean);\n    background: #fff;\n  }\n  \/* iOS Safari triggers auto-zoom on text\/textarea inputs whose font-size\n     is below 16px. With body in position:fixed (our scroll lock), that\n     zoom gets stuck and the virtual keyboard fails to open — only\n     type=\"number\" and type=\"email\" remain functional. Force 16px on\n     mobile to disable the auto-zoom. *\/\n  @media (max-width: 640px) {\n    .quote-field input,\n    .quote-field select,\n    .quote-field textarea {\n      font-size: 16px;\n    }\n  }\n  .quote-field input.invalid,\n  .quote-field select.invalid {\n    border-color: var(--coral);\n    background: #fff5f3;\n  }\n  .quote-field-error {\n    color: var(--coral);\n    font-size: 11px;\n    font-family: 'JetBrains Mono', monospace;\n    margin-top: 2px;\n    display: none;\n  }\n  .quote-field-error.show { display: block; }\n\n  \/* Honeypot anti-spam: hidden off-screen for humans, but still in the DOM\n     and submitted by naive bots that auto-fill every visible input. We\n     avoid display:none \/ visibility:hidden because some bots skip those. *\/\n  .quote-honeypot {\n    position: absolute;\n    left: -10000px;\n    top: auto;\n    width: 1px;\n    height: 1px;\n    overflow: hidden;\n  }\n  .quote-modal-submit {\n    width: 100%;\n    margin-top: 8px;\n    padding: 16px 22px;\n    background: linear-gradient(135deg, var(--ocean-deep), var(--ocean));\n    color: var(--foam);\n    border: none;\n    border-radius: 12px;\n    font-family: 'Archivo', sans-serif;\n    font-weight: 800;\n    font-size: 15px;\n    letter-spacing: 0.04em;\n    text-transform: uppercase;\n    cursor: pointer;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 10px;\n    transition: transform 0.2s ease, box-shadow 0.2s ease;\n  }\n  .quote-modal-submit:hover {\n    transform: translateY(-1px);\n    box-shadow: 0 12px 28px rgba(0, 70, 110, 0.35);\n  }\n  .quote-modal-submit svg { width: 16px; height: 16px; }\n  .quote-modal-footnote {\n    text-align: center;\n    font-size: 11px;\n    color: var(--ink-soft);\n    margin-top: 14px;\n  }\n  .quote-success {\n    text-align: center;\n    padding: 40px 20px;\n  }\n  .quote-success .check {\n    width: 64px;\n    height: 64px;\n    border-radius: 50%;\n    background: linear-gradient(135deg, #22c55e, #16a34a);\n    color: #fff;\n    margin: 0 auto 18px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 32px;\n    font-weight: 700;\n  }\n  .quote-success h4 {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-size: 22px;\n    margin: 0 0 8px;\n    color: var(--ink);\n  }\n  .quote-success p {\n    font-size: 14px;\n    color: var(--ink-soft);\n    margin: 0 auto;\n    max-width: 36ch;\n    line-height: 1.5;\n  }\n\n  @media (max-width: 720px) {\n    .pricing-readout { grid-template-columns: 1fr; gap: 16px; text-align: left; }\n    .readout-discount, .readout-price { text-align: left; }\n    .tier-grid { grid-template-columns: repeat(2, 1fr); }\n    .bulk-inquiry { padding: 18px 16px; }\n    .bulk-inquiry h4 { font-size: 18px; }\n    .pricing::before { display: none; }\n  }\n\n  \/* ============ HERO BANNER ============ *\/\n  .hero {\n    position: relative;\n    border-radius: 28px;\n    overflow: hidden;\n    background: linear-gradient(160deg, var(--ocean-deep) 0%, var(--ocean) 45%, var(--aqua) 100%);\n    color: var(--foam);\n    padding: 64px 48px 72px;\n    isolation: isolate;\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n    gap: 40px;\n    align-items: center;\n  }\n  .hero-text { position: relative; z-index: 2; }\n  .hero-visual {\n    position: relative;\n    z-index: 1;\n    aspect-ratio: 1 \/ 1;\n    width: 100%;\n    max-width: 460px;\n    justify-self: end;\n    border-radius: 24px;\n    overflow: hidden;\n    background:\n      radial-gradient(ellipse at 30% 20%, rgba(255,255,255,0.35), transparent 55%),\n      linear-gradient(150deg, rgba(255,255,255,0.18), rgba(255,255,255,0.04));\n    border: 1px solid rgba(255,255,255,0.22);\n    box-shadow: 0 30px 60px -20px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.18);\n    backdrop-filter: blur(4px);\n  }\n  .hero-visual svg.honeycomb,\n  .hero-visual img.honeycomb {\n    position: absolute;\n    inset: 0;\n    width: 100%;\n    height: 100%;\n    display: block;\n    object-fit: cover;\n  }\n  .hero-visual .hc-label {\n    position: absolute;\n    left: 18px; bottom: 18px;\n    z-index: 3;\n    display: inline-flex; flex-direction: column; gap: 4px;\n    padding: 10px 14px;\n    background: rgba(255,255,255,0.92);\n    color: var(--ink);\n    border-radius: 12px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.18em;\n    text-transform: uppercase;\n    box-shadow: 0 8px 24px -8px rgba(0,0,0,0.3);\n  }\n  .hero-visual .hc-label strong {\n    font-family: 'Archivo Narrow', sans-serif;\n    font-size: 18px;\n    letter-spacing: -0.01em;\n    text-transform: none;\n    font-weight: 800;\n    color: var(--ocean-deep);\n  }\n  .hero-visual .hc-feather {\n    position: absolute;\n    right: 16px; top: 16px;\n    z-index: 3;\n    display: inline-flex; align-items: center; gap: 6px;\n    padding: 6px 12px;\n    background: rgba(255,255,255,0.18);\n    border: 1px solid rgba(255,255,255,0.4);\n    color: #fff;\n    border-radius: 100px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    backdrop-filter: blur(6px);\n  }\n  .hero-visual .hc-feather::before { content: \"\"; width: 5px; height: 5px; background: var(--sun); border-radius: 50%; box-shadow: 0 0 0 3px rgba(245,177,61,0.4); }\n  @keyframes hc-breathe { 0%,100% { opacity: 0.7; } 50% { opacity: 1; } }\n  .hero-visual svg.honeycomb .cell-a { animation: hc-breathe 5s ease-in-out infinite; }\n  .hero-visual svg.honeycomb .cell-b { animation: hc-breathe 5s ease-in-out infinite; animation-delay: -1.6s; }\n  .hero-visual svg.honeycomb .cell-c { animation: hc-breathe 5s ease-in-out infinite; animation-delay: -3.2s; }\n  .hero::before {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background:\n      radial-gradient(circle at 85% 20%, rgba(245, 177, 61, 0.35), transparent 45%),\n      radial-gradient(circle at 10% 90%, rgba(255, 255, 255, 0.18), transparent 50%);\n    z-index: -1;\n  }\n  .hero svg.waves {\n    position: absolute;\n    left: 0; right: 0; bottom: -2px;\n    width: 100%;\n    height: 110px;\n    z-index: 0;\n  }\n  .hero-eyebrow {\n    display: inline-flex;\n    align-items: center;\n    gap: 10px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.22em;\n    text-transform: uppercase;\n    background: rgba(255,255,255,0.14);\n    border: 1px solid rgba(255,255,255,0.3);\n    padding: 8px 14px;\n    border-radius: 100px;\n    backdrop-filter: blur(6px);\n  }\n  .hero-eyebrow .dot {\n    width: 6px; height: 6px;\n    background: var(--sun);\n    border-radius: 50%;\n    box-shadow: 0 0 0 4px rgba(245,177,61,0.3);\n  }\n  .hero h2 {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-size: clamp(40px, 6vw, 76px);\n    line-height: 0.95;\n    letter-spacing: -0.03em;\n    margin: 22px 0 18px;\n    text-wrap: balance;\n  }\n  .hero h2 .ital {\n    font-style: italic;\n    font-weight: 800;\n    color: var(--sun);\n  }\n  .hero p {\n    font-size: 17px;\n    line-height: 1.5;\n    max-width: 540px;\n    opacity: 0.92;\n    margin: 0;\n  }\n  .hero-meta {\n    display: flex;\n    gap: 24px;\n    margin-top: 36px;\n    flex-wrap: wrap;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 12px;\n    letter-spacing: 0.08em;\n    text-transform: uppercase;\n  }\n  .hero-meta span {\n    display: flex; align-items: center; gap: 8px;\n  }\n  .hero-meta span::before {\n    content: \"\";\n    width: 8px; height: 8px;\n    border: 1.5px solid var(--sun);\n    transform: rotate(45deg);\n  }\n\n  \/* ============ SECTION HEAD ============ *\/\n  .section-head {\n    margin: 72px 0 28px;\n    display: flex;\n    align-items: end;\n    justify-content: space-between;\n    gap: 24px;\n    flex-wrap: wrap;\n  }\n  .section-head .num {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 12px;\n    color: var(--ocean);\n    letter-spacing: 0.2em;\n  }\n  .section-head h2 {\n    font-family: 'Archivo Narrow', sans-serif;\n    font-weight: 700;\n    font-size: clamp(34px, 4.5vw, 54px);\n    line-height: 0.95;\n    letter-spacing: -0.02em;\n    margin: 6px 0 0;\n    text-transform: uppercase;\n  }\n  .section-head .lede {\n    max-width: 360px;\n    font-size: 14px;\n    line-height: 1.5;\n    color: var(--ink-soft);\n  }\n\n  \/* ============ TECHNOLOGY CARDS (Microsense \u0026 Native) ============ *\/\n  .tech-grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));\n    gap: 20px;\n  }\n  .tech-card {\n    position: relative;\n    border-radius: 24px;\n    padding: 36px 32px 32px;\n    overflow: hidden;\n    color: var(--foam);\n    isolation: isolate;\n    min-height: 460px;\n    display: flex;\n    flex-direction: column;\n  }\n  .tech-card.acquazero {\n    background:\n      radial-gradient(ellipse 600px 400px at 80% 10%, rgba(31,182,193,0.7), transparent),\n      linear-gradient(160deg, var(--ocean-deep), var(--ocean));\n  }\n  .tech-card.eclipse {\n    background:\n      radial-gradient(ellipse 500px 400px at 90% 90%, rgba(245,177,61,0.55), transparent),\n      linear-gradient(160deg, var(--ink), var(--ink-soft));\n  }\n  .tech-card .badge {\n    display: inline-flex;\n    align-items: center;\n    gap: 8px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.2em;\n    text-transform: uppercase;\n    background: rgba(255,255,255,0.15);\n    border: 1px solid rgba(255,255,255,0.3);\n    padding: 6px 12px;\n    border-radius: 100px;\n    align-self: flex-start;\n  }\n  .tech-card h3 {\n    font-family: 'Archivo', sans-serif;\n    font-weight: 900;\n    font-style: italic;\n    font-size: 64px;\n    line-height: 0.9;\n    letter-spacing: -0.04em;\n    margin: 22px 0 6px;\n  }\n  .tech-card .tagline {\n    font-size: 15px;\n    opacity: 0.85;\n    margin: 0 0 28px;\n    max-width: 280px;\n    line-height: 1.4;\n  }\n  .tech-features {\n    list-style: none;\n    padding: 0;\n    margin: auto 0 0;\n    display: grid;\n    gap: 12px;\n  }\n  .tech-features li {\n    display: flex;\n    align-items: center;\n    gap: 14px;\n    padding: 12px 14px;\n    background: rgba(255,255,255,0.08);\n    border: 1px solid rgba(255,255,255,0.14);\n    border-radius: 14px;\n    backdrop-filter: blur(8px);\n    transition: transform 0.3s ease, background 0.3s ease;\n  }\n  .tech-features li:hover {\n    transform: translateX(4px);\n    background: rgba(255,255,255,0.14);\n  }\n  .tech-features .ico {\n    width: 38px; height: 38px;\n    flex-shrink: 0;\n    border-radius: 10px;\n    display: grid;\n    place-items: center;\n    font-size: 18px;\n    background: rgba(255,255,255,0.16);\n  }\n  .tech-card.eclipse .tech-features .ico {\n    background: rgba(245,177,61,0.25);\n  }\n  .tech-features .label {\n    font-size: 14px;\n    font-weight: 600;\n    letter-spacing: 0.01em;\n  }\n\n  \/* Decorative drop \/ sun *\/\n  .tech-card .deco {\n    position: absolute;\n    top: 28px; right: 28px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.18em;\n    opacity: 0.55;\n  }\n  .tech-card .ring {\n    position: absolute;\n    border-radius: 50%;\n    border: 1.5px dashed rgba(255,255,255,0.18);\n    pointer-events: none;\n  }\n  .acquazero .ring-1 { width: 320px; height: 320px; top: -120px; right: -100px; animation: spin 60s linear infinite; }\n  .acquazero .ring-2 { width: 180px; height: 180px; top: -40px; right: -20px; animation: spin 40s linear infinite reverse; }\n  .eclipse .ring-1 { width: 280px; height: 280px; bottom: -100px; right: -80px; animation: spin 70s linear infinite; }\n  .eclipse .feather {\n    position: absolute;\n    width: 86px; height: 150px;\n    top: 18px; right: 26px;\n    pointer-events: none;\n    opacity: 0.92;\n    filter: drop-shadow(0 6px 18px rgba(255,255,255,0.18));\n    transform-origin: 50% 8%;\n    animation: feather-float 7s ease-in-out infinite;\n  }\n  @keyframes spin {\n    to { transform: rotate(360deg); }\n  }\n  @keyframes feather-float {\n    0%, 100% { transform: translate(0, 0) rotate(18deg); }\n    50%      { transform: translate(-6px, -10px) rotate(24deg); }\n  }\n\n  \/* ============ PERFORMANCE STRIP ============ *\/\n  .perf-strip {\n    background: var(--ink);\n    color: var(--foam);\n    border-radius: 24px;\n    padding: 48px 40px;\n    margin-top: 28px;\n    position: relative;\n    overflow: hidden;\n  }\n  .perf-strip::after {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background: radial-gradient(ellipse 800px 200px at 50% 100%, rgba(31,182,193,0.25), transparent);\n    pointer-events: none;\n  }\n  .perf-strip h3 {\n    font-family: 'Archivo Narrow', sans-serif;\n    text-transform: uppercase;\n    letter-spacing: -0.01em;\n    font-size: 32px;\n    font-weight: 700;\n    margin: 0 0 6px;\n  }\n  .perf-strip .sub {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.2em;\n    color: var(--aqua);\n    text-transform: uppercase;\n    margin: 0 0 32px;\n  }\n  .perf-grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n    gap: 16px;\n    position: relative;\n    z-index: 1;\n  }\n  .perf-card {\n    background: rgba(255,255,255,0.04);\n    border: 1px solid rgba(255,255,255,0.1);\n    border-radius: 16px;\n    padding: 22px 20px;\n    transition: all 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);\n    cursor: default;\n  }\n  .perf-card:hover {\n    background: rgba(31,182,193,0.12);\n    border-color: var(--aqua);\n    transform: translateY(-4px);\n  }\n  .perf-card .icon-box {\n    width: 48px; height: 48px;\n    border-radius: 12px;\n    background: linear-gradient(135deg, var(--aqua), var(--ocean));\n    display: grid;\n    place-items: center;\n    font-size: 22px;\n    margin-bottom: 18px;\n  }\n  .perf-card h4 {\n    font-family: 'Archivo', sans-serif;\n    font-size: 17px;\n    font-weight: 800;\n    margin: 0 0 6px;\n    letter-spacing: -0.01em;\n  }\n  .perf-card p {\n    font-size: 13px;\n    line-height: 1.45;\n    color: rgba(255,255,255,0.65);\n    margin: 0;\n  }\n\n  \/* ============ CUSTOM PRINT STRIP ============ *\/\n  .custom-strip {\n    background: linear-gradient(140deg, color-mix(in oklab, var(--ocean-deep) 70%, black) 0%, var(--ocean-deep) 50%, color-mix(in oklab, var(--ocean) 80%, var(--aqua)) 100%);\n    color: var(--foam);\n    border-radius: 28px;\n    padding: 56px 48px;\n    margin-top: 24px;\n    position: relative;\n    overflow: hidden;\n  }\n  .custom-strip::before {\n    content: \"\/\/ 01 → 50+ pieces\";\n    position: absolute;\n    top: 22px; right: 28px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.22em;\n    text-transform: uppercase;\n    color: rgba(255,255,255,0.55);\n  }\n  .custom-strip::after {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background: radial-gradient(900px circle at 110% -10%, rgba(31,182,193,0.28), transparent 55%),\n                radial-gradient(700px circle at -10% 110%, rgba(255,255,255,0.06), transparent 60%);\n    pointer-events: none;\n  }\n  .custom-strip h3 {\n    font-family: 'Archivo Narrow', sans-serif;\n    text-transform: uppercase;\n    font-size: 36px;\n    font-weight: 700;\n    letter-spacing: -0.01em;\n    margin: 0 0 6px;\n    position: relative;\n    z-index: 1;\n  }\n  .custom-strip .sub {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.22em;\n    text-transform: uppercase;\n    color: rgba(255,255,255,0.6);\n    margin: 0 0 32px;\n    position: relative;\n    z-index: 1;\n  }\n  .custom-grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n    gap: 16px;\n    position: relative;\n    z-index: 1;\n  }\n  .custom-card {\n    background: rgba(255,255,255,0.05);\n    border: 1px solid rgba(255,255,255,0.12);\n    border-radius: 18px;\n    padding: 24px 22px;\n    position: relative;\n    overflow: hidden;\n    transition: transform .3s cubic-bezier(.2,.8,.2,1), background .3s, border-color .3s;\n  }\n  .custom-card:hover {\n    background: rgba(31,182,193,0.14);\n    border-color: var(--aqua);\n    transform: translateY(-4px);\n  }\n  .custom-num {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.2em;\n    color: var(--aqua);\n    margin-bottom: 18px;\n  }\n  .custom-card h4 {\n    font-family: 'Archivo', sans-serif;\n    font-size: 17px;\n    font-weight: 700;\n    margin: 0 0 8px;\n    color: var(--foam);\n    letter-spacing: -0.01em;\n  }\n  .custom-card p {\n    font-size: 13px;\n    line-height: 1.5;\n    color: rgba(255,255,255,0.7);\n    margin: 0;\n  }\n\n  \/* ============ USE CASES ============ *\/\n  .usecase { margin-top: 28px; display: flex; flex-direction: column; gap: 20px; }\n  .compare { background: linear-gradient(160deg, var(--paper-warm), #fff); border: 1px solid var(--line); border-radius: 24px; padding: 32px 28px; position: relative; overflow: hidden; }\n  .compare::before { content: \"\/\/ vs · standard sports tee\"; position: absolute; top: 16px; right: 22px; font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--ocean); opacity: 0.6; }\n  .compare h3 { font-family: 'Archivo Narrow', sans-serif; text-transform: uppercase; font-size: 26px; font-weight: 700; margin: 14px 0 6px; line-height: 1; letter-spacing: -0.01em; }\n  .compare h3 .em { font-family: 'Archivo', sans-serif; font-style: italic; font-weight: 900; background: linear-gradient(110deg, var(--ocean-deep), var(--aqua)); -webkit-background-clip: text; background-clip: text; color: transparent; }\n  .compare-lead { font-size: 13px; line-height: 1.55; color: var(--ink-soft); margin: 0 0 22px; }\n  .compare-rows { display: grid; gap: 8px; }\n  .compare-row { display: grid; grid-template-columns: 1fr 1fr; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: #fff; }\n  .compare-row .col { padding: 12px 14px; font-size: 12.5px; line-height: 1.35; display: flex; align-items: center; gap: 10px; }\n  .compare-row .col.lo { color: var(--ink-soft); background: rgba(10, 31, 44, 0.025); }\n  .compare-row .col.hi { color: var(--ink); font-weight: 600; background: linear-gradient(110deg, rgba(31, 182, 193, 0.12), rgba(0, 102, 162, 0.06)); border-left: 1px solid var(--line); }\n  .compare-row .col.hi::before { content: \"\"; width: 12px; height: 12px; border-radius: 50%; background: linear-gradient(135deg, var(--ocean-deep), var(--aqua)); flex-shrink: 0; box-shadow: 0 0 0 3px rgba(31,182,193,0.2); }\n  .compare-row .col.lo::before { content: \"\"; width: 12px; height: 12px; border-radius: 50%; border: 1.5px solid var(--line); flex-shrink: 0; background: #fff; }\n  .compare-row .lab { grid-column: 1 \/ -1; background: var(--ink); color: var(--foam); font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase; padding: 8px 14px; }\n  .compare-pill { display: inline-flex; align-items: center; gap: 8px; font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase; background: var(--ink); color: var(--foam); padding: 6px 12px; border-radius: 100px; }\n  .compare-pill .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--sun); }\n  .compare { display: grid; grid-template-columns: auto 1fr auto; column-gap: 28px; row-gap: 14px; align-items: center; }\n  .compare .compare-pill { grid-column: 1 \/ -1; justify-self: start; }\n  .fit-headline { text-align: left; }\n  .fit-headline h3 { margin: 0 0 8px; font-size: 30px; }\n  .fit-headline .compare-lead { margin: 0; max-width: 60ch; }\n  .fit-mark { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; margin: 0; padding: 0; border-top: none; align-self: center; max-width: 220px; }\n  .fit-mark span { font-family: 'JetBrains Mono', monospace; font-size: 9px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ocean-deep); background: rgba(31, 182, 193, 0.08); padding: 6px 10px; border-radius: 100px; }\n  @media (max-width: 720px) { .compare { grid-template-columns: 1fr; } .fit-headline { text-align: left; } .fit-mark { justify-content: flex-start; max-width: none; } }\n  .usecase-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; align-content: start; }\n  .uc-card { background: #fff; border: 1px solid var(--line); border-radius: 18px; padding: 22px 20px 20px; position: relative; overflow: hidden; transition: transform .3s cubic-bezier(.2,.8,.2,1), border-color .3s ease, box-shadow .3s ease; display: flex; flex-direction: column; gap: 14px; }\n  .uc-card::before { content: \"\"; position: absolute; top: 0; left: 0; width: 4px; height: 100%; background: linear-gradient(180deg, var(--ocean-deep), var(--aqua)); opacity: 0.85; }\n  .uc-card:hover { transform: translateY(-4px); border-color: var(--ocean); box-shadow: 0 14px 30px rgba(0, 70, 110, 0.1); }\n  .uc-card:hover .uc-icon { background: linear-gradient(135deg, var(--ocean-deep), var(--aqua)); color: var(--foam); border-color: transparent; }\n  .uc-icon { width: 56px; height: 56px; border-radius: 14px; border: 1.5px solid var(--line); background: var(--paper-warm); display: grid; place-items: center; color: var(--ocean-deep); transition: all .3s ease; flex-shrink: 0; }\n  .uc-icon svg { width: 28px; height: 28px; stroke: currentColor; stroke-width: 1.6; fill: none; stroke-linecap: round; stroke-linejoin: round; }\n  .uc-num { font-family: 'JetBrains Mono', monospace; font-size: 9px; letter-spacing: 0.22em; color: var(--ocean); display: flex; align-items: center; gap: 8px; text-transform: uppercase; }\n  .uc-num::after { content: \"\"; flex: 1; height: 1px; background: var(--line); }\n  .uc-card h4 { font-family: 'Archivo Narrow', sans-serif; font-weight: 700; text-transform: uppercase; font-size: 20px; line-height: 1; margin: 0; letter-spacing: -0.01em; color: var(--ink); }\n  .uc-card h4 .ital { font-family: 'Archivo', sans-serif; font-style: italic; font-weight: 900; color: var(--ocean); }\n  .uc-benefit { font-size: 12.5px; line-height: 1.4; color: var(--ink-soft); margin: 0; padding: 10px 12px; background: rgba(31, 182, 193, 0.06); border-left: 2px solid var(--aqua); border-radius: 4px; }\n  .uc-benefit b { color: var(--ink); font-weight: 700; }\n  .uc-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: auto; }\n  .uc-tags span { font-family: 'JetBrains Mono', monospace; font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ocean-deep); background: rgba(0, 102, 162, 0.06); border: 1px solid rgba(0, 102, 162, 0.18); padding: 4px 8px; border-radius: 100px; }\n  @media (max-width: 900px) { .usecase-list { grid-template-columns: repeat(3, 1fr); } }\n  @media (max-width: 720px) { .usecase-list { grid-template-columns: 1fr 1fr; } }\n  @media (max-width: 540px) { .usecase-list { grid-template-columns: 1fr; } .compare-row { grid-template-columns: 1fr; } .compare-row .col.hi { border-left: none; border-top: 1px solid var(--line); } }\n\n  \/* ============ CERTIFICATIONS ============ *\/\n  .certs {\n    margin-top: 28px;\n    background: var(--paper-warm);\n    border-radius: 24px;\n    padding: 40px;\n    position: relative;\n    overflow: hidden;\n  }\n  .certs-head {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    margin-bottom: 28px;\n    flex-wrap: wrap;\n    gap: 16px;\n  }\n  .certs h3 {\n    font-family: 'Archivo Narrow', sans-serif;\n    text-transform: uppercase;\n    font-size: 28px;\n    font-weight: 700;\n    margin: 0;\n    letter-spacing: -0.01em;\n  }\n  .certs .stamp {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.2em;\n    color: var(--ocean-deep);\n    text-transform: uppercase;\n    border: 1.5px solid var(--ocean-deep);\n    padding: 6px 12px;\n    border-radius: 100px;\n  }\n  .cert-grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n    gap: 12px;\n  }\n  .cert {\n    background: var(--foam);\n    border: 1px solid var(--line);\n    border-radius: 16px;\n    padding: 22px 20px;\n    display: flex;\n    align-items: center;\n    gap: 14px;\n    transition: all 0.3s ease;\n  }\n  .cert:hover {\n    border-color: var(--ocean);\n    transform: translateY(-2px);\n    box-shadow: 0 8px 24px rgba(0,70,110,0.08);\n  }\n  .cert .glyph {\n    width: 44px; height: 44px;\n    border-radius: 12px;\n    background: var(--paper);\n    display: grid;\n    place-items: center;\n    font-size: 20px;\n    flex-shrink: 0;\n  }\n  .cert .name {\n    font-weight: 700;\n    font-size: 14px;\n    line-height: 1.2;\n    letter-spacing: -0.01em;\n  }\n  .cert .meta {\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 9px;\n    letter-spacing: 0.15em;\n    color: var(--ocean);\n    text-transform: uppercase;\n    margin-top: 3px;\n  }\n\n  \/* ============ FAQ ============ *\/\n  .faq {\n    margin-top: 28px;\n    background: var(--paper-warm);\n    border: 1px solid var(--line);\n    border-radius: 24px;\n    padding: 40px 36px;\n    position: relative;\n    overflow: hidden;\n  }\n  .faq::before {\n    content: \"\/\/ frequently asked\";\n    position: absolute;\n    top: 18px; right: 24px;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px;\n    letter-spacing: 0.22em;\n    text-transform: uppercase;\n    color: var(--ocean);\n    opacity: 0.55;\n  }\n  .faq-list {\n    display: flex;\n    flex-direction: column;\n    gap: 0;\n    margin-top: 8px;\n  }\n  .faq-item {\n    border-top: 1px solid var(--line);\n    padding: 0;\n  }\n  .faq-item:last-child { border-bottom: 1px solid var(--line); }\n  .faq-item summary {\n    list-style: none;\n    cursor: pointer;\n    padding: 22px 48px 22px 0;\n    font-family: 'Archivo', sans-serif;\n    font-size: 17px;\n    font-weight: 600;\n    color: var(--ink);\n    letter-spacing: -0.005em;\n    position: relative;\n    transition: color .2s;\n  }\n  .faq-item summary::-webkit-details-marker { display: none; }\n  .faq-item summary::after {\n    content: \"+\";\n    position: absolute;\n    right: 4px; top: 50%;\n    transform: translateY(-50%);\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 22px;\n    color: var(--ocean-deep);\n    font-weight: 400;\n    transition: transform .25s cubic-bezier(.2,.8,.2,1);\n  }\n  .faq-item[open] summary::after { content: \"\\2013\"; }\n  .faq-item summary:hover { color: var(--ocean-deep); }\n  .faq-item .answer {\n    padding: 0 24px 24px 0;\n    font-size: 14.5px;\n    line-height: 1.65;\n    color: #4b5663;\n    max-width: 780px;\n  }\n  .faq-item .answer strong { color: var(--ink); }\n  @media (max-width: 720px) {\n    .faq { padding: 32px 22px; }\n    .faq-item summary { font-size: 15.5px; padding: 20px 40px 20px 0; }\n  }\n\n  \/* ============ CLOSING TICKER ============ *\/\n  .ticker {\n    margin-top: 28px;\n    background: var(--ocean-deep);\n    color: var(--foam);\n    border-radius: 100px;\n    overflow: hidden;\n    position: relative;\n    height: 56px;\n    display: flex;\n    align-items: center;\n  }\n  .ticker-track {\n    display: flex;\n    gap: 48px;\n    white-space: nowrap;\n    animation: ticker-scroll 28s linear infinite;\n    padding-right: 48px;\n  }\n  .ticker-track span {\n    font-family: 'Archivo Narrow', sans-serif;\n    font-weight: 700;\n    font-size: 18px;\n    text-transform: uppercase;\n    letter-spacing: 0.05em;\n    display: flex;\n    align-items: center;\n    gap: 48px;\n  }\n  .ticker-track span::after {\n    content: \"✦\";\n    color: var(--sun);\n  }\n  @keyframes ticker-scroll {\n    to { transform: translateX(-50%); }\n  }\n\n  \/* ============ INTRO ANIMATION ============ *\/\n  @media (prefers-reduced-motion: no-preference) {\n    [data-anim] {\n      opacity: 0;\n      will-change: opacity, transform, filter, clip-path;\n    }\n    [data-anim=\"fade\"]    { transform: translateY(8px); }\n    [data-anim=\"rise\"]    { transform: translateY(28px); }\n    [data-anim=\"rise-lg\"] { transform: translateY(56px); }\n    [data-anim=\"drop\"]    { transform: translateY(-22px); }\n    [data-anim=\"left\"]    { transform: translateX(-32px); }\n    [data-anim=\"right\"]   { transform: translateX(32px); }\n    [data-anim=\"scale\"]   { transform: scale(0.92); }\n    [data-anim=\"zoom\"]    { transform: scale(0.6); filter: blur(8px); }\n    [data-anim=\"reveal\"]  { clip-path: inset(0 100% 0 0); }\n    [data-anim=\"blur\"]    { filter: blur(14px); transform: translateY(12px); }\n\n    [data-anim].in {\n      opacity: 1;\n      transform: none;\n      filter: none;\n      clip-path: inset(0 0 0 0);\n      transition:\n        opacity 0.9s cubic-bezier(0.2, 0.8, 0.2, 1),\n        transform 1s cubic-bezier(0.2, 0.8, 0.2, 1),\n        filter 0.9s ease,\n        clip-path 1.1s cubic-bezier(0.7, 0, 0.3, 1);\n    }\n  }\n\n  \/* ============ TWEAKS — DENSITY ============ *\/\n  \/* Active preset: \"compact\" (tighter, denser). Base vars are inherited by\n     all density-scoped rules below. *\/\n  html { --tw-pad-scale: 1; --tw-radius-scale: 1; --tw-weight-shift: 0; --tw-tracking-add: 0em; --tw-line-shift: 0; }\n  html[data-density=\"compact\"]   { --tw-pad-scale: 0.72; --tw-radius-scale: 0.45; --tw-weight-shift: 100; --tw-tracking-add: -0.005em; --tw-line-shift: -0.06; }\n\n  \/* Apply density to the major surfaces *\/\n  html[data-density] .product-desc { padding: calc(24px * var(--tw-pad-scale)) calc(20px * var(--tw-pad-scale)) calc(80px * var(--tw-pad-scale)); }\n  html[data-density] .hero,\n  html[data-density] .perf-strip,\n  html[data-density] .custom-strip,\n  html[data-density] .certs,\n  html[data-density] .faq,\n  html[data-density] .pricing,\n  html[data-density] .compare,\n  html[data-density] .tech-card,\n  html[data-density] .uc-card,\n  html[data-density] .perf-card,\n  html[data-density] .custom-card,\n  html[data-density] .cert,\n  html[data-density] .pricing-readout,\n  html[data-density] .tier,\n  html[data-density] .bulk-inquiry { border-radius: calc(var(--natural-radius, 20px) * var(--tw-radius-scale)); }\n  \/* assign each surface its natural base radius via custom prop *\/\n  html[data-density] .hero          { --natural-radius: 28px; padding: calc(64px * var(--tw-pad-scale)) calc(48px * var(--tw-pad-scale)) calc(72px * var(--tw-pad-scale)); }\n  html[data-density] .perf-strip    { --natural-radius: 24px; padding: calc(48px * var(--tw-pad-scale)) calc(40px * var(--tw-pad-scale)); }\n  html[data-density] .custom-strip  { --natural-radius: 28px; padding: calc(56px * var(--tw-pad-scale)) calc(48px * var(--tw-pad-scale)); }\n  html[data-density] .certs         { --natural-radius: 24px; padding: calc(40px * var(--tw-pad-scale)); }\n  html[data-density] .faq           { --natural-radius: 24px; padding: calc(40px * var(--tw-pad-scale)) calc(36px * var(--tw-pad-scale)); }\n  html[data-density] .pricing       { --natural-radius: 20px; padding: calc(28px * var(--tw-pad-scale)) calc(28px * var(--tw-pad-scale)) calc(24px * var(--tw-pad-scale)); }\n  html[data-density] .compare       { --natural-radius: 24px; padding: calc(32px * var(--tw-pad-scale)) calc(28px * var(--tw-pad-scale)); }\n  html[data-density] .tech-card     { --natural-radius: 24px; padding: calc(36px * var(--tw-pad-scale)) calc(32px * var(--tw-pad-scale)) calc(32px * var(--tw-pad-scale)); }\n  html[data-density] .uc-card       { --natural-radius: 18px; padding: calc(22px * var(--tw-pad-scale)) calc(20px * var(--tw-pad-scale)) calc(20px * var(--tw-pad-scale)); }\n  html[data-density] .perf-card     { --natural-radius: 16px; padding: calc(22px * var(--tw-pad-scale)) calc(20px * var(--tw-pad-scale)); }\n  html[data-density] .custom-card   { --natural-radius: 18px; padding: calc(24px * var(--tw-pad-scale)) calc(22px * var(--tw-pad-scale)); }\n  html[data-density] .cert          { --natural-radius: 16px; padding: calc(22px * var(--tw-pad-scale)) calc(20px * var(--tw-pad-scale)); }\n  html[data-density] .pricing-readout { --natural-radius: 16px; padding: calc(22px * var(--tw-pad-scale)) calc(26px * var(--tw-pad-scale)); }\n  html[data-density] .bulk-inquiry  { --natural-radius: 14px; }\n  html[data-density] .tier          { --natural-radius: 12px; padding: calc(14px * var(--tw-pad-scale)) calc(10px * var(--tw-pad-scale)); }\n\n  \/* Editorial: lighter weights, looser tracking; Compact: heavier, tighter *\/\n  html[data-density] h1,\n  html[data-density] h2,\n  html[data-density] h3,\n  html[data-density] h4,\n  html[data-density] .pricing-title,\n  html[data-density] .uc-card h4 {\n    font-weight: calc(700 + var(--tw-weight-shift));\n    letter-spacing: calc(-0.02em + var(--tw-tracking-add));\n  }\n  html[data-density=\"compact\"]   .product-title h1 { font-weight: 800; letter-spacing: -0.035em; }\n  html[data-density=\"compact\"]   .hero h2 { font-weight: 900; letter-spacing: -0.045em; }\n\n  \/* Compact thickens borders, sharpens contrast *\/\n  html[data-density=\"compact\"] .pricing,\n  html[data-density=\"compact\"] .compare,\n  html[data-density=\"compact\"] .faq,\n  html[data-density=\"compact\"] .uc-card,\n  html[data-density=\"compact\"] .cert,\n  html[data-density=\"compact\"] .perf-card,\n  html[data-density=\"compact\"] .tier,\n  html[data-density=\"compact\"] .compare-row { border-width: 2px; }\n  html[data-density=\"compact\"] .uc-card::before { width: 6px; }\n\n  \/* ============ TWEAKS — MOTION ============ *\/\n  \/* Active preset: \"riptide\" (everything pulsing). *\/\n  html[data-motion=\"riptide\"] {\n    --tw-spin-mult: 0.18;     \/* rings spin much faster *\/\n    --tw-ticker-mult: 0.35;   \/* ticker much faster *\/\n    --tw-pulse-mult: 0.45;\n  }\n  html[data-motion=\"riptide\"] .acquazero .ring-1 { animation-duration: calc(60s * var(--tw-spin-mult)); }\n  html[data-motion=\"riptide\"] .acquazero .ring-2 { animation-duration: calc(40s * var(--tw-spin-mult)); }\n  html[data-motion=\"riptide\"] .eclipse .ring-1   { animation-duration: calc(70s * var(--tw-spin-mult)); }\n  html[data-motion=\"riptide\"] .ticker-track       { animation-duration: calc(28s * var(--tw-ticker-mult)); }\n  html[data-motion=\"riptide\"] .cta-btn--primary   { animation-duration: calc(2.6s * var(--tw-pulse-mult)); }\n  html[data-motion=\"riptide\"] .cta-btn--primary::before { animation-duration: calc(2.6s * var(--tw-pulse-mult)); }\n  html[data-motion=\"riptide\"] .cta-btn--primary::after  { animation-duration: calc(3.2s * var(--tw-pulse-mult)); }\n  html[data-motion=\"riptide\"] .cta-btn--primary .nudge  { animation-duration: calc(1.6s * var(--tw-pulse-mult)); }\n  html[data-motion=\"riptide\"] .product-title .pill .pulse { animation-duration: 0.8s; }\n  \/* In riptide, add a livelier float to the eclipse feather. *\/\n  html[data-motion=\"riptide\"] .eclipse .feather { animation-duration: 4.5s; }\n  html[data-motion=\"riptide\"] .hero-eyebrow .dot,\n  html[data-motion=\"riptide\"] .pricing-readout::after { animation: tw-glow 2.4s ease-in-out infinite; }\n  @keyframes tw-glow {\n    0%, 100% { opacity: 0.6; }\n    50%      { opacity: 1; }\n  }\n\n  \/* ============ RESPONSIVE ============ *\/\n  @media (max-width: 800px) {\n    .hero { padding: 44px 28px 56px; grid-template-columns: 1fr; gap: 28px; }\n    .hero-visual { max-width: 100%; justify-self: stretch; aspect-ratio: 16 \/ 11; }\n    .tech-grid { grid-template-columns: 1fr; }\n    .perf-grid { grid-template-columns: repeat(2, 1fr); }\n    .cert-grid { grid-template-columns: repeat(2, 1fr); }\n    .custom-grid { grid-template-columns: repeat(2, 1fr); }\n    .custom-strip { padding: 44px 28px; }\n    .custom-strip h3 { font-size: 28px; }\n    .product-desc { padding: 16px 12px 60px; }\n  }\n  @media (max-width: 480px) {\n    .perf-grid, .cert-grid { grid-template-columns: 1fr; }\n    .custom-grid { grid-template-columns: 1fr; }\n    .tech-card h3 { font-size: 48px; }\n  }\n\n  \/* ============ A11Y: respect prefers-reduced-motion ============ *\/\n  \/* Disable all infinite\/looping decorative animations when the user has\n     selected \"reduce motion\" in their OS settings. The brief one-shot\n     intro animations on [data-anim] are already guarded by their own\n     @media (prefers-reduced-motion: no-preference) block above and so\n     do not run at all in this mode. *\/\n  @media (prefers-reduced-motion: reduce) {\n    .acquazero .ring-1,\n    .acquazero .ring-2,\n    .eclipse .ring-1,\n    .eclipse .feather,\n    .ticker-track,\n    .product-title .pill .pulse,\n    .hero-visual svg.honeycomb .cell-a,\n    .hero-visual svg.honeycomb .cell-b,\n    .hero-visual svg.honeycomb .cell-c,\n    .cta-btn--primary,\n    .cta-btn--primary::before,\n    .cta-btn--primary::after,\n    .cta-btn--primary .nudge,\n    .pricing-readout::after,\n    .hero-eyebrow .dot {\n      animation: none !important;\n    }\n  }\n\n  \/* ============ PERF: content-visibility ============ *\/\n  \/* Sections below the initial fold: the browser skips layout\/paint\/style\n     until they scroll near the viewport. contain-intrinsic-size reserves\n     approximate space so the scrollbar doesn't jump. Supported by\n     Chrome\/Edge\/Safari 16+; older browsers ignore both properties safely. *\/\n  .perf-strip,\n  .custom-strip,\n  .usecase,\n  .certs,\n  .faq,\n  .ticker {\n    content-visibility: auto;\n    contain-intrinsic-size: auto 800px;\n  }\n\u003c\/style\u003e\n\n\n\u003cdiv class=\"product-desc\"\u003e\n\n  \u003c!-- ============ PRODUCT TITLE ============ --\u003e\n  \u003cheader class=\"product-title\" style=\"padding: 28px 8px 40px\"\u003e\n    \u003cdiv class=\"top-row\"\u003e\n      \u003cdiv class=\"pill\" data-anim=\"drop\"\u003e\n\u003cspan class=\"pulse\"\u003e\u003c\/span\u003eFully Customizable\u003c\/div\u003e\n      \u003cdiv class=\"meta-row\" data-anim=\"right\"\u003e\n        \u003cspan\u003eSKU · BCH-SH-01\u003c\/span\u003e\n        \u003cspan\u003e95 g\/m² · Honeycomb\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"kicker\" data-anim=\"left\"\u003eHoneycomb Knit · Beach Performance Series\u003c\/div\u003e\n    \u003ch1 data-anim=\"reveal\"\u003eThe Beach\u003cbr\u003e\u003cspan class=\"accent\"\u003eShirt\u003c\/span\u003e\n\u003c\/h1\u003e\n    \u003cp class=\"product-full-title\" data-anim=\"rise\"\u003eUltralight Technical T-Shirt - Reef Quarter\u003c\/p\u003e\n    \u003cp class=\"subline\" data-anim=\"blur\"\u003e\u003cstrong\u003eThe ultralight beach jersey.\u003c\/strong\u003e A featherweight \u003cstrong\u003e95 g\/m²\u003c\/strong\u003e Italian knit with a \u003cstrong\u003ehoneycomb structure\u003c\/strong\u003e that lets air flow through like a sea breeze. Recycled NATIVE yarn, MICROSENSE soft-touch finish. Cut for \u003cstrong\u003ebeach volley, beach tennis and every sport in the sand\u003c\/strong\u003e — print your \u003cstrong\u003elogo, numbers and sponsors\u003c\/strong\u003e, from one piece to full team kits. Lighter, fresher, more breathable than anything else on the line.\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🍃 95 g\/m² Ultralight\u003c\/span\u003e\n      \u003cspan data-anim=\"rise\"\u003e⬡ Honeycomb Knit\u003c\/span\u003e\n      \u003cspan data-anim=\"rise\"\u003e♻ NATIVE Recycled\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=dad4586b8288fd64b9b884f01c601617\" 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=\"Ultralight Technical T-Shirt - Reef Quarter\"\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 jerseys for our beach volley 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\"\u003eLighter than\u003cbr\u003e\u003cspan class=\"ital\"\u003ea sea breeze.\u003c\/span\u003e\n\u003c\/h2\u003e\n    \u003cp data-anim=\"blur\"\u003eA 95 g\/m² honeycomb knit woven by SITIP in Bergamo on the NATIVE LINDA base ; air moves through it the way it moves across the sand. The lightest, freshest, most breathable shirt we make — engineered for beach volley, beach tennis and every sport played barefoot.\u003c\/p\u003e\n    \u003cdiv class=\"hero-meta\" data-anim-stagger=\"80\"\u003e\n      \u003cspan data-anim=\"rise\"\u003e95 g\/m² · Honeycomb knit\u003c\/span\u003e\n      \u003cspan data-anim=\"rise\"\u003e100% Recycled yarn\u003c\/span\u003e\n      \u003cspan data-anim=\"rise\"\u003eMade in Italy\u003c\/span\u003e\n    \u003c\/div\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"hero-visual\" data-anim=\"zoom\" aria-label=\"Macro view of white honeycomb knit fabric, showing the open hexagonal structure that gives the shirt its lightness and breathability\"\u003e\n      \u003cspan class=\"hc-feather\"\u003e95 g\/m² · Featherweight\u003c\/span\u003e\n      \u003cimg class=\"honeycomb\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0988\/4323\/0595\/files\/native-linda-honeycomb.png?v=1778759184\" alt=\"Macro view of NATIVE LINDA honeycomb knit fabric, showing the open hexagonal mesh structure that gives the shirt its lightness and breathability\" decoding=\"async\" fetchpriority=\"high\" width=\"460\" height=\"460\"\u003e\n      \u003cspan class=\"hc-label\"\u003e\n        Honeycomb Knit\n        \u003cstrong\u003eSITIP · NATIVE LINDA\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 innovations.\u003cbr\u003eOne breeze.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eTwo SITIP technologies stacked on a single 95 g\/m² base ; one makes the fabric feel like silk on the skin, the other rebuilds it from recycled yarn with the lowest possible footprint.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003cdiv class=\"tech-grid\" data-anim-stagger=\"180\"\u003e\n    \u003c!-- MICROSENSE --\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·SOFT\u003c\/div\u003e\n      \u003cdiv class=\"badge\"\u003e◐ Soft Performance System\u003c\/div\u003e\n      \u003ch3\u003eMicrosense\u003c\/h3\u003e\n      \u003cp class=\"tagline\"\u003eMicro-filament yarn that mimics silk. Soft on the skin, brutal on sweat.\u003c\/p\u003e\n      \u003cul class=\"tech-features\"\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e🪶\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eSilk-like next-to-skin softness\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e💨\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eSuperior moisture wicking\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e⚡\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eDries faster than natural fibers\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e👕\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eEasy care ; no ironing required\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·ECO\u003c\/div\u003e\n      \u003cdiv class=\"badge\"\u003e♻ Recycled Yarn System\u003c\/div\u003e\n      \u003ch3\u003eNative\u003c\/h3\u003e\n      \u003cp class=\"tagline\"\u003ePre \u0026amp; post-consumer recycled yarn, low-impact chemistry, lower energy.\u003c\/p\u003e\n      \u003cul class=\"tech-features\"\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e♻️\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003e100% recycled polyester yarn\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e🌍\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eGRS \u0026amp; ISO 14001 certified\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e🧪\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eFluorine-free, low-impact chemistry\u003c\/div\u003e\n        \u003c\/li\u003e\n        \u003cli\u003e\n          \u003cdiv class=\"ico\"\u003e⚡\u003c\/div\u003e\n          \u003cdiv class=\"label\"\u003eLower non-renewable energy use\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 set on the sand to the last point of the tournament ; a fabric so light you'll forget you're wearing it.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003csection class=\"perf-strip\" data-anim=\"rise-lg\"\u003e\n    \u003ch3 data-anim=\"reveal\"\u003eEngineered for the sand\u003c\/h3\u003e\n    \u003cp class=\"sub\" data-anim=\"fade\"\u003eUltralight · Maximum airflow · All-day fresh\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\u003e95 g\/m² Ultralight\u003c\/h4\u003e\n        \u003cp\u003eLess than half the weight of a standard performance tee ; it disappears on you.\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\u003eHoneycomb Knit\u003c\/h4\u003e\n        \u003cp\u003eA hexagonal mesh structure lets fresh air circulate inside like a breeze through a window.\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\u003eComfort stretch in every direction ; jumps, dives, full-extension digs 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\u003eSweat is wicked to the surface and gone in minutes. Stays cool, stays dry, stays light.\u003c\/p\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/section\u003e\n\n  \u003c!-- ============ CUSTOM PRINT (SEO: custom beach volley shirt, beach team kits, custom beach tennis jersey) ============ --\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 beach shirt built around your team. Print your logo, numbers and sponsors on the lightest 95 g\/m² Italian honeycomb knit ; 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 beach shirt, 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 chest, sleeves and back. Photo-grade detail on a custom beach volley shirt that won't crack, peel or fade — even after a hundred matches in the sun.\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\u003eTournament ready. Add player numbers, names or sponsor blocks ; perfect for beach volley clubs, beach tennis squads and sand-sport teams.\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 beach shirt. 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 95 gsm honeycomb knit woven by SITIP in Bergamo. 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\u003enothing at all.\u003c\/h2\u003e\n    \u003c\/div\u003e\n    \u003cp class=\"lede\" data-anim=\"blur\"\u003eA \u003cstrong\u003elighter, more open knit\u003c\/strong\u003e than any standard sports tee. Built to \u003cstrong\u003emove air through the fabric\u003c\/strong\u003e the way a sea breeze moves through a hammock — pure ventilation, pure freshness, all day long.\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\u003eFeatherweight beach fit\u003c\/div\u003e\n\n      \u003cdiv class=\"fit-headline\"\u003e\n        \u003ch3\u003eFeatherweight \u003cspan class=\"em\"\u003efreshness.\u003c\/span\u003e\n\u003c\/h3\u003e\n        \u003cp class=\"compare-lead\"\u003eA \u003cstrong\u003ethinner, lighter\u003c\/strong\u003e Italian knit than any standard sports tee ; built to \u003cstrong\u003ebreathe\u003c\/strong\u003e, not just to cover. The honeycomb mesh lets fresh air flow through the fabric and pushes humid air out ; you stay cool in 35 °C on the sand.\u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"fit-mark\"\u003e\n        \u003cspan\u003e95 g\/m² ultralight\u003c\/span\u003e\n        \u003cspan\u003eHoneycomb mesh\u003c\/span\u003e\n        \u003cspan\u003eMaximum airflow\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 \/ Beach Volley\u003c\/div\u003e\n        \u003ch4\u003eSand \u0026amp; \u003cspan class=\"ital\"\u003espikes\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eHoneycomb airflow\u003c\/b\u003e ; stays cool through long matches in the sun, never sticks to the skin.\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eBeach volley\u003c\/span\u003e\u003cspan\u003e2v2\u003c\/span\u003e\u003cspan\u003e4v4\u003c\/span\u003e\u003cspan\u003eTournament play\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 \/ Beach Tennis\u003c\/div\u003e\n        \u003ch4\u003eFast \u003cspan class=\"ital\"\u003erallies\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003e4-way stretch\u003c\/b\u003e + 95 g\/m² ultralight ; no drag on smashes, no weight on sprints.\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eBeach tennis\u003c\/span\u003e\u003cspan\u003ePadel beach\u003c\/span\u003e\u003cspan\u003ePickleball\u003c\/span\u003e\u003cspan\u003eSand court\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 \/ Heat\u003c\/div\u003e\n        \u003ch4\u003e35 °C and \u003cspan class=\"ital\"\u003erising\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eMicrosense moisture-wicking\u003c\/b\u003e + open mesh ; humidity exits faster than it builds up.\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eMediterranean summer\u003c\/span\u003e\u003cspan\u003eTropical climates\u003c\/span\u003e\u003cspan\u003eHeatwave training\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 \/ Sand Sports\u003c\/div\u003e\n        \u003ch4\u003eBeach \u003cspan class=\"ital\"\u003eathletics\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eFeatherweight\u003c\/b\u003e ; total range of motion for footvolley, beach handball, beach soccer.\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eFootvolley\u003c\/span\u003e\u003cspan\u003eBeach handball\u003c\/span\u003e\u003cspan\u003eBeach soccer\u003c\/span\u003e\u003cspan\u003eBeach rugby\u003c\/span\u003e\u003cspan\u003eBeach ultimate\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 \/ Training\u003c\/div\u003e\n        \u003ch4\u003eBeach \u003cspan class=\"ital\"\u003efitness\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eDries in minutes\u003c\/b\u003e between sets ; stays fresh from sunrise runs to sunset workouts.\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eBeach running\u003c\/span\u003e\u003cspan\u003eSand workouts\u003c\/span\u003e\u003cspan\u003eHIIT\u003c\/span\u003e\u003cspan\u003eCrossFit beach\u003c\/span\u003e\u003cspan\u003eYoga\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 \/ Lifestyle\u003c\/div\u003e\n        \u003ch4\u003eOff \u003cspan class=\"ital\"\u003eduty\u003c\/span\u003e\n\u003c\/h4\u003e\n        \u003cp class=\"uc-benefit\"\u003e\u003cb\u003eSoft-touch Microsense\u003c\/b\u003e ; wears like a premium tee from beach club to dinner.\u003c\/p\u003e\n        \u003cdiv class=\"uc-tags\"\u003e\n\u003cspan\u003eBeach club\u003c\/span\u003e\u003cspan\u003eBoardwalk\u003c\/span\u003e\u003cspan\u003eTravel\u003c\/span\u003e\u003cspan\u003eResort wear\u003c\/span\u003e\u003cspan\u003eFestival\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\"\u003eGRS Certified\u003c\/div\u003e\n          \u003cdiv class=\"meta\"\u003eGlobal Recycle Standard\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® · ZDHC\u003c\/div\u003e\n          \u003cdiv class=\"meta\"\u003eISO 14001 · Audited supply chain\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\u003eHow light is The Beach Shirt, really?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003e\n\u003cstrong\u003e95 g\/m²\u003c\/strong\u003e. That's less than half the weight of a standard performance tee and about a third of a rashguard. The honeycomb knit structure removes mass without losing strength ; you'll feel the difference the moment you put it on.\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eWhat is the honeycomb knit and why does it matter?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eIt's a hexagonal mesh structure woven into the fabric itself ; \u003cstrong\u003enot a print, not a perforation\u003c\/strong\u003e. The open cells let fresh air flow in and humid air escape, exactly like a breeze passing through an open window. On the sand at 35 °C, the difference is night and day.\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eCan I print my own logo on the beach shirt?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eEven better; you can \u003cstrong\u003ebuild your beach shirt 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 beach shirt 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\u003eWhat is it made of?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003e\n\u003cstrong\u003e100% recycled polyester\u003c\/strong\u003e from SITIP's NATIVE range ; pre- and post-consumer recycled yarn, GRS certified, produced with low-impact chemistry and reduced non-renewable energy. The same fabric is then finished with \u003cstrong\u003eMICROSENSE\u003c\/strong\u003e technology for a silk-like next-to-skin feel and superior moisture-wicking.\u003c\/div\u003e\n      \u003c\/details\u003e\n      \u003cdetails class=\"faq-item\" data-anim=\"rise\"\u003e\n        \u003csummary\u003eWhat sports is it best for?\u003c\/summary\u003e\n        \u003cdiv class=\"answer\"\u003eEngineered for \u003cstrong\u003ebeach volley, beach tennis, footvolley, beach handball, beach soccer, beach running\u003c\/strong\u003e and any sport where ventilation and ultralight feel matter more than thickness or compression. It also works beautifully off-duty as a premium beach \u0026amp; resort tee.\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 regular sport fit of this model.\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 (NATIVE LINDA) 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\"\u003eMachine wash cold (30°C) on a gentle cycle, no fabric softener, no tumble dry. \u003cstrong\u003eNo ironing required\u003c\/strong\u003e — MICROSENSE technology keeps the fabric smooth on its own. Hang to dry; it'll be ready in minutes.\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\": \"The Beach Shirt\",\n    \"description\": \"Ultralight 95 g\/m² honeycomb-knit jersey for beach volley, beach tennis and beach sports. 100% recycled polyester (SITIP NATIVE LINDA) with MICROSENSE soft-touch finish. Custom printable from 1 piece. Made in Italy.\",\n    \"category\": \"Sportswear \/ Beach Sports\",\n    \"brand\": { \"@type\": \"Brand\", \"name\": \"Inferno Beachwear\" },\n    \"material\": \"100% Recycled Polyester (PLR) · SITIP NATIVE LINDA · MICROSENSE\",\n    \"weight\": { \"@type\": \"QuantitativeValue\", \"value\": 95, \"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\": \"How light is The Beach Shirt, really?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"95 g\/m². That is less than half the weight of a standard performance tee and about a third of a rashguard. The honeycomb knit structure removes mass without losing strength.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"What is the honeycomb knit and why does it matter?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"A hexagonal mesh structure woven into the fabric itself, not a print or perforation. The open cells let fresh air flow in and humid air escape, like a breeze through an open window.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"Can I print my own logo on the beach shirt?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"Yes. You can build your beach shirt 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.\"\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 beach shirt or a full team kit of 50+ pieces. Bulk discounts apply automatically from 3 pieces upwards.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"What is it made of?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"100% recycled polyester from SITIP's NATIVE range; pre- and post-consumer recycled yarn, GRS certified, produced with low-impact chemistry and reduced non-renewable energy. Finished with MICROSENSE technology for a silk-like next-to-skin feel and superior moisture-wicking.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"What sports is it best for?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"Engineered for beach volley, beach tennis, footvolley, beach handball, beach soccer, beach running and any sport where ventilation and ultralight feel matter more than thickness or compression.\"\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.\"\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 regular sport fit of this model.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"Where is it made?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"Entirely produced in Italy. Fabric (NATIVE LINDA) is woven by SITIP in Bergamo, then cut, sewn, printed and finished in our facility in Parma.\"\n        }\n      },\n      {\n        \"@type\": \"Question\",\n        \"name\": \"How do I care for The Beach Shirt?\",\n        \"acceptedAnswer\": {\n          \"@type\": \"Answer\",\n          \"text\": \"Machine wash cold (30°C) on a gentle cycle, no fabric softener, no tumble dry. No ironing required thanks to MICROSENSE technology. Hang to dry.\"\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\u003eThe Beach Shirt\u003c\/span\u003e\n      \u003cspan\u003e95 g\/m² Ultralight\u003c\/span\u003e\n      \u003cspan\u003eHoneycomb Knit\u003c\/span\u003e\n      \u003cspan\u003eNATIVE Recycled Yarn\u003c\/span\u003e\n      \u003cspan\u003eMICROSENSE Soft Touch\u003c\/span\u003e\n      \u003cspan\u003eMade in Italy\u003c\/span\u003e\n      \u003cspan\u003eThe Beach Shirt\u003c\/span\u003e\n      \u003cspan\u003e95 g\/m² Ultralight\u003c\/span\u003e\n      \u003cspan\u003eHoneycomb Knit\u003c\/span\u003e\n      \u003cspan\u003eNATIVE Recycled Yarn\u003c\/span\u003e\n      \u003cspan\u003eMICROSENSE Soft Touch\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":58370053767555,"sku":"TT-XS","price":56.81,"currency_code":"USD","in_stock":true},{"title":"S","offer_id":58370053800323,"sku":"TT-S","price":56.81,"currency_code":"USD","in_stock":true},{"title":"M","offer_id":58370053833091,"sku":"TT-M","price":56.81,"currency_code":"USD","in_stock":true},{"title":"L","offer_id":58370053865859,"sku":"TT-L","price":56.81,"currency_code":"USD","in_stock":true},{"title":"XL","offer_id":58370053898627,"sku":"TT-XL","price":56.81,"currency_code":"USD","in_stock":true},{"title":"XXL","offer_id":58370053931395,"sku":"TT-XXL","price":56.81,"currency_code":"USD","in_stock":true},{"title":"3XL","offer_id":58370053964163,"sku":"TT-3XL","price":56.81,"currency_code":"USD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0988\/4323\/0595\/files\/8532bebf024caec31b173fee289003ae.jpg?v=1782905270","url":"https:\/\/infernobeachwear.com\/products\/ultralight-technical-t-shirt-reef-quarter","provider":"Inferno Beachwear","version":"1.0","type":"link"}