{"id":156471,"date":"2021-12-07T13:48:05","date_gmt":"2021-12-07T12:48:05","guid":{"rendered":"https:\/\/bikefinder.com\/ny-shop\/"},"modified":"2026-11-03T01:20:54","modified_gmt":"2026-11-03T00:20:54","slug":"buy","status":"publish","type":"page","link":"https:\/\/bikefinder.com\/fi\/buy\/","title":{"rendered":"Osta py\u00f6r\u00e4npaikannin"},"content":{"rendered":"\n<script>\/* Run before the page content can paint; keep native products available on failure. *\/\n(function () {\n    const page = document.documentElement;\n    page.classList.add('bf-buy-loading');\n    window.setTimeout(function () {\n        const root = document.querySelector('.bf-buy');\n        if (root && !root.classList.contains('is-ready')) {\n            page.classList.remove('bf-buy-loading');\n            root.querySelector('.bf-buy-initial-error').hidden = false;\n        }\n    }, 25000);\n})();\n<\/script>\n<style>.bf-buy {\n    --ink: #182b38;\n    --muted: #60707c;\n    --line: #dce3e8;\n    --blue: #0075b9;\n    --wash: #eff7fc;\n    --paper: #f8f9fb;\n    --radius: 14px;\n    background: var(--paper);\n    color: var(--ink);\n    font:\n        14px\/1.6 'Open Sans',\n        Arial,\n        sans-serif;\n    padding: 52px max(24px, calc((100% - 1240px) \/ 2)) 64px;\n    isolation: isolate;\n}\n.bf-buy [hidden] {\n    display: none !important;\n}\n.bf-buy .bf-buy-app {\n    display: none;\n    max-width: 1240px;\n    margin: auto;\n}\n.bf-buy.is-ready .bf-buy-app {\n    display: block;\n}\n.bf-buy.is-ready .bf-buy-fallback {\n    display: none;\n}\n.bf-buy-loading .bf-buy .bf-buy-fallback {\n    display: none;\n}\n.bf-buy .bf-buy-loading-message {\n    display: none;\n    max-width: 1240px;\n    min-height: max(600px, 100vh);\n    min-height: max(600px, 100svh);\n    margin: auto;\n    color: var(--muted);\n}\n.bf-buy-loading .bf-buy .bf-buy-loading-message {\n    display: block;\n}\n.bf-buy .bf-buy-fallback {\n    max-width: 1240px;\n    margin: auto;\n}\n.bf-buy .bf-source-trackers li.product img {\n    width: 75px;\n    max-width: 75px;\n    height: auto;\n}\n.bf-buy .bf-buy-native-plan {\n    border: 1px solid #dce3e8;\n    border-radius: 10px;\n    background: #fff;\n    padding: 18px;\n    margin: 10px 0;\n}\n.bf-buy .bf-buy-alert,\n.bf-buy .bf-buy-initial-error {\n    max-width: 1240px;\n    margin: 0 auto 20px;\n    font-size: 13px;\n    color: #a73232;\n}\n.bf-buy .bf-buy-cart-note {\n    margin-top: 16px;\n    padding: 12px 14px;\n    border-radius: 9px;\n    background: #eaf1f5;\n    font-size: 11px;\n}\n.bf-buy .bf-buy-cart-note a {\n    color: #0075b9;\n}\n.bf-buy .bf-buy-cart-note button {\n    background: none;\n    padding: 0;\n    color: #0075b9;\n    text-decoration: underline;\n    margin-top: 5px;\n    font-size: 11px;\n}\n.bf-buy .billing-choices .billed * {\n    font: inherit;\n    color: inherit;\n}\n.bf-buy .billing-choices .billed p {\n    display: inline;\n}\n.bf-buy .primary:disabled {\n    opacity: 0.6;\n    cursor: wait;\n}\n.bf-buy .primary[aria-disabled='true'] {\n    opacity: 0.6;\n    cursor: not-allowed;\n}\n.bf-buy .bf-buy-busy {\n    font-size: 11px;\n    color: #60707c;\n    text-align: center;\n    margin-top: 10px;\n}\n@media (max-width: 760px) {\n    .bf-buy {\n        padding: 30px 20px 120px;\n    }\n    .bf-buy .bf-buy-app {\n        margin: 0;\n    }\n    .bf-buy .mobile-checkout {\n        font:\n            14px\/1.6 'Open Sans',\n            Arial,\n            sans-serif;\n    }\n}\n\n.bf-buy {\n    --ink: #182b38;\n    --muted: #60707c;\n    --line: #dce3e8;\n    --blue: #0075b9;\n    --wash: #eff7fc;\n    --paper: #f8f9fb;\n    --radius: 14px;\n}\n.bf-buy * {\n    box-sizing: border-box;\n}\n.bf-buy h1,\n.bf-buy h2,\n.bf-buy h3,\n.bf-buy strong,\n.bf-buy button,\n.bf-buy .price {\n    font-family: Montserrat, Arial, sans-serif;\n    font-weight: 600;\n}\n.bf-buy h1,\n.bf-buy h2,\n.bf-buy h3,\n.bf-buy p {\n    margin: 0;\n}\n.bf-buy button,\n.bf-buy input,\n.bf-buy select {\n    font: inherit;\n    color: inherit;\n}\n.bf-buy button,\n.bf-buy a,\n.bf-buy label,\n.bf-buy select {\n    -webkit-tap-highlight-color: transparent;\n}\n.bf-buy button,\n.bf-buy select,\n.bf-buy summary {\n    cursor: pointer;\n}\n.bf-buy a {\n    color: inherit;\n    text-underline-offset: 4px;\n}\n.bf-buy button {\n    border: 0;\n}\n.bf-buy :focus-visible {\n    outline: 3px solid #0075b9;\n    outline-offset: 4px;\n}\n.bf-buy [hidden] {\n    display: none !important;\n}\n.bf-buy svg {\n    display: block;\n    width: 22px;\n    height: 22px;\n    fill: none;\n    stroke: currentColor;\n    stroke-width: 1.6;\n    stroke-linecap: round;\n    stroke-linejoin: round;\n    flex-shrink: 0;\n}\n.bf-buy .svg-library,\n.bf-buy .sr-only {\n    position: absolute;\n    width: 1px;\n    height: 1px;\n    padding: 0;\n    overflow: hidden;\n    clip-path: inset(50%);\n    white-space: nowrap;\n}\n.bf-buy .buy-layout {\n    display: grid;\n    grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr);\n    gap: clamp(40px, 6vw, 88px);\n    align-items: start;\n}\n.bf-buy .eyebrow {\n    text-transform: uppercase;\n    letter-spacing: 0.16em;\n    font-size: 10px;\n    color: var(--blue);\n    margin-bottom: 17px;\n    font-weight: 600;\n}\n.bf-buy h1 {\n    font-size: clamp(40px, 4.4vw, 61px);\n    letter-spacing: -2.6px;\n    line-height: 1.08;\n    margin-bottom: 20px;\n}\n.bf-buy .intro {\n    color: var(--muted);\n    max-width: 415px;\n    font-size: 15px;\n    line-height: 1.8;\n}\n.bf-buy .product-stage {\n    position: relative;\n    margin-top: 28px;\n    height: 460px;\n    overflow: hidden;\n    border-radius: 18px;\n    background: #f0f1f2;\n    isolation: isolate;\n}\n.bf-buy .stage-top {\n    position: absolute;\n    z-index: 2;\n    top: 22px;\n    left: 24px;\n    display: grid;\n    gap: 3px;\n}\n.bf-buy .stage-top strong {\n    font-size: 14px;\n}\n.bf-buy .stage-top small {\n    color: var(--muted);\n    font-size: 10px;\n}\n.bf-buy .product-stage::before {\n    content: '';\n    position: absolute;\n    width: 330px;\n    height: 330px;\n    border: 1px solid #d6dde2;\n    border-radius: 50%;\n    top: 52px;\n    left: calc(50% - 165px);\n}\n.bf-buy .product-stage::after {\n    content: '';\n    position: absolute;\n    width: 235px;\n    height: 235px;\n    border: 1px solid #dce2e6;\n    border-radius: 50%;\n    top: 100px;\n    left: calc(50% - 118px);\n    z-index: -1;\n}\n.bf-buy .product-photo {\n    width: 100%;\n    height: 100%;\n    object-fit: cover;\n    mix-blend-mode: multiply;\n    transition: opacity 0.2s;\n}\n.bf-buy .product-stage[data-model='g1'] .product-photo,\n.bf-buy .product-stage[data-model='fahrradfinden'] .product-photo {\n    object-fit: contain;\n    padding: 55px 15px 45px;\n}\n.bf-buy .stage-caption {\n    position: absolute;\n    z-index: 2;\n    bottom: 20px;\n    left: 24px;\n    right: 24px;\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    gap: 12px;\n    font-size: 10px;\n    color: var(--muted);\n}\n.bf-buy .stage-tag {\n    border: 1px solid #ccd8df;\n    border-radius: 20px;\n    padding: 5px 10px;\n    display: inline-flex;\n    align-items: center;\n    gap: 6px;\n    color: var(--ink);\n    background: #f5f6f7;\n}\n.bf-buy .stage-tag svg {\n    width: 13px;\n    height: 13px;\n    color: var(--blue);\n}\n.bf-buy .feature-strip {\n    display: grid;\n    grid-template-columns: repeat(3, 1fr);\n    gap: 12px;\n    padding: 22px 0 0;\n}\n.bf-buy .feature {\n    display: flex;\n    align-items: center;\n    gap: 9px;\n    font-size: 11px;\n}\n.bf-buy .feature svg {\n    color: var(--blue);\n    width: 20px;\n    height: 20px;\n}\n.bf-buy .product-details {\n    margin-top: 25px;\n    border-top: 1px solid var(--line);\n    font-size: 12px;\n}\n.bf-buy details {\n    border-bottom: 1px solid var(--line);\n}\n.bf-buy summary {\n    padding: 15px 0;\n    list-style: none;\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    font-weight: 600;\n}\n.bf-buy summary::-webkit-details-marker {\n    display: none;\n}\n.bf-buy summary::after {\n    content: '+';\n    font-size: 19px;\n    font-weight: 400;\n}\n.bf-buy details[open] summary::after {\n    content: '\u2212';\n}\n.bf-buy details p {\n    padding: 0 0 18px;\n    color: var(--muted);\n}\n.bf-buy .configurator {\n    padding-top: 2px;\n}\n.bf-buy .config-title {\n    font-size: 27px;\n    letter-spacing: -0.7px;\n    margin-bottom: 5px;\n}\n.bf-buy .config-subtitle {\n    font-size: 12px;\n    color: var(--muted);\n}\n.bf-buy .hardware-row {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    margin: 22px 0 10px;\n    padding-bottom: 16px;\n    border-bottom: 1px solid var(--line);\n    gap: 12px;\n}\n.bf-buy .hardware-info {\n    display: flex;\n    align-items: center;\n    gap: 11px;\n}\n.bf-buy .hardware-icon {\n    display: grid;\n    place-items: center;\n    width: 36px;\n    height: 36px;\n    background: #eaf1f5;\n    border-radius: 9px;\n    color: var(--blue);\n}\n.bf-buy .hardware-info strong {\n    font-size: 13px;\n}\n.bf-buy .hardware-info small {\n    display: block;\n    font-size: 10px;\n    color: var(--muted);\n}\n.bf-buy .hardware-price {\n    font-size: 15px;\n    white-space: nowrap;\n}\n.bf-buy .owner-toggle {\n    width: fit-content;\n    display: flex;\n    align-items: center;\n    gap: 7px;\n    color: var(--muted);\n    font-size: 11px;\n    cursor: pointer;\n}\n.bf-buy input[type='checkbox'] {\n    accent-color: var(--blue);\n    width: 15px;\n    height: 15px;\n    margin: 0;\n    flex-shrink: 0;\n}\n.bf-buy fieldset {\n    border: 0;\n    padding: 0;\n    margin: 24px 0 0;\n    min-width: 0;\n}\n.bf-buy legend {\n    width: 100%;\n    padding: 0;\n    font-family: Montserrat, sans-serif;\n    font-weight: 600;\n    font-size: 13px;\n    margin-bottom: 12px;\n    display: flex;\n    align-items: center;\n    gap: 9px;\n}\n.bf-buy .step {\n    color: var(--muted);\n    width: 19px;\n    height: 19px;\n    display: inline-grid;\n    place-items: center;\n    font-size: 10px;\n    border: 1px solid #c9d3da;\n    border-radius: 50%;\n}\n.bf-buy .choices {\n    display: grid;\n    grid-template-columns: 1fr 1fr;\n    gap: 10px;\n}\n.bf-buy .choice {\n    position: relative;\n    cursor: pointer;\n}\n.bf-buy .choice input {\n    position: absolute;\n    inset: 0;\n    width: 100%;\n    height: 100%;\n    margin: 0;\n    opacity: 0;\n    z-index: 1;\n    cursor: pointer;\n}\n.bf-buy .choice-face {\n    height: 100%;\n    border: 1px solid #cdd8e0;\n    border-radius: 10px;\n    padding: 15px 13px;\n    display: grid;\n    grid-template-columns: 1fr 15px;\n    align-items: start;\n    column-gap: 5px;\n    background: #fff;\n    transition:\n        border-color 0.15s,\n        background 0.15s;\n}\n.bf-buy .choice:hover .choice-face {\n    border-color: var(--blue);\n}\n.bf-buy .choice input:checked + .choice-face {\n    border: 2px solid var(--blue);\n    padding: 14px 12px;\n    background: var(--wash);\n}\n.bf-buy .choice input:focus-visible + .choice-face {\n    outline: 3px solid var(--blue);\n    outline-offset: 3px;\n}\n.bf-buy .choice input:disabled {\n    cursor: not-allowed;\n}\n.bf-buy .choice input:disabled + .choice-face {\n    opacity: 0.55;\n    background: #edf0f2;\n}\n.bf-buy .choice-face strong {\n    display: block;\n    font-size: 12px;\n}\n.bf-buy .choice-face small {\n    font-size: 10px;\n    color: var(--muted);\n    display: block;\n    margin-top: 5px;\n    line-height: 1.5;\n}\n.bf-buy .radio-mark {\n    border: 1px solid #b9c7d0;\n    border-radius: 50%;\n    width: 15px;\n    height: 15px;\n    margin-top: 2px;\n}\n.bf-buy input:checked + .choice-face .radio-mark {\n    border: 4px solid var(--blue);\n    background: #fff;\n}\n.bf-buy .insurance-box {\n    margin-top: 12px;\n    padding: 16px;\n    border: 1px solid #d5e4ed;\n    background: #f0f6fa;\n    border-radius: 10px;\n}\n.bf-buy .insurance-box > label {\n    display: block;\n    font-size: 11px;\n    margin-bottom: 7px;\n}\n.bf-buy .value-select {\n    width: 100%;\n    padding: 10px 12px;\n    border: 1px solid #bdced9;\n    border-radius: 7px;\n    background: #fff;\n    font-size: 12px;\n}\n.bf-buy .eligibility {\n    color: var(--muted);\n    font-size: 10px;\n    line-height: 1.7;\n    margin-top: 10px;\n}\n.bf-buy .policy-links {\n    display: flex;\n    flex-wrap: wrap;\n    gap: 14px;\n    margin-top: 7px;\n    font-size: 10px;\n    color: var(--blue);\n}\n.bf-buy .residence-check {\n    display: flex;\n    align-items: flex-start;\n    gap: 8px;\n    margin-top: 13px;\n    font-size: 11px;\n    cursor: pointer;\n}\n.bf-buy .residence-check input {\n    margin-top: 3px;\n}\n.bf-buy .market-note {\n    font-size: 10px;\n    line-height: 1.6;\n    color: var(--muted);\n    margin-top: 9px;\n}\n.bf-buy .billing-choices {\n    grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n.bf-buy .billing-choices .choice-face {\n    display: block;\n    padding: 14px 10px;\n    position: relative;\n}\n.bf-buy .billing-choices input:checked + .choice-face {\n    padding: 13px 9px;\n}\n.bf-buy .billing-choices .choice-face strong {\n    font-size: 11px;\n    margin-bottom: 9px;\n}\n.bf-buy .monthly-price {\n    font-family: Montserrat, sans-serif;\n    font-weight: 600;\n    font-size: 20px;\n    white-space: nowrap;\n    letter-spacing: -0.6px;\n}\n.bf-buy .per-month {\n    color: var(--muted);\n    font-size: 10px;\n    margin-left: 2px;\n}\n.bf-buy .choice-face .billed {\n    font-size: 9px;\n    margin-top: 7px;\n}\n.bf-buy .saving {\n    display: inline-block;\n    margin-top: 9px;\n    padding: 2px 6px;\n    border-radius: 4px;\n    background: #e7eee9;\n    color: #315841;\n    font-size: 9px;\n}\n.bf-buy .billing-note {\n    color: var(--muted);\n    font-size: 10px;\n    margin-top: 10px;\n}\n.bf-buy .accessory {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    gap: 12px;\n    border-top: 1px solid var(--line);\n    margin-top: 22px;\n    padding-top: 18px;\n    font-size: 11px;\n    cursor: pointer;\n}\n.bf-buy .accessory-copy {\n    display: flex;\n    align-items: center;\n    gap: 10px;\n}\n.bf-buy .accessory small {\n    display: block;\n    font-size: 10px;\n    color: var(--muted);\n}\n.bf-buy .accessory .price {\n    white-space: nowrap;\n    font-size: 11px;\n}\n.bf-buy .order-summary {\n    background: #fff;\n    border: 1px solid var(--line);\n    border-radius: var(--radius);\n    margin-top: 22px;\n    padding: 19px 20px;\n}\n.bf-buy .summary-line {\n    display: flex;\n    justify-content: space-between;\n    gap: 12px;\n    color: var(--muted);\n    font-size: 11px;\n}\n.bf-buy .summary-line + .summary-line {\n    margin-top: 6px;\n}\n.bf-buy .summary-line span:last-child {\n    white-space: nowrap;\n}\n.bf-buy .today-line {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    gap: 12px;\n    padding-top: 13px;\n    margin-top: 13px;\n    border-top: 1px solid var(--line);\n}\n.bf-buy .today-line strong {\n    font-size: 12px;\n}\n.bf-buy .today-line .price {\n    font-size: 24px;\n    letter-spacing: -0.5px;\n}\n.bf-buy .renewal {\n    margin-top: 5px;\n    color: var(--muted);\n    font-size: 10px;\n    text-align: right;\n}\n.bf-buy .shipping-note {\n    color: var(--muted);\n    font-size: 9px;\n    margin-top: 9px;\n    text-align: right;\n}\n.bf-buy .primary {\n    width: 100%;\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    gap: 12px;\n    background: var(--blue);\n    color: #fff;\n    border-radius: 9px;\n    padding: 16px 20px;\n    font-family: Montserrat, sans-serif;\n    font-weight: 600;\n    font-size: 13px;\n    transition: background 0.15s;\n}\n.bf-buy .primary:hover {\n    background: #005e95;\n}\n.bf-buy .primary svg {\n    width: 18px;\n    height: 18px;\n}\n.bf-buy .desktop-cta {\n    margin-top: 15px;\n}\n.bf-buy .cta-footnote {\n    text-align: center;\n    color: var(--muted);\n    font-size: 9px;\n    margin-top: 9px;\n}\n.bf-buy .inline-error {\n    color: #a73232;\n    font-size: 11px;\n    margin-top: 12px;\n}\n.bf-buy .mobile-checkout {\n    display: none;\n}\n.bf-buy .how-section {\n    border-top: 1px solid var(--line);\n    padding-top: 50px;\n    margin-top: 58px;\n}\n.bf-buy .section-intro {\n    display: flex;\n    align-items: baseline;\n    justify-content: space-between;\n    gap: 20px;\n    margin-bottom: 25px;\n}\n.bf-buy .section-intro h2 {\n    font-size: 25px;\n    letter-spacing: -0.6px;\n}\n.bf-buy .section-intro p {\n    color: var(--muted);\n    font-size: 12px;\n}\n.bf-buy .how-grid {\n    display: grid;\n    grid-template-columns: repeat(3, 1fr);\n    gap: 28px;\n}\n.bf-buy .how-card {\n    padding: 24px;\n    background: #fff;\n    border: 1px solid var(--line);\n    border-radius: var(--radius);\n}\n.bf-buy .how-number {\n    color: var(--blue);\n    font-size: 10px;\n    letter-spacing: 0.1em;\n}\n.bf-buy .how-card h3 {\n    font-size: 15px;\n    margin: 11px 0 9px;\n}\n.bf-buy .how-card p {\n    color: var(--muted);\n    font-size: 12px;\n}\n.bf-buy .faq-section {\n    margin: 50px auto 0;\n    max-width: 720px;\n}\n.bf-buy .faq-section h2 {\n    font-size: 25px;\n    letter-spacing: -0.6px;\n    margin-bottom: 18px;\n}\n.bf-buy .faq-section details {\n    font-size: 12px;\n}\n@media (min-width: 1021px) {\n    .bf-buy .product-column {\n        position: sticky;\n        top: 28px;\n    }\n}\n@media (max-width: 1150px) {\n    .bf-buy .buy-layout {\n        gap: 38px;\n    }\n    .bf-buy .monthly-price {\n        font-size: 18px;\n    }\n}\n@media (max-width: 1020px) {\n    .bf-buy .buy-layout {\n        gap: 28px;\n    }\n    .bf-buy h1 {\n        font-size: 44px;\n    }\n    .bf-buy .product-stage {\n        height: 375px;\n    }\n    .bf-buy .feature-strip {\n        grid-template-columns: 1fr;\n        gap: 10px;\n    }\n    .bf-buy .config-title {\n        font-size: 23px;\n    }\n    .bf-buy .choice-face strong {\n        font-size: 11px;\n    }\n    .bf-buy .billing-choices .choice-face strong {\n        font-size: 10px;\n    }\n    .bf-buy .monthly-price {\n        font-size: 16px;\n    }\n    .bf-buy .billing-choices .choice-face {\n        padding: 12px 7px;\n    }\n    .bf-buy .billing-choices input:checked + .choice-face {\n        padding: 11px 6px;\n    }\n}\n@media (max-width: 760px) {\n    .bf-buy .buy-layout {\n        grid-template-columns: 1fr;\n        gap: 34px;\n    }\n    .bf-buy h1 {\n        font-size: clamp(39px, 10vw, 56px);\n        letter-spacing: -1.9px;\n    }\n    .bf-buy .eyebrow {\n        margin-bottom: 13px;\n        font-size: 9px;\n    }\n    .bf-buy .intro {\n        font-size: 13px;\n        max-width: 430px;\n    }\n    .bf-buy .product-stage {\n        height: 290px;\n        margin-top: 22px;\n    }\n    .bf-buy .product-stage::before {\n        width: 235px;\n        height: 235px;\n        top: 28px;\n        left: calc(50% - 118px);\n    }\n    .bf-buy .product-stage::after {\n        width: 180px;\n        height: 180px;\n        top: 55px;\n        left: calc(50% - 90px);\n    }\n    .bf-buy .stage-top {\n        top: 16px;\n        left: 18px;\n    }\n    .bf-buy .stage-top strong {\n        font-size: 12px;\n    }\n    .bf-buy .stage-caption {\n        left: 18px;\n        right: 18px;\n        bottom: 16px;\n        font-size: 9px;\n    }\n    .bf-buy .feature-strip {\n        grid-template-columns: repeat(3, 1fr);\n        gap: 8px;\n        padding-top: 18px;\n    }\n    .bf-buy .feature {\n        gap: 7px;\n        font-size: 9px;\n    }\n    .bf-buy .feature svg {\n        width: 17px;\n        height: 17px;\n    }\n    .bf-buy .product-details {\n        display: none;\n    }\n    .bf-buy .config-title {\n        font-size: 25px;\n    }\n    .bf-buy .choice-face strong {\n        font-size: 12px;\n    }\n    .bf-buy .billing-choices .choice-face {\n        padding: 14px 10px;\n    }\n    .bf-buy .billing-choices input:checked + .choice-face {\n        padding: 13px 9px;\n    }\n    .bf-buy .billing-choices .choice-face strong {\n        font-size: 11px;\n    }\n    .bf-buy .monthly-price {\n        font-size: 19px;\n    }\n    .bf-buy .desktop-cta,\n    .bf-buy .cta-footnote {\n        display: none;\n    }\n    .bf-buy .mobile-checkout {\n        display: flex;\n        align-items: center;\n        justify-content: space-between;\n        gap: 16px;\n        padding: 12px 20px calc(12px + env(safe-area-inset-bottom)) 56px;\n        position: fixed;\n        bottom: 0;\n        left: 0;\n        right: 0;\n        z-index: 4;\n        background: #ffffffef;\n        backdrop-filter: blur(12px);\n        border-top: 1px solid var(--line);\n    }\n    .bf-buy .mobile-total {\n        flex-shrink: 0;\n    }\n    .bf-buy .mobile-total small {\n        color: var(--muted);\n        font-size: 9px;\n        display: block;\n    }\n    .bf-buy .mobile-total strong {\n        font-size: 18px;\n    }\n    .bf-buy .mobile-checkout .primary {\n        width: auto;\n        flex: 1;\n        max-width: 245px;\n        padding: 14px 16px;\n        font-size: 11px;\n    }\n    .bf-buy .how-section {\n        margin-top: 38px;\n        padding-top: 32px;\n    }\n    .bf-buy .section-intro {\n        display: block;\n    }\n    .bf-buy .section-intro p {\n        margin-top: 7px;\n    }\n    .bf-buy .how-grid {\n        grid-template-columns: 1fr;\n        gap: 12px;\n    }\n    .bf-buy .how-card {\n        padding: 20px;\n    }\n    .bf-buy .how-card h3 {\n        margin-top: 7px;\n    }\n    .bf-buy .faq-section {\n        margin-top: 35px;\n    }\n}\n@media (max-width: 360px) {\n    .bf-buy .monthly-price {\n        font-size: 17px;\n    }\n    .bf-buy .billing-choices .choice-face {\n        padding: 12px 7px;\n    }\n    .bf-buy .billing-choices input:checked + .choice-face {\n        padding: 11px 6px;\n    }\n    .bf-buy .feature {\n        font-size: 8px;\n    }\n    .bf-buy .stage-caption {\n        font-size: 8px;\n        gap: 8px;\n    }\n}\n@media (prefers-reduced-motion: reduce) {\n    .bf-buy * {\n        transition: none !important;\n    }\n}\n\n\/* Approved compact builder, scoped to page content. *\/\n\/* Page-content study. Existing prototype header and footer are retained. *\/\n.bf-buy .config-title {\n    font-size: 28px;\n    line-height: 1.25;\n}\n.bf-buy .purchase-mode {\n    display: grid;\n    grid-template-columns: 1fr 1fr;\n    gap: 8px;\n    margin: 20px 0 0;\n}\n.bf-buy .purchase-mode legend {\n    font:\n        12px\/1.5 'Open Sans',\n        sans-serif;\n    color: var(--muted);\n    margin-bottom: 8px;\n}\n.bf-buy .mode-choice {\n    position: relative;\n    cursor: pointer;\n}\n.bf-buy .mode-choice input {\n    position: absolute;\n    inset: 0;\n    opacity: 0;\n    width: 100%;\n    height: 100%;\n    margin: 0;\n    cursor: pointer;\n}\n.bf-buy .mode-choice span {\n    display: block;\n    padding: 12px 10px;\n    border: 1px solid var(--line);\n    border-radius: 8px;\n    background: #fff;\n    font-size: 12px;\n    text-align: center;\n}\n.bf-buy .mode-choice input:checked + span {\n    border-color: var(--blue);\n    background: var(--wash);\n    color: var(--blue);\n    box-shadow: inset 0 0 0 1px var(--blue);\n}\n.bf-buy .mode-choice input:focus-visible + span {\n    outline: 3px solid var(--blue);\n    outline-offset: 3px;\n}\n.bf-buy .owner-note {\n    margin-top: 14px;\n    color: var(--muted);\n    font-size: 12px;\n}\n.bf-buy .hardware-row {\n    margin-top: 18px;\n}\n.bf-buy .choices > .choice-face {\n    min-width: 0;\n}\n.bf-buy .choice-face strong {\n    font-size: 13px;\n}\n.bf-buy .choice-face small {\n    font-size: 12px;\n    line-height: 1.5;\n}\n.bf-buy .choice-face {\n    padding: 15px 12px;\n}\n.bf-buy .choice input:checked + .choice-face {\n    padding: 14px 11px;\n}\n.bf-buy .choices.tracking-only {\n    grid-template-columns: 1fr;\n}\n.bf-buy .choices.tracking-only .choice:last-child {\n    display: none;\n}\n.bf-buy .market-note {\n    font-size: 12px;\n}\n.bf-buy .billing-choices .choice-face {\n    display: flex;\n    flex-direction: column;\n    gap: 8px;\n    padding: 16px 12px;\n}\n.bf-buy .billing-choices input:checked + .choice-face {\n    padding: 15px 11px;\n}\n.bf-buy .billing-choices .choice-face strong {\n    font-size: 12px;\n    margin: 0;\n}\n.bf-buy .charge-price {\n    font:\n        600 23px\/1.25 Montserrat,\n        sans-serif;\n    letter-spacing: -0.6px;\n    white-space: nowrap;\n}\n.bf-buy .billing-choices .charge-frequency {\n    font-size: 11px;\n    color: var(--muted);\n}\n.bf-buy .billing-choices .equivalent {\n    font-size: 12px;\n    color: var(--muted);\n}\n.bf-buy .billing-choices .saving {\n    align-self: flex-start;\n    margin: 0;\n    font-size: 10px;\n}\n.bf-buy .billing-note,\n.bf-buy .value-hint {\n    font-size: 12px;\n    line-height: 1.6;\n}\n.bf-buy .value-hint {\n    margin: 8px 0 12px;\n    color: var(--muted);\n}\n.bf-buy .value-select {\n    font-size: 14px;\n    min-height: 46px;\n}\n.bf-buy .eligibility,\n.bf-buy .policy-links,\n.bf-buy .residence-check {\n    font-size: 12px;\n}\n.bf-buy .residence-check {\n    padding: 10px;\n    background: #fff;\n    border: 1px solid var(--line);\n    border-radius: 7px;\n}\n.bf-buy .accessory {\n    font-size: 12px;\n    min-height: 56px;\n}\n.bf-buy .accessory small {\n    font-size: 11px;\n}\n.bf-buy .summary-line {\n    font-size: 12px;\n}\n.bf-buy .renewal {\n    font-size: 12px;\n    text-align: left;\n    margin-top: 12px;\n}\n.bf-buy .shipping-note {\n    font-size: 11px;\n    text-align: left;\n}\n.bf-buy .today-line strong {\n    font-size: 14px;\n}\n.bf-buy .today-line .price {\n    font-size: 26px;\n}\n.bf-buy .fit-range {\n    color: var(--blue);\n    font-size: 12px;\n    white-space: nowrap;\n    margin-left: auto;\n    margin-right: 14px;\n}\n.bf-buy .product-details summary {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n}\n.bf-buy .product-details summary::after {\n    flex-shrink: 0;\n}\n.bf-buy .inline-error {\n    font-size: 12px;\n}\n@media (max-width: 760px) {\n    .bf-buy {\n        margin-top: 24px;\n    }\n    .bf-buy .buy-layout {\n        gap: 24px;\n    }\n    .bf-buy h1 {\n        font-size: 36px;\n        line-height: 1.14;\n        letter-spacing: -1.3px;\n    }\n    .bf-buy .eyebrow {\n        margin-bottom: 10px;\n    }\n    .bf-buy .intro {\n        margin-top: 12px;\n        font-size: 12px;\n        line-height: 1.6;\n    }\n    .bf-buy .product-stage {\n        height: 185px;\n        margin-top: 18px;\n    }\n    .bf-buy .product-photo {\n        display: block;\n        width: auto;\n        max-width: 100%;\n        margin: 0 auto;\n        object-fit: contain;\n        object-position: center;\n        mask-image: linear-gradient(90deg, transparent, #000 20%, #000 80%, transparent);\n    }\n    .bf-buy .product-stage[data-model='g1'] .product-photo,\n    .bf-buy .product-stage[data-model='fahrradfinden'] .product-photo {\n        padding: 14px 0;\n    }\n    .bf-buy .product-stage::before {\n        width: 160px;\n        height: 160px;\n        top: 13px;\n        left: calc(50% - 80px);\n    }\n    .bf-buy .product-stage::after {\n        width: 120px;\n        height: 120px;\n        top: 33px;\n        left: calc(50% - 60px);\n    }\n    .bf-buy .stage-top {\n        top: 12px;\n        left: 14px;\n    }\n    .bf-buy .stage-top strong {\n        font-size: 11px;\n    }\n    .bf-buy .stage-caption {\n        left: 14px;\n        right: 14px;\n        bottom: 12px;\n        font-size: 8px;\n    }\n    .bf-buy .stage-tag {\n        padding: 4px 7px;\n    }\n    .bf-buy .feature-strip {\n        padding-top: 14px;\n    }\n    .bf-buy .product-details {\n        display: block;\n        margin-top: 10px;\n    }\n    .bf-buy .product-details summary {\n        padding: 10px 0;\n        font-size: 12px;\n    }\n    .bf-buy .product-details p {\n        font-size: 12px;\n    }\n    .bf-buy .config-title {\n        font-size: 24px;\n    }\n    .bf-buy .choices {\n        gap: 8px;\n    }\n    .bf-buy .choice-face {\n        grid-template-columns: 1fr;\n        gap: 8px;\n        position: relative;\n    }\n    .bf-buy .choice-face .radio-mark {\n        position: absolute;\n        right: 10px;\n        top: 12px;\n    }\n    .bf-buy .choice-face strong {\n        padding-right: 17px;\n        font-size: 12px;\n    }\n    .bf-buy .choice-face small {\n        font-size: 12px;\n    }\n    .bf-buy .billing-choices {\n        grid-template-columns: 1fr;\n    }\n    .bf-buy .billing-choices .choice-face {\n        display: grid;\n        grid-template-columns: minmax(0, 1fr) auto;\n        column-gap: 12px;\n        row-gap: 3px;\n        align-items: center;\n        padding: 13px 14px;\n    }\n    .bf-buy .billing-choices input:checked + .choice-face {\n        padding: 12px 13px;\n    }\n    .bf-buy .billing-choices .choice-face strong {\n        font-size: 13px;\n        padding-right: 0;\n    }\n    .bf-buy .charge-price {\n        font-size: 23px;\n        grid-column: 2;\n        grid-row: 1 \/ span 2;\n        text-align: right;\n    }\n    .bf-buy .billing-choices .charge-frequency {\n        grid-column: 1;\n        grid-row: 2;\n    }\n    .bf-buy .billing-choices .equivalent {\n        grid-column: 1;\n        grid-row: 3;\n        font-size: 11px;\n    }\n    .bf-buy .billing-choices .saving {\n        grid-column: 2;\n        grid-row: 3;\n        justify-self: end;\n    }\n    .bf-buy .desktop-cta,\n    .bf-buy .cta-footnote {\n        display: flex;\n    }\n    .bf-buy .cta-footnote {\n        justify-content: center;\n        font-size: 11px;\n    }\n    .bf-buy .order-summary {\n        padding: 18px 16px;\n    }\n}\n@media (max-width: 360px) {\n    .bf-buy .stage-caption > span:last-child {\n        display: none;\n    }\n    .bf-buy .mode-choice span {\n        font-size: 11px;\n        padding: 12px 6px;\n    }\n    .bf-buy .charge-price {\n        font-size: 21px;\n    }\n}\n\n\/* Page-content sketch; original prototype navigation and footer are retained. *\/\n.bf-buy .product-column {\n    position: static;\n}\n.bf-buy .gallery-stage {\n    height: 550px;\n    overflow: hidden;\n    background: #eff0f1;\n    border-radius: 5px;\n}\n.bf-buy .gallery-stage img,\n.bf-buy .gallery-thumbnail img {\n    display: block;\n    width: 100%;\n    height: 100%;\n    object-fit: contain;\n    transform: translate(var(--pan-x, 0), var(--pan-y, 0)) scale(var(--zoom, 1));\n}\n.bf-buy .gallery-name {\n    margin: 16px 0 12px;\n    font-size: 14px;\n}\n.bf-buy .gallery-thumbnails {\n    display: flex;\n    gap: 12px;\n}\n.bf-buy .gallery-thumbnail {\n    width: 86px;\n    aspect-ratio: 1;\n    padding: 0;\n    border: 1px solid var(--line);\n    background: #eff0f1;\n    border-radius: 5px;\n    overflow: hidden;\n    cursor: pointer;\n}\n.bf-buy .gallery-thumbnail[aria-pressed='true'] {\n    border: 2px solid var(--blue);\n}\n.bf-buy .product-details {\n    margin-top: 18px;\n}\n.bf-buy .config-title {\n    font-size: 28px;\n    letter-spacing: -0.8px;\n    margin: 0;\n}\n.bf-buy .config-subtitle {\n    margin-top: 8px;\n}\n.bf-buy .setup-builder {\n    margin-top: 24px;\n}\n.bf-buy .section-label {\n    font:\n        600 13px\/1.5 Montserrat,\n        sans-serif;\n    margin-bottom: 12px;\n}\n.bf-buy .subscription-settings {\n    margin-top: 24px;\n}\n.bf-buy .plan-type {\n    font-size: 12px;\n    color: var(--muted);\n    margin-top: 12px;\n}\n.bf-buy fieldset {\n    margin: 0;\n}\n.bf-buy .billing-fieldset {\n    margin-top: 24px;\n}\n.bf-buy .hardware-row {\n    margin-top: 0;\n}\n.bf-buy .hardware-icon {\n    flex-shrink: 0;\n}\n.bf-buy .owner-controls {\n    display: flex;\n    align-items: center;\n    flex-wrap: wrap;\n    justify-content: space-between;\n    gap: 10px 18px;\n}\n.bf-buy .purchase-link {\n    padding: 0;\n    border: 0;\n    background: transparent;\n    color: var(--blue);\n    font-size: 11px;\n    text-decoration: underline;\n    text-underline-offset: 3px;\n    cursor: pointer;\n}\n.bf-buy .protection-choices {\n    grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n.bf-buy .protection-choices .choice-face {\n    height: 100%;\n    min-height: 90px;\n    border-radius: 10px;\n}\n.bf-buy .insurance-settings {\n    margin-top: 20px;\n}\n.bf-buy .tracking-requirement {\n    font-size: 11px;\n    color: var(--muted);\n    line-height: 1.6;\n    margin-top: 12px;\n}\n.bf-buy .value-heading {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    flex-wrap: wrap;\n    gap: 12px;\n}\n.bf-buy .value-heading label {\n    font-size: 13px;\n    font-weight: 600;\n}\n.bf-buy #bf-bike-value-amount {\n    color: var(--ink);\n    font:\n        600 22px\/1.4 Montserrat,\n        sans-serif;\n    white-space: nowrap;\n}\n.bf-buy .bike-value-range {\n    display: block;\n    width: 100%;\n    margin: 16px 0 0;\n    height: 36px;\n    background: transparent;\n    appearance: none;\n    cursor: pointer;\n}\n.bf-buy .bike-value-range::-webkit-slider-runnable-track {\n    height: 6px;\n    border-radius: 10px;\n    background: linear-gradient(\n        to right,\n        var(--blue) var(--value-progress, 0%),\n        #d9e2e9 var(--value-progress, 0%)\n    );\n}\n.bf-buy .bike-value-range::-moz-range-track {\n    height: 6px;\n    background: #d9e2e9;\n    border-radius: 10px;\n}\n.bf-buy .bike-value-range::-moz-range-progress {\n    height: 6px;\n    background: var(--blue);\n    border-radius: 10px;\n}\n.bf-buy .bike-value-range::-webkit-slider-thumb {\n    appearance: none;\n    width: 24px;\n    height: 24px;\n    margin-top: -9px;\n    border: 3px solid #fff;\n    border-radius: 50%;\n    background: var(--blue);\n    box-shadow:\n        0 0 0 1px var(--blue),\n        0 2px 5px #17334226;\n}\n.bf-buy .bike-value-range::-moz-range-thumb {\n    width: 18px;\n    height: 18px;\n    border: 3px solid #fff;\n    border-radius: 50%;\n    background: var(--blue);\n    box-shadow: 0 0 0 1px var(--blue);\n}\n.bf-buy .value-stops {\n    position: relative;\n    height: 30px;\n    margin: 0 12px;\n    font-size: 10px;\n    color: var(--muted);\n}\n.bf-buy .value-stop {\n    position: absolute;\n    left: var(--stop-position);\n    width: 0;\n}\n.bf-buy .value-stop::before {\n    content: '';\n    display: block;\n    width: 3px;\n    height: 5px;\n    background: #b0c0cc;\n    border-radius: 2px;\n    transform: translateX(-50%);\n}\n.bf-buy .value-stop span {\n    position: absolute;\n    top: 10px;\n    white-space: nowrap;\n    transform: translateX(-50%);\n}\n.bf-buy .value-stop:first-child span {\n    transform: translateX(-12px);\n}\n.bf-buy .value-stop:last-child span {\n    transform: translateX(calc(-100% + 12px));\n}\n.bf-buy .bike-value-picker input:focus-visible {\n    outline: 3px solid var(--blue);\n    outline-offset: 4px;\n}\n.bf-buy .eligibility {\n    margin-top: 10px;\n}\n.bf-buy .eligibility a {\n    color: var(--blue);\n    text-decoration: underline;\n    text-underline-offset: 2px;\n}\n.bf-buy .eligibility a:focus-visible {\n    outline: 2px solid var(--blue);\n    outline-offset: 3px;\n}\n.bf-buy .billing-choices {\n    gap: 8px;\n    grid-template-columns: repeat(3, minmax(0, 1fr));\n    container: billing-cards \/ inline-size;\n}\n.bf-buy .billing-choices .choice-face {\n    display: grid;\n    grid-template-columns: minmax(0, 1fr);\n    grid-template-rows: 20px 32px 32px 18px;\n    place-items: center;\n    align-content: center;\n    height: 100%;\n    min-height: 154px;\n    padding: 16px 10px;\n    border-radius: 6px;\n    gap: 7px;\n    text-align: center;\n}\n.bf-buy .billing-choices input:checked + .choice-face {\n    padding: 15px 9px;\n}\n.bf-buy .charge-price {\n    font-size: 21px;\n}\n.bf-buy .billing-choices .choice-face strong {\n    font-size: 11px;\n    grid-column: 1;\n    grid-row: 1;\n    padding: 0;\n    margin: 0;\n}\n.bf-buy .billing-choices .charge-price {\n    display: flex;\n    grid-column: 1;\n    grid-row: 2;\n    align-items: baseline;\n    align-content: center;\n    justify-content: center;\n    flex-wrap: wrap;\n    gap: 2px 3px;\n    width: 100%;\n    height: 100%;\n    line-height: 1.4;\n}\n.bf-buy .charge-number {\n    display: inline-flex;\n    align-items: baseline;\n    gap: 3px;\n    white-space: nowrap;\n}\n.bf-buy .charge-currency {\n    font-size: inherit;\n    font-weight: inherit;\n}\n.bf-buy .rate-unit {\n    font-size: 10px;\n    color: var(--muted);\n    font-weight: 400;\n    letter-spacing: 0;\n}\n.bf-buy .billing-choices .saving {\n    grid-column: 1;\n    grid-row: 4;\n    place-self: center;\n    font-size: 9px;\n    color: #315841;\n    margin: 0;\n}\n.bf-buy .billing-choices .charge-frequency {\n    grid-column: 1;\n    grid-row: 3;\n    margin: 0;\n    font-size: 10px;\n    line-height: 1.6;\n}\n.bf-buy .billing-note {\n    margin-top: 12px;\n    font-size: 10px;\n}\n.bf-buy .quote-placeholder {\n    border-top: 1px solid var(--line);\n    padding-top: 22px;\n    font-size: 12px;\n    color: var(--muted);\n}\n.bf-buy .order-summary {\n    border: 1px solid var(--line);\n    border-radius: 14px;\n    background: #fff;\n    margin-top: 24px;\n    padding: 22px 20px;\n}\n.bf-buy .today-line {\n    border-top: 1px solid var(--line);\n    padding-top: 16px;\n    margin-top: 16px;\n}\n.bf-buy .today-line .price {\n    font-size: 25px;\n}\n.bf-buy .setup-description {\n    margin-top: 10px;\n    font-size: 12px;\n    color: var(--muted);\n}\n.bf-buy .renewal,\n.bf-buy .shipping-note {\n    font-size: 11px;\n    margin-top: 8px;\n    text-align: right;\n}\n.bf-buy .order-breakdown {\n    border: 0;\n    margin-top: 10px;\n}\n.bf-buy .order-breakdown summary {\n    font-size: 11px;\n    color: var(--muted);\n    padding: 0;\n    justify-content: flex-start;\n    gap: 10px;\n    width: fit-content;\n}\n.bf-buy .order-breakdown[open] summary {\n    margin-bottom: 14px;\n}\n.bf-buy .flow-action {\n    margin-top: 22px;\n    border-radius: 6px;\n}\n.bf-buy .flow-action:disabled {\n    background: #ced7df;\n    cursor: default;\n    transform: none;\n    box-shadow: none;\n}\n.bf-buy .how-section {\n    margin-top: 70px;\n}\n.bf-buy .how-card {\n    background: transparent;\n    border: 0;\n    border-radius: 0;\n    padding: 0;\n}\n.bf-buy .how-number {\n    display: none;\n}\n.bf-buy .how-card h3 {\n    margin-top: 0;\n    font-size: 14px;\n}\n.bf-buy .how-card p {\n    font-size: 12px;\n}\n.bf-buy .faq-section {\n    margin-top: 48px;\n}\n.bf-buy .faq-section h2 {\n    font-size: 24px;\n}\n.bf-buy .faq-section summary {\n    font-size: 12px;\n}\n.bf-buy button:focus-visible {\n    outline: 3px solid var(--blue);\n    outline-offset: 4px;\n}\n@media (max-width: 760px) {\n    .bf-buy {\n        margin-top: 24px;\n    }\n    .bf-buy .buy-layout {\n        gap: 28px;\n    }\n    .bf-buy .gallery-stage {\n        height: 310px;\n    }\n    .bf-buy .gallery-name {\n        margin-top: 12px;\n    }\n    .bf-buy .gallery-thumbnails {\n        gap: 10px;\n    }\n    .bf-buy .gallery-thumbnail {\n        width: 66px;\n    }\n    .bf-buy .config-title {\n        font-size: 25px;\n    }\n    .bf-buy .billing-choices .choice-face {\n        padding: 14px 6px;\n    }\n    .bf-buy .billing-choices input:checked + .choice-face {\n        padding: 13px 5px;\n    }\n    .bf-buy .billing-choices .choice-face strong {\n        font-size: 12px;\n    }\n    .bf-buy #bf-bike-value-amount {\n        font-size: 19px;\n    }\n    .bf-buy .charge-price {\n        font-size: 18px;\n    }\n    .bf-buy .how-section {\n        margin-top: 48px;\n    }\n}\n@media (max-width: 360px) {\n    .bf-buy .gallery-stage {\n        height: 280px;\n    }\n    .bf-buy .gallery-thumbnails {\n        gap: 8px;\n    }\n    .bf-buy .gallery-thumbnail {\n        width: 60px;\n    }\n}\n@container billing-cards (max-width: 400px) {\n    .bf-buy .billing-choices .choice-face {\n        grid-template-rows: 20px 44px 32px 18px;\n        padding: 14px 6px;\n    }\n    .bf-buy .billing-choices input:checked + .choice-face {\n        padding: 13px 5px;\n    }\n    .bf-buy .charge-price {\n        font-size: 18px;\n    }\n}\n@container billing-cards (max-width: 320px) {\n    .bf-buy .charge-price {\n        font-size: 16px;\n    }\n    .bf-buy .billing-choices .choice-face strong {\n        font-size: 10px;\n    }\n}\n\n.bf-buy .sr-only {\n    position: absolute;\n    width: 1px;\n    height: 1px;\n    padding: 0;\n    margin: -1px;\n    overflow: hidden;\n    clip-path: inset(50%);\n    white-space: nowrap;\n    border: 0;\n}\n.bf-buy .hardware-icon svg {\n    width: 21px;\n    height: 21px;\n}\n.bf-buy .gallery-thumbnails {\n    flex-wrap: wrap;\n}\n.bf-buy .gallery-thumbnail {\n    flex-shrink: 0;\n}\n.bf-buy .gallery-stage img {\n    padding: 0;\n    mix-blend-mode: normal;\n}\n.bf-buy .desktop-cta {\n    display: flex;\n}\n.bf-buy .cta-footnote {\n    display: block;\n    text-align: center;\n    font-size: 10px;\n    margin-top: 10px;\n}\n.bf-buy .charge-frequency * {\n    font: inherit;\n    color: inherit;\n}\n.bf-buy .charge-frequency p {\n    display: inline;\n    margin: 0;\n}\n.bf-buy .owner-toggle input:focus-visible {\n    outline: 3px solid var(--blue);\n    outline-offset: 3px;\n}\n@media (max-width: 760px) {\n    .bf-buy {\n        padding-bottom: 64px;\n    }\n}\n\n\/* Purchase-panel presentation adapted from the Hydrogen PurchaseConfigurator.\n   Native checkboxes, radios and details retain their browser behavior. *\/\n.bf-buy {\n    --ink: #231f20;\n    --muted: #5f6265;\n    --line: #dedede;\n    --blue: #0074c8;\n    --wash: #edf6fc;\n    --paper: #f8f8f8;\n    font-family: 'Open Sans', Arial, sans-serif;\n}\n.bf-buy :is(h1, h2, h3, strong, button, .price) {\n    font-family: inherit;\n}\n.bf-buy .buy-layout {\n    grid-template-columns: minmax(0, 1fr) minmax(0, 560px);\n    gap: 48px;\n}\n.bf-buy .configurator {\n    min-width: 0;\n    padding-top: 0;\n}\n.bf-buy .configurator .purchase-category {\n    margin: 0 0 16px;\n    color: var(--muted);\n    font-size: 12px;\n}\n.bf-buy .configurator .config-title {\n    margin: 0;\n    font-size: clamp(28px, 3vw, 38px);\n    font-weight: 500;\n    line-height: 1.2;\n    letter-spacing: -0.8px;\n}\n.bf-buy .configurator .purchase-description {\n    max-width: 46ch;\n    margin: 18px 0 0;\n    color: var(--ink);\n    font-size: 16px;\n    line-height: 1.7;\n}\n.bf-buy .configurator .purchase-hint {\n    margin: 22px 0 0;\n    color: var(--muted);\n    font-size: 12px;\n}\n.bf-buy .configurator .setup-builder {\n    display: grid;\n    gap: 18px;\n    margin-top: 24px;\n}\n.bf-buy .configurator .purchase-card {\n    min-width: 0;\n    margin: 0;\n    padding: 0;\n    border: 1px solid var(--line);\n    border-radius: 18px;\n    background: #fff;\n    box-shadow: 0 12px 32px #231f2010, 0 2px 6px #231f2006;\n    overflow: hidden;\n}\n.bf-buy .configurator .purchase-card[data-selected='true'] {\n    border-color: #c8c7c7;\n}\n.bf-buy .configurator .purchase-card-header {\n    display: grid;\n    grid-template-columns: 22px minmax(0, 1fr) auto;\n    align-items: center;\n    gap: 16px;\n    width: 100%;\n    margin: 0;\n    padding: 22px 24px;\n    color: var(--ink);\n    cursor: pointer;\n    list-style: none;\n}\n.bf-buy .configurator .subscription-card > .purchase-card-header {\n    grid-template-columns: 22px minmax(0, 1fr) 16px;\n}\n.bf-buy .configurator .purchase-card-header::after,\n.bf-buy .configurator .purchase-card-header::-webkit-details-marker {\n    display: none;\n    content: none;\n}\n.bf-buy .configurator .purchase-card-header input {\n    position: relative;\n    width: 22px;\n    height: 22px;\n    margin: 0;\n    accent-color: var(--blue);\n    cursor: pointer;\n}\n.bf-buy .configurator .purchase-card-copy {\n    display: grid;\n    gap: 4px;\n    margin: 0;\n    font-weight: 400;\n    cursor: pointer;\n}\n.bf-buy .configurator .purchase-card-copy strong {\n    font-size: 16px;\n    font-weight: 600;\n    line-height: 1.4;\n    letter-spacing: -0.3px;\n}\n.bf-buy .configurator .purchase-card-copy small,\n.bf-buy .configurator .purchase-card-price small {\n    color: var(--muted);\n    font-family: inherit;\n    font-size: 12px;\n    font-style: normal;\n    font-weight: 400;\n    line-height: 1.5;\n    letter-spacing: normal;\n}\n.bf-buy .configurator .purchase-card-price {\n    display: grid;\n    gap: 5px;\n    margin: 0;\n    text-align: right;\n    font-size: 18px;\n    font-weight: 600;\n    line-height: 1.5;\n    font-variant-numeric: tabular-nums;\n    white-space: nowrap;\n}\n.bf-buy .configurator .purchase-card-price .price {\n    font-size: inherit;\n    font-weight: 600;\n}\n.bf-buy .configurator .purchase-card-chevron {\n    width: 16px;\n    height: 16px;\n    fill: none;\n    stroke: currentColor;\n    stroke-width: 1.5;\n}\n.bf-buy .configurator .subscription-card[open] .purchase-card-chevron {\n    transform: rotate(180deg);\n}\n.bf-buy .configurator .subscription-settings {\n    margin: 0;\n    padding: 0;\n    container: purchase-settings \/ inline-size;\n    border-top: 1px solid #f0f0f0;\n}\n.bf-buy .configurator .billing-fieldset {\n    margin: 0;\n}\n.bf-buy .configurator .section-label {\n    display: block;\n    margin-bottom: 12px;\n    color: var(--muted);\n    font-family: inherit;\n    font-size: 13px;\n    font-weight: 500;\n}\n.bf-buy .configurator .step {\n    display: none;\n}\n.bf-buy .configurator .billing-choices {\n    display: grid;\n    grid-template-columns: minmax(0, 1fr);\n    gap: 0;\n    border: 0;\n    border-radius: 0;\n    overflow: hidden;\n    container-type: normal;\n}\n.bf-buy .configurator .billing-choices .choice {\n    display: grid;\n    grid-template-columns: 22px minmax(0, 1fr);\n    align-items: center;\n    gap: 16px;\n    margin: 0;\n    min-height: 56px;\n    padding: 14px 24px 14px 36px;\n    border-bottom: 1px solid var(--line);\n    background: #fff;\n}\n.bf-buy .configurator .billing-choices .choice:last-child {\n    border-bottom: 0;\n}\n.bf-buy .configurator .billing-choices .choice:has(input:checked) {\n    background: var(--wash);\n}\n.bf-buy .configurator .billing-choices .choice:hover {\n    background: #f8f8f8;\n}\n.bf-buy .configurator .billing-choices .choice:has(:focus-visible) {\n    outline: 2px solid var(--blue);\n    outline-offset: -3px;\n}\n.bf-buy .configurator .billing-choices input {\n    position: static;\n    justify-self: center;\n    width: 18px;\n    height: 18px;\n    margin: 0;\n    opacity: 1;\n    accent-color: var(--blue);\n}\n.bf-buy .configurator .billing-choices .choice-face,\n.bf-buy .configurator .billing-choices input:checked + .choice-face {\n    display: grid;\n    grid-template-columns: minmax(0, 1fr) auto;\n    grid-template-rows: auto;\n    grid-template-areas: 'heading price';\n    align-items: center;\n    justify-items: stretch;\n    gap: 10px;\n    min-width: 0;\n    min-height: 24px;\n    height: auto;\n    padding: 0;\n    border: 0;\n    border-radius: 0;\n    background: transparent;\n    text-align: left;\n}\n.bf-buy .configurator .period-heading {\n    grid-area: heading;\n    display: flex;\n    flex-wrap: nowrap;\n    align-items: center;\n    gap: 8px;\n    white-space: nowrap;\n}\n.bf-buy .configurator .billing-choices .choice-face strong {\n    margin: 0;\n    padding: 0;\n    font-size: 14px;\n    font-weight: 500;\n}\n.bf-buy .configurator .billing-choices .charge-price {\n    grid-area: price;\n    font-family: inherit;\n    justify-content: flex-end;\n    width: auto;\n    height: auto;\n    flex-wrap: nowrap;\n    gap: 4px;\n    font-size: 16px;\n    font-weight: 600;\n    font-variant-numeric: tabular-nums;\n    letter-spacing: normal;\n    white-space: nowrap;\n}\n.bf-buy .configurator .rate-unit {\n    font-size: 12px;\n    font-weight: 400;\n    letter-spacing: normal;\n}\n.bf-buy .configurator .billing-choices .saving {\n    margin: 0;\n    padding: 1px 7px;\n    border: 1px solid #c4def0;\n    border-radius: 20px;\n    color: var(--blue);\n    background: #f2f8fd;\n    font-size: 11px;\n    font-weight: 500;\n    line-height: 1.5;\n}\n\/* Full billing amounts remain in each radio's accessible label. *\/\n.bf-buy .configurator .billing-choices .charge-frequency {\n    position: absolute;\n}\n@container purchase-settings (max-width: 320px) {\n    .bf-buy .configurator .billing-choices .saving {\n        display: none;\n    }\n}\n.bf-buy .configurator .order-summary {\n    margin-top: 28px;\n    padding: 24px 6px 0;\n    border: 0;\n    border-top: 1px solid var(--line);\n    border-radius: 0;\n    background: transparent;\n}\n.bf-buy .configurator .summary-line {\n    margin: 0;\n    padding: 8px 0;\n    font-size: 14px;\n    line-height: 1.6;\n}\n.bf-buy .configurator .summary-line > :last-child {\n    font-size: 14px;\n    color: var(--ink);\n}\n.bf-buy .configurator .today-line {\n    align-items: baseline;\n    margin-top: 18px;\n    padding-top: 20px;\n}\n.bf-buy .configurator .today-line strong {\n    font-family: inherit;\n    font-size: 15px;\n    font-weight: 600;\n}\n.bf-buy .configurator .today-line .price {\n    font-size: 28px;\n    font-weight: 600;\n    letter-spacing: -0.8px;\n}\n.bf-buy .configurator .renewal {\n    display: flex;\n    justify-content: space-between;\n    gap: 16px;\n    margin-top: 14px;\n    font-size: 12px;\n    text-align: left;\n}\n.bf-buy .configurator .renewal > :last-child {\n    text-align: right;\n}\n.bf-buy .configurator .shipping-note {\n    margin-top: 16px;\n    font-size: 12px;\n    text-align: left;\n}\n.bf-buy .configurator .desktop-cta {\n    justify-content: center;\n    gap: 12px;\n    margin-top: 24px;\n    padding: 18px 24px;\n    border: 1px solid transparent;\n    border-radius: 999px;\n    background: var(--blue);\n    color: #fff;\n    font-size: 14px;\n    transition: background-color 180ms ease-out;\n}\n\/* The legacy theme forces inversion with !important; scope this exception to the CTA. *\/\n.bf-buy .configurator .desktop-cta:is(:hover, :focus) {\n    border-color: transparent;\n    background-color: #006bb8 !important;\n    color: #fff !important;\n}\n.bf-buy .configurator .desktop-cta:focus-visible {\n    outline: 2px solid var(--blue);\n    outline-offset: 4px;\n}\n@media (prefers-reduced-motion: no-preference) {\n    .bf-buy .configurator .desktop-cta svg {\n        transition: transform 180ms ease-out;\n    }\n    .bf-buy .configurator .desktop-cta:is(:hover, :focus-visible):not(:disabled):not([aria-disabled='true']) svg {\n        transform: translateX(3px);\n    }\n}\n.bf-buy .configurator :is(input, summary):focus-visible {\n    outline: 2px solid var(--blue);\n    outline-offset: 4px;\n}\n@media (max-width: 1000px) {\n    .bf-buy .buy-layout {\n        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n        gap: 32px;\n    }\n    .bf-buy .configurator .purchase-card-header {\n        gap: 12px;\n        padding: 20px;\n    }\n    .bf-buy .configurator .billing-choices .choice {\n        gap: 12px;\n        padding-inline: 32px 20px;\n    }\n}\n@media (max-width: 900px) {\n    .bf-buy .buy-layout {\n        grid-template-columns: minmax(0, 1fr);\n        gap: 40px;\n    }\n    .bf-buy .product-column {\n        position: static;\n    }\n}\n@media (max-width: 360px) {\n    .bf-buy .configurator .purchase-card-header {\n        gap: 10px;\n        padding: 20px 16px;\n    }\n    .bf-buy .configurator .purchase-card-copy strong {\n        font-size: 15px;\n    }\n\n    .bf-buy .configurator .purchase-card-price {\n        font-size: 14px;\n    }\n    .bf-buy .configurator .billing-choices .choice {\n        gap: 10px;\n        padding-inline: 24px 16px;\n    }\n    .bf-buy .configurator .billing-choices .choice-face strong {\n        font-size: 13px;\n    }\n    .bf-buy .configurator .billing-choices .charge-price {\n        font-size: 14px;\n    }\n    .bf-buy .configurator .rate-unit {\n        font-size: 11px;\n    }\n}\n\n.bf-buy .configurator .billing-choices input:focus-visible,\n.bf-buy .configurator .billing-choices input:focus-visible + .choice-face {\n    outline: 0;\n    box-shadow: none;\n}\n<\/style>\n<main class=\"bf-buy\" data-language=\"fi\"><p class=\"bf-buy-loading-message\" role=\"status\">Ladataan valintojasi\u2026<\/p><div class=\"bf-buy-app\">\n    <svg class=\"svg-library\" aria-hidden=\"true\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n        <symbol id=\"bf-i-pin\" viewBox=\"0 0 24 24\">\n            <path d=\"M20 10c0 6-8 12-8 12S4 16 4 10a8 8 0 1 1 16 0Z\"><\/path>\n            <circle cx=\"12\" cy=\"10\" r=\"2.5\"><\/circle>\n        <\/symbol>\n        <symbol id=\"bf-i-shield\" viewBox=\"0 0 24 24\">\n            <path d=\"M12 3 3.5 6v6c0 5 8.5 9 8.5 9s8.5-4 8.5-9V6Z\"><\/path>\n            <path d=\"m8 12 2.5 2.5L16 9\"><\/path>\n        <\/symbol>\n        <symbol id=\"bf-i-tool\" viewBox=\"0 0 24 24\">\n            <path d=\"M14 5a6 6 0 0 0-7.5 7.5L3 16a3 3 0 0 0 4 4l3.5-3.5A6 6 0 0 0 18 9l-4 4-3-3Z\"><\/path>\n        <\/symbol>\n        <symbol id=\"bf-i-phone\" viewBox=\"0 0 24 24\">\n            <rect x=\"6\" y=\"2\" width=\"12\" height=\"20\" rx=\"2\"><\/rect>\n            <path d=\"M10 5h4m-3 14h2\"><\/path>\n        <\/symbol>\n        <symbol id=\"bf-i-arrow\" viewBox=\"0 0 24 24\"><path d=\"M4 12h16m-6-6 6 6-6 6\"><\/path><\/symbol>\n        <symbol id=\"bf-i-chevron\" viewBox=\"0 0 24 24\"><path d=\"m6 9 6 6 6-6\"><\/path><\/symbol>\n        <symbol id=\"bf-i-close\" viewBox=\"0 0 24 24\"><path d=\"m6 6 12 12M6 18 18 6\"><\/path><\/symbol>\n        <symbol id=\"bf-i-check\" viewBox=\"0 0 24 24\">\n            <circle cx=\"12\" cy=\"12\" r=\"9\"><\/circle>\n            <path d=\"m8 12 3 3 5-6\"><\/path>\n        <\/symbol>\n        <symbol id=\"bf-i-device\" viewBox=\"0 0 24 24\">\n            <rect x=\"8\" y=\"3\" width=\"8\" height=\"18\" rx=\"2\"><\/rect>\n            <path d=\"M6 7h12M9 16h6\"><\/path>\n        <\/symbol>\n    <\/svg>\n    <div class=\"buy-layout\">\n        <section class=\"product-column\" aria-labelledby=\"bf-product-name\">\n            <div class=\"gallery-stage\" id=\"bf-product-stage\" data-model=\"g2\" data-view=\"overview\">\n                <img id=\"bf-product-photo\" alt=\"Bikefinder Tracker Gen2\">\n            <\/div>\n            <h2 class=\"gallery-name model-name\" id=\"bf-product-name\">Bikefinder Tracker Gen2<\/h2>\n            <div class=\"gallery-thumbnails\" id=\"bf-gallery-thumbnails\" role=\"group\" aria-label=\"Product images\"><\/div>\n            <div class=\"product-details\">\n                <details>\n                    <summary>\n                        <span data-copy=\"fitHeading\">Sopiiko se py\u00f6r\u00e4\u00e4ni?<\/span><span class=\"fit-range\">15\u201327 mm<\/span>\n                    <\/summary>\n                    <p data-copy=\"fitCopy\">Paikannin sopii ohjaustankoihin, joiden sis\u00e4halkaisija on 15\u201327 mm. Tarkista ohjaustangon sis\u00e4puoli ennen tilaamista.<\/p>\n                <\/details>\n            <\/div>\n        <\/section>\n        <section class=\"configurator\" id=\"start\" aria-labelledby=\"bf-config-heading\">\n            <p class=\"purchase-category\" data-copy=\"productCategory\">GPS-paikannin<\/p>\n            <h1 class=\"config-title\" id=\"bf-config-heading\" tabindex=\"-1\"><\/h1>\n            <p class=\"purchase-description\" data-copy=\"intro\">Piilossa ohjaustangossa. Yhteydess\u00e4 puhelimeesi. Ota BikeFinder mukaan seuraavalle lenkille.<\/p>\n            <p class=\"purchase-hint\" data-copy=\"chooseProducts\">Valitse ostoskoriin lis\u00e4tt\u00e4v\u00e4t tuotteet.<\/p>\n            <p class=\"config-subtitle sr-only\" id=\"bf-destination-copy\"><\/p>\n            <div class=\"setup-builder\">\n                <div class=\"purchase-card tracker-card\" id=\"bf-tracker-card\">\n                    <label class=\"purchase-card-header\">\n                        <input id=\"bf-include-tracker\" type=\"checkbox\" checked=\"\">\n                        <span class=\"purchase-card-copy\">\n                            <strong id=\"bf-hardware-name\"><\/strong>\n                            <small data-copy=\"trackerRequirement\">Vaatii erillisen tilauksen<\/small>\n                        <\/span>\n                        <span class=\"purchase-card-price\">\n                            <span class=\"price\" id=\"bf-hardware-price\"><\/span>\n                            <small data-copy=\"oneTime\">Kertaostos<\/small>\n                        <\/span>\n                    <\/label>\n                <\/div>\n                <details class=\"purchase-card subscription-card\" id=\"bf-subscription-card\" open=\"\">\n                    <summary class=\"purchase-card-header\">\n                        <input id=\"bf-include-subscription\" type=\"checkbox\" checked=\"\" aria-labelledby=\"bf-subscription-label\">\n                        <label class=\"purchase-card-copy\" for=\"bf-include-subscription\">\n                            <strong id=\"bf-subscription-label\" data-copy=\"subscriptionLabel\">Tilaus<\/strong>\n                            <small data-copy=\"fallbackTracking\">GPS-paikannus<\/small>\n                        <\/label>\n                        <svg class=\"purchase-card-chevron\" aria-hidden=\"true\">\n                            <use href=\"#bf-i-chevron\"><\/use>\n                        <\/svg>\n                    <\/summary>\n                    <div class=\"subscription-settings\" id=\"bf-subscription-settings\">\n                        <fieldset class=\"protection-fieldset\" id=\"bf-protection-settings\">\n                            <legend class=\"section-label\">\n                                <span class=\"step\" aria-hidden=\"true\">1<\/span><span data-copy=\"protectionTitle\">Valitse suojaus<\/span>\n                            <\/legend>\n                            <div class=\"choices protection-choices\">\n                                <label class=\"choice\"><input type=\"radio\" name=\"bf-protection\" value=\"tracking\" checked=\"\"><span class=\"choice-face\"><span><strong data-copy=\"tracking\">Paikannus<\/strong><small data-copy=\"trackingDesc\">Paikanna py\u00f6r\u00e4si sovelluksessa aktiivisella tilauksella.<\/small><\/span><span class=\"radio-mark\" aria-hidden=\"true\"><\/span><\/span><\/label>\n                                <label class=\"choice\"><input type=\"radio\" name=\"bf-protection\" value=\"insurance\" id=\"bf-insurance-option\"><span class=\"choice-face\"><span><strong data-copy=\"insured\">Paikannus + vakuutus<\/strong><small data-copy=\"insuredDesc\">Paikannus ja valinnainen polkupy\u00f6r\u00e4vakuutus.<\/small><\/span><span class=\"radio-mark\" aria-hidden=\"true\"><\/span><\/span><\/label>\n                            <\/div>\n                        <\/fieldset>\n                        <section class=\"insurance-settings\" id=\"bf-insurance-settings\" aria-labelledby=\"bf-bike-value-label\">\n                            <div class=\"bike-value-picker\">\n                                <div class=\"value-heading\">\n                                    <label id=\"bf-bike-value-label\" for=\"bf-bike-value\" data-copy=\"valueLabel\">Py\u00f6r\u00e4n arvo enint\u00e4\u00e4n<\/label>\n                                    <output id=\"bf-bike-value-amount\" for=\"bf-bike-value\"><\/output>\n                                <\/div>\n                                <input id=\"bf-bike-value\" class=\"bike-value-range\" type=\"range\" min=\"0\" step=\"1\" value=\"0\" aria-describedby=\"bf-plan-type\">\n                                <div class=\"value-stops\" id=\"bf-value-stops\" aria-hidden=\"true\"><\/div>\n                            <\/div>\n                        <\/section>\n                        <p class=\"plan-type\" id=\"bf-plan-type\"><\/p>\n                        <fieldset class=\"billing-fieldset\">\n                            <legend class=\"section-label sr-only\">\n                                <span class=\"step\" id=\"bf-billing-number\" aria-hidden=\"true\">2<\/span><span data-copy=\"billingTitle\">Valitse maksujakso<\/span>\n                            <\/legend>\n                            <div class=\"choices billing-choices\" id=\"bf-billing-choices\"><\/div>\n                        <\/fieldset>\n                        <p class=\"eligibility\" id=\"bf-eligibility-copy\" hidden=\"\"><\/p>\n                    <\/div>\n                <\/details>\n            <\/div>\n\n            <div class=\"order-summary\" id=\"bf-order-summary\" aria-live=\"polite\" aria-atomic=\"true\">\n                <div class=\"summary-line\" id=\"bf-tracker-summary-row\">\n                    <span data-copy=\"trackerPayment\">Paikannin \u00b7 kertamaksu<\/span><span id=\"bf-tracker-summary-price\"><\/span>\n                <\/div>\n                <div class=\"summary-line\" id=\"bf-plan-summary-row\">\n                    <span id=\"bf-plan-summary-label\"><\/span><span id=\"bf-plan-summary-price\"><\/span>\n                <\/div>\n                <div class=\"today-line\">\n                    <strong id=\"bf-total-heading\" tabindex=\"-1\" data-copy=\"dueToday\">Maksettava t\u00e4n\u00e4\u00e4n<\/strong><span class=\"price today-price\"><\/span>\n                <\/div>\n\n                <div class=\"renewal\" id=\"bf-renewal-copy\">\n                    <span data-copy=\"renewal\">Sen j\u00e4lkeen<\/span><span id=\"bf-renewal-amount\"><\/span>\n                <\/div>\n                <p class=\"tracking-requirement\" id=\"bf-hardware-only-note\" data-copy=\"trackingRequirement\" hidden=\"\">Paikannus edellytt\u00e4\u00e4 aktiivista tilausta.<\/p>\n                <p class=\"shipping-note\" data-copy=\"shippingNote\">Toimituskulut ja lopulliset verot lasketaan kassalla.<\/p>\n            <\/div><div class=\"bf-buy-cart-note\" hidden=\"\"><p>Ostoskorissasi on jo tuotteita. Tarkista ne jatkaaksesi tai poista ne uutta valintaa varten.<\/p><button type=\"button\" data-review-cart=\"\">Tarkista ostoskori<\/button><\/div>\n            <p class=\"inline-error\" id=\"bf-eligibility-error\" hidden=\"\" role=\"alert\"><\/p>\n            <p class=\"bf-buy-alert\" hidden=\"\" role=\"alert\"><\/p><p class=\"bf-buy-busy\" hidden=\"\" role=\"status\"><\/p><button class=\"primary flow-action desktop-cta\" id=\"bf-flow-action\" type=\"button\" data-checkout=\"\">\n                <span id=\"bf-action-label\" data-copy=\"checkout\">Jatka kassalle<\/span><svg aria-hidden=\"true\"><use href=\"#bf-i-arrow\"><\/use><\/svg>\n            <\/button>\n            <p class=\"cta-footnote\" data-copy=\"reviewNote\">Tarkista valintasi ennen maksamista.<\/p>\n        <\/section>\n    <\/div>\n    <section class=\"how-section\" id=\"bf-how-it-works\" aria-labelledby=\"bf-how-heading\">\n        <div class=\"section-intro\">\n            <h2 id=\"bf-how-heading\" data-copy=\"howHeading\">Pieni paikannin. Helppo aloittaa.<\/h2>\n            <p data-copy=\"howIntro\">Pakkauksesta seuraavalle lenkille.<\/p>\n        <\/div>\n        <div class=\"how-grid\">\n            <article class=\"how-card\">\n                <span class=\"how-number\">01 \/<\/span>\n                <h3 data-copy=\"installTitle\">Piilota ohjaustankoon.<\/h3>\n                <p data-copy=\"installCopy\">Kiinnit\u00e4 paikannin mukana tulevalla asennusty\u00f6kalulla. Se pysyy huomaamattomana ja py\u00f6r\u00e4si n\u00e4ytt\u00e4\u00e4 entiselt\u00e4\u00e4n.<\/p>\n            <\/article>\n            <article class=\"how-card\">\n                <span class=\"how-number\">02 \/<\/span>\n                <h3 data-copy=\"activateTitle\">Yhdist\u00e4 sovellukseen.<\/h3>\n                <p data-copy=\"activateCopy\">Lataa BikeFinder-sovellus, yhdist\u00e4 paikannin ja aktivoi tilaus.<\/p>\n            <\/article>\n            <article class=\"how-card\">\n                <span class=\"how-number\">03 \/<\/span>\n                <h3 data-copy=\"rideTitle\">Nauti py\u00f6r\u00e4ilyst\u00e4.<\/h3>\n                <p data-copy=\"rideCopy\">Seuraa py\u00f6r\u00e4n sijaintia sovelluksessa ja ilmoita varkaudesta, jos tarvitset apua.<\/p>\n            <\/article>\n        <\/div>\n    <\/section>\n    <section class=\"faq-section\" id=\"bf-questions\" aria-labelledby=\"bf-faq-heading\">\n        <h2 id=\"bf-faq-heading\" data-copy=\"faqHeading\">Hyv\u00e4 tiet\u00e4\u00e4.<\/h2>\n        <details>\n            <summary data-copy=\"subscriptionQuestion\">Miksi tarvitsen tilauksen?<\/summary>\n            <p data-copy=\"subscriptionAnswer\">Aktiivinen tilaus yhdist\u00e4\u00e4 paikantimen BikeFinder-palveluun ja mahdollistaa paikannuksen sovelluksessa. Paikannin ja tilaus ovat ostoksen erillisi\u00e4 osia.<\/p>\n        <\/details>\n        <details>\n            <summary data-copy=\"paymentQuestion\">Milloin maksan tilauksen?<\/summary>\n            <p data-copy=\"paymentAnswer\">Ensimm\u00e4inen tilausmaksu sis\u00e4ltyy t\u00e4m\u00e4n p\u00e4iv\u00e4n summaan. Kuukausitilaus uusiutuu kuukausittain. 12 tai 24 kuukauden tilaus maksetaan kokonaan ja uusiutuu samalla aikav\u00e4lill\u00e4. Yhteenveto n\u00e4ytt\u00e4\u00e4 uusimismaksun erill\u00e4\u00e4n paikantimesta.<\/p>\n        <\/details>\n\n        <details>\n            <summary data-copy=\"destinationQuestion\">Miksi toimitusmaa on t\u00e4rke\u00e4?<\/summary>\n            <p data-copy=\"destinationAnswer\">Toimitusmaa m\u00e4\u00e4ritt\u00e4\u00e4 saatavilla olevan paikantimen ja hinnat. Voit vaihtaa kielt\u00e4 muuttamatta toimitusmaata.<\/p>\n        <\/details>\n        <details>\n            <summary data-copy=\"boxHeading\">Mit\u00e4 pakkauksessa on?<\/summary>\n            <p id=\"bf-box-copy\"><\/p>\n        <\/details>\n    <\/section>\n<span data-page-end=\"\" aria-hidden=\"true\" style=\"display: block; height: 1px;\"><\/span><\/div><p class=\"bf-buy-initial-error\" role=\"alert\" hidden>Valintasi lataaminen ei onnistunut. Voit silti k\u00e4ytt\u00e4\u00e4 alla olevia tuotevaihtoehtoja.<\/p><div class=\"bf-buy-fallback\"><h1>Osta BikeFinder<\/h1><p data-country-name>Unknown<\/p><div class=\"bf-source-trackers\"><div class=\"woocommerce columns-3 \"><\/div><div class=\"woocommerce columns-3 \"><ul class=\"products columns-3\">\n<li class=\"desktop-align-left tablet-align-left mobile-align-left product type-product post-345376 status-publish first instock product_cat-bikefinder-tracker product_cat-tracker has-post-thumbnail taxable shipping-taxable purchasable product-type-simple\">\n\t<a href=\"https:\/\/bikefinder.com\/fi\/product\/bikefinder-tracker-bfg2\/\" class=\"woocommerce-LoopProduct-link woocommerce-loop-product__link\"><img loading=\"lazy\" decoding=\"async\" width=\"75\" height=\"75\" src=\"https:\/\/bikefinder.com\/wp-content\/uploads\/2025\/01\/BikeFinder_Tracker_Buy_DE_1-75x75.jpg\" class=\"attachment-woocommerce_thumbnail size-woocommerce_thumbnail\" alt=\"BikeFinder G2 -paikannin ja pakkaus puhelimen vieress\u00e4, jonka n\u00e4yt\u00f6ll\u00e4 on seurantasovellus\" srcset=\"https:\/\/bikefinder.com\/wp-content\/uploads\/2025\/01\/BikeFinder_Tracker_Buy_DE_1-75x75.jpg 75w, https:\/\/bikefinder.com\/wp-content\/uploads\/2025\/01\/BikeFinder_Tracker_Buy_DE_1-150x150.jpg 150w, https:\/\/bikefinder.com\/wp-content\/uploads\/2025\/01\/BikeFinder_Tracker_Buy_DE_1-100x100.jpg 100w\" sizes=\"auto, (max-width: 75px) 100vw, 75px\" \/><h2 class=\"woocommerce-loop-product__title\">Bikefinder Tracker Gen2<\/h2>\n\t<span class=\"price\"><span class=\"woocommerce-Price-amount amount\"><bdi>1.979,00&nbsp;<span class=\"woocommerce-Price-currencySymbol\" translate=\"no\" dir=\"auto\"><span class=\"woocommerce-Price-currencyCode\">NOK<\/span><\/span><\/bdi><\/span><\/span>\n<\/a><a href=\"\/fi\/wp-json\/wp\/v2\/pages\/156471?add-to-cart=345376\" aria-describedby=\"woocommerce_loop_add_to_cart_link_describedby_345376\" data-quantity=\"1\" class=\"button product_type_simple add_to_cart_button ajax_add_to_cart\" data-product_id=\"345376\" data-product_sku=\"BFG2\" aria-label=\"Add to cart: &ldquo;Bikefinder Tracker Gen2&rdquo;\" rel=\"nofollow\" data-success_message=\"&ldquo;Bikefinder Tracker Gen2&rdquo; has been added to your cart\" role=\"button\">Add to cart<\/a>\t<span id=\"woocommerce_loop_add_to_cart_link_describedby_345376\" class=\"screen-reader-text\">\n\t\t\t<\/span>\n<\/li>\n<\/ul>\n<\/div><\/div><div class=\"bf-source-accessory\"><p class=\"product woocommerce add_to_cart_inline bikefinder-native-accessory\" style=\"\"><span class=\"woocommerce-Price-amount amount\"><bdi>135,00&nbsp;<span class=\"woocommerce-Price-currencySymbol\" translate=\"no\" dir=\"auto\"><span class=\"woocommerce-Price-currencyCode\">NOK<\/span><\/span><\/bdi><\/span><a href=\"\/fi\/wp-json\/wp\/v2\/pages\/156471?add-to-cart=317929\" aria-describedby=\"woocommerce_loop_add_to_cart_link_describedby_317929\" data-quantity=\"1\" class=\"button product_type_simple add_to_cart_button ajax_add_to_cart\" data-product_id=\"317929\" data-product_sku=\"dummy-bar-end-2\" aria-label=\"Add to cart: &ldquo;Dummy Bar End&rdquo;\" rel=\"nofollow\" data-success_message=\"&ldquo;Dummy Bar End&rdquo; has been added to your cart\" role=\"button\">Add to cart<\/a>\t<span id=\"woocommerce_loop_add_to_cart_link_describedby_317929\" class=\"screen-reader-text\">\n\t\t\t<\/span>\n<\/p><\/div><h2>GPS-paikannus<\/h2><div class=\"bf-buy-native-plan\" data-tier=\"0\" data-months=\"24\" data-product-id=\"117197\"><h3>24 kuukautta<\/h3><p class=\"product woocommerce add_to_cart_inline bikefinder-native-plan\" style=\"\"><span class=\"woocommerce-Price-amount amount\"><bdi>1.320,00&nbsp;<span class=\"woocommerce-Price-currencySymbol\" translate=\"no\" dir=\"auto\"><span class=\"woocommerce-Price-currencyCode\">NOK<\/span><\/span><\/bdi><\/span> <span class=\"subscription-details\"> joka 2 vuotta<\/span><a href=\"https:\/\/bikefinder.com\/fi\/product\/subscription\/?attribute_payment-period=24+months&#038;attribute_tier=Tier+0&#038;variation_id=117197&#038;add-to-cart=111250\" aria-describedby=\"woocommerce_loop_add_to_cart_link_describedby_117197\" data-quantity=\"1\" class=\"button product_type_subscription_variation add_to_cart_button ajax_add_to_cart\" data-product_id=\"117197\" data-product_sku=\"subscription-24months-tier0-v2\" aria-label=\"Add to cart: &ldquo;Subscription&rdquo;\" rel=\"nofollow\" data-success_message=\"&ldquo;Subscription&rdquo; has been added to your cart\" role=\"button\">Lis\u00e4\u00e4 ostoskoriin<\/a>\t<span id=\"woocommerce_loop_add_to_cart_link_describedby_117197\" class=\"screen-reader-text\">\n\t\t\t<\/span>\n<\/p><\/div>\n<div class=\"bf-buy-native-plan\" data-tier=\"0\" data-months=\"12\" data-product-id=\"117191\"><h3>12 kuukautta<\/h3><p class=\"product woocommerce add_to_cart_inline bikefinder-native-plan\" style=\"\"><span class=\"woocommerce-Price-amount amount\"><bdi>708,00&nbsp;<span class=\"woocommerce-Price-currencySymbol\" translate=\"no\" dir=\"auto\"><span class=\"woocommerce-Price-currencyCode\">NOK<\/span><\/span><\/bdi><\/span> <span class=\"subscription-details\"> \/ year<\/span><a href=\"https:\/\/bikefinder.com\/fi\/product\/subscription\/?attribute_payment-period=12+months&#038;attribute_tier=Tier+0&#038;variation_id=117191&#038;add-to-cart=111250\" aria-describedby=\"woocommerce_loop_add_to_cart_link_describedby_117191\" data-quantity=\"1\" class=\"button product_type_subscription_variation add_to_cart_button ajax_add_to_cart\" data-product_id=\"117191\" data-product_sku=\"subscription-12months-tier0-v2\" aria-label=\"Add to cart: &ldquo;Subscription&rdquo;\" rel=\"nofollow\" data-success_message=\"&ldquo;Subscription&rdquo; has been added to your cart\" role=\"button\">Lis\u00e4\u00e4 ostoskoriin<\/a>\t<span id=\"woocommerce_loop_add_to_cart_link_describedby_117191\" class=\"screen-reader-text\">\n\t\t\t<\/span>\n<\/p><\/div>\n<div class=\"bf-buy-native-plan\" data-tier=\"0\" data-months=\"1\" data-product-id=\"117183\"><h3>1 kuukausi<\/h3><p class=\"product woocommerce add_to_cart_inline bikefinder-native-plan\" style=\"\"><span class=\"woocommerce-Price-amount amount\"><bdi>69,00&nbsp;<span class=\"woocommerce-Price-currencySymbol\" translate=\"no\" dir=\"auto\"><span class=\"woocommerce-Price-currencyCode\">NOK<\/span><\/span><\/bdi><\/span> <span class=\"subscription-details\"> \/ month<\/span><a href=\"https:\/\/bikefinder.com\/fi\/product\/subscription\/?attribute_payment-period=1+month&#038;attribute_tier=Tier+0&#038;variation_id=117183&#038;add-to-cart=111250\" aria-describedby=\"woocommerce_loop_add_to_cart_link_describedby_117183\" data-quantity=\"1\" class=\"button product_type_subscription_variation add_to_cart_button ajax_add_to_cart\" data-product_id=\"117183\" data-product_sku=\"subscription-1months-tier0-v2\" aria-label=\"Add to cart: &ldquo;Subscription&rdquo;\" rel=\"nofollow\" data-success_message=\"&ldquo;Subscription&rdquo; has been added to your cart\" role=\"button\">Lis\u00e4\u00e4 ostoskoriin<\/a>\t<span id=\"woocommerce_loop_add_to_cart_link_describedby_117183\" class=\"screen-reader-text\">\n\t\t\t<\/span>\n<\/p><\/div>\n\n\n\n\n\n\n\n\n<\/div><script type=\"application\/json\" class=\"bf-buy-config\">{\"locale\":\"fi-FI\",\"copy\":{\"eyebrow\":\"Pieni paikannin. Enemm\u00e4n mielenrauhaa.\",\"heroOne\":\"Py\u00f6r\u00e4ile enemm\u00e4n.\",\"heroTwo\":\"Huolehdi v\u00e4hemm\u00e4n.\",\"intro\":\"Piilossa ohjaustangossa. Yhteydess\u00e4 puhelimeesi. Ota BikeFinder mukaan seuraavalle lenkille.\",\"designed\":\"Suunniteltu Norjassa\",\"hidden\":\"Piilossa ohjaustangossa\",\"trackFeature\":\"Seuraa py\u00f6r\u00e4\u00e4si\",\"installFeature\":\"Asenna itse\",\"appFeature\":\"Yhteydess\u00e4 sovellukseen\",\"boxHeading\":\"Mit\u00e4 pakkauksessa on?\",\"fitHeading\":\"Sopiiko se py\u00f6r\u00e4\u00e4ni?\",\"fitCopy\":\"Paikannin sopii ohjaustankoihin, joiden sis\u00e4halkaisija on 15\u201327 mm. Tarkista ohjaustangon sis\u00e4puoli ennen tilaamista.\",\"configTitle\":\"Kokoa oma BikeFinderisi.\",\"alreadyOwn\":\"Onko sinulla jo paikannin? Valitse vain tilaus.\",\"protectionTitle\":\"Valitse suojaus\",\"tracking\":\"Paikannus\",\"trackingDesc\":\"Paikanna py\u00f6r\u00e4si sovelluksessa aktiivisella tilauksella.\",\"insured\":\"Paikannus + vakuutus\",\"insuredDesc\":\"Paikannus ja valinnainen polkupy\u00f6r\u00e4vakuutus.\",\"valueLabel\":\"Py\u00f6r\u00e4n arvo enint\u00e4\u00e4n\",\"policy\":\"Vakuutusehdot \u2197\",\"ipid\":\"Tuotetiedot \u2197\",\"billingTitle\":\"Valitse maksujakso\",\"accessory\":\"Lis\u00e4\u00e4 yhteensopiva DummyBarEnd\",\"accessoryHelp\":\"Samanlainen tangonp\u00e4\u00e4 toiseen p\u00e4\u00e4h\u00e4n.\",\"dueToday\":\"Maksettava t\u00e4n\u00e4\u00e4n\",\"shippingNote\":\"Toimituskulut ja lopulliset verot lasketaan kassalla.\",\"checkout\":\"Jatka kassalle\",\"reviewNote\":\"Tarkista valintasi ennen maksamista.\",\"howHeading\":\"Pieni paikannin. Helppo aloittaa.\",\"howIntro\":\"Pakkauksesta seuraavalle lenkille.\",\"installTitle\":\"Piilota ohjaustankoon.\",\"installCopy\":\"Kiinnit\u00e4 paikannin mukana tulevalla asennusty\u00f6kalulla. Se pysyy huomaamattomana ja py\u00f6r\u00e4si n\u00e4ytt\u00e4\u00e4 entiselt\u00e4\u00e4n.\",\"activateTitle\":\"Yhdist\u00e4 sovellukseen.\",\"activateCopy\":\"Lataa BikeFinder-sovellus, yhdist\u00e4 paikannin ja aktivoi tilaus.\",\"rideTitle\":\"Nauti py\u00f6r\u00e4ilyst\u00e4.\",\"rideCopy\":\"Seuraa py\u00f6r\u00e4n sijaintia sovelluksessa ja ilmoita varkaudesta, jos tarvitset apua.\",\"faqHeading\":\"Hyv\u00e4 tiet\u00e4\u00e4.\",\"subscriptionQuestion\":\"Miksi tarvitsen tilauksen?\",\"subscriptionAnswer\":\"Aktiivinen tilaus yhdist\u00e4\u00e4 paikantimen BikeFinder-palveluun ja mahdollistaa paikannuksen sovelluksessa. Paikannin ja tilaus ovat ostoksen erillisi\u00e4 osia.\",\"paymentQuestion\":\"Milloin maksan tilauksen?\",\"paymentAnswer\":\"Ensimm\u00e4inen tilausmaksu sis\u00e4ltyy t\u00e4m\u00e4n p\u00e4iv\u00e4n summaan. Kuukausitilaus uusiutuu kuukausittain. 12 tai 24 kuukauden tilaus maksetaan kokonaan ja uusiutuu samalla aikav\u00e4lill\u00e4. Yhteenveto n\u00e4ytt\u00e4\u00e4 uusimismaksun erill\u00e4\u00e4n paikantimesta.\",\"insuranceQuestion\":\"Sis\u00e4ltyyk\u00f6 vakuutus?\",\"insuranceAnswer\":\"Vain jos valitset paikannuksen ja vakuutuksen. Saatavuus, py\u00f6r\u00e4n arvon rajat ja kelpoisuus riippuvat toimitusmaasta ja vakuutusehdoista. Toimitusmaa ei yksin osoita vakuutuskelpoisuutta.\",\"destinationQuestion\":\"Miksi toimitusmaa on t\u00e4rke\u00e4?\",\"destinationAnswer\":\"Toimitusmaa m\u00e4\u00e4ritt\u00e4\u00e4 saatavilla olevan paikantimen ja hinnat. Voit vaihtaa kielt\u00e4 muuttamatta toimitusmaata.\",\"month\":\"kuukausi\",\"months\":\"kuukautta\",\"monthly\":\"Kuukausittain\",\"billed\":\"maksetaan\",\"save\":\"S\u00e4\u00e4st\u00e4\",\"perMonth\":\"\/ kk\",\"destination\":\"Valintasi toimitukseen maahan\",\"hardwareHelp\":\"Paikannin + asennussarja \u00b7 kertaostos\",\"ownerHelp\":\"Vain tilaus \u00b7 ei paikanninta\",\"ownerLabel\":\"Nykyinen paikantimesi\",\"billingMonthly\":\"Kuukausimaksu. Ensimm\u00e4inen kuukausi sis\u00e4ltyy alle.\",\"billingLong\":\"Maksetaan kokonaan, ei kuukausieriss\u00e4. Uusiutuu samalla aikav\u00e4lill\u00e4.\",\"renewal\":\"Sen j\u00e4lkeen\",\"renewalMonth\":\"kuukausittain\",\"renewalLong\":\"joka\",\"planFirst\":\"ensimm\u00e4iset\",\"valueUp\":\"Py\u00f6r\u00e4n arvo enint\u00e4\u00e4n\",\"eligibility\":\"Vakinainen asuinmaa on oltava\",\"eligibilityEnd\":\"Tarkista vakuutusturva ja kelpoisuus ehdoista.\",\"germanEligibility\":\"T\u00e4m\u00e4 on Saksan vakuutusvaihtoehto. Tarkista vakuutusturva ja kelpoisuus ehdoista.\",\"residence\":\"Vakinainen asuinmaani on\",\"error\":\"Vahvista vakinainen asuminen toimitusmaassa t\u00e4t\u00e4 vakuutusta varten. Valitse muuten paikannus ilman vakuutusta.\",\"unavailable\":\"Polkupy\u00f6r\u00e4vakuutusta ei ole saatavilla toimitukseen maahan\",\"stillTracking\":\"Paikannus on saatavilla.\",\"boxG2\":\"Paikannin, ohjaustankosovitin, latauskaapeli, asennusty\u00f6kalu, akkumoduulin irrotusty\u00f6kalu ja k\u00e4ytt\u00f6opas.\",\"boxG1\":\"Paikannin, ohjaustankosovitin, USB-C-kaapeli, asennusty\u00f6kalu ja k\u00e4ytt\u00f6opas.\",\"priceUnavailable\":\"Valintasi lataaminen ei onnistunut. Voit silti k\u00e4ytt\u00e4\u00e4 alla olevia tuotevaihtoehtoja.\",\"checkoutError\":\"Tuotetta ei voitu lis\u00e4t\u00e4. Tarkista ostoskori tai yrit\u00e4 uudelleen.\",\"partialError\":\"Jotkin tuotteet saattavat jo olla ostoskorissa. Tarkista ne ennen muutoksia tai yrit\u00e4 samaa valintaa uudelleen.\",\"existingCart\":\"Ostoskorissasi on jo tuotteita. Tarkista ne jatkaaksesi tai poista ne uutta valintaa varten.\",\"reviewCart\":\"Tarkista ostoskori\",\"retry\":\"Yrit\u00e4 uudelleen\",\"adding\":\"Lis\u00e4t\u00e4\u00e4n valintojasi\u2026\",\"deliveryChanged\":\"Toimitusmaasi muuttui. Lataa sivu uudelleen n\u00e4hd\u00e4ksesi oikeat vaihtoehdot.\",\"unavailableHardware\":\"Paikanninta ei ole juuri nyt saatavilla. Voit silti valita tilauksen nykyiselle paikantimelle.\",\"fallbackTitle\":\"Osta BikeFinder\",\"fallbackTracking\":\"GPS-paikannus\",\"fallbackInsurance\":\"Paikannus ja vakuutus\",\"trackerOnly\":\"Osta vain paikannin\",\"addSubscription\":\"Lis\u00e4\u00e4 tilaus\",\"trackerHelp\":\"Vain paikannin \u00b7 aktiivinen tilaus vaaditaan.\",\"trackingRequirement\":\"Paikannus edellytt\u00e4\u00e4 aktiivista tilausta.\",\"noInsurance\":\"Ilman vakuutusta\",\"gallery\":\"Tuotekuvat\",\"policyInline\":\"ehdoista\",\"policyInlineGerman\":\"ehdoista\",\"loadingSetup\":\"Ladataan valintojasi\u2026\",\"productCategory\":\"GPS-paikannin\",\"chooseProducts\":\"Valitse ostoskoriin lis\u00e4tt\u00e4v\u00e4t tuotteet.\",\"subscriptionLabel\":\"Tilaus\",\"oneTime\":\"Kertaostos\",\"trackerRequirement\":\"Vaatii erillisen tilauksen\",\"trackerPayment\":\"Paikannin \u00b7 kertamaksu\",\"billingPayment\":\"{amount} maksetaan nyt: {period}.\",\"billingRenewal\":\"Uusiutuu automaattisesti {cadence}.\",\"billingCadences\":{\"1\":\"kuukausittain\",\"12\":\"vuosittain\",\"24\":\"2 vuoden v\u00e4lein\"}},\"models\":{\"117475\":{\"role\":\"g1\",\"name\":\"BikeFinder G1\",\"image\":{\"id\":124411,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2020\/03\/IMG_0553-scaled.jpg\",\"alt\":\"BikeFinder-paikannin, latauskaapeli ja ty\u00f6kalut pakkauksen vieress\u00e4\"},\"images\":[{\"id\":124411,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2020\/03\/IMG_0553-scaled.jpg\",\"alt\":\"BikeFinder-paikannin, latauskaapeli ja ty\u00f6kalut pakkauksen vieress\u00e4\"},{\"id\":99347,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2020\/02\/BikeFinder-product-box-new-copy.jpg\",\"alt\":\"BikeFinder-paikantimen pakkaus\"},{\"id\":124398,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2020\/03\/IMG_0594-scaled.jpg\",\"alt\":\"BikeFinder-paikannin ja lis\u00e4varusteet pakkauksen edess\u00e4\"},{\"id\":243877,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2023\/11\/IMG_0543-scaled-1.jpg\",\"alt\":\"Avoin BikeFinder-pakkaus, jossa on paikannin ja lis\u00e4varusteet\"}]},\"185643\":{\"role\":\"fahrradfinden\",\"name\":\"FahrradFinden G1\",\"image\":{\"id\":185824,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2022\/08\/50-FahradFinden-net-shop-photo-3893-e1664871102963.jpg\",\"alt\":\"FahrradFinden-paikannin, latauskaapeli ja lis\u00e4varusteet pakkauksen vieress\u00e4\"},\"images\":[{\"id\":185824,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2022\/08\/50-FahradFinden-net-shop-photo-3893-e1664871102963.jpg\",\"alt\":\"FahrradFinden-paikannin, latauskaapeli ja lis\u00e4varusteet pakkauksen vieress\u00e4\"},{\"id\":185797,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2022\/08\/50-FahradFinden-net-shop-photo-3878-e1664871243399.jpg\",\"alt\":\"FahrradFinden-paikantimen pakkaus\"},{\"id\":185842,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2022\/08\/50-FahradFinden-net-shop-photo-3879-e1664870905588.jpg\",\"alt\":\"Avoin FahrradFinden-pakkaus, jossa on paikannin ja lis\u00e4varusteet\"},{\"id\":185833,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2022\/08\/50-FahradFinden-net-shop-photo-3890-e1664871030325.jpg\",\"alt\":\"FahrradFinden-paikannin ja lis\u00e4varusteet pakkauksen edess\u00e4\"}]},\"345376\":{\"role\":\"g2\",\"name\":\"Bikefinder Tracker Gen2\",\"image\":{\"id\":312861,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2025\/01\/BikeFinder_Tracker_Buy_2.jpg\",\"alt\":\"Pystyasennossa oleva BikeFinder G2 -paikannin\"},\"images\":[{\"id\":312861,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2025\/01\/BikeFinder_Tracker_Buy_2.jpg\",\"alt\":\"Pystyasennossa oleva BikeFinder G2 -paikannin\"},{\"id\":360564,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2025\/01\/BikeFinder_Tracker_Buy_DE_1.jpg\",\"alt\":\"BikeFinder G2 -paikannin ja pakkaus puhelimen vieress\u00e4, jonka n\u00e4yt\u00f6ll\u00e4 on seurantasovellus\"},{\"id\":360537,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2025\/01\/BikeFinder_Tracker_Buy_DE_3.jpg\",\"alt\":\"BikeFinder G2 -paikannin, pakkaus, asennusty\u00f6kalut ja latauskaapeli\"},{\"id\":312879,\"src\":\"https:\/\/bikefinder.com\/wp-content\/uploads\/2025\/01\/BikeFinder_Tracker_Buy_4.jpg\",\"alt\":\"L\u00e4hikuva BikeFinder G2 -paikantimen laajennusmekanismista\"}]}}}<\/script><\/main>\n<script>\/** Buying-page presentation over native WooCommerce shortcodes and cart endpoints. *\/\n(function () {\n    'use strict';\n\n    async function initialise() {\n        const root = document.querySelector('.bf-buy');\n        if (!root || root.dataset.initialised) return;\n        root.dataset.initialised = 'true';\n        const config = JSON.parse(root.querySelector('.bf-buy-config').textContent);\n        const copy = config.copy;\n        const find = (id) => root.querySelector('#bf-' + id);\n        const note = root.querySelector('.bf-buy-cart-note');\n        const source = root.querySelector('.bf-buy-fallback');\n        const ajaxParams = window.wc_add_to_cart_params;\n        const currencyMeta = {};\n        const state = {\n            insurance: false,\n            tier: 0,\n            insuranceTier: 1,\n            subscription: true,\n            months: 12,\n            owner: false,\n            image: 0,\n            busy: false,\n            job: null,\n            cart: null,\n        };\n        const market = source.querySelector('[data-offer-zone]');\n        const bands = JSON.parse(market?.dataset.bands || '[]');\n        const countryName = source.querySelector('[data-country-name]').textContent.trim();\n        const country = () =>\n            document.querySelector('select.wcpbc-country-switcher')?.value ||\n            state.cart?.shipping_address?.country;\n        const expectedCountry = country();\n        const plans = new Map();\n        let tracker;\n        let cartNonce;\n\n        function rememberSelection() {\n            try {\n                window.sessionStorage.setItem(\n                    'bikefinder-buying-selection',\n                    JSON.stringify({\n                        country: state.cart.shipping_address.country,\n                        insurance: state.insurance,\n                        tier: state.tier,\n                        insuranceTier: state.insuranceTier,\n                        subscription: state.subscription,\n                        months: state.months,\n                        owner: state.owner,\n                    }),\n                );\n            } catch {\n                \/* Browser storage is optional; native products remain usable. *\/\n            }\n        }\n\n        function restoreSelection() {\n            try {\n                const saved = JSON.parse(\n                    window.sessionStorage.getItem('bikefinder-buying-selection'),\n                );\n                if (!saved) return;\n                if ([1, 12, 24].includes(saved.months)) state.months = saved.months;\n                \/\/ Each page visit starts with the tracker selected, including old drafts.\n                \/\/ Subscription-only remains an explicit choice on the current page.\n                state.owner = false;\n                state.subscription = saved.subscription !== false;\n                if (saved.country === state.cart.shipping_address.country) {\n                    if (Number.isInteger(saved.tier) && plans.has(`${saved.tier}-${state.months}`))\n                        state.tier = saved.tier;\n                    state.insurance =\n                        saved.insurance === true &&\n                        Boolean(market.dataset.insuranceCountry) &&\n                        plans.has(`${state.tier}-${state.months}`);\n                    if (\n                        Number.isInteger(saved.insuranceTier) &&\n                        saved.insuranceTier > 0 &&\n                        plans.has(`${saved.insuranceTier}-${state.months}`)\n                    )\n                        state.insuranceTier = saved.insuranceTier;\n                    if (state.insurance && state.tier > 0) state.insuranceTier = state.tier;\n                    else {\n                        state.insurance = false;\n                        state.tier = 0;\n                    }\n                }\n            } catch {\n                \/* Ignore a missing or outdated draft. *\/\n            }\n        }\n\n        function message(text) {\n            const alert = root.querySelector(\n                root.classList.contains('is-ready') ? '.bf-buy-alert' : '.bf-buy-initial-error',\n            );\n            alert.textContent = text;\n            alert.hidden = !text;\n        }\n\n        async function json(url, options = {}) {\n            \/\/ Match FunnelKit's page language explicitly. After a language switch,\n            \/\/ the previous AJAX-language cookie can otherwise translate cart items\n            \/\/ during this read and invalidate the drawer's freshly fetched keys.\n            \/\/ WordPress publishes WPML's localized REST root. The country-pricing\n            \/\/ plugin recognizes frontend API requests against that native root.\n            const restRoot =\n                document.querySelector('link[rel=\"https:\/\/api.w.org\/\"]')?.href ||\n                new URL('\/wp-json\/', window.location.origin).href;\n            const requestUrl = new URL(url.replace(\/^\\\/wp-json\\\/\/, ''), restRoot);\n            requestUrl.searchParams.set('lang', root.dataset.language);\n            const response = await fetch(requestUrl, {\n                credentials: 'same-origin',\n                cache: 'no-store',\n                signal: AbortSignal.timeout(20000),\n                ...options,\n            });\n            if (!response.ok) throw new Error(copy.checkoutError);\n            cartNonce = response.headers.get('Nonce') || cartNonce;\n            const result = await response.json();\n            return result;\n        }\n\n        const cart = () => json('\/wp-json\/wc\/store\/v1\/cart?bf_buy=' + Date.now());\n        const quantity = (data, id) =>\n            data.items\n                .filter((item) => Number(item.id) === Number(id))\n                .reduce((sum, item) => sum + item.quantity, 0);\n        const selectedPlan = () =>\n            state.subscription\n                ? plans.get(`${state.insurance ? state.tier : 0}-${state.months}`)\n                : null;\n\n        function parsePrice(element) {\n            const amount =\n                element?.querySelector('ins .woocommerce-Price-amount') ||\n                element?.querySelector('.woocommerce-Price-amount');\n            if (!amount) return null;\n            const text = amount.textContent;\n            const stripped = text\n                .replaceAll(currencyMeta.currency_thousand_separator, '')\n                .replace(\/[^\\d.,-]\/g, '')\n                .replace(currencyMeta.currency_decimal_separator, '.');\n            const number = Number(stripped);\n            return Number.isFinite(number) && number >= 0\n                ? Math.round(number * 10 ** currencyMeta.currency_minor_unit)\n                : null;\n        }\n\n        function money(minor) {\n            return new Intl.NumberFormat(config.locale, {\n                style: 'currency',\n                currency: currencyMeta.currency_code,\n                minimumFractionDigits:\n                    minor % 10 ** currencyMeta.currency_minor_unit\n                        ? currencyMeta.currency_minor_unit\n                        : 0,\n                maximumFractionDigits: currencyMeta.currency_minor_unit,\n            }).format(minor \/ 10 ** currencyMeta.currency_minor_unit);\n        }\n\n        function nativeProduct(element) {\n            const button = element?.querySelector('.add_to_cart_button[data-product_id]');\n            const price = parsePrice(element?.querySelector('.price') || element);\n            return button && price !== null\n                ? { id: Number(button.dataset.product_id), price }\n                : null;\n        }\n\n        function setPrice(selector, price) {\n            root.querySelectorAll(selector).forEach((el) => {\n                el.textContent = money(price);\n            });\n        }\n\n        function openCart() {\n            if (window.jQuery && window.fkcart_app_data) {\n                window.jQuery(document.body).trigger('fkcart_open');\n            } else if (ajaxParams?.cart_url) {\n                window.location.assign(ajaxParams.cart_url);\n            }\n        }\n\n        function setBusy(busy) {\n            state.busy = busy;\n            root.querySelector('.configurator').setAttribute('aria-busy', String(busy));\n            root.querySelectorAll(\n                '.bf-buy-app input, .bf-buy-app select, .bf-buy-app button',\n            ).forEach((el) => {\n                if (busy) {\n                    el.dataset.wasDisabled = el.disabled ? 'true' : 'false';\n                    el.disabled = true;\n                } else {\n                    el.disabled = el.dataset.wasDisabled === 'true';\n                    delete el.dataset.wasDisabled;\n                }\n            });\n            root.querySelector('.bf-buy-busy').hidden = !busy;\n        }\n\n        function renderGallery() {\n            const model = config.models[config.trackerId];\n            const images = model.images || [model.image];\n            const image = images[state.image];\n            if (image) {\n                find('product-photo').src = image.src;\n                find('product-photo').alt = image.alt || model.name;\n            }\n            find('gallery-thumbnails')\n                .querySelectorAll('button')\n                .forEach((button, index) => {\n                    button.setAttribute('aria-pressed', String(index === state.image));\n                });\n        }\n\n        function renderBikeValue() {\n            const slider = find('bike-value');\n            const stops = [0, ...bands];\n            slider.max = bands.length;\n            slider.disabled = !bands.length;\n            slider.value = state.tier;\n            const value = money(stops[state.tier] * 10 ** currencyMeta.currency_minor_unit);\n            find('bike-value-amount').textContent = state.insurance ? value : copy.noInsurance;\n            slider.setAttribute(\n                'aria-valuetext',\n                state.insurance\n                    ? copy.valueUp + ' ' + value\n                    : copy.tracking + ' \u00b7 ' + copy.noInsurance,\n            );\n            slider.style.setProperty(\n                '--value-progress',\n                bands.length ? (state.tier \/ bands.length) * 100 + '%' : '0%',\n            );\n            find('value-stops').replaceChildren(\n                ...stops.map((limit, index) => {\n                    const stop = document.createElement('span');\n                    stop.className = 'value-stop';\n                    stop.style.setProperty(\n                        '--stop-position',\n                        bands.length ? (index \/ bands.length) * 100 + '%' : '0%',\n                    );\n                    if (!(bands.length > 3) || index === 0 || index === bands.length) {\n                        const label = document.createElement('span');\n                        label.textContent = money(limit * 10 ** currencyMeta.currency_minor_unit);\n                        stop.append(label);\n                    }\n                    return stop;\n                }),\n            );\n        }\n\n        function billingCadence(months) {\n            return (\n                copy.billingCadences?.[months] ||\n                (months === 1\n                    ? copy.renewalMonth\n                    : copy.renewalLong + ' ' + months + ' ' + copy.months)\n            );\n        }\n\n        function renderBilling() {\n            const active = root.ownerDocument.activeElement;\n            const focused = active?.name === 'bf-billing' ? active.value : null;\n            const tier = state.insurance ? state.tier : 0;\n            const monthly = plans.get(tier + '-1');\n            const holder = find('billing-choices');\n            holder.replaceChildren();\n            [1, 12, 24].forEach((months) => {\n                const plan = plans.get(tier + '-' + months);\n                const label = document.createElement('label');\n                label.className = 'choice';\n                const input = document.createElement('input');\n                input.type = 'radio';\n                input.name = 'bf-billing';\n                input.value = months;\n                input.checked = state.months === months;\n                input.disabled = !plan;\n                const face = document.createElement('span');\n                face.className = 'choice-face';\n                const title = document.createElement('strong');\n                title.className = 'period-label';\n                title.textContent = months === 1 ? copy.monthly : months + ' ' + copy.months;\n                const equivalent = document.createElement('span');\n                equivalent.className = 'charge-price';\n                const number = document.createElement('span');\n                number.className = 'charge-number';\n                const rate = plan ? money(Math.round(plan.price \/ months)) : '\u2014';\n                number.textContent = rate;\n                const suffix = document.createElement('span');\n                suffix.className = 'rate-unit';\n                suffix.textContent = copy.perMonth;\n                equivalent.append(number, suffix);\n                const billed = document.createElement('small');\n                billed.className = 'charge-frequency sr-only';\n                \/\/ Keep every option's full native charge accessible without a second visual row.\n                billed.textContent = plan ? money(plan.price) + ' ' + billingCadence(months) : '';\n                const saving =\n                    plan && monthly\n                        ? Math.round((1 - plan.price \/ (monthly.price * months)) * 100)\n                        : 0;\n                const badge = document.createElement('small');\n                badge.className = 'saving';\n                badge.textContent = copy.save + ' ' + saving + ' %';\n                badge.hidden = !(saving > 0) || months === 1;\n                const heading = document.createElement('span');\n                heading.className = 'period-heading';\n                heading.append(title, badge);\n                face.append(heading, equivalent, billed);\n                label.append(input, face);\n                holder.append(label);\n            });\n            if (focused) holder.querySelector('input[value=\"' + focused + '\"]').focus();\n        }\n\n        function render() {\n            const plan = selectedPlan();\n            const stock = Boolean(tracker);\n            const hasCart = state.cart?.items.length > 0 && !state.job;\n            const hardwarePrice = tracker ? money(tracker.price) : '\u2014';\n            find('hardware-price').textContent = hardwarePrice;\n            find('hardware-name').textContent =\n                config.models[config.trackerId]?.name || copy.fallbackTitle;\n            find('config-heading').textContent =\n                config.models[config.trackerId]?.name || copy.fallbackTitle;\n            find('include-tracker').checked = !state.owner;\n            find('include-subscription').checked = state.subscription;\n            find('tracker-card').dataset.selected = String(!state.owner);\n            find('subscription-card').dataset.selected = String(state.subscription);\n            find('subscription-settings').hidden = !state.subscription;\n            find('protection-settings').hidden = !bands.length;\n            find('insurance-settings').hidden = !bands.length;\n            find('insurance-option').disabled = !bands.length;\n            find('billing-number').textContent = bands.length ? '2' : '1';\n            find('plan-type').hidden = true;\n            find('plan-type').textContent = copy.trackingDesc;\n            find('eligibility-copy').hidden = !state.insurance || !state.subscription;\n            root.querySelectorAll('input[name=\"bf-protection\"]').forEach((input) => {\n                input.checked = (input.value === 'insurance') === state.insurance;\n            });\n            renderBikeValue();\n            renderBilling();\n            find('tracker-summary-row').hidden = state.owner;\n            if (tracker) find('tracker-summary-price').textContent = money(tracker.price);\n            find('plan-summary-row').hidden = !state.subscription;\n            find('plan-summary-label').textContent =\n                (state.insurance ? copy.insured : copy.subscriptionLabel) +\n                ' \u00b7 ' +\n                state.months +\n                ' ' +\n                (state.months === 1 ? copy.month : copy.months);\n            find('plan-summary-price').textContent = plan ? money(plan.price) : '\u2014';\n            const total = (plan?.price || 0) + (state.owner ? 0 : tracker?.price || 0);\n            setPrice('.today-price', total);\n            find('renewal-copy').hidden = !state.subscription;\n            find('renewal-amount').textContent = plan\n                ? money(plan.price) + ' ' + billingCadence(state.months)\n                : '';\n            find('hardware-only-note').hidden = state.subscription;\n            note.hidden = !hasCart;\n            const purchaseLabel = state.job ? copy.retry : copy.checkout;\n            root.querySelectorAll('[data-checkout]').forEach((button) => {\n                button.querySelector('span').textContent = hasCart\n                    ? copy.reviewCart\n                    : purchaseLabel;\n                button.setAttribute(\n                    'aria-disabled',\n                    String(\n                        !hasCart &&\n                            ((state.owner && !state.subscription) ||\n                                (state.subscription && !plan) ||\n                                (!stock && !state.owner)),\n                    ),\n                );\n            });\n            find('eligibility-error').hidden = true;\n            if (!stock && !state.owner) message(copy.unavailableHardware);\n            rememberSelection();\n        }\n\n        function checkoutUrl(fragments) {\n            const fragment = Object.values(fragments || {})\n                .filter((value) => typeof value === 'string')\n                .join('');\n            const document = new window.DOMParser().parseFromString(fragment, 'text\/html');\n            const anchor =\n                document.querySelector('#fkcart-checkout-button, a.checkout.wc-forward') ||\n                window.document.querySelector('#fkcart-checkout-button, a.checkout.wc-forward');\n            if (anchor) {\n                const url = new URL(anchor.href, window.location.href);\n                if (url.origin === window.location.origin) return url.href;\n            }\n            return ajaxParams.cart_url;\n        }\n\n        function refreshDrawer() {\n            if (!window.jQuery || !window.fkcart_app_data) return Promise.resolve();\n            \/\/ Let FunnelKit replace and persist its own fragments. Store API analytics\n            \/\/ already track the batch; emitting legacy added_to_cart would count it twice.\n            return new Promise((resolve, reject) => {\n                const body = window.jQuery(document.body);\n                const event = 'wc_fragments_refreshed.bfbuycheckout';\n                const done = () => {\n                    clearTimeout(timeout);\n                    body.off(event, done);\n                    resolve();\n                };\n                const timeout = setTimeout(() => {\n                    body.off(event, done);\n                    reject(new Error(copy.checkoutError));\n                }, 20000);\n                body.one(event, done);\n                body.trigger('fkcart_update_side_cart', [false]);\n            });\n        }\n\n        async function purchase() {\n            if (state.busy) return;\n            if (state.cart.items.length && !state.job) {\n                openCart();\n                return;\n            }\n            if (\n                (state.owner && !state.subscription) ||\n                (state.subscription && !selectedPlan()) ||\n                (!state.owner && !tracker)\n            )\n                return;\n            const products = [\n                ...(!state.owner ? [tracker.id] : []),\n                ...(state.subscription ? [selectedPlan().id] : []),\n            ];\n            const fingerprint = products.join(',');\n            if (state.job && state.job.fingerprint !== fingerprint) {\n                message(copy.partialError);\n                openCart();\n                return;\n            }\n            setBusy(true);\n            message('');\n            try {\n                let current = await cart();\n                if (expectedCountry && current.shipping_address.country !== expectedCountry)\n                    throw new Error(copy.deliveryChanged);\n                if (!state.job && current.items.length) {\n                    state.cart = current;\n                    await refreshDrawer();\n                    setBusy(false);\n                    render();\n                    openCart();\n                    return;\n                }\n                state.job ||= {\n                    fingerprint,\n                    products,\n                    baseline: Object.fromEntries(products.map((id) => [id, quantity(current, id)])),\n                };\n                const job = state.job;\n                const remaining = job.products.filter((id) => {\n                    const count = quantity(current, id);\n                    if (count === job.baseline[id] + 1) return false;\n                    if (count !== job.baseline[id]) throw new Error(copy.partialError);\n                    return true;\n                });\n                if (current.items.some((item) => !job.products.includes(Number(item.id))))\n                    throw new Error(copy.partialError);\n                if (remaining.length) {\n                    try {\n                        const result = await json('\/wp-json\/wc\/store\/v1\/batch', {\n                            method: 'POST',\n                            headers: { 'Content-Type': 'application\/json' },\n                            body: JSON.stringify({\n                                requests: remaining.map((id) => ({\n                                    path: '\/wc\/store\/v1\/cart\/add-item',\n                                    method: 'POST',\n                                    headers: { Nonce: cartNonce },\n                                    body: { id, quantity: 1 },\n                                })),\n                            }),\n                        });\n                        if (\n                            result.responses?.length !== remaining.length ||\n                            result.responses.some(\n                                (response) => !(response.status >= 200 && 300 > response.status),\n                            )\n                        )\n                            throw new Error(copy.checkoutError);\n                        current = result.responses.at(-1).body;\n                    } catch (error) {\n                        \/\/ A lost response can still mean success. Re-read only on failure.\n                        current = await cart();\n                        if (\n                            !job.products.every(\n                                (id) => quantity(current, id) === job.baseline[id] + 1,\n                            )\n                        )\n                            throw error;\n                    }\n                }\n                if (!job.products.every((id) => quantity(current, id) === job.baseline[id] + 1))\n                    throw new Error(copy.partialError);\n                state.cart = current;\n                if (expectedCountry && state.cart.shipping_address.country !== expectedCountry)\n                    throw new Error(copy.deliveryChanged);\n                await refreshDrawer();\n                window.location.assign(checkoutUrl());\n            } catch (error) {\n                message(error.message || copy.checkoutError);\n                try {\n                    state.cart = await cart();\n                    await refreshDrawer();\n                } catch {\n                    \/* Preserve the attempt so a retry cannot duplicate it. *\/\n                }\n                if (!state.cart.items.length) state.job = null;\n                setBusy(false);\n                render();\n            }\n        }\n\n        try {\n            if (!ajaxParams?.wc_ajax_url || !ajaxParams.cart_url)\n                throw new Error(copy.priceUnavailable);\n            if (!market || source.querySelectorAll('[data-offer-zone]').length !== 1)\n                throw new Error(copy.priceUnavailable);\n            const trackerCards = source.querySelectorAll('.bf-source-trackers li.product');\n            if (trackerCards.length > 1) throw new Error(copy.priceUnavailable);\n            state.cart = await cart();\n            Object.assign(currencyMeta, state.cart.totals);\n            if (expectedCountry && state.cart.shipping_address.country !== expectedCountry)\n                throw new Error(copy.deliveryChanged);\n            tracker = nativeProduct(trackerCards[0]);\n            const title = trackerCards[0]\n                ?.querySelector('.woocommerce-loop-product__title')\n                ?.textContent.trim();\n            config.trackerId =\n                tracker?.id || Number(trackerCards[0]?.className.match(\/\\bpost-(\\d+)\\b\/)?.[1]);\n            const model = config.models[config.trackerId];\n            source.querySelectorAll('.bf-buy-native-plan').forEach((el) => {\n                const product = nativeProduct(el);\n                if (product) {\n                    \/\/ Correct the Norwegian cadence supplied by the native price markup.\n                    \/\/ Only text nodes change; amounts and billing intervals stay native.\n                    if (config.locale === 'nb-NO') {\n                        const text = document.createTreeWalker(el, window.NodeFilter.SHOW_TEXT);\n                        while (text.nextNode()) {\n                            text.currentNode.nodeValue = text.currentNode.nodeValue.replace(\n                                \/\\bhver\\s+2\\s+\u00e5r\\b\/gu,\n                                'hvert 2. \u00e5r',\n                            );\n                        }\n                    }\n                    plans.set(`${el.dataset.tier}-${el.dataset.months}`, product);\n                }\n            });\n            if (![1, 12, 24].every((months) => plans.has('0-' + months)))\n                throw new Error(copy.priceUnavailable);\n            root.querySelectorAll('.model-name').forEach((el) => {\n                el.textContent = title || model?.name || '';\n            });\n            find('destination-copy').textContent = `${copy.destination} ${countryName}.`;\n            find('product-stage').dataset.model = model?.role || 'g2';\n            find('box-copy').textContent = model?.role === 'g2' ? copy.boxG2 : copy.boxG1;\n            const nativeImage = trackerCards[0]?.querySelector('img');\n            const images = model?.images || [\n                model?.image || { src: nativeImage?.src, alt: nativeImage?.alt },\n            ];\n            if (!model || !images[0]?.src) throw new Error(copy.priceUnavailable);\n            \/\/ Keep headings, the tracker card and gallery aligned with the native product title.\n            model.name = title || model.name;\n            model.images = images;\n            find('gallery-thumbnails').setAttribute('aria-label', copy.gallery);\n            images.forEach((image, index) => {\n                const button = document.createElement('button');\n                button.className = 'gallery-thumbnail';\n                button.type = 'button';\n                button.setAttribute('aria-label', copy.gallery + ': ' + (index + 1));\n                const photo = document.createElement('img');\n                photo.src = image.src;\n                photo.alt = '';\n                photo.loading = 'lazy';\n                button.append(photo);\n                button.addEventListener('click', () => {\n                    state.image = index;\n                    renderGallery();\n                });\n                find('gallery-thumbnails').append(button);\n            });\n            renderGallery();\n            const eligibility =\n                market.dataset.offerZone === 'germany'\n                    ? copy.germanEligibility\n                    : copy.eligibility + ' ' + countryName + '. ' + copy.eligibilityEnd;\n            const linkText =\n                market.dataset.offerZone === 'germany'\n                    ? copy.policyInlineGerman\n                    : copy.policyInline;\n            const linkStart = eligibility.indexOf(linkText);\n            if (bands.length && linkStart === -1) throw new Error(copy.priceUnavailable);\n            const policyLink = document.createElement('a');\n            policyLink.id = 'bf-policy-link';\n            policyLink.textContent = linkText;\n            policyLink.href = '\/terms\/' + market.dataset.offerZone + '\/';\n            policyLink.target = '_blank';\n            policyLink.rel = 'noopener';\n            find('eligibility-copy').replaceChildren(\n                eligibility.slice(0, linkStart),\n                policyLink,\n                eligibility.slice(linkStart + linkText.length),\n            );\n            root.querySelectorAll('input[name=\"bf-protection\"]').forEach((input) => {\n                const selectProtection = () => {\n                    state.insurance = input.value === 'insurance';\n                    state.tier = state.insurance ? state.insuranceTier : 0;\n                    render();\n                };\n                input.addEventListener('change', selectProtection);\n                input.addEventListener('click', selectProtection);\n            });\n            find('billing-choices').addEventListener('change', (event) => {\n                state.months = Number(event.target.value);\n                render();\n            });\n            find('bike-value').addEventListener('input', (event) => {\n                state.tier = Number(event.target.value);\n                state.insurance = state.tier > 0;\n                if (state.insurance) state.insuranceTier = state.tier;\n                render();\n            });\n            find('include-tracker').addEventListener('change', (event) => {\n                state.owner = !event.target.checked;\n                render();\n            });\n            find('include-subscription').addEventListener('change', (event) => {\n                state.subscription = event.target.checked;\n                find('subscription-card').open = state.subscription;\n                render();\n            });\n            root.querySelectorAll('[data-checkout]').forEach((button) => {\n                button.addEventListener('click', purchase);\n            });\n            root.querySelector('[data-review-cart]').addEventListener('click', openCart);\n            root.querySelector('.bf-buy-busy').textContent = copy.adding;\n            if (window.jQuery)\n                window\n                    .jQuery(document.body)\n                    .on('removed_from_cart.bfbuy wc_fragments_refreshed.bfbuy', () => {\n                        if (state.busy) return;\n                        const drawer = document.querySelector('#fkcart-modal');\n                        if (!drawer || !window.fkcart_app_data) return;\n                        \/\/ The native drawer response already tells us whether to offer\n                        \/\/ cart review. Avoid another session request during cart mutations;\n                        \/\/ purchase still reads the authoritative Store API cart and nonce.\n                        state.cart.items = Array.from(\n                            drawer.querySelectorAll('.fkcart--item[data-key]'),\n                        ).map((item) => ({\n                            ...state.cart.items.find((known) => known.key === item.dataset.key),\n                            key: item.dataset.key,\n                            quantity: Number(\n                                item.querySelector('.fkcart-quantity__input')?.value || 1,\n                            ),\n                        }));\n                        if (!state.cart.items.length) state.job = null;\n                        render();\n                    });\n            restoreSelection();\n            render();\n            root.querySelector('.bf-buy-initial-error').hidden = true;\n            root.classList.add('is-ready');\n            document.documentElement.classList.remove('bf-buy-loading');\n        } catch (error) {\n            message(error.message || copy.priceUnavailable);\n            document.documentElement.classList.remove('bf-buy-loading');\n            \/\/ Native product\/plan buttons remain usable if the enhancement cannot initialise.\n        }\n    }\n    if (document.readyState === 'loading')\n        \/\/ WPML writes its AJAX-language cookie in a later DOMContentLoaded handler.\n        \/\/ Start after those native handlers so the first cart read uses this page's language.\n        document.addEventListener('DOMContentLoaded', () => window.setTimeout(initialise, 0));\n    else initialise();\n})();\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"<p>Ladataan valintojasi\u2026 Bikefinder Tracker Gen2 Sopiiko se py\u00f6r\u00e4\u00e4ni?15\u201327 mm Paikannin sopii ohjaustankoihin, joiden sis\u00e4halkaisija on 15\u201327 mm. Tarkista ohjaustangon sis\u00e4puoli ennen tilaamista. GPS-paikannin Piilossa ohjaustangossa. Yhteydess\u00e4 puhelimeesi. Ota BikeFinder mukaan seuraavalle lenkille. Valitse ostoskoriin lis\u00e4tt\u00e4v\u00e4t tuotteet. Vaatii erillisen tilauksen Kertaostos Tilaus GPS-paikannus 1Valitse suojaus PaikannusPaikanna py\u00f6r\u00e4si sovelluksessa aktiivisella tilauksella. Paikannus + vakuutusPaikannus ja valinnainen polkupy\u00f6r\u00e4vakuutus. [&hellip;]<\/p>\n","protected":false},"author":7498,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"block-theme-template.php","meta":{"site-sidebar-layout":"no-sidebar","site-content-layout":"page-builder","ast-site-content-layout":"full-width-container","site-content-style":"unboxed","site-sidebar-style":"unboxed","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"disabled","ast-breadcrumbs-content":"","ast-featured-img":"disabled","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-156471","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Osta BikeFinder | Py\u00f6r\u00e4n paikannin ja tilaus<\/title>\n<meta name=\"description\" content=\"Paikanna py\u00f6r\u00e4si sovelluksessa aktiivisella tilauksella.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/bikefinder.com\/fi\/buy\/\" \/>\n<meta property=\"og:locale\" content=\"fi_FI\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Osta BikeFinder | Py\u00f6r\u00e4n paikannin ja tilaus\" \/>\n<meta property=\"og:description\" content=\"Paikanna py\u00f6r\u00e4si sovelluksessa aktiivisella tilauksella.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/bikefinder.com\/fi\/buy\/\" \/>\n<meta property=\"og:site_name\" content=\"BikeFinder\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/teambikefinder\" \/>\n<meta property=\"article:modified_time\" content=\"2026-11-03T00:20:54+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/bikefinder.com\/wp-content\/uploads\/2025\/09\/Box-design-clean-no-logo-PNG_without-side-scaled.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1962\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@TeamBikeFinder\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":[\"WebPage\",\"ItemPage\"],\"@id\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/buy\\\/\",\"url\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/buy\\\/\",\"name\":\"Osta BikeFinder | Py\u00f6r\u00e4n paikannin ja tilaus\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/#website\"},\"datePublished\":\"2021-12-07T12:48:05+00:00\",\"dateModified\":\"2026-11-03T00:20:54+00:00\",\"description\":\"Paikanna py\u00f6r\u00e4si sovelluksessa aktiivisella tilauksella.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/buy\\\/#breadcrumb\"},\"inLanguage\":\"fi-FI\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/bikefinder.com\\\/fi\\\/buy\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/buy\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"osta py\u00f6r\u00e4npaikannin\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/#website\",\"url\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/\",\"name\":\"BikeFinder\",\"description\":\"GPS-sporing og forsikring til sykkel\",\"publisher\":{\"@id\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fi-FI\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/#organization\",\"name\":\"BikeFinder\",\"url\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fi-FI\",\"@id\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/bikefinder.com\\\/wp-content\\\/uploads\\\/2020\\\/05\\\/logo_drop_big.png\",\"contentUrl\":\"https:\\\/\\\/bikefinder.com\\\/wp-content\\\/uploads\\\/2020\\\/05\\\/logo_drop_big.png\",\"width\":200,\"height\":200,\"caption\":\"BikeFinder\"},\"image\":{\"@id\":\"https:\\\/\\\/bikefinder.com\\\/fi\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/teambikefinder\",\"https:\\\/\\\/x.com\\\/TeamBikeFinder\",\"https:\\\/\\\/www.instagram.com\\\/teambikefinder\\\/\",\"https:\\\/\\\/www.youtube.com\\\/@teambikefinder\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/bikefinder\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Osta BikeFinder | Py\u00f6r\u00e4n paikannin ja tilaus","description":"Paikanna py\u00f6r\u00e4si sovelluksessa aktiivisella tilauksella.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/bikefinder.com\/fi\/buy\/","og_locale":"fi_FI","og_type":"article","og_title":"Osta BikeFinder | Py\u00f6r\u00e4n paikannin ja tilaus","og_description":"Paikanna py\u00f6r\u00e4si sovelluksessa aktiivisella tilauksella.","og_url":"https:\/\/bikefinder.com\/fi\/buy\/","og_site_name":"BikeFinder","article_publisher":"https:\/\/www.facebook.com\/teambikefinder","article_modified_time":"2026-11-03T00:20:54+00:00","og_image":[{"width":2560,"height":1962,"url":"https:\/\/bikefinder.com\/wp-content\/uploads\/2025\/09\/Box-design-clean-no-logo-PNG_without-side-scaled.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_site":"@TeamBikeFinder","twitter_misc":{"Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["WebPage","ItemPage"],"@id":"https:\/\/bikefinder.com\/fi\/buy\/","url":"https:\/\/bikefinder.com\/fi\/buy\/","name":"Osta BikeFinder | Py\u00f6r\u00e4n paikannin ja tilaus","isPartOf":{"@id":"https:\/\/bikefinder.com\/fi\/#website"},"datePublished":"2021-12-07T12:48:05+00:00","dateModified":"2026-11-03T00:20:54+00:00","description":"Paikanna py\u00f6r\u00e4si sovelluksessa aktiivisella tilauksella.","breadcrumb":{"@id":"https:\/\/bikefinder.com\/fi\/buy\/#breadcrumb"},"inLanguage":"fi-FI","potentialAction":[{"@type":"ReadAction","target":["https:\/\/bikefinder.com\/fi\/buy\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/bikefinder.com\/fi\/buy\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/bikefinder.com\/fi\/"},{"@type":"ListItem","position":2,"name":"osta py\u00f6r\u00e4npaikannin"}]},{"@type":"WebSite","@id":"https:\/\/bikefinder.com\/fi\/#website","url":"https:\/\/bikefinder.com\/fi\/","name":"BikeFinder","description":"GPS-sporing og forsikring til sykkel","publisher":{"@id":"https:\/\/bikefinder.com\/fi\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/bikefinder.com\/fi\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fi-FI"},{"@type":"Organization","@id":"https:\/\/bikefinder.com\/fi\/#organization","name":"BikeFinder","url":"https:\/\/bikefinder.com\/fi\/","logo":{"@type":"ImageObject","inLanguage":"fi-FI","@id":"https:\/\/bikefinder.com\/fi\/#\/schema\/logo\/image\/","url":"https:\/\/bikefinder.com\/wp-content\/uploads\/2020\/05\/logo_drop_big.png","contentUrl":"https:\/\/bikefinder.com\/wp-content\/uploads\/2020\/05\/logo_drop_big.png","width":200,"height":200,"caption":"BikeFinder"},"image":{"@id":"https:\/\/bikefinder.com\/fi\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/teambikefinder","https:\/\/x.com\/TeamBikeFinder","https:\/\/www.instagram.com\/teambikefinder\/","https:\/\/www.youtube.com\/@teambikefinder\/","https:\/\/www.linkedin.com\/company\/bikefinder"]}]}},"_links":{"self":[{"href":"https:\/\/bikefinder.com\/fi\/wp-json\/wp\/v2\/pages\/156471","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bikefinder.com\/fi\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bikefinder.com\/fi\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bikefinder.com\/fi\/wp-json\/wp\/v2\/users\/7498"}],"replies":[{"embeddable":true,"href":"https:\/\/bikefinder.com\/fi\/wp-json\/wp\/v2\/comments?post=156471"}],"version-history":[{"count":29,"href":"https:\/\/bikefinder.com\/fi\/wp-json\/wp\/v2\/pages\/156471\/revisions"}],"predecessor-version":[{"id":398048,"href":"https:\/\/bikefinder.com\/fi\/wp-json\/wp\/v2\/pages\/156471\/revisions\/398048"}],"wp:attachment":[{"href":"https:\/\/bikefinder.com\/fi\/wp-json\/wp\/v2\/media?parent=156471"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}