{"id":10775,"date":"2026-07-28T16:23:16","date_gmt":"2026-07-28T16:23:16","guid":{"rendered":"https:\/\/www.playyourcourt.com\/news\/?page_id=10775"},"modified":"2026-07-30T17:36:27","modified_gmt":"2026-07-30T17:36:27","slug":"the-tennis-racket-finder","status":"publish","type":"page","link":"https:\/\/www.playyourcourt.com\/news\/the-tennis-racket-finder\/","title":{"rendered":"The Tennis Racket Finder"},"content":{"rendered":"\n<style data-wp-block-html=\"css\">\n\/* Fonts hosted at www.playyourcourt.com\/news\/ai\/racketfinder\/ *\/\n@font-face{font-family:'RF GT America';src:url('https:\/\/www.playyourcourt.com\/news\/ai\/racketfinder\/GT-America-Extended-Black.woff2') format('woff2');font-weight:900;font-style:normal;font-display:swap}\n@font-face{font-family:'RF Supreme';src:url('https:\/\/www.playyourcourt.com\/news\/ai\/racketfinder\/Supreme-Medium.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}\n\n\/* The only global rule: paints the page black behind the tool so it blends with the\n   dark header\/footer. Delete if your template already has a dark background. *\/\nbody{background:#0A0A0A}\n\n\/* -- Scope + reset ------------------------------------------------- *\/\n.pyc-rf{--rf-yellow:#E8FF3D;--rf-black:#0A0A0A;--rf-white:#FFFFFF;--rf-blue:#1565FF;--rf-blue-light:#6B9EFF;--rf-green:#00E5A0;--rf-orange:#FF6B1A;--rf-orange-light:#FF8C4E;--rf-g400:#A0A09A;--rf-g600:#5A5A55;--rf-g700:#3A3A35;--rf-display:'RF GT America',Impact,'Arial Black',sans-serif;--rf-body:'RF Supreme','Helvetica Neue',Helvetica,sans-serif;background:var(--rf-black);color:var(--rf-white);font-family:var(--rf-body);line-height:1.5;-webkit-font-smoothing:antialiased;text-align:left}\n.pyc-rf *,.pyc-rf *::before,.pyc-rf *::after{box-sizing:border-box}\n.pyc-rf h1,.pyc-rf h2,.pyc-rf h3,.pyc-rf p,.pyc-rf div,.pyc-rf span,.pyc-rf button,.pyc-rf a,.pyc-rf img,.pyc-rf nav,.pyc-rf section,.pyc-rf aside,.pyc-rf footer,.pyc-rf strong{margin:0;padding:0;border:0;outline:0;background:none;font:inherit;color:inherit;letter-spacing:normal;text-transform:none;text-shadow:none;box-shadow:none;max-width:none;float:none;list-style:none}\n.pyc-rf button{cursor:pointer;-webkit-appearance:none;appearance:none;text-align:left}\n.pyc-rf img{display:block;height:auto}\n.pyc-rf a{color:var(--rf-yellow);text-decoration:none}\n.pyc-rf a:hover{color:var(--rf-white)}\n\n\/* -- Shared bits --------------------------------------------------- *\/\n.pyc-rf .rf-eyebrow{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--rf-yellow);margin-bottom:18px;display:flex;align-items:center;gap:10px}\n.pyc-rf .rf-eyebrow::before{content:'';display:block;width:24px;height:2px;background:var(--rf-yellow)}\n.pyc-rf .rf-btn{background:var(--rf-yellow);color:var(--rf-black);font-family:var(--rf-display);font-size:14px;font-weight:900;text-transform:uppercase;letter-spacing:.02em;padding:16px 32px;border-radius:6px;transition:all 150ms ease-out;display:inline-flex;align-items:center;gap:10px}\n.pyc-rf .rf-btn:hover{background:#F5FF66;transform:translate(-1px,-2px)}\n.pyc-rf .rf-btn-outline{display:inline-flex;align-items:center;gap:8px;color:var(--rf-g400);font-family:var(--rf-display);font-size:11px;font-weight:900;text-transform:uppercase;letter-spacing:.04em;padding:12px 20px;border-radius:6px;border:1px solid var(--rf-g700);transition:all 150ms ease-out}\n.pyc-rf .rf-btn-outline:hover{color:var(--rf-white);border-color:var(--rf-g400)}\n\n\/* -- Section 1 - Hero ---------------------------------------------- *\/\n.pyc-rf .rf-hero{padding:96px 48px;display:flex;justify-content:center}\n.pyc-rf .rf-hero-inner{max-width:760px;width:100%}\n.pyc-rf .rf-hero-title{font-family:var(--rf-display);font-weight:900;font-size:clamp(48px,6.5vw,96px);line-height:.9;letter-spacing:-.02em;text-transform:uppercase;color:var(--rf-white);margin-bottom:28px}\n.pyc-rf .rf-hero-title span{color:var(--rf-yellow);text-transform:uppercase}\n.pyc-rf .rf-hero-body{font-size:17px;line-height:1.7;color:var(--rf-g400);max-width:480px;margin-bottom:36px}\n\n\/* -- Section 2 - Quiz ---------------------------------------------- *\/\n.pyc-rf .rf-quiz{display:none;padding:16px 48px 80px}\n.pyc-rf .rf-quiz.rf-show{display:block}\n.pyc-rf .rf-prog-wrap{display:flex;align-items:center;gap:20px;margin-bottom:32px}\n.pyc-rf .rf-back{color:var(--rf-g400);font-size:11px;letter-spacing:.1em;text-transform:uppercase;display:inline-flex;align-items:center;gap:6px;padding:6px 0;transition:color 150ms}\n.pyc-rf .rf-back:hover{color:var(--rf-white)}\n.pyc-rf .rf-back[disabled]{opacity:.3;cursor:default}\n.pyc-rf .rf-step-label{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--rf-g400);display:flex;align-items:center;gap:10px;line-height:1}\n.pyc-rf .rf-step-label::before{content:'';width:1px;height:12px;background:#2a2a2a;display:block}\n.pyc-rf .rf-step-num{font-family:var(--rf-display);font-size:11px;font-weight:900;color:var(--rf-yellow);line-height:1}\n.pyc-rf .rf-prog-bar{flex:1;max-width:360px;margin-left:auto;height:4px;background:#1e1e1e;border-radius:100px;overflow:hidden}\n.pyc-rf .rf-prog-fill{height:100%;background:var(--rf-yellow);width:0;transition:width 400ms cubic-bezier(.34,1.56,.64,1)}\n.pyc-rf .rf-shell{display:grid;grid-template-columns:1fr 280px;gap:48px;align-items:start;max-width:1280px;margin:0 auto}\n.pyc-rf .rf-question{max-width:1200px;margin:0 auto}\n.pyc-rf .rf-headline{font-family:var(--rf-display);font-weight:900;font-size:clamp(42px,5.5vw,76px);line-height:.9;letter-spacing:-.02em;text-transform:uppercase;color:var(--rf-white);margin-bottom:18px;max-width:900px}\n.pyc-rf .rf-headline span{color:var(--rf-yellow);text-transform:uppercase}\n.pyc-rf .rf-sub{font-size:17px;line-height:1.6;color:var(--rf-g400);max-width:640px;margin-bottom:48px}\n.pyc-rf .rf-choice-grid{display:grid;gap:16px}\n.pyc-rf .rf-choice-grid.rf-cols-2{grid-template-columns:repeat(2,1fr)}\n.pyc-rf .rf-choice-grid.rf-cols-3{grid-template-columns:repeat(3,1fr)}\n.pyc-rf .rf-choice{position:relative;background:#0D0D0D;border:1px solid #1e1e1e;border-radius:12px;padding:32px 28px;transition:all 200ms cubic-bezier(.34,1.56,.64,1);display:flex;flex-direction:column;gap:12px;min-height:220px;overflow:hidden}\n.pyc-rf .rf-choice::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:var(--rf-yellow);transform:scaleX(0);transform-origin:left;transition:transform 220ms ease-out}\n.pyc-rf .rf-choice:hover{border-color:var(--rf-yellow);background:#121208;transform:translate(-2px,-3px);box-shadow:4px 4px 0 var(--rf-yellow)}\n.pyc-rf .rf-choice:hover::before{transform:scaleX(1)}\n.pyc-rf .rf-choice.rf-c-b:hover{border-color:var(--rf-blue-light);box-shadow:4px 4px 0 var(--rf-blue);background:#0a0e1a}\n.pyc-rf .rf-choice.rf-c-b:hover::before{background:var(--rf-blue-light)}\n.pyc-rf .rf-choice.rf-c-g:hover{border-color:var(--rf-green);box-shadow:4px 4px 0 var(--rf-green);background:#051512}\n.pyc-rf .rf-choice.rf-c-g:hover::before{background:var(--rf-green)}\n.pyc-rf .rf-choice.rf-c-o:hover{border-color:var(--rf-orange-light);box-shadow:4px 4px 0 var(--rf-orange);background:#160c06}\n.pyc-rf .rf-choice.rf-c-o:hover::before{background:var(--rf-orange-light)}\n.pyc-rf .rf-choice-tag{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--rf-g400)}\n.pyc-rf .rf-choice-tag.rf-t-y{color:var(--rf-yellow)}\n.pyc-rf .rf-choice-tag.rf-t-b{color:var(--rf-blue-light)}\n.pyc-rf .rf-choice-tag.rf-t-g{color:var(--rf-green)}\n.pyc-rf .rf-choice-tag.rf-t-o{color:var(--rf-orange-light)}\n.pyc-rf .rf-choice-title{font-family:var(--rf-display);font-size:clamp(19px,1.9vw,32px);font-weight:900;text-transform:uppercase;line-height:.95;color:var(--rf-white);letter-spacing:-.02em;word-break:keep-all;hyphens:none}\n.pyc-rf .rf-choice-desc{font-size:14px;color:var(--rf-g400);line-height:1.55;margin-top:4px;flex:1}\n.pyc-rf .rf-choice-foot{display:flex;align-items:center;justify-content:space-between;margin-top:12px;font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--rf-g600);transition:color 200ms}\n.pyc-rf .rf-choice:hover .rf-choice-foot{color:var(--rf-white)}\n.pyc-rf .rf-choice-foot .rf-arr{font-family:var(--rf-display);font-size:16px;transition:transform 200ms}\n.pyc-rf .rf-choice:hover .rf-choice-foot .rf-arr{transform:translateX(4px)}\n.pyc-rf .rf-aside{background:#0D0D0D;border:1px solid #1e1e1e;border-radius:12px;padding:24px;position:sticky;top:24px}\n.pyc-rf .rf-aside-label{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--rf-g600);margin-bottom:16px}\n.pyc-rf .rf-aside-list{display:flex;flex-direction:column;gap:12px}\n.pyc-rf .rf-aside-item{display:flex;flex-direction:column;gap:4px;padding-bottom:12px;border-bottom:1px solid #1e1e1e}\n.pyc-rf .rf-aside-item:last-child{border-bottom:none;padding-bottom:0}\n.pyc-rf .rf-aside-q{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--rf-g600)}\n.pyc-rf .rf-aside-a{font-family:var(--rf-display);font-size:13px;font-weight:900;text-transform:uppercase;color:var(--rf-white);line-height:1.2}\n.pyc-rf .rf-aside-a.rf-pending{color:var(--rf-g700)}\n.pyc-rf .rf-aside-a.rf-pending::after{content:'\\00B7'}\n.pyc-rf .rf-aside-empty{font-size:12px;color:var(--rf-g600);line-height:1.6}\n.pyc-rf .rf-aside-restart{margin-top:20px;width:100%;text-align:center;justify-content:center;font-size:10px;padding:10px}\n\n\/* -- Section 3 - Result -------------------------------------------- *\/\n.pyc-rf .rf-result{display:none;padding:56px 48px 80px}\n.pyc-rf .rf-result.rf-show{display:block}\n.pyc-rf .rf-result-inner{max-width:1280px;margin:0 auto}\n.pyc-rf .rf-rhero{background:#0D0D0D;border:1px solid #1e1e1e;border-radius:20px;overflow:hidden;margin-bottom:24px;display:grid;grid-template-columns:1.32fr .9fr;align-items:stretch}\n.pyc-rf .rf-rhero-copy{padding:52px 48px;display:flex;flex-direction:column;justify-content:center}\n.pyc-rf .rf-kicker{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--rf-g400);margin-bottom:12px}\n.pyc-rf .rf-family{font-family:var(--rf-display);font-size:clamp(48px,6vw,86px);font-weight:900;line-height:.86;text-transform:uppercase;color:var(--rf-yellow);letter-spacing:-.03em;margin-bottom:20px}\n.pyc-rf .rf-tagline{font-family:var(--rf-display);font-size:clamp(20px,2.4vw,28px);font-weight:900;text-transform:uppercase;color:var(--rf-white);line-height:1;margin-bottom:16px;letter-spacing:-.01em}\n.pyc-rf .rf-desc{font-size:16px;line-height:1.7;color:var(--rf-g400);max-width:520px;margin-bottom:28px}\n.pyc-rf .rf-market{font-size:13px;color:var(--rf-g400);line-height:1.7;max-width:520px}\n.pyc-rf .rf-rhero-photo{background:var(--rf-white);display:flex;align-items:center;justify-content:center;padding:28px;min-height:440px}\n.pyc-rf .rf-rhero-photo img{width:100%;height:100%;object-fit:contain}\n.pyc-rf .rf-spotlight{background:var(--rf-yellow);color:var(--rf-black);border-radius:16px;padding:40px 48px;margin-bottom:32px;display:flex;flex-direction:column;align-items:flex-start}\n.pyc-rf .rf-spot-label{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:rgba(0,0,0,.6);margin-bottom:10px;display:flex;align-items:center;gap:10px}\n.pyc-rf .rf-spot-label::before{content:'\\2605'}\n.pyc-rf .rf-spot-name{font-family:var(--rf-display);font-size:clamp(36px,5vw,64px);font-weight:900;text-transform:uppercase;line-height:.95;letter-spacing:-.02em;color:var(--rf-black);margin-bottom:14px}\n.pyc-rf .rf-spot-desc{font-size:15px;line-height:1.65;color:rgba(0,0,0,.72);max-width:560px}\n.pyc-rf .rf-fc{width:100%;max-width:480px;margin:22px 0 4px}\n.pyc-rf .rf-fc-title{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:rgba(0,0,0,.55);margin-bottom:8px}\n.pyc-rf .rf-stat-row{display:flex;align-items:center;gap:18px;padding:11px 0;border-bottom:1px solid rgba(0,0,0,.14)}\n.pyc-rf .rf-stat-row:last-child{border-bottom:none}\n.pyc-rf .rf-stat-name{font-family:var(--rf-display);font-size:13px;font-weight:900;text-transform:uppercase;color:var(--rf-black);letter-spacing:.02em;width:80px;flex-shrink:0}\n.pyc-rf .rf-stat-pips{display:flex;gap:5px;flex:1}\n.pyc-rf .rf-stat-pip{flex:1;height:11px;border-radius:100px;background:rgba(0,0,0,.13)}\n.pyc-rf .rf-stat-pip.rf-on{background:var(--rf-black)}\n.pyc-rf .rf-stat-value{font-family:var(--rf-display);font-size:14px;font-weight:900;color:var(--rf-black);width:28px;text-align:right;flex-shrink:0}\n.pyc-rf .rf-coach{font-size:14px;line-height:1.6;color:var(--rf-black);border-left:3px solid var(--rf-black);padding-left:14px;margin:18px 0 22px;max-width:560px}\n.pyc-rf .rf-coach strong{font-family:var(--rf-display);font-size:11px;letter-spacing:.12em;font-weight:900}\n.pyc-rf .rf-spot-cta{display:inline-block;background:var(--rf-black);color:var(--rf-yellow);font-family:var(--rf-display);font-size:12px;font-weight:900;text-transform:uppercase;letter-spacing:.02em;padding:14px 24px;border-radius:6px;white-space:nowrap;transition:opacity 150ms}\n.pyc-rf .rf-spot-cta:hover{opacity:.85;color:var(--rf-yellow)}\n.pyc-rf .rf-variants-head{display:flex;align-items:flex-end;justify-content:space-between;margin-bottom:24px;gap:24px}\n.pyc-rf .rf-variants-title{font-family:var(--rf-display);font-size:clamp(28px,3.5vw,44px);font-weight:900;text-transform:uppercase;line-height:.95;letter-spacing:-.02em;color:var(--rf-white)}\n.pyc-rf .rf-variants-sub{font-size:14px;color:var(--rf-g400);max-width:380px;line-height:1.6}\n.pyc-rf .rf-variant-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:16px}\n.pyc-rf .rf-variant{position:relative;background:#0D0D0D;border:1px solid #1e1e1e;border-radius:12px;padding:24px;display:flex;flex-direction:column;gap:12px;transition:all 200ms cubic-bezier(.34,1.56,.64,1)}\n.pyc-rf .rf-variant:hover{transform:translate(-2px,-3px);border-color:var(--rf-yellow);box-shadow:4px 4px 0 var(--rf-yellow)}\n.pyc-rf .rf-variant.rf-featured{border-color:var(--rf-yellow);background:#131309}\n.pyc-rf .rf-pill{position:absolute;top:14px;right:14px;background:var(--rf-yellow);color:var(--rf-black);font-family:var(--rf-display);font-size:9px;font-weight:900;text-transform:uppercase;letter-spacing:.06em;padding:4px 8px;border-radius:100px}\n.pyc-rf .rf-variant-spec{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--rf-g600);padding-right:80px}\n.pyc-rf .rf-variant-name{font-family:var(--rf-display);font-size:22px;font-weight:900;text-transform:uppercase;line-height:.95;color:var(--rf-white);letter-spacing:-.01em}\n.pyc-rf .rf-variant-desc{font-size:12px;color:var(--rf-g400);line-height:1.5;flex:1}\n.pyc-rf .rf-variant-metrics{display:flex;gap:16px;padding-top:12px;border-top:1px solid #1e1e1e}\n.pyc-rf .rf-metric-lbl{font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--rf-g600)}\n.pyc-rf .rf-metric-val{font-family:var(--rf-display);font-size:13px;font-weight:900;color:var(--rf-white)}\n.pyc-rf .rf-restart-wrap{text-align:center;margin-top:48px}\n\n\/* -- Entrance animation -------------------------------------------- *\/\n@keyframes rfSlideUp{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}\n.pyc-rf .rf-in{animation:rfSlideUp 380ms cubic-bezier(.16,1,.3,1) both}\n.pyc-rf .rf-in.rf-d1{animation-delay:60ms}\n.pyc-rf .rf-in.rf-d2{animation-delay:120ms}\n.pyc-rf .rf-in.rf-d3{animation-delay:180ms}\n\n\/* -- Responsive ---------------------------------------------------- *\/\n@media(max-width:1024px){.pyc-rf .rf-shell{grid-template-columns:1fr}.pyc-rf .rf-aside{position:static}.pyc-rf .rf-choice-grid.rf-cols-3{grid-template-columns:repeat(2,1fr)}}\n@media(max-width:900px){.pyc-rf .rf-hero{padding:48px 20px}.pyc-rf .rf-quiz{padding:16px 20px 60px}.pyc-rf .rf-result{padding:32px 20px 60px}.pyc-rf .rf-choice-grid.rf-cols-2,.pyc-rf .rf-choice-grid.rf-cols-3{grid-template-columns:1fr}.pyc-rf .rf-choice{min-height:0;padding:24px 22px}.pyc-rf .rf-rhero{grid-template-columns:1fr}.pyc-rf .rf-rhero-photo{min-height:320px;order:-1}.pyc-rf .rf-rhero-copy{padding:32px 24px}.pyc-rf .rf-spotlight{padding:28px}.pyc-rf .rf-variants-head{flex-direction:column;align-items:flex-start}}\n<\/style>\n\n<script data-wp-block-html=\"js\">\n\n(function(){\n\"use strict\";\n\n\/* Racket photos from WordPress Media Library (www.playyourcourt.com\/news) *\/\nvar ASSETS = \"https:\/\/www.playyourcourt.com\/news\/wp-content\/uploads\/2026\/07\/\";\nvar WILSON_UTM = 'utm_source=playyourcourt&utm_medium=blog&utm_campaign=racket-finder';\nfunction wilsonProductUrl(url){\n  return url + (url.indexOf('?') >= 0 ? '&' : '?') + WILSON_UTM;\n}\n\n\/* -- QUESTIONS ------------------------------------------------------\n   EDIT: All question copy. For each question: \"label\" is the sidebar +\n   progress name, \"prompt\" is the big headline (text inside <span> turns\n   yellow), \"sub\" is the paragraph under it, and each option has a small\n   tag, a title, and a description. Don't change \"id\" or \"value\" -- the\n   matching logic uses them. *\/\nvar STEPS = [\n  { id:'level', label:'Player Level', cols:3,\n    prompt:'Are you a casual, competitive or <span>pro player?<\/span>',\n    sub:\"This tells us how much swing weight and stiffness you can handle, not how good you are. (You\\u0027re great.)\",\n    options:[\n      { value:'casual', tag:'Level 01', title:'Casual', color:'y',\n        desc:'Weekend hitter, learning the strokes, or just back to it. You want fun, forgiveness, and pop.' },\n      { value:'competitive', tag:'Level 02', title:'Competitive', color:'b',\n        desc:\"You\\u0027re in a league, play regularly, and your game has shape. Time to match a frame to it.\" },\n      { value:'pro', tag:'Level 03', title:'Pro', color:'o',\n        desc:'High-NTRP, tournament, or college level. You want a tour-spec frame and a familiar feel.' }\n    ] },\n  { id:'priority', label:'What you want', cols:3,\n    prompt:'What do you want most <span>out of your racket?<\/span>',\n    sub:'Power moves the ball fast. Spin gives shape and net clearance. Control puts the ball where you want it. Pick the one you want a little more of.',\n    options:[\n      { value:'power', tag:'Trait', title:'Power', color:'o',\n        desc:'You want depth and pace without swinging out of your shoes. Frames with stiffer beams and lively response.' },\n      { value:'spin', tag:'Trait', title:'Spin', color:'g',\n        desc:'You want shape, a heavy ball, and angles. Open string patterns and a frame engineered to grab the felt.' },\n      { value:'control', tag:'Trait', title:'Control', color:'b',\n        desc:'You want surgical placement and a connected feel on every shot. Tight patterns, lower stiffness.' }\n    ] },\n  { id:'profile', label:'Power source', cols:2,\n    prompt:'Do you want your racket to give you <span>extra power?<\/span>',\n    sub:'Some frames are built to add free power for you, with a stiffer beam and more launch. Others put the power in your hands, with a softer, more controlled response you shape yourself.',\n    skipIf:function(a){ return a.priority === 'spin'; },\n    options:[\n      { value:'explosive', tag:'Add It For Me', title:'I Want Extra Power', color:'o',\n        desc:'Let the racket do the heavy lifting. Penetrating, head-turning shots with a stiffer beam and more launch.' },\n      { value:'versatile', tag:'I\\u0027ll Control It', title:'I\\u0027ll Generate My Own', color:'y',\n        desc:'You supply the power and want the racket to place it. Softer flex, bigger sweet spot, all-court feel you shape yourself.' }\n    ] },\n  { id:'swingType', label:'Swing path', cols:3,\n    prompt:'How do you swing <span>right now?<\/span>',\n    sub:'Think about how you naturally hit today. A horizontal swing follows a flatter, linear path, powerful and direct. A vertical swing brushes up and over, spin and high net clearance.',\n    options:[\n      { value:'horizontal', tag:'Style A', title:'Horizontal', color:'y',\n        desc:'You currently swing on a linear, flat path. Powerful low-spin shots that hug the line.' },\n      { value:'vertical', tag:'Style B', title:'Vertical', color:'g',\n        desc:'You currently brush up the back of the ball for topspin. Higher net clearance, dipping ball.' },\n      { value:'either', tag:'Style C', title:'A Bit Of Both', color:'b',\n        desc:'You already shape it depending on the shot. Spin and flat, both in the bag.' }\n    ] },\n  { id:'swingSpeed', label:'Swing speed', cols:3,\n    prompt:'How fast do you <span>swing today?<\/span>',\n    sub:\"Be honest about your current stroke, not your goal. Slower swings get the most out of power-segmented frames. Faster swings need spin and control frames that won\\u0027t over-launch the ball.\",\n    options:[\n      { value:'average', tag:'Speed A', title:'Average', color:'y',\n        desc:'Your stroke today is short and measured. You generate just enough racket-head speed, let the frame add the rest.' },\n      { value:'medium', tag:'Speed B', title:'Medium', color:'b',\n        desc:'A smooth, repeatable stroke with steady pace. You want a balanced frame that rewards a controlled swing.' },\n      { value:'fast', tag:'Speed C', title:'Fast', color:'o',\n        desc:'You bring the heat with long, accelerating strokes. You want a frame that absorbs your speed without launching long.' }\n    ] },\n  { id:'weight', label:'Racket weight', cols:3,\n    prompt:'Do you want a light, medium or <span>heavy racket?<\/span>',\n    sub:'Lighter frames are easier to swing and more maneuverable at the net. Medium and heavier frames give you more stability, plow-through, and a locked-in feel on big strokes.',\n    options:[\n      { value:'light', tag:'Build', title:'Light', color:'y',\n        desc:'Easier maneuverability, fast hands at net, less fatigue late in matches. Great for doubles and developing arms.' },\n      { value:'medium', tag:'Build', title:'Medium', color:'b',\n        desc:'A balanced weight between easy swing speed and stability. Tour-like feel without the heaviest swing weight.' },\n      { value:'heavy', tag:'Build', title:'Heavy', color:'o',\n        desc:'Stability, mass behind the ball, and a tour-grade plow-through that powers your strokes from the back of the court.' }\n    ] },\n  { id:'headsize', label:'Head size', cols:3,\n    prompt:'Do you want a large, medium or <span>small head size?<\/span>',\n    sub:'Larger heads give you a bigger sweet spot and more forgiveness. Medium and smaller heads concentrate the string bed for faster swings and tighter control.',\n    options:[\n      { value:'large', tag:'Spec', title:'Large Head', color:'y',\n        desc:\"Bigger sweet spot, more power, more forgiveness on off-center hits. Great if you\\u0027re still finding the strings.\" },\n      { value:'medium', tag:'Spec', title:'Medium Head', color:'g',\n        desc:'A mid-size head that balances forgiveness with control. Enough margin on mishits without giving up precision.' },\n      { value:'small', tag:'Spec', title:'Small Head', color:'b',\n        desc:'Faster swings and more pinpoint control. A tighter string bed for the player who finds the middle every time.' }\n    ] }\n];\n\n\/* -- RACKET FAMILIES ------------------------------------------------\n   EDIT: All racket copy, prices, specs, shop links and image filenames.\n   \"stats\" are the 1-to-5 Power \/ Spin \/ Control bars. Each variant's\n   \"match\" block decides which build gets the \"Your Match\" pill. *\/\nvar FAMILIES = {\n  clash:{ id:'clash', name:'Clash', tagline:'Versatile Power. All-Court Feel.',\n    desc:\"The Clash is one of the most arm-friendly power frames in tennis. Carbon-mapping technology lets the racket flex like nothing else, translating into effortless depth, a giant sweet spot, and a feel that\\u0027s wildly forgiving. The all-court racket that lets you hit your way out of any spot on the court.\",\n    stats:{power:5,spin:4,control:4}, img:'racket-clash.png',\n    productUrl:'https:\/\/www.wilson.com\/en-us\/tennis\/collections\/clash-v3',\n    variants:[\n      { code:'100 PRO', name:'Clash 100 Pro', headSize:'100 in\\u00B2', weight:'310 g', tier:'pro', match:{weight:'heavy',headsize:'small'},\n        desc:'Tour-spec Clash. Heaviest in the family with classic 100 in\\u00B2 head. Pro players who want plow-through with Clash flex.' },\n      { code:'100', name:'Clash 100 v3', headSize:'100 in\\u00B2', weight:'295 g', tier:'std', match:{weight:'heavy',headsize:'large'},\n        desc:'The flagship. The most popular Clash, the one your coach is probably already using. Forgiving, powerful, balanced.' },\n      { code:'100L', name:'Clash 100L', headSize:'100 in\\u00B2', weight:'280 g', tier:'light', match:{weight:'light',headsize:'small'},\n        desc:'Lightweight Clash with the same shape and feel as the 100. Easier to swing for doubles and players returning from injury.' },\n      { code:'100UL', name:'Clash 100UL', headSize:'100 in\\u00B2', weight:'265 g', tier:'ulight', match:{weight:'light',headsize:'small',alt:true},\n        desc:'Ultra-lightweight version. The lightest Clash, built for developing players who want the Clash feel without the mass.' },\n      { code:'108', name:'Clash 108', headSize:'108 in\\u00B2', weight:'275 g', tier:'os', match:{weight:'light',headsize:'large'},\n        desc:'Oversize 108-in\\u00B2 Clash. Maximum sweet spot, maximum forgiveness, the biggest help on the off-center hits.' }\n    ] },\n  ultra:{ id:'ultra', name:'Ultra', tagline:'Explosive Power. Dominate With Depth.',\n    desc:\"The Ultra is engineered for one thing: free power. A stiffer beam, a Power Rib for energy transfer, and a frame built to launch the ball deep into the court. You don\\u0027t hit through opponents on this racket. You hit through them and out the back fence.\",\n    stats:{power:5,spin:2,control:4}, img:'racket-ultra.png',\n    productUrl:'https:\/\/www.wilson.com\/en-us\/tennis\/tennis-rackets\/performance-rackets\/ultra',\n    variants:[\n      { code:'99 PRO', name:'Ultra 99 Pro', headSize:'99 in\\u00B2', weight:'310 g', tier:'pro', match:{weight:'heavy',headsize:'small'},\n        desc:'Tour-spec Ultra with the smaller 99 in\\u00B2 head. Heavy, stable, and built to detonate baseline rallies with control.' },\n      { code:'100', name:'Ultra 100 v4', headSize:'100 in\\u00B2', weight:'300 g', tier:'std', match:{weight:'heavy',headsize:'large'},\n        desc:\"The standard Ultra. The aggressive baseliner\\u0027s best friend: depth, pace, and a frame that absorbs your speed.\" },\n      { code:'100L', name:'Ultra 100L', headSize:'100 in\\u00B2', weight:'280 g', tier:'light', match:{weight:'light',headsize:'small'},\n        desc:'Lightweight Ultra. Same power profile in a more maneuverable package, built for fast hands and quick swings.' },\n      { code:'100UL', name:'Ultra 100UL', headSize:'100 in\\u00B2', weight:'262 g', tier:'ulight', match:{weight:'light',headsize:'small',alt:true},\n        desc:'Ultra-lightweight. The easiest-swinging Ultra, for players who want explosive shots without the swing weight.' },\n      { code:'111', name:'Ultra 111', headSize:'111 in\\u00B2', weight:'270 g', tier:'os', match:{weight:'light',headsize:'large'},\n        desc:'Massive 111 in\\u00B2 head. The most forgiving Ultra. Combine the largest sweet spot in the lineup with Ultra power.' }\n    ] },\n  defyer:{ id:'defyer', name:'Defyer', tagline:'Heavy Spin. Heavy Ball.',\n    desc:'The Defyer is the spin specialist. An open string pattern, an aero-tuned beam, and a frame engineered around one job: grabbing the felt and ripping it. Heavy topspin, wicked angles, and a ball that dips and explodes off the bounce.',\n    stats:{power:4,spin:5,control:4}, img:'racket-defyer.png',\n    productUrl:'https:\/\/www.wilson.com\/en-us\/tennis\/tennis-rackets\/performance-rackets\/defyer',\n    variants:[\n      { code:'98 PRO', name:'Defyer 98 Pro', headSize:'98 in\\u00B2', weight:'315 g', tier:'pro', match:{weight:'heavy',headsize:'small'},\n        desc:'Tour-spec Defyer. Heaviest, smallest head, most precise. The spin weapon for the player who can swing it.' },\n      { code:'100', name:'Defyer 100', headSize:'100 in\\u00B2', weight:'300 g', tier:'std', match:{weight:'heavy',headsize:'large'},\n        desc:'The standard Defyer. Big spin, balanced specs: the heavy-topspin frame for the modern baseliner.' },\n      { code:'100L', name:'Defyer 100L', headSize:'100 in\\u00B2', weight:'280 g', tier:'light', match:{weight:'light',headsize:'small'},\n        desc:'Lightweight Defyer. Same string pattern, easier to swing, for the developing topspin player.' },\n      { code:'100UL', name:'Defyer 100UL', headSize:'100 in\\u00B2', weight:'262 g', tier:'ulight', match:{weight:'light',headsize:'small',alt:true},\n        desc:'Ultra-lightweight. The most maneuverable spin frame: easy on the arm, easy to whip.' }\n    ] },\n  blade:{ id:'blade', name:'Blade', tagline:'Explosive Control. Dictate Play.',\n    desc:\"The Blade is a legend. Feel Flex technology delivers a crisp, connected response on every shot, the racket that goes exactly where you point it. It\\u0027s the choice of serious players who win matches with placement, not power. You don\\u0027t hit harder on the Blade. You hit smarter.\",\n    stats:{power:2,spin:3,control:5}, img:'racket-blade.png',\n    productUrl:'https:\/\/www.wilson.com\/en-us\/tennis\/tennis-rackets\/blade',\n    variants:[\n      { code:'98 (16\\u00D719)', name:'Blade 98 v9 \\u00B7 16\\u00D719', headSize:'98 in\\u00B2', weight:'305 g', tier:'pro', match:{weight:'heavy',headsize:'small'},\n        desc:\"The open-pattern Blade. More spin and bite than the 18\\u00D720. The tournament player\\u0027s control weapon.\" },\n      { code:'98 (18\\u00D720)', name:'Blade 98 v9 \\u00B7 18\\u00D720', headSize:'98 in\\u00B2', weight:'305 g', tier:'pro', match:{weight:'heavy',headsize:'small',alt:true},\n        desc:'The tight-pattern Blade. The flattest, most predictable response in the lineup. Pure control players love this one.' },\n      { code:'100 PRO', name:'Blade 100 Pro', headSize:'100 in\\u00B2', weight:'300 g', tier:'pro', match:{weight:'heavy',headsize:'large'},\n        desc:'Blade feel with a forgiving 100 in\\u00B2 head. The control-first all-courter, for the player who wants pinpoint placement and some margin.' },\n      { code:'100', name:'Blade 100', headSize:'100 in\\u00B2', weight:'300 g', tier:'std', match:{weight:'heavy',headsize:'large',alt:true},\n        desc:'Standard Blade 100. The accessible Blade, same flex story in a more forgiving spec.' },\n      { code:'100L', name:'Blade 100L', headSize:'100 in\\u00B2', weight:'280 g', tier:'light', match:{weight:'light',headsize:'small'},\n        desc:'Lightweight Blade. Quick hands and Blade control in one. Doubles players who hit with shape, this is your stick.' },\n      { code:'100UL', name:'Blade 100UL', headSize:'100 in\\u00B2', weight:'262 g', tier:'ulight', match:{weight:'light',headsize:'small',alt:true},\n        desc:'Ultra-lightweight Blade. The easiest-swinging control frame, Blade DNA for developing competitive players.' },\n      { code:'104', name:'Blade 104', headSize:'104 in\\u00B2', weight:'290 g', tier:'os', match:{weight:'light',headsize:'large'},\n        desc:'Oversize Blade. The forgiving control frame: bigger sweet spot, same Feel Flex response.' }\n    ] },\n  'pro-staff':{ id:'pro-staff', name:'Pro Staff', tagline:'Versatile Control. Effortless Feel.',\n    desc:\"The Pro Staff is the racket of champions. Braided graphite delivers a feel so connected it\\u0027s almost telepathic. A headlight balance means fast, surgical swings. The Pro Staff isn\\u0027t the easiest racket, it\\u0027s the most rewarding. The frame for the player who has found their game and now wants to perfect it.\",\n    stats:{power:3,spin:2,control:5}, img:'racket-pro-staff.png',\n    productUrl:'https:\/\/www.wilson.com\/en-us\/tennis\/tennis-rackets\/performance-rackets\/pro-staff',\n    variants:[\n      { code:'97', name:'Pro Staff 97 v14', headSize:'97 in\\u00B2', weight:'315 g', tier:'pro', match:{weight:'heavy',headsize:'small'},\n        desc:'The flagship Pro Staff. 97 in\\u00B2 head, headlight balance, tour weight. The frame Federer made famous, and the one champions still reach for.' },\n      { code:'97', name:'Pro Staff 97 v14', headSize:'97 in\\u00B2', weight:'315 g', tier:'pro', match:{weight:'heavy',headsize:'large',alt:true},\n        desc:\"Pro Staff doesn\\u0027t come in an oversize. The 97 is as forgiving as this family gets. Tour-precise and surgical.\" },\n      { code:'97L', name:'Pro Staff 97L', headSize:'97 in\\u00B2', weight:'290 g', tier:'light', match:{weight:'light',headsize:'small'},\n        desc:'Lightweight Pro Staff. The same feel and balance in a more maneuverable spec, for the competitive doubles player.' },\n      { code:'97UL', name:'Pro Staff 97UL', headSize:'97 in\\u00B2', weight:'270 g', tier:'ulight', match:{weight:'light',headsize:'small',alt:true},\n        desc:'Ultra-lightweight Pro Staff. The most accessible entry into the Pro Staff family: same feel, lower swing weight.' },\n      { code:'97', name:'Pro Staff 97 (Std)', headSize:'97 in\\u00B2', weight:'315 g', tier:'std', match:{weight:'light',headsize:'large',alt:true},\n        desc:'No oversize Pro Staff exists. The 97 is the family. Pick the lighter spec for an easier swing, or step over to a Blade 104 for a bigger head.' }\n    ] }\n};\n\n\/* -- MATCHING RULES -------------------------------------------------\n   EDIT (advanced): which family each answer path lands on.\n   power + extra power = Ultra | power + own power = Clash | spin = Defyer\n   control + extra power = Blade | control + own power = Pro Staff *\/\nfunction chooseFamily(a){\n  if(a.priority === 'spin') return 'defyer';\n  if(a.priority === 'power') return a.profile === 'explosive' ? 'ultra' : 'clash';\n  if(a.priority === 'control') return a.profile === 'explosive' ? 'blade' : 'pro-staff';\n  return 'clash';\n}\nfunction chooseVariant(key,a){\n  var fam = FAMILIES[key], v = null, i, x, y, p;\n  var weight = a.weight === 'medium' ? 'heavy' : a.weight;\n  var headsize = a.headsize === 'medium' ? 'small' : a.headsize;\n  for(i=0;i<fam.variants.length;i++){\n    x=fam.variants[i];\n    if(x.match.weight===weight){\n      if(x.match.headsize===headsize){\n        if(!x.match.alt){ v=x; break; }\n      }\n    }\n  }\n  if(!v){\n    for(i=0;i<fam.variants.length;i++){\n      y=fam.variants[i];\n      if(y.match.weight===weight){\n        if(y.match.headsize===headsize){ v=y; break; }\n      }\n    }\n  }\n  if(a.level === 'pro'){\n    for(i=0;i<fam.variants.length;i++){\n      p=fam.variants[i];\n      if(p.tier==='pro'){\n        if(!p.match.alt){ v=p; break; }\n      }\n    }\n  }\n  return v || fam.variants[0];\n}\n\n\/* -- App state + helpers (no copy below this line) ------------------- *\/\nvar state = { view:'hero', stepIndex:0, history:[], answers:{} };\nvar $ = function(id){ return document.getElementById(id); };\nvar TIER = { pro:'Pro Spec', os:'Oversize', light:'Light', ulight:'Ultra-Light', std:'Standard' };\nvar BUILD = { pro:'Tour-spec build', os:'Oversize frame', light:'Lightweight build', ulight:'Ultra-lightweight build', std:'Standard build' };\nfunction esc(s){ return String(s).replace(\/\\u0026\/g,'\\u0026amp;').replace(\/<\/g,'&lt;').replace(\/>\/g,'&gt;').replace(\/\"\/g,'&quot;'); }\nfunction pushDL(obj){\n  window.dataLayer = window.dataLayer || [];\n  window.dataLayer.push(obj);\n}\nfunction stepById(id){\n  var i;\n  for(i=0;i<STEPS.length;i++){ if(STEPS[i].id === id) return STEPS[i]; }\n  return null;\n}\nfunction optionFor(step,value){\n  var opt = null;\n  if(!step) return null;\n  step.options.forEach(function(o){ if(o.value === value) opt = o; });\n  return opt;\n}\nfunction visibleSteps(){ return STEPS.filter(function(s){ return !s.skipIf || !s.skipIf(state.answers); }); }\nfunction nextIndex(from){ for(var i=from+1;i<STEPS.length;i++){ var s=STEPS[i]; if(!s.skipIf || !s.skipIf(state.answers)) return i; } return -1; }\n\nfunction rfRoot(id){\n  var el = $(id);\n  return el && el.closest ? el.closest('.pyc-rf') : null;\n}\nfunction setView(view){\n  var hero = $('rf-hero'), quiz = $('rf-quiz'), result = $('rf-result');\n  var heroRoot = rfRoot('rf-hero'), quizRoot = rfRoot('rf-quiz'), resultRoot = rfRoot('rf-result');\n  var sharedRoot = heroRoot && heroRoot === quizRoot && quizRoot === resultRoot;\n  if(hero) hero.style.display = view === 'hero' ? '' : 'none';\n  if(quiz) quiz.classList.toggle('rf-show', view === 'quiz');\n  if(result) result.classList.toggle('rf-show', view === 'result');\n  if(!sharedRoot){\n    if(heroRoot) heroRoot.style.display = view === 'hero' ? '' : 'none';\n    if(quizRoot) quizRoot.style.display = view === 'quiz' ? '' : 'none';\n    if(resultRoot) resultRoot.style.display = view === 'result' ? '' : 'none';\n  }\n  state.view = view;\n  window.scrollTo({ top:0, behavior:'smooth' });\n}\nfunction startQuiz(){\n  state.answers={}; state.history=[]; state.stepIndex=0;\n  pushDL({\n    event:'Key Action',\n    action:'racket-finder-start',\n    funnel:'racket_finder',\n    page:'the-tennis-racket-finder'\n  });\n  setView('quiz'); renderStep();\n}\nfunction restart(){ state.answers={}; state.history=[]; state.stepIndex=0; setView('hero'); renderAside(); }\nfunction goBack(){\n  if(!state.history.length) return;\n  var prev = state.history.pop();\n  for(var i=prev;i<STEPS.length;i++) delete state.answers[STEPS[i].id];\n  state.stepIndex = prev;\n  if(state.view !== 'quiz') setView('quiz');\n  renderStep();\n}\nfunction answer(stepId,value){\n  var step = stepById(stepId), opt = optionFor(step,value), visible = visibleSteps(), idx = 0, i;\n  for(i=0;i<visible.length;i++) if(visible[i].id === stepId) idx = i;\n  pushDL({\n    event:'Key Action',\n    action:'racket-finder-answer',\n    funnel:'racket_finder',\n    question_id:stepId,\n    question_label:step ? step.label : stepId,\n    answer_value:value,\n    answer_label:opt ? opt.title : value,\n    step_number:idx + 1,\n    step_total:visible.length\n  });\n  state.answers[stepId] = value;\n  state.history.push(state.stepIndex);\n  var n = nextIndex(state.stepIndex);\n  if(n === -1){ renderResult(); setView('result'); }\n  else { state.stepIndex = n; renderStep(); }\n}\n\nfunction renderStep(){\n  window.scrollTo({ top:0, behavior:'smooth' });\n  var step = STEPS[state.stepIndex], visible = visibleSteps();\n  var idx = 0;\n  for(var i=0;i<visible.length;i++) if(visible[i].id === step.id) idx = i;\n  var total = visible.length;\n  $('rf-step-num').textContent = String(idx+1).padStart(2,'0') + ' \/ ' + String(total).padStart(2,'0');\n  $('rf-step-name').textContent = step.label;\n  $('rf-prog-fill').style.width = ((idx\/total)*100 + (100\/total)*0.15) + '%';\n  var back = $('rf-back');\n  if(state.history.length) back.removeAttribute('disabled'); else back.setAttribute('disabled','');\n\n  var choices = step.options.map(function(opt,i){\n    var cc = opt.color === 'b' ? 'rf-c-b' : opt.color === 'g' ? 'rf-c-g' : opt.color === 'o' ? 'rf-c-o' : '';\n    return '<button type=\"button\" class=\"rf-choice '+cc+' rf-in rf-d'+Math.min(i,3)+'\" data-rf=\"answer\" data-step=\"'+step.id+'\" data-value=\"'+opt.value+'\">'\n      + '<span class=\"rf-choice-tag rf-t-'+opt.color+'\">'+esc(opt.tag)+'<\/span>'\n      + '<span class=\"rf-choice-title\">'+esc(opt.title)+'<\/span>'\n      + '<span class=\"rf-choice-desc\">'+esc(opt.desc)+'<\/span>'\n      + '<span class=\"rf-choice-foot\"><span>Pick this<\/span><span class=\"rf-arr\">&rarr;<\/span><\/span><\/button>';\n  }).join('');\n\n  $('rf-question').innerHTML =\n    '<div class=\"rf-eyebrow rf-in\">Question '+(idx+1)+' of '+total+'<\/div>'\n    + '<h2 class=\"rf-headline rf-in\">'+step.prompt+'<\/h2>'\n    + '<p class=\"rf-sub rf-in rf-d1\">'+esc(step.sub)+'<\/p>'\n    + '<div class=\"rf-choice-grid '+(step.cols === 3 ? 'rf-cols-3' : 'rf-cols-2')+'\">'+choices+'<\/div>';\n  renderAside();\n}\n\nfunction renderAside(){\n  var list = $('rf-aside-list'), steps = visibleSteps(), any = false, i;\n  for(i=0;i<steps.length;i++) if(state.answers[steps[i].id]) any = true;\n  if(!any){\n    \/* EDIT: Empty-sidebar message *\/\n    list.innerHTML = \"<div class=\\\"rf-aside-empty\\\">No selections yet. Pick one option per question, we\\u0027ll match you to a racket in under a minute.<\/div>\";\n    return;\n  }\n  list.innerHTML = steps.map(function(s){\n    var a = state.answers[s.id], opt = null;\n    if(a) s.options.forEach(function(o){ if(o.value === a) opt = o; });\n    return '<div class=\"rf-aside-item\"><div class=\"rf-aside-q\">'+esc(s.label)+'<\/div>'\n      + '<div class=\"rf-aside-a'+(opt ? '' : ' rf-pending')+'\">'+(opt ? esc(opt.title) : '')+'<\/div><\/div>';\n  }).join('');\n}\n\nfunction statRow(name,value){\n  var pips = '';\n  for(var n=1;n<=5;n++) pips += '<span class=\"rf-stat-pip'+(n <= value ? ' rf-on' : '')+'\"><\/span>';\n  return '<div class=\"rf-stat-row\"><span class=\"rf-stat-name\">'+name+'<\/span>'\n    + '<span class=\"rf-stat-pips\">'+pips+'<\/span><span class=\"rf-stat-value\">'+value+'<\/span><\/div>';\n}\n\n\/* EDIT: The \"Coach says\" read-back sentence *\/\nfunction coachSays(a,family){\n  var level = a.level === 'pro' ? 'high-level' : a.level === 'competitive' ? 'competitive' : 'casual';\n  var profile = a.profile ? a.profile + '-power ' : '';\n  var swing = a.swingType === 'either' ? 'a mixed swing path' : 'a ' + a.swingType + ' swing';\n  var speed = a.swingSpeed === 'fast' ? 'a fast swing speed' : a.swingSpeed === 'medium' ? 'a medium swing speed' : 'an average swing speed';\n  var weight = a.weight === 'light' ? 'lighter' : a.weight === 'medium' ? 'medium-weight' : 'heavier';\n  var head = a.headsize === 'large' ? 'larger sweet spot' : a.headsize === 'medium' ? 'mid-size head' : 'tighter string bed';\n  return 'A ' + level + ' player who wants ' + a.priority + ', with ' + profile + swing + ' and ' + speed\n    + \", paired with a \" + weight + \" frame and a \" + head + \". That\\u0027s exactly what the \" + family.name + \" is built for.\";\n}\n\nfunction renderResult(){\n  var a = state.answers, key = chooseFamily(a), family = FAMILIES[key], variant = chooseVariant(key,a);\n  var seen = {}, shown = family.variants.filter(function(v){\n    var k = v.code + '|' + v.name; if(seen[k]) return false; seen[k] = 1; return true;\n  });\n  var variantsHtml = shown.map(function(v){\n    var mine = v.name === variant.name ? v.code === variant.code : false;\n    return '<div class=\"rf-variant'+(mine ? ' rf-featured' : '')+'\">'\n      + (mine ? '<span class=\"rf-pill\">Your Match<\/span>' : '')\n      + '<div class=\"rf-variant-spec\">'+(TIER[v.tier] || 'Standard')+' \\u00B7 '+esc(v.code)+'<\/div>'\n      + '<div class=\"rf-variant-name\">'+esc(v.name)+'<\/div>'\n      + '<div class=\"rf-variant-desc\">'+esc(v.desc)+'<\/div>'\n      + '<div class=\"rf-variant-metrics\">'\n      + '<div><div class=\"rf-metric-lbl\">Head<\/div><div class=\"rf-metric-val\">'+esc(v.headSize)+'<\/div><\/div>'\n      + '<div><div class=\"rf-metric-lbl\">Weight<\/div><div class=\"rf-metric-val\">'+esc(v.weight)+'<\/div><\/div>'\n      + '<\/div><\/div>';\n  }).join('');\n\n  $('rf-result-inner').innerHTML =\n    '<div class=\"rf-eyebrow rf-in\">Your Match<\/div>'\n    + '<div class=\"rf-rhero rf-in rf-d1\"><div class=\"rf-rhero-copy\">'\n      + '<div class=\"rf-kicker\">Your recommended racket<\/div>'\n      + '<div class=\"rf-family\">THE WILSON<br>'+esc(family.name).toUpperCase()+'<\/div>'\n      + '<div class=\"rf-tagline\">'+esc(family.tagline)+'<\/div>'\n      + '<p class=\"rf-desc\">'+esc(family.desc)+'<\/p>'\n      + '<p class=\"rf-market\">We matched your answers against dozens of frames across the market. For your game, this is the one.<\/p>'\n    + '<\/div><div class=\"rf-rhero-photo\"><img decoding=\"async\" src=\"'+ASSETS+family.img+'\" alt=\"Wilson '+esc(family.name)+'\"><\/div><\/div>'\n    + '<div class=\"rf-spotlight rf-in rf-d2\">'\n      + '<div class=\"rf-spot-label\">Your Specific Model<\/div>'\n      + '<div class=\"rf-spot-name\">'+esc(variant.name)+'<\/div>'\n      + '<p class=\"rf-spot-desc\">'+esc(variant.desc)+'<br><br><strong>Spec:<\/strong> '+esc(variant.headSize)+' head \\u00B7 '+esc(variant.weight)+' unstrung \\u00B7 '+(BUILD[variant.tier] || 'Standard build')+'.<\/p>'\n      + '<div class=\"rf-fc\"><div class=\"rf-fc-title\">Frame Character \\u00B7 1-to-5 scale<\/div>'\n        + statRow('Power',family.stats.power) + statRow('Spin',family.stats.spin) + statRow('Control',family.stats.control)\n      + '<\/div>'\n      + '<p class=\"rf-coach\"><strong>COACH SAYS<\/strong><br>'+esc(coachSays(a,family))+'<\/p>'\n      + '<a class=\"rf-spot-cta\" href=\"'+wilsonProductUrl(family.productUrl)+'\" target=\"_blank\" rel=\"noopener\">Shop at Wilson.com &rarr;<\/a>'\n    + '<\/div>'\n    + '<div class=\"rf-variants-head rf-in rf-d3\"><div>'\n      + '<div class=\"rf-eyebrow\" style=\"margin-bottom:14px\">Which '+esc(family.name)+' fits you<\/div>'\n      + '<h3 class=\"rf-variants-title\">PICK YOUR BUILD.<\/h3><\/div>'\n      + \"<p class=\\\"rf-variants-sub\\\">The Wilson \"+esc(family.name)+\" comes in a few builds. Here\\u0027s the weight and head size that fits how you swing.<\/p>\"\n    + '<\/div>'\n    + '<div class=\"rf-variant-grid\">'+variantsHtml+'<\/div>'\n    + '<div class=\"rf-restart-wrap\"><button type=\"button\" class=\"rf-btn-outline\" data-rf=\"restart\">&#8635; Re-take Quiz<\/button><\/div>';\n\n  $('rf-prog-fill').style.width = '100%';\n  pushDL({\n    event:'Key Action',\n    action:'racket-finder-complete',\n    funnel:'racket_finder',\n    recommended_family:family.name,\n    recommended_variant:variant.name,\n    recommended_family_id:key,\n    level:a.level || null,\n    priority:a.priority || null,\n    profile:a.profile || null,\n    swing_type:a.swingType || null,\n    swing_speed:a.swingSpeed || null,\n    weight:a.weight || null,\n    headsize:a.headsize || null\n  });\n}\n\n\/* One click handler for the whole tool -- nothing is bound to the global page. *\/\ndocument.addEventListener('click', function(e){\n  var t = e.target.closest ? e.target.closest('[data-rf]') : null;\n  if(!t) return;\n  var act = t.getAttribute('data-rf');\n  if(act === 'start'){ e.preventDefault(); startQuiz(); }\n  else if(act === 'back'){ e.preventDefault(); goBack(); }\n  else if(act === 'restart'){ e.preventDefault(); restart(); }\n  else if(act === 'answer'){ e.preventDefault(); answer(t.getAttribute('data-step'), t.getAttribute('data-value')); }\n});\n\nrenderAside();\n})();\n<\/script>\n\n<!-- ======================================================================\n     SECTIONS 1\u20133  (hero, quiz, result \u2014 one wrapper so inactive views\n     don't leave empty blocks \/ extra gap above the quiz bar)\n     ================================================================== -->\n<div class=\"pyc-rf\">\n  <section class=\"rf-hero\" id=\"rf-hero\">\n    <div class=\"rf-hero-inner\">\n      <!-- EDIT: Small label above the headline -->\n      <div class=\"rf-eyebrow\">The PlayYourCourt Racket Finder<\/div>\n      <!-- EDIT: Big headline. The word inside <span> is the yellow one. -->\n      <h1 class=\"rf-hero-title\">FIND THE<br><span>RIGHT<\/span><br>RACKET.<\/h1>\n      <!-- EDIT: Intro paragraph -->\n      <p class=\"rf-hero-body\">The racket you play with should fit your game: your level, your swing, your style. Answer a couple of quick questions about how you play, and we'll show you the racket that's right for you.<\/p>\n      <div>\n        <!-- EDIT: Button label -->\n        <button class=\"rf-btn\" data-rf=\"start\" type=\"button\">Start the Quiz <span style=\"font-size:18px\">\u2192<\/span><\/button>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"rf-quiz\" id=\"rf-quiz\">\n    <div class=\"rf-prog-wrap\">\n      <!-- EDIT: Back button label -->\n      <button class=\"rf-back\" id=\"rf-back\" data-rf=\"back\" type=\"button\" disabled=\"\">\u2190 Back<\/button>\n      <div class=\"rf-step-label\"><span class=\"rf-step-num\" id=\"rf-step-num\">01 \/ 07<\/span><span id=\"rf-step-name\">Player Level<\/span><\/div>\n      <div class=\"rf-prog-bar\"><div class=\"rf-prog-fill\" id=\"rf-prog-fill\"><\/div><\/div>\n    <\/div>\n    <div class=\"rf-shell\">\n      <div class=\"rf-question\" id=\"rf-question\"><\/div>\n      <aside class=\"rf-aside\">\n        <!-- EDIT: Sidebar heading -->\n        <div class=\"rf-aside-label\">Your Answers<\/div>\n        <div class=\"rf-aside-list\" id=\"rf-aside-list\"><\/div>\n        <!-- EDIT: Restart button label -->\n        <button class=\"rf-btn-outline rf-aside-restart\" data-rf=\"restart\" type=\"button\">Restart Quiz<\/button>\n      <\/aside>\n    <\/div>\n  <\/section>\n\n  <section class=\"rf-result\" id=\"rf-result\">\n    <div class=\"rf-result-inner\" id=\"rf-result-inner\"><\/div>\n  <\/section>\n<\/div>\n\n\n","protected":false},"excerpt":{"rendered":"<p>The PlayYourCourt Racket Finder FIND THERIGHTRACKET. The racket you play with should fit your game: your level, your swing, your style. Answer a couple of quick questions about how you play, and we&#8217;ll show you the racket that&#8217;s right for you. Start the Quiz \u2192 \u2190 Back 01 \/ 07Player Level Your Answers Restart Quiz<\/p>\n","protected":false},"author":19,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"rop_custom_images_group":[],"rop_custom_messages_group":[],"rop_publish_now":"initial","rop_publish_now_accounts":[],"rop_publish_now_history":[],"rop_publish_now_status":"pending","_kad_post_transparent":"disable","_kad_post_title":"hide","_kad_post_layout":"fullwidth","_kad_post_sidebar_id":"","_kad_post_content_style":"unboxed","_kad_post_vertical_padding":"","_kad_post_feature":"hide","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"class_list":["post-10775","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>The Tennis Racket Finder - Improve Your game - Win More Matches<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.playyourcourt.com\/news\/the-tennis-racket-finder\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"The Tennis Racket Finder - Improve Your game - Win More Matches\" \/>\n<meta property=\"og:description\" content=\"The PlayYourCourt Racket Finder FIND THERIGHTRACKET. The racket you play with should fit your game: your level, your swing, your style. Answer a couple of quick questions about how you play, and we&#039;ll show you the racket that&#039;s right for you. Start the Quiz \u2192 \u2190 Back 01 \/ 07Player Level Your Answers Restart Quiz\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.playyourcourt.com\/news\/the-tennis-racket-finder\/\" \/>\n<meta property=\"og:site_name\" content=\"Improve Your game - Win More Matches\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/PlayYourCourt\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-30T17:36:27+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@playyourcourt\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/the-tennis-racket-finder\\\/\",\"url\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/the-tennis-racket-finder\\\/\",\"name\":\"The Tennis Racket Finder - Improve Your game - Win More Matches\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/#website\"},\"datePublished\":\"2026-07-28T16:23:16+00:00\",\"dateModified\":\"2026-07-30T17:36:27+00:00\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/the-tennis-racket-finder\\\/\"]}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/#website\",\"url\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/\",\"name\":\"Improve Your game - Win More Matches\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/#organization\",\"name\":\"PlayYourCourt\",\"url\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/wp-content\\\/uploads\\\/2023\\\/12\\\/PYC-Social-Logo-Black-copy.png\",\"contentUrl\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/wp-content\\\/uploads\\\/2023\\\/12\\\/PYC-Social-Logo-Black-copy.png\",\"width\":2263,\"height\":2263,\"caption\":\"PlayYourCourt\"},\"image\":{\"@id\":\"https:\\\/\\\/www.playyourcourt.com\\\/news\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/PlayYourCourt\",\"https:\\\/\\\/x.com\\\/playyourcourt\",\"https:\\\/\\\/www.instagram.com\\\/playyourcourt\\\/\",\"https:\\\/\\\/www.youtube.com\\\/playyourcourt\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"The Tennis Racket Finder - Improve Your game - Win More Matches","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:\/\/www.playyourcourt.com\/news\/the-tennis-racket-finder\/","og_locale":"en_US","og_type":"article","og_title":"The Tennis Racket Finder - Improve Your game - Win More Matches","og_description":"The PlayYourCourt Racket Finder FIND THERIGHTRACKET. The racket you play with should fit your game: your level, your swing, your style. Answer a couple of quick questions about how you play, and we'll show you the racket that's right for you. Start the Quiz \u2192 \u2190 Back 01 \/ 07Player Level Your Answers Restart Quiz","og_url":"https:\/\/www.playyourcourt.com\/news\/the-tennis-racket-finder\/","og_site_name":"Improve Your game - Win More Matches","article_publisher":"https:\/\/www.facebook.com\/PlayYourCourt","article_modified_time":"2026-07-30T17:36:27+00:00","twitter_card":"summary_large_image","twitter_site":"@playyourcourt","twitter_misc":{"Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.playyourcourt.com\/news\/the-tennis-racket-finder\/","url":"https:\/\/www.playyourcourt.com\/news\/the-tennis-racket-finder\/","name":"The Tennis Racket Finder - Improve Your game - Win More Matches","isPartOf":{"@id":"https:\/\/www.playyourcourt.com\/news\/#website"},"datePublished":"2026-07-28T16:23:16+00:00","dateModified":"2026-07-30T17:36:27+00:00","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.playyourcourt.com\/news\/the-tennis-racket-finder\/"]}]},{"@type":"WebSite","@id":"https:\/\/www.playyourcourt.com\/news\/#website","url":"https:\/\/www.playyourcourt.com\/news\/","name":"Improve Your game - Win More Matches","description":"","publisher":{"@id":"https:\/\/www.playyourcourt.com\/news\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.playyourcourt.com\/news\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.playyourcourt.com\/news\/#organization","name":"PlayYourCourt","url":"https:\/\/www.playyourcourt.com\/news\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.playyourcourt.com\/news\/#\/schema\/logo\/image\/","url":"https:\/\/www.playyourcourt.com\/news\/wp-content\/uploads\/2023\/12\/PYC-Social-Logo-Black-copy.png","contentUrl":"https:\/\/www.playyourcourt.com\/news\/wp-content\/uploads\/2023\/12\/PYC-Social-Logo-Black-copy.png","width":2263,"height":2263,"caption":"PlayYourCourt"},"image":{"@id":"https:\/\/www.playyourcourt.com\/news\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/PlayYourCourt","https:\/\/x.com\/playyourcourt","https:\/\/www.instagram.com\/playyourcourt\/","https:\/\/www.youtube.com\/playyourcourt"]}]}},"_links":{"self":[{"href":"https:\/\/www.playyourcourt.com\/news\/wp-json\/wp\/v2\/pages\/10775","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.playyourcourt.com\/news\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.playyourcourt.com\/news\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.playyourcourt.com\/news\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/www.playyourcourt.com\/news\/wp-json\/wp\/v2\/comments?post=10775"}],"version-history":[{"count":17,"href":"https:\/\/www.playyourcourt.com\/news\/wp-json\/wp\/v2\/pages\/10775\/revisions"}],"predecessor-version":[{"id":10869,"href":"https:\/\/www.playyourcourt.com\/news\/wp-json\/wp\/v2\/pages\/10775\/revisions\/10869"}],"wp:attachment":[{"href":"https:\/\/www.playyourcourt.com\/news\/wp-json\/wp\/v2\/media?parent=10775"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}