{"id":3555,"date":"2026-05-13T13:22:25","date_gmt":"2026-05-13T13:22:25","guid":{"rendered":"https:\/\/www.passionnementtennis.com\/?page_id=3555"},"modified":"2026-05-13T14:16:11","modified_gmt":"2026-05-13T14:16:11","slug":"book","status":"publish","type":"page","link":"https:\/\/www.passionnementtennis.com\/fr\/book\/","title":{"rendered":"Book"},"content":{"rendered":"<div data-elementor-type=\"wp-page\" data-elementor-id=\"3555\" class=\"elementor elementor-3555\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3d4389c e-flex e-con-boxed e-con e-parent\" data-id=\"3d4389c\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-f279fca elementor-widget elementor-widget-html\" data-id=\"f279fca\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div id=\"pt-booking-stepper\" style=\"font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Arial,sans-serif;color:#173629;background:#f7f5ef;\">\n  <style>\n    #pt-booking-stepper * { box-sizing:border-box; }\n    #pt-booking-stepper .ptb-wrap { max-width:1120px; margin:0 auto; padding:24px 16px; }\n    #pt-booking-stepper .ptb-shell { display:grid; grid-template-columns:minmax(0,1fr) 330px; gap:20px; align-items:start; }\n    #pt-booking-stepper .ptb-title { margin:0 0 6px; font-size:34px; line-height:1.08; letter-spacing:0; font-family:Georgia,'Times New Roman',serif; }\n    #pt-booking-stepper .ptb-sub { margin:0 0 22px; color:#4a5d54; line-height:1.55; }\n    #pt-booking-stepper .ptb-step {\n      background:#fff; border:1px solid rgba(23,54,41,.10); border-radius:18px; margin-bottom:12px;\n      box-shadow:0 8px 30px rgba(0,0,0,.045); overflow:hidden;\n    }\n    #pt-booking-stepper .ptb-step-head {\n      width:100%; border:0; background:#fff; color:#173629; display:flex; align-items:center; gap:12px;\n      padding:18px; text-align:left; cursor:pointer;\n    }\n    #pt-booking-stepper .ptb-num {\n      width:34px; height:34px; border-radius:50%; background:#173629; color:#fff; display:flex;\n      align-items:center; justify-content:center; font-weight:800; flex:0 0 auto;\n    }\n    #pt-booking-stepper .ptb-head-main { flex:1; min-width:0; }\n    #pt-booking-stepper .ptb-head-main strong { display:block; font-size:17px; }\n    #pt-booking-stepper .ptb-head-main span { display:block; color:#617168; font-size:13px; margin-top:3px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n    #pt-booking-stepper .ptb-edit { font-weight:800; color:#173629; font-size:13px; }\n    #pt-booking-stepper .ptb-body { padding:0 18px 18px; }\n    #pt-booking-stepper .ptb-step:not(.is-active) .ptb-body { display:none; }\n    #pt-booking-stepper .ptb-step.is-complete:not(.is-active) .ptb-num { background:#d8b36a; color:#173629; }\n    #pt-booking-stepper label { display:block; font-weight:800; font-size:13px; margin:0 0 7px; }\n    #pt-booking-stepper input[type=\"text\"],\n    #pt-booking-stepper input[type=\"tel\"],\n    #pt-booking-stepper input[type=\"date\"],\n    #pt-booking-stepper input[type=\"time\"] {\n      width:100%; border:1px solid rgba(23,54,41,.16); border-radius:12px; padding:13px 12px;\n      font:inherit; background:#fbfaf6; color:#173629; min-height:46px;\n    }\n    #pt-booking-stepper input[type=\"range\"] { width:100%; accent-color:#173629; }\n    #pt-booking-stepper .ptb-fields { display:grid; grid-template-columns:1fr 1fr; gap:12px; }\n    #pt-booking-stepper .ptb-options { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; }\n    #pt-booking-stepper .ptb-option {\n      border:1px solid rgba(23,54,41,.14); background:#fbfaf6; border-radius:16px; padding:14px;\n      cursor:pointer; min-height:92px; display:flex; gap:12px; align-items:flex-start; position:relative;\n    }\n    #pt-booking-stepper .ptb-option input { position:absolute; opacity:0; pointer-events:none; }\n    #pt-booking-stepper .ptb-option.is-selected { border-color:#d8b36a; box-shadow:0 0 0 2px rgba(216,179,106,.26); background:#fff; }\n    #pt-booking-stepper .ptb-option-main { flex:1; min-width:0; }\n    #pt-booking-stepper .ptb-option strong { display:block; font-size:15px; }\n    #pt-booking-stepper .ptb-option small { display:block; margin-top:4px; color:#617168; line-height:1.35; }\n    #pt-booking-stepper .ptb-price { font-weight:900; white-space:nowrap; color:#173629; }\n    #pt-booking-stepper .ptb-pack {\n      width:44px; height:58px; border-radius:9px; flex:0 0 auto; box-shadow:inset 0 0 0 1px rgba(255,255,255,.28), 0 7px 16px rgba(0,0,0,.12);\n      display:flex; align-items:center; justify-content:center; color:#fff; font-size:10px; font-weight:900; text-align:center; padding:4px; line-height:1.05;\n    }\n    #pt-booking-stepper .ptb-pack.light { color:#173629; }\n    #pt-booking-stepper .ptb-string-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; max-height:520px; overflow:auto; padding-right:3px; }\n    #pt-booking-stepper .ptb-slider-box { background:#fbfaf6; border:1px solid rgba(23,54,41,.10); border-radius:16px; padding:14px; margin-bottom:12px; }\n    #pt-booking-stepper .ptb-slider-row { display:flex; justify-content:space-between; align-items:center; gap:12px; margin-bottom:8px; }\n    #pt-booking-stepper .ptb-slider-row strong { font-size:22px; }\n    #pt-booking-stepper .ptb-actions { display:flex; justify-content:flex-end; gap:10px; margin-top:16px; flex-wrap:wrap; }\n    #pt-booking-stepper .ptb-btn {\n      border:0; border-radius:999px; padding:13px 18px; font-weight:900; cursor:pointer; font:inherit;\n      min-height:46px; text-decoration:none; display:inline-flex; align-items:center; justify-content:center;\n    }\n    #pt-booking-stepper .ptb-btn-primary { background:#173629; color:#fff; }\n    #pt-booking-stepper .ptb-btn-secondary { background:#d8b36a; color:#173629; }\n    #pt-booking-stepper .ptb-btn-plain { background:#efe7d4; color:#173629; }\n    #pt-booking-stepper .ptb-summary {\n      position:sticky; top:14px; background:#173629; color:#fff; border-radius:20px; padding:18px;\n      box-shadow:0 12px 36px rgba(0,0,0,.12);\n    }\n    #pt-booking-stepper .ptb-summary h3 { margin:0 0 12px; font-size:18px; color:#fff; }\n    #pt-booking-stepper .ptb-total { font-size:42px; font-weight:950; line-height:1; margin:0 0 12px; color:#fff; }\n    #pt-booking-stepper .ptb-line { display:flex; justify-content:space-between; gap:12px; padding:9px 0; border-top:1px solid rgba(255,255,255,.14); font-size:14px; }\n    #pt-booking-stepper .ptb-line span:first-child { color:rgba(255,255,255,.78); }\n    #pt-booking-stepper .ptb-note { margin:12px 0 0; color:rgba(255,255,255,.78); font-size:13px; line-height:1.45; }\n    #pt-booking-stepper .ptb-review {\n      background:#fbfaf6; border:1px solid rgba(23,54,41,.10); border-radius:16px; padding:14px; line-height:1.55;\n    }\n    #pt-booking-stepper .ptb-success {\n      display:none; background:#173629; color:#fff; border-radius:18px; padding:18px; margin-top:14px;\n    }\n    #pt-booking-stepper .ptb-success h3 { margin:0 0 8px; color:#fff; }\n    #pt-booking-stepper .ptb-success p { color:rgba(255,255,255,.86); }\n    #pt-booking-stepper .ptb-error { display:none; color:#9a2a1f; font-weight:800; margin-top:10px; }\n    #pt-booking-stepper .ptb-send-note { display:none; margin:10px 0 0; color:#617168; font-weight:800; font-size:13px; }\n    @media (max-width: 920px) {\n      #pt-booking-stepper .ptb-shell { grid-template-columns:1fr; }\n      #pt-booking-stepper .ptb-summary { position:sticky; top:0; z-index:5; border-radius:0 0 20px 20px; margin:-24px -16px 18px; }\n      #pt-booking-stepper .ptb-fields, #pt-booking-stepper .ptb-options, #pt-booking-stepper .ptb-string-grid { grid-template-columns:1fr; }\n      #pt-booking-stepper .ptb-title { font-size:28px; }\n      #pt-booking-stepper .ptb-total { font-size:36px; }\n    }\n  <\/style>\n\n  <div class=\"ptb-wrap\">\n    <h2 class=\"ptb-title\">Book Tennis Racket Stringing<\/h2>\n    <p class=\"ptb-sub\">Choose your drop-off, string, tension and turnaround. The price updates as you build your setup.<\/p>\n\n    <div class=\"ptb-shell\">\n      <div class=\"ptb-flow\">\n        <section class=\"ptb-step is-active\" data-step=\"1\">\n          <button class=\"ptb-step-head\" type=\"button\" data-open-step=\"1\">\n            <span class=\"ptb-num\">1<\/span>\n            <span class=\"ptb-head-main\"><strong>Drop-off date and time<\/strong><span data-summary=\"dropoff\">Choose a drop-off slot<\/span><\/span>\n            <span class=\"ptb-edit\">Edit<\/span>\n          <\/button>\n          <div class=\"ptb-body\">\n            <div class=\"ptb-fields\">\n              <div>\n                <label for=\"ptb-date\">Drop-off date<\/label>\n                <input id=\"ptb-date\" type=\"date\" required>\n              <\/div>\n              <div>\n                <label for=\"ptb-time\">Drop-off time<\/label>\n                <input id=\"ptb-time\" type=\"time\" value=\"18:00\" required>\n              <\/div>\n            <\/div>\n            <div class=\"ptb-actions\"><button class=\"ptb-btn ptb-btn-primary\" type=\"button\" data-next=\"2\">Continue<\/button><\/div>\n          <\/div>\n        <\/section>\n\n        <section class=\"ptb-step\" data-step=\"2\">\n          <button class=\"ptb-step-head\" type=\"button\" data-open-step=\"2\">\n            <span class=\"ptb-num\">2<\/span>\n            <span class=\"ptb-head-main\"><strong>Choose string<\/strong><span data-summary=\"string\">Bring your own string or choose from stock<\/span><\/span>\n            <span class=\"ptb-edit\">Edit<\/span>\n          <\/button>\n          <div class=\"ptb-body\">\n            <div class=\"ptb-string-grid\" id=\"ptb-string-options\"><\/div>\n            <div class=\"ptb-actions\">\n              <button class=\"ptb-btn ptb-btn-plain\" type=\"button\" data-next=\"1\">Back<\/button>\n              <button class=\"ptb-btn ptb-btn-primary\" type=\"button\" data-next=\"3\">Continue<\/button>\n            <\/div>\n          <\/div>\n        <\/section>\n\n        <section class=\"ptb-step\" data-step=\"3\">\n          <button class=\"ptb-step-head\" type=\"button\" data-open-step=\"3\">\n            <span class=\"ptb-num\">3<\/span>\n            <span class=\"ptb-head-main\"><strong>Choose tension<\/strong><span data-summary=\"tension\">Mains 52 lbs \/ crosses 52 lbs<\/span><\/span>\n            <span class=\"ptb-edit\">Edit<\/span>\n          <\/button>\n          <div class=\"ptb-body\">\n            <div class=\"ptb-slider-box\">\n              <div class=\"ptb-slider-row\"><label for=\"ptb-mains\">Mains tension<\/label><strong><span id=\"ptb-mains-val\">52<\/span> lbs<\/strong><\/div>\n              <input id=\"ptb-mains\" type=\"range\" min=\"40\" max=\"65\" value=\"52\">\n            <\/div>\n            <div class=\"ptb-slider-box\">\n              <div class=\"ptb-slider-row\"><label for=\"ptb-crosses\">Crosses tension<\/label><strong><span id=\"ptb-crosses-val\">52<\/span> lbs<\/strong><\/div>\n              <input id=\"ptb-crosses\" type=\"range\" min=\"40\" max=\"65\" value=\"52\">\n            <\/div>\n            <div class=\"ptb-actions\">\n              <button class=\"ptb-btn ptb-btn-plain\" type=\"button\" data-next=\"2\">Back<\/button>\n              <button class=\"ptb-btn ptb-btn-primary\" type=\"button\" data-next=\"4\">Continue<\/button>\n            <\/div>\n          <\/div>\n        <\/section>\n\n        <section class=\"ptb-step\" data-step=\"4\">\n          <button class=\"ptb-step-head\" type=\"button\" data-open-step=\"4\">\n            <span class=\"ptb-num\">4<\/span>\n            <span class=\"ptb-head-main\"><strong>Collection speed<\/strong><span data-summary=\"speed\">Standard collection within 7 days<\/span><\/span>\n            <span class=\"ptb-edit\">Edit<\/span>\n          <\/button>\n          <div class=\"ptb-body\">\n            <div class=\"ptb-options\" id=\"ptb-speed-options\">\n              <label class=\"ptb-option\"><input type=\"radio\" name=\"speed\" value=\"standard\" data-label=\"Standard\" data-days=\"7\" data-price=\"0\" checked><span class=\"ptb-option-main\"><strong>Standard<\/strong><small>Ready within 7 days<\/small><\/span><span class=\"ptb-price\">+\u00a30<\/span><\/label>\n              <label class=\"ptb-option\"><input type=\"radio\" name=\"speed\" value=\"fast\" data-label=\"Fast\" data-days=\"4\" data-price=\"2\"><span class=\"ptb-option-main\"><strong>Fast<\/strong><small>Ready within 4 days<\/small><\/span><span class=\"ptb-price\">+\u00a32<\/span><\/label>\n              <label class=\"ptb-option\"><input type=\"radio\" name=\"speed\" value=\"urgent\" data-label=\"Urgent\" data-days=\"1\" data-price=\"6\"><span class=\"ptb-option-main\"><strong>Urgent<\/strong><small>Ready within 24 hours<\/small><\/span><span class=\"ptb-price\">+\u00a36<\/span><\/label>\n            <\/div>\n            <div class=\"ptb-actions\">\n              <button class=\"ptb-btn ptb-btn-plain\" type=\"button\" data-next=\"3\">Back<\/button>\n              <button class=\"ptb-btn ptb-btn-primary\" type=\"button\" data-next=\"5\">Continue<\/button>\n            <\/div>\n          <\/div>\n        <\/section>\n\n        <section class=\"ptb-step\" data-step=\"5\">\n          <button class=\"ptb-step-head\" type=\"button\" data-open-step=\"5\">\n            <span class=\"ptb-num\">5<\/span>\n            <span class=\"ptb-head-main\"><strong>Additional services<\/strong><span data-summary=\"addons\">No extras selected<\/span><\/span>\n            <span class=\"ptb-edit\">Edit<\/span>\n          <\/button>\n          <div class=\"ptb-body\">\n            <div class=\"ptb-options\">\n              <label class=\"ptb-option\"><input type=\"checkbox\" name=\"addon\" value=\"overgrip\" data-label=\"Overgrip\" data-price=\"3\"><span class=\"ptb-option-main\"><strong>Overgrip<\/strong><small>Fresh overgrip fitted before collection<\/small><\/span><span class=\"ptb-price\">+\u00a33<\/span><\/label>\n              <label class=\"ptb-option\"><input type=\"checkbox\" name=\"addon\" value=\"dampener\" data-label=\"Dampener\" data-price=\"2\"><span class=\"ptb-option-main\"><strong>Dampener<\/strong><small>Add a vibration dampener<\/small><\/span><span class=\"ptb-price\">+\u00a32<\/span><\/label>\n            <\/div>\n            <div class=\"ptb-actions\">\n              <button class=\"ptb-btn ptb-btn-plain\" type=\"button\" data-next=\"4\">Back<\/button>\n              <button class=\"ptb-btn ptb-btn-primary\" type=\"button\" data-next=\"6\">Continue<\/button>\n            <\/div>\n          <\/div>\n        <\/section>\n\n        <section class=\"ptb-step\" data-step=\"6\">\n          <button class=\"ptb-step-head\" type=\"button\" data-open-step=\"6\">\n            <span class=\"ptb-num\">6<\/span>\n            <span class=\"ptb-head-main\"><strong>Your details<\/strong><span data-summary=\"details\">Name and phone number required<\/span><\/span>\n            <span class=\"ptb-edit\">Edit<\/span>\n          <\/button>\n          <div class=\"ptb-body\">\n            <div class=\"ptb-fields\">\n              <div>\n                <label for=\"ptb-name\">Name<\/label>\n                <input id=\"ptb-name\" type=\"text\" autocomplete=\"name\" required>\n              <\/div>\n              <div>\n                <label for=\"ptb-phone\">Phone number<\/label>\n                <input id=\"ptb-phone\" type=\"tel\" autocomplete=\"tel\" required>\n              <\/div>\n            <\/div>\n            <div class=\"ptb-error\" id=\"ptb-details-error\">Please enter your name and phone number.<\/div>\n            <div class=\"ptb-actions\">\n              <button class=\"ptb-btn ptb-btn-plain\" type=\"button\" data-next=\"5\">Back<\/button>\n              <button class=\"ptb-btn ptb-btn-primary\" type=\"button\" data-next=\"7\">Review<\/button>\n            <\/div>\n          <\/div>\n        <\/section>\n\n        <section class=\"ptb-step\" data-step=\"7\">\n          <button class=\"ptb-step-head\" type=\"button\" data-open-step=\"7\">\n            <span class=\"ptb-num\">7<\/span>\n            <span class=\"ptb-head-main\"><strong>Review and confirm<\/strong><span data-summary=\"review\">Check everything before confirming<\/span><\/span>\n            <span class=\"ptb-edit\">Edit<\/span>\n          <\/button>\n          <div class=\"ptb-body\">\n            <div class=\"ptb-review\" id=\"ptb-review\"><\/div>\n            <div class=\"ptb-actions\">\n              <button class=\"ptb-btn ptb-btn-plain\" type=\"button\" data-next=\"6\">Back<\/button>\n              <button class=\"ptb-btn ptb-btn-secondary\" type=\"button\" id=\"ptb-confirm\">Confirm request<\/button>\n            <\/div>\n            <div class=\"ptb-send-note\" id=\"ptb-send-note\">Sending request...<\/div>\n            <div class=\"ptb-success\" id=\"ptb-success\">\n              <h3>Request received<\/h3>\n              <p>We will reach out to confirm your drop-off and collection. You can also message us directly on WhatsApp.<\/p>\n              <a class=\"ptb-btn ptb-btn-secondary\" id=\"ptb-whatsapp\" href=\"https:\/\/wa.me\/447467911129\" target=\"_blank\" rel=\"noopener\">Message on WhatsApp<\/a>\n            <\/div>\n          <\/div>\n        <\/section>\n      <\/div>\n\n      <aside class=\"ptb-summary\">\n        <h3>Current total<\/h3>\n        <div class=\"ptb-total\" id=\"ptb-total\">\u00a320<\/div>\n        <div class=\"ptb-line\"><span>Base stringing<\/span><strong>\u00a320<\/strong><\/div>\n        <div class=\"ptb-line\"><span id=\"ptb-string-label\">String<\/span><strong id=\"ptb-string-price\">+\u00a30<\/strong><\/div>\n        <div class=\"ptb-line\"><span id=\"ptb-speed-label\">Turnaround<\/span><strong id=\"ptb-speed-price\">+\u00a30<\/strong><\/div>\n        <div class=\"ptb-line\"><span id=\"ptb-addon-label\">Extras<\/span><strong id=\"ptb-addon-price\">+\u00a30<\/strong><\/div>\n        <p class=\"ptb-note\" id=\"ptb-collection-note\">Standard collection is within 7 days.<\/p>\n      <\/aside>\n    <\/div>\n  <\/div>\n\n  <script>\n    (function(){\n      const webhookUrl = 'https:\/\/hooks.zapier.com\/hooks\/catch\/2101830\/4ye4ugf\/';\n      const basePrice = 20;\n      const strings = [\n        {name:\"Bring own string\", tier:\"Own string\", gauge:\"\", colour:\"\", type:\"\", profile:\"Use your own set\", price:0, swatch:\"linear-gradient(135deg,#f7f5ef,#e4ddcb)\", light:true},\n        {name:\"Solinco Confidential\", tier:\"Tier 1\", gauge:\"16\", colour:\"Grey\", type:\"Co-polyester\", profile:\"Control poly\", price:20, swatch:\"linear-gradient(135deg,#3e4447,#aeb4b8)\"},\n        {name:\"Babolat RPM Blast Rough\", tier:\"Tier 1\", gauge:\"17\", colour:\"Grey\", type:\"Textured co-polyester\", profile:\"Rough spin poly\", price:20, swatch:\"linear-gradient(135deg,#555,#b7b7b7)\"},\n        {name:\"Babolat RPM Blast\", tier:\"Tier 1\", gauge:\"17\", colour:\"Black\", type:\"Co-polyester\", profile:\"Shaped spin poly\", price:20, swatch:\"linear-gradient(135deg,#050505,#4b4b4b)\"},\n        {name:\"Luxilon ALU Power\", tier:\"Tier 1\", gauge:\"17\", colour:\"Grey\", type:\"Co-polyester\", profile:\"Premium control poly\", price:20, swatch:\"linear-gradient(135deg,#c8c8c8,#111)\"},\n        {name:\"Solinco Hyper-G\", tier:\"Tier 1\", gauge:\"17\", colour:\"Green\", type:\"Shaped co-polyester\", profile:\"Spin\/control poly\", price:20, swatch:\"linear-gradient(135deg,#78c850,#1f7a3a)\"},\n        {name:\"Luxilon Element\", tier:\"Tier 1\", gauge:\"17\", colour:\"Bronze\", type:\"Soft co-polyester\", profile:\"Comfort poly\", price:20, swatch:\"linear-gradient(135deg,#b57a42,#f2c27b)\"},\n        {name:\"Luxilon 4G\", tier:\"Tier 1\", gauge:\"17\", colour:\"Yellow\", type:\"Co-polyester\", profile:\"Tension stability poly\", price:20, swatch:\"linear-gradient(135deg,#f3df38,#837319)\", light:true},\n        {name:\"Yonex Poly Tour Fire\", tier:\"Tier 2\", gauge:\"17\", colour:\"Red\", type:\"Co-polyester\", profile:\"Round performance poly\", price:10, swatch:\"linear-gradient(135deg,#d71920,#7a0b0e)\"},\n        {name:\"TRU PRO Ghost Wire\", tier:\"Tier 2\", gauge:\"18\", colour:\"White\", type:\"Co-polyester\", profile:\"Round soft poly\", price:10, swatch:\"linear-gradient(135deg,#fff,#dadde2)\", light:true},\n        {name:\"Head Lynx Tour\", tier:\"Tier 2\", gauge:\"17\", colour:\"Black\", type:\"Co-polyester\", profile:\"Shaped poly\", price:10, swatch:\"linear-gradient(135deg,#111,#3d3d3d)\"},\n        {name:\"Wilson Revolve\", tier:\"Tier 2\", gauge:\"16\", colour:\"Black\/Grey\", type:\"Co-polyester\", profile:\"Spin poly\", price:10, swatch:\"linear-gradient(135deg,#111,#8f98a0)\"},\n        {name:\"Solinco Mach 10\", tier:\"Tier 2\", gauge:\"18\", colour:\"Blue\", type:\"Co-polyester\", profile:\"Modern spin\/control poly\", price:10, swatch:\"linear-gradient(135deg,#0d5bd7,#0a2f77)\"},\n        {name:\"Dunlop Explosive Speed\", tier:\"Tier 2\", gauge:\"16\", colour:\"Black\", type:\"Co-polyester\", profile:\"Power\/control poly\", price:10, swatch:\"linear-gradient(135deg,#050505,#3c3c3c)\"},\n        {name:\"Gamma Ocho\", tier:\"Tier 2\", gauge:\"16\", colour:\"White\", type:\"Co-polyester\", profile:\"Shaped poly\", price:10, swatch:\"linear-gradient(135deg,#fff,#d9d9d9)\", light:true},\n        {name:\"Wilson Sensation Plus\", tier:\"Tier 3\", gauge:\"17\", colour:\"Black\", type:\"Multifilament\", profile:\"Comfort string\", price:5, swatch:\"linear-gradient(135deg,#111,#535b66)\"},\n        {name:\"Babolat Synthetic Gut\", tier:\"Tier 3\", gauge:\"16\", colour:\"Clear\/White\", type:\"Synthetic gut\", profile:\"Value all-round string\", price:5, swatch:\"linear-gradient(135deg,#fff,#e6e1d7)\", light:true}\n      ];\n\n      const root = document.getElementById('pt-booking-stepper');\n      const stringWrap = root.querySelector('#ptb-string-options');\n      const currency = value => '\u00a3' + value;\n\n      strings.forEach((item, index) => {\n        const id = 'ptb-string-' + index;\n        const label = document.createElement('label');\n        label.className = 'ptb-option';\n        label.innerHTML = '<input type=\"radio\" name=\"string\" id=\"' + id + '\" value=\"' + index + '\" ' + (index === 0 ? 'checked' : '') + '>' +\n          '<span class=\"ptb-pack ' + (item.light ? 'light' : '') + '\" style=\"background:' + item.swatch + '\">' + (item.tier === 'Own string' ? 'OWN' : item.name.split(' ')[0]) + '<\/span>' +\n          '<span class=\"ptb-option-main\"><strong>' + item.name + '<\/strong><small>' + item.tier + (item.gauge ? ' \u00b7 ' + item.gauge + 'g \u00b7 ' + item.profile : ' \u00b7 no string charge') + '<\/small><\/span>' +\n          '<span class=\"ptb-price\">+' + currency(item.price) + '<\/span>';\n        stringWrap.appendChild(label);\n      });\n\n      const state = {\n        step: 1,\n        stringIndex: 0,\n        mains: 52,\n        crosses: 52,\n        speed: 'standard',\n        addons: [],\n        name: '',\n        phone: ''\n      };\n\n      const els = {\n        total: root.querySelector('#ptb-total'),\n        stringLabel: root.querySelector('#ptb-string-label'),\n        stringPrice: root.querySelector('#ptb-string-price'),\n        speedLabel: root.querySelector('#ptb-speed-label'),\n        speedPrice: root.querySelector('#ptb-speed-price'),\n        addonLabel: root.querySelector('#ptb-addon-label'),\n        addonPrice: root.querySelector('#ptb-addon-price'),\n        collectionNote: root.querySelector('#ptb-collection-note'),\n        date: root.querySelector('#ptb-date'),\n        time: root.querySelector('#ptb-time'),\n        mains: root.querySelector('#ptb-mains'),\n        crosses: root.querySelector('#ptb-crosses'),\n        mainsVal: root.querySelector('#ptb-mains-val'),\n        crossesVal: root.querySelector('#ptb-crosses-val'),\n        name: root.querySelector('#ptb-name'),\n        phone: root.querySelector('#ptb-phone'),\n        review: root.querySelector('#ptb-review'),\n        error: root.querySelector('#ptb-details-error'),\n        success: root.querySelector('#ptb-success'),\n        whatsapp: root.querySelector('#ptb-whatsapp'),\n        sendNote: root.querySelector('#ptb-send-note'),\n        confirm: root.querySelector('#ptb-confirm')\n      };\n\n      const tomorrow = new Date();\n      tomorrow.setDate(tomorrow.getDate() + 1);\n      const yyyyMmDd = date => date.toISOString().slice(0, 10);\n      els.date.min = yyyyMmDd(new Date());\n      els.date.value = yyyyMmDd(tomorrow);\n\n      function selectedString(){ return strings[Number(root.querySelector('input[name=\"string\"]:checked').value)]; }\n      function selectedSpeed(){ return root.querySelector('input[name=\"speed\"]:checked'); }\n      function selectedAddons(){ return Array.from(root.querySelectorAll('input[name=\"addon\"]:checked')); }\n      function totalPrice(){\n        const speed = selectedSpeed();\n        return basePrice + selectedString().price + Number(speed.dataset.price) + selectedAddons().reduce((sum, item) => sum + Number(item.dataset.price), 0);\n      }\n      function collectionDateText(){\n        const speed = selectedSpeed();\n        const date = els.date.value ? new Date(els.date.value + 'T12:00:00') : new Date();\n        date.setDate(date.getDate() + Number(speed.dataset.days));\n        return date.toLocaleDateString('en-GB', { weekday:'short', day:'numeric', month:'short' });\n      }\n      function markSelected(){\n        root.querySelectorAll('.ptb-option').forEach(option => {\n          const input = option.querySelector('input');\n          option.classList.toggle('is-selected', input.checked);\n        });\n      }\n      function setStep(step){\n        state.step = Number(step);\n        root.querySelectorAll('.ptb-step').forEach(card => {\n          const cardStep = Number(card.dataset.step);\n          card.classList.toggle('is-active', cardStep === state.step);\n          card.classList.toggle('is-complete', cardStep < state.step);\n        });\n        update();\n      }\n      function validateDetails(){\n        state.name = els.name.value.trim();\n        state.phone = els.phone.value.trim();\n        const ok = Boolean(state.name && state.phone);\n        els.error.style.display = ok ? 'none' : 'block';\n        return ok;\n      }\n      function updateReview(){\n        const string = selectedString();\n        const speed = selectedSpeed();\n        const addons = selectedAddons();\n        const addonText = addons.length ? addons.map(item => item.dataset.label).join(', ') : 'None';\n        const lines = [\n          '<strong>Drop-off:<\/strong> ' + (els.date.value || 'Not selected') + ' at ' + (els.time.value || 'Not selected'),\n          '<strong>String:<\/strong> ' + string.name + ' (' + string.tier + ')',\n          '<strong>Tension:<\/strong> mains ' + els.mains.value + ' lbs \/ crosses ' + els.crosses.value + ' lbs',\n          '<strong>Turnaround:<\/strong> ' + speed.dataset.label + ' \u00b7 estimated collection ' + collectionDateText(),\n          '<strong>Extras:<\/strong> ' + addonText,\n          '<strong>Name:<\/strong> ' + (els.name.value || '-'),\n          '<strong>Phone:<\/strong> ' + (els.phone.value || '-'),\n          '<strong>Total:<\/strong> ' + currency(totalPrice())\n        ];\n        els.review.innerHTML = lines.join('<br>');\n        const message = 'Tennis stringing request\\n' + lines.map(line => line.replace(\/<[^>]+>\/g, '')).join('\\n');\n        els.whatsapp.href = 'https:\/\/wa.me\/447467911129?text=' + encodeURIComponent(message);\n      }\n      function bookingPayload(){\n        const string = selectedString();\n        const speed = selectedSpeed();\n        const addons = selectedAddons();\n        return {\n          source: 'tennis-stringing-stepper-form',\n          submitted_at: new Date().toISOString(),\n          name: els.name.value.trim(),\n          phone: els.phone.value.trim(),\n          dropoff_date: els.date.value,\n          dropoff_time: els.time.value,\n          string_name: string.name,\n          string_tier: string.tier,\n          string_gauge: string.gauge,\n          string_colour: string.colour,\n          string_type: string.type,\n          string_price_addon: string.price,\n          mains_tension_lbs: Number(els.mains.value),\n          crosses_tension_lbs: Number(els.crosses.value),\n          turnaround: speed.dataset.label,\n          turnaround_days: Number(speed.dataset.days),\n          turnaround_price_addon: Number(speed.dataset.price),\n          estimated_collection: collectionDateText(),\n          addons: addons.map(item => ({\n            name: item.dataset.label,\n            price: Number(item.dataset.price)\n          })),\n          addons_total: addons.reduce((sum, item) => sum + Number(item.dataset.price), 0),\n          base_price: basePrice,\n          total_price: totalPrice()\n        };\n      }\n      function bookingFormData(){\n        const payload = bookingPayload();\n        const formData = new FormData();\n        Object.keys(payload).forEach(key => {\n          const value = payload[key];\n          formData.append(key, typeof value === 'object' ? JSON.stringify(value) : String(value));\n        });\n        return formData;\n      }\n      function update(){\n        const string = selectedString();\n        const speed = selectedSpeed();\n        const addons = selectedAddons();\n        const addonTotal = addons.reduce((sum, item) => sum + Number(item.dataset.price), 0);\n        const addonLabels = addons.map(item => item.dataset.label);\n        els.mainsVal.textContent = els.mains.value;\n        els.crossesVal.textContent = els.crosses.value;\n        els.total.textContent = currency(totalPrice());\n        els.stringLabel.textContent = string.name;\n        els.stringPrice.textContent = '+' + currency(string.price);\n        els.speedLabel.textContent = speed.dataset.label + ' turnaround';\n        els.speedPrice.textContent = '+' + currency(Number(speed.dataset.price));\n        els.addonLabel.textContent = addonLabels.length ? addonLabels.join(', ') : 'Extras';\n        els.addonPrice.textContent = '+' + currency(addonTotal);\n        els.collectionNote.textContent = speed.dataset.label + ' collection estimate: ' + collectionDateText() + '.';\n        root.querySelector('[data-summary=\"dropoff\"]').textContent = (els.date.value || 'Choose date') + ' at ' + (els.time.value || 'choose time') + ' \u00b7 base \u00a320';\n        root.querySelector('[data-summary=\"string\"]').textContent = string.name + ' \u00b7 ' + (string.price ? '+' + currency(string.price) : 'no string charge');\n        root.querySelector('[data-summary=\"tension\"]').textContent = 'Mains ' + els.mains.value + ' lbs \/ crosses ' + els.crosses.value + ' lbs';\n        root.querySelector('[data-summary=\"speed\"]').textContent = speed.dataset.label + ' \u00b7 collection estimate ' + collectionDateText();\n        root.querySelector('[data-summary=\"addons\"]').textContent = addonLabels.length ? addonLabels.join(', ') : 'No extras selected';\n        root.querySelector('[data-summary=\"details\"]').textContent = els.name.value && els.phone.value ? els.name.value + ' \u00b7 ' + els.phone.value : 'Name and phone number required';\n        updateReview();\n        markSelected();\n      }\n\n      root.addEventListener('click', event => {\n        const open = event.target.closest('[data-open-step]');\n        const next = event.target.closest('[data-next]');\n        if (open) setStep(open.dataset.openStep);\n        if (next) {\n          if (next.dataset.next === '7' && !validateDetails()) return;\n          setStep(next.dataset.next);\n        }\n      });\n      root.addEventListener('input', update);\n      root.addEventListener('change', update);\n      root.querySelector('#ptb-confirm').addEventListener('click', async () => {\n        if (!validateDetails()) {\n          setStep(6);\n          return;\n        }\n        updateReview();\n        els.confirm.disabled = true;\n        els.confirm.textContent = 'Sending...';\n        els.sendNote.style.display = 'block';\n        try {\n          await fetch(webhookUrl, {\n            method: 'POST',\n            mode: 'no-cors',\n            body: bookingFormData()\n          });\n          els.sendNote.textContent = 'Request sent.';\n        } catch (error) {\n          els.sendNote.textContent = 'Could not send automatically. Please message us on WhatsApp.';\n        }\n        els.success.style.display = 'block';\n        els.confirm.style.display = 'none';\n      });\n      update();\n    })();\n  <\/script>\n<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"Book Tennis Racket Stringing Choose your drop-off, string, tension and turnaround. The price updates as you build your&hellip;","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_gspb_post_css":"","csco_display_header_overlay":false,"csco_singular_sidebar":"","csco_page_header_type":"","csco_page_load_nextpost":"","csco_post_video_location":[],"csco_post_video_location_hash":"","csco_post_video_url":"","csco_post_video_bg_start_time":0,"csco_post_video_bg_end_time":0,"footnotes":""},"class_list":{"0":"post-3555","1":"page","2":"type-page","3":"status-publish","5":"cs-entry","6":"cs-video-wrap"},"_links":{"self":[{"href":"https:\/\/www.passionnementtennis.com\/fr\/wp-json\/wp\/v2\/pages\/3555","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.passionnementtennis.com\/fr\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.passionnementtennis.com\/fr\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.passionnementtennis.com\/fr\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.passionnementtennis.com\/fr\/wp-json\/wp\/v2\/comments?post=3555"}],"version-history":[{"count":10,"href":"https:\/\/www.passionnementtennis.com\/fr\/wp-json\/wp\/v2\/pages\/3555\/revisions"}],"predecessor-version":[{"id":3565,"href":"https:\/\/www.passionnementtennis.com\/fr\/wp-json\/wp\/v2\/pages\/3555\/revisions\/3565"}],"wp:attachment":[{"href":"https:\/\/www.passionnementtennis.com\/fr\/wp-json\/wp\/v2\/media?parent=3555"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}