{
  "version": 3,
  "sources": ["/cdn/shop/t/4/assets/s-sound-guide.js?guide_revision=upgrade-only-20261010"],
  "sourcesContent": ["// Drives the Find your sound guide. Shoppers tick one or more goals and a product budget; this element\n// loads the mapped collections (real products and prices from `?view=guide-picks`, product-guard applied)\n// and fills Good / Better / Best tiers with one product per item being upgraded. Tiers are picked from\n// price percentiles inside each product type, so Good starts mid-range rather than at the cheapest item.\n// Nothing here claims vehicle fit or that parts are electrically matched; the block copy says so.\n\nconst GOALS = ['bass', 'speakers', 'power', 'cables', 'marine', 'clarity', 'headlights', 'stealth-boxes', 'oem-carplay', 'carplay-radio'];\n\n// Upgraded LED headlight bulbs (owner-specified): Good = Lucas L1, Better = Lucas L3, Best = Lucas L5, taken only\n// from the Upgraded LED Headlight Bulbs collection. No bulb size or vehicle fit is chosen or implied; every tier\n// shows the bulb-size note and the Lucas Lighting bulb finder link.\nconst LUCAS_HEADLIGHT_TIERS = [\n  /\\blucas lighting l1 series led headlight bulbs\\b/,\n  /\\blucas lighting l3 series led headlight bulbs\\b/,\n  /\\blucas lighting l5 series led headlight bulbs\\b/,\n];\n\n\n// ---- Stealth Boxes (JL Audio Stealthbox vehicle matching) ----\n// Recommends only JL Audio Stealthboxes whose SKU (or handle) has a verified make / model / model-year entry\n// in JL's fitment table below for the selected vehicle. Entries without confirmed years never match, and a\n// product with no entry is never shown. No title-only or partial-year guessing.\nfunction normVehicle(value) { return String(value || '').toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim().replace(/\\s+/g, ' '); }\nfunction makeMatches(candidate, wanted) {\n  const aliases = { chevrolet: ['chevy'], volkswagen: ['vw'], mercedes: ['mercedes benz'], ram: ['dodge ram', 'dodge'], dodge: ['dodge ram', 'ram'] };\n  const a = normVehicle(candidate), b = normVehicle(wanted);\n  return a === b || (aliases[a] || []).includes(b) || (aliases[b] || []).includes(a);\n}\n\nfunction yearMatches(rangeText, year) {\n  const fullYears = [...String(rangeText || '').matchAll(/\\b(?:19|20)\\d{2}\\b/g)].map((match) => Number(match[0]));\n  if (!fullYears.length) return false;\n  let from = fullYears[0], to = fullYears[1] || from;\n  if (fullYears.length === 1 && /\\b(up|newer|on)\\b|\\+/.test(String(rangeText).toLowerCase())) to = Infinity;\n  return Number(year) >= from && Number(year) <= to;\n}\nfunction zz2VehicleMatch(item, vehicle) {\n  if (!item.description || String(item.vendor || '').toLowerCase().replace(/[^a-z0-9]/g, '') !== 'zz2' || !/\\bit(?:\\d|[a-z])?-/i.test(item.title || '')) return false;\n  const selection = vehicle?.selection;\n  if (!selection?.year || !selection?.make || !selection?.model || vehicle.manual) return false;\n  const doc = new DOMParser().parseFromString(item.description, 'text/html');\n  const wantedModel = normVehicle(selection.model);\n  for (const table of doc.querySelectorAll('table')) {\n    const headers = [...table.querySelectorAll('tr:first-child th, tr:first-child td')].map((cell) => normVehicle(cell.textContent));\n    const modelIndex = headers.findIndex((header) => header === 'model' || header.includes('model'));\n    const yearIndex = headers.findIndex((header) => header.includes('year'));\n    if (modelIndex < 0 || yearIndex < 0) continue;\n    let heading = table.previousElementSibling;\n    while (heading && !/^H[1-4]$/.test(heading.tagName)) heading = heading.previousElementSibling;\n    const makeMatch = (heading?.textContent || '').match(/compatibility\\s*[-:]\\s*([^:]+)/i);\n    const tableMake = makeMatch?.[1] || '';\n    for (const row of table.querySelectorAll('tbody tr')) {\n      const cells = [...row.querySelectorAll('td')];\n      if (!cells[modelIndex] || !cells[yearIndex] || !yearMatches(cells[yearIndex].textContent, selection.year)) continue;\n      const rowModel = normVehicle(cells[modelIndex].textContent);\n      const options = rowModel.split(/[,;\\/]|\\bor\\b/).map((part) => part.trim()).filter(Boolean);\n      const modelMatch = options.some((part) => wantedModel === part || wantedModel.startsWith(part + ' ') || part.startsWith(wantedModel + ' ') || (normVehicle(selection.make) === 'bmw' && /^[1-8]\\d{2}[a-z]*$/.test(wantedModel) && part === wantedModel[0] + ' series'));\n      if (modelMatch && (makeMatches(tableMake, selection.make) || makeMatches(row.textContent, selection.make))) return true;\n    }\n  }\n  return false;\n}\n\n// Exact PAC AmpPRO applications from the published application table. The vehicle selector does not identify\n// factory audio trims, so recommendations still ask customers to confirm their factory system.\nconst PAC_APPS = {\n  'ap4-ch21': [['chrysler',['town country'],2008,2016],['dodge',['challenger'],2008,2014],['dodge',['charger'],2008,2010],['dodge',['durango'],2009,2013],['dodge',['grand caravan'],2008,2018],['dodge',['ram truck','ram','1500','2500','3500','4500','5500'],2009,2012],['jeep',['grand cherokee'],2008,2013],['jeep',['wrangler'],2007,2018],['jeep',['wrangler unlimited'],2007,2018],['ram',['ram truck','ram','1500','2500','3500','4500','5500'],2010,2012]],\n  'ap4-ch31': [['chrysler',['300'],2011,2014],['dodge',['charger'],2011,2014],['dodge',['journey'],2011,2015],['maserati',['ghibli'],2015,2015],['maserati',['quattroporte'],2014,2016]],\n  'ap4-ch41': [['chrysler',['200'],2015,2017],['chrysler',['300'],2015,2022],['chrysler',['pacifica'],2017,2022],['dodge',['challenger'],2015,2023],['dodge',['charger'],2015,2023],['dodge',['durango'],2014,2021],['dodge',['ram truck','ram','1500','2500','3500','4500','5500'],2013,2024],['jeep',['cherokee'],2015,2021]],\n  'ap4-ch42': [['chrysler',['pacifica'],2021,2022],['dodge',['durango'],2021,2021],['dodge',['ram truck','ram','1500','2500','3500','4500','5500'],2022,2024],['jeep',['wrangler'],2024,2024],['jeep',['wrangler unlimited'],2024,2024],['ram',['ram truck','ram','1500','2500','3500','4500','5500'],2022,2024]],\n  'ap4-fd11': [['ford',['f 150','f150'],2009,2012],['ford',['flex'],2009,2012],['ford',['fusion'],2010,2012],['ford',['taurus'],2010,2012],['lincoln',['mks'],2009,2012],['lincoln',['mkt'],2010,2012],['lincoln',['mkx'],2007,2010],['lincoln',['mkz'],2007,2012],['lincoln',['navigator'],2007,2014]],\n  'ap4-fd21': [['ford',['edge'],2015,2017],['ford',['escape'],2016,2016],['ford',['expedition'],2015,2017],['ford',['explorer'],2011,2018],['ford',['f 150','f150'],2013,2017],['ford',['f 250','f250'],2013,2019],['ford',['f 350','f350'],2013,2019],['ford',['f 450','f450'],2013,2019],['ford',['f 550','f550'],2013,2019],['ford',['focus'],2012,2017],['ford',['fusion'],2013,2016],['ford',['mustang'],2019,2020]],\n  'ap4-fd31': [['ford',['bronco'],2021,2024],['ford',['bronco sport'],2021,2024],['ford',['eco sport','ecosport'],2021,2021],['ford',['edge'],2019,2022],['ford',['escape'],2021,2022],['ford',['expedition'],2018,2020],['ford',['explorer'],2020,2024],['ford',['f 150','f150'],2018,2024],['ford',['f 250','f250'],2020,2024],['ford',['f 350','f350'],2020,2024],['ford',['f 450','f450'],2020,2020],['ford',['lightning'],2022,2022],['ford',['maverick'],2022,2022],['ford',['mustang'],2024,2024],['ford',['mustang mach e','mustang mach-e'],2021,2023],['ford',['ranger'],2020,2023]],\n  'ap4-gm61': [['cadillac',['ats'],2015,2015],['cadillac',['ct6'],2017,2017],['cadillac',['escalade'],2015,2019],['chevrolet',['camaro'],2016,2018],['chevrolet',['colorado'],2015,2018],['chevrolet',['corvette'],2014,2019],['chevrolet',['cruze'],2017,2018],['chevrolet',['equinox'],2018,2018],['chevrolet',['impala'],2014,2019],['chevrolet',['malibu'],2016,2018],['chevrolet',['silverado'],2014,2019],['chevrolet',['silverado hd'],2015,2019],['chevrolet',['suburban'],2015,2019],['chevrolet',['tahoe'],2015,2019],['chevrolet',['traverse'],2018,2019],['chevrolet',['volt'],2016,2018],['gmc',['acadia'],2018,2019],['gmc',['canyon'],2015,2018],['gmc',['sierra'],2014,2019],['gmc',['sierra hd'],2015,2019],['gmc',['terrain'],2018,2018],['gmc',['yukon'],2015,2019],['gmc',['yukon xl'],2015,2019]],\n  'ap4-ty11': [['lexus',['ct 200h'],2011,2013],['lexus',['es 300'],2002,2003],['lexus',['es 300h'],2013,2014],['lexus',['es 330'],2004,2006],['lexus',['es 350'],2007,2014],['lexus',['gx 460'],2009,2013],['lexus',['gx 470'],2004,2009],['lexus',['hs 250h'],2010,2012]],\n  'ap4-ty12': [['lexus',['ct 200h'],2014,2017],['lexus',['es 350'],2015,2017],['lexus',['gx 460'],2014,2017],['lexus',['is 200t'],2016,2017],['lexus',['is 250'],2014,2015],['lexus',['is 300'],2016,2017],['lexus',['nx 200t'],2015,2017]],\n  'ap4-ty13': [['lexus',['es 250'],2019,2021],['lexus',['es 350'],2019,2021],['lexus',['nx 300'],2019,2021],['lexus',['rx 350'],2019,2021],['lexus',['rx 450h'],2019,2020],['toyota',['4runner'],2019,2020],['toyota',['avalon'],2019,2021],['toyota',['camry'],2018,2021],['toyota',['corolla'],2019,2019],['toyota',['highlander'],2020,2021],['toyota',['rav4'],2019,2020],['toyota',['sequoia'],2019,2021],['toyota',['sienna'],2018,2020],['toyota',['tacoma'],2019,2021],['toyota',['tundra'],2020,2021]],\n  'ap4-ty14': [['toyota',['corolla hatchback'],2023,2023],['toyota',['highlander'],2024,2024],['toyota',['land cruiser'],2024,2024],['toyota',['tacoma'],2024,2024],['toyota',['tundra'],2022,2024]],\n};\nconst PAC_SUB_ALIAS = { 'apsub-ch21':'ap4-ch21', 'apsub-ch41':'ap4-ch41', 'apsub-ch42':'ap4-ch42', 'apsub-fd21':'ap4-fd21', 'apsub-gm61':'ap4-gm61', 'apsub-ty12':'ap4-ty12', 'apsub-ty13':'ap4-ty13' };\nfunction pacPart(item) {\n  const match = String(item.title || '').toLowerCase().match(/\\b(ap4|apsub)[- ]?([a-z]{2}\\d{2})\\b/);\n  return match ? (match[1] + '-' + match[2]).replace(/\\s/g, '') : '';\n}\nfunction pacVehicleMatch(item, vehicle, useAmpPro4) {\n  const part = pacPart(item), isSubPart = part.startsWith('apsub-');\n  if (!part || isSubPart === useAmpPro4) return false;\n  const key = PAC_APPS[part] ? part : PAC_SUB_ALIAS[part], selection = vehicle?.selection || vehicle;\n  if (!key || !selection?.year || !selection?.make || !selection?.model) return false;\n  const year = Number(selection.year), make = normVehicle(selection.make), model = normVehicle(selection.model);\n  return PAC_APPS[key].some(([rowMake, models, from, to]) => year >= from && year <= to && makeMatches(rowMake, make) && models.some((alias) => {\n    const normalized = normVehicle(alias);\n    return model.replace(/\\s/g, '') === normalized.replace(/\\s/g, '') || model.startsWith(normalized + ' ') || normalized.startsWith(model + ' ');\n  }));\n}\nfunction isAudioControl(item, model) {\n  const vendor = String(item.vendor || '').toLowerCase().replace(/[^a-z0-9]/g, '');\n  return vendor === 'audiocontrol' && new RegExp('\\\\b' + model + '(?:\\\\s+pro)?\\\\b').test(String(item.title || '').toLowerCase());\n}\nfunction isDspAmp(item) {\n  const text = `${item?.title || ''} ${item?.description || ''}`.toLowerCase();\n  const vendor = String(item?.vendor || '').toLowerCase().replace(/[^a-z0-9]/g, '');\n  return /\\b(dsp|digital signal processing|digital signal processor)\\b/.test(text) ||\n    (vendor === 'jlaudio' && /\\bvx\\d|\\bvxi\\b/.test(text));\n}\nfunction compatibleFactoryInterfaces(poolItems, vehicle, useAmpPro4) {\n  const products = [...(poolItems['installation-accessories'] || []), ...(poolItems['audio-processors'] || [])];\n  const pac = products.filter((item) => pacVehicleMatch(item, vehicle, useAmpPro4));\n  return pac.length ? pac : products.filter((item) => isAudioControl(item, useAmpPro4 ? 'lc7i' : 'lc2i'));\n}\nfunction hasCompleteVehicle(vehicle) {\n  const selection = vehicle?.selection || vehicle || {};\n  return /^(19|20)\\d{2}$/.test(String(selection.year || '')) && Boolean(selection.make) && Boolean(selection.model) && !vehicle?.manual;\n}\n\nconst JL_VEHICLE_APPS = [\n  { handle: /jl-audio-stealthbox-sbx-j-jltailgt/, make: 'jeep', models: ['wrangler'], from: 2018, to: Infinity, note: 'Fits 2-door and 4-door Wrangler models.' },\n  { handle: /jl-audio-stealthbox-enclosed-subwoofer-for-2016-2023-toyota-tacoma/, make: 'toyota', models: ['tacoma'], from: 2016, to: 2023, note: 'Double Cab application; confirm cab style.' },\n  { handle: /jl-audio-sb-gm-3gslvcnsl/, make: 'chevrolet', models: ['silverado'], from: 2014, to: 2018, note: 'Requires front bucket seats and factory console; does not fit eAssist.' },\n  { handle: /jl-audio-sb-gm-3gslvcnsl/, make: 'gmc', models: ['sierra'], from: 2014, to: 2018, note: 'Requires front bucket seats and factory console; does not fit eAssist.' },\n  { handle: /jl-audio-sb-d-qdramd/, make: 'ram', models: ['1500'], from: 2002, to: 2018, note: 'Quad Cab or Crew Cab only; excludes 2002\u20132008 Crew Cab and Mega Cab.' },\n  { handle: /jl-audio-sb-d-qdramd/, make: 'ram', models: ['2500', '3500'], from: 2003, to: Infinity, note: 'Quad Cab or Crew Cab only; excludes Mega Cab.' },\n  { handle: /jl-audio-sb-d-qdramd/, make: 'dodge', models: ['1500'], from: 2002, to: 2018, note: 'Quad Cab or Crew Cab only; excludes 2002\u20132008 Crew Cab and Mega Cab.' },\n  { handle: /jl-audio-sb-d-qdramd/, make: 'dodge', models: ['2500', '3500'], from: 2003, to: Infinity, note: 'Quad Cab or Crew Cab only; excludes Mega Cab.' },\n  { handle: /jl-audio-sb-f-exped4g/, make: 'ford', models: ['expedition'], from: 2018, to: Infinity, note: 'Requires the factory subwoofer; confirm factory audio equipment.' },\n  { handle: /jl-audio-sbx-f-150-scdbl/, make: 'ford', models: ['f 150'], from: 2015, to: Infinity, note: 'F-150 SuperCrew only; confirm cab style.' },\n  { handle: /jl-audio-sbx-f-150-scdbl/, make: 'ford', models: ['f 250', 'f 350', 'f 250 350 super duty'], from: 2017, to: Infinity, note: 'Super Duty Crew Cab only; confirm cab style.' },\n  { handle: /jl-audio-sb-f-muscpe/, make: 'ford', models: ['mustang'], from: 2015, to: Infinity, note: 'Coupe only; does not fit convertible models.' },\n  { handle: /jl-audio-sbx-t-tcmax3g/, make: 'toyota', models: ['tundra'], from: 2022, to: Infinity, note: 'CrewMax only; does not fit hybrid engine models.' },\n  { handle: /jl-audio-sb-t-tundb3/, make: 'toyota', models: ['tundra'], from: 2007, to: 2021, note: 'Double Cab only; requires Black or Red Rock interior; does not fit CrewMax.' },\n];\n\n// SKU-level applications transcribed from JL Audio's dealer product pages and cross-checked against\n// the current JL electronic price list. Cab, seat, body, trim, and factory-audio caveats stay in the\n// shopper-facing note because the vehicle picker does not collect all of those fields.\nconst JL_SKU_VEHICLE_APPS = [\n  { skus: ['010-03751-00','010-03752-00','010-03749-00','010-03750-00'], make: 'polaris', models: ['rzr pro xp'], from: 2020, to: 2024, note: 'Select RZR Pro XP application; Ride Command versions require the compatible Ride Command configuration.' },\n  { skus: ['010-03751-00','010-03752-00','010-03749-00','010-03750-00'], make: 'polaris', models: ['rzr pro r','rzr turbo r'], from: 2022, to: 2024, note: 'Select RZR Pro R/Turbo R application; Ride Command versions require the compatible Ride Command configuration.' },\n  { skus: ['010-03695-00'], make: 'polaris', models: ['rzr 4 900','rzr 900xc','rzr xp 1000','rzr xp4 1000'], from: 2014, to: Infinity, note: 'For listed RZR 4/XP models; does not fit 2020+ RZR Pro models. Confirm seat/model configuration.' },\n  { skus: ['010-03994-00'], make: 'polaris', models: ['rzr 4 900','rzr 900xc','rzr xp 1000','rzr xp4 1000'], from: 2014, to: Infinity, note: 'For listed RZR 4/XP models; does not fit Turbo models.' },\n  { skus: ['010-03691-00'], make: 'polaris', models: ['rzr 4 900','rzr 900xc','rzr xp 1000','rzr xp4 1000'], from: 2019, to: Infinity, note: 'For listed RZR 4/XP models; does not fit 2020 RZR Pro.' },\n  { skus: ['010-04136-00'], make: 'polaris', models: ['rzr pro xp','rzr turbo r'], from: 2020, to: 2024, note: 'Four-seat RZR Pro XP/Turbo R application; verify seating configuration.' },\n  { skus: ['010-03671-00'], make: 'polaris', models: ['slingshot'], from: 2015, to: Infinity, note: 'Passenger side, 2-ohm version. Driver/passenger side and impedance options are sold separately.' },\n  { skus: ['010-03669-00'], make: 'polaris', models: ['slingshot'], from: 2015, to: Infinity, note: 'Driver side, 2-ohm version. Driver/passenger side and impedance options are sold separately.' },\n  { skus: ['010-03668-00'], make: 'polaris', models: ['slingshot'], from: 2015, to: Infinity, note: 'Driver side, 4-ohm version. Driver/passenger side and impedance options are sold separately.' },\n  { skus: ['010-03670-00'], make: 'polaris', models: ['slingshot'], from: 2015, to: Infinity, note: 'Passenger side, 4-ohm version. Driver/passenger side and impedance options are sold separately.' },\n  { skus: ['010-03689-00'], make: 'can am', models: ['maverick x3'], from: 2019, to: Infinity, note: 'Driver-side version for 2-seat Maverick X3; verify 2-seat configuration.' },\n  { skus: ['010-03690-00'], make: 'can am', models: ['maverick x3'], from: 2019, to: Infinity, note: 'Passenger-side version for 2-seat Maverick X3; verify 2-seat configuration.' },\n  { skus: ['010-03628-00','010-03627-00','010-03629-00'], make: 'ford', models: ['f 250','f 350','f 450','f 550','super duty'], from: 2004, to: 2016, note: 'SuperDuty Crew Cab with FlexFold 60/40 split rear bench; these SKUs differ by interior color. Confirm seat and interior before ordering.' },\n  { skus: ['010-03610-00'], make: 'chevrolet', models: ['corvette'], from: 2005, to: 2013, note: 'C6 coupe only; does not fit convertible or ZR-1.' },\n  { skus: ['010-03656-00','010-03655-00'], make: 'chevrolet', models: ['corvette'], from: 2014, to: 2019, note: 'C7 Coupe application; single-driver and dual-driver versions are separate.' },\n  { skus: ['010-03665-00'], make: 'chevrolet', models: ['camaro'], from: 2016, to: Infinity, note: 'Does not fit convertible models.' },\n  { skus: ['010-03667-00'], make: 'chevrolet', models: ['colorado'], from: 2015, to: 2022, note: 'Crew Cab only.' },\n  { skus: ['010-03667-00'], make: 'gmc', models: ['canyon'], from: 2015, to: 2022, note: 'Crew Cab only.' },\n  { skus: ['010-04652-00'], make: 'chevrolet', models: ['silverado 1500'], from: 2019, to: 2024, note: 'Crew Cab only.' },\n  { skus: ['010-04652-00'], make: 'gmc', models: ['sierra 1500'], from: 2019, to: 2024, note: 'Crew Cab only.' },\n  { skus: ['010-04652-00'], make: 'chevrolet', models: ['silverado 2500','silverado 3500'], from: 2020, to: 2024, note: 'Crew Cab only.' },\n  { skus: ['010-04652-00'], make: 'gmc', models: ['sierra 2500','sierra 3500'], from: 2020, to: 2024, note: 'Crew Cab only.' },\n  { skus: ['010-03650-00'], make: 'chevrolet', models: ['silverado'], from: 2007, to: 2013, note: 'Crew Cab; excludes Classic models.' },\n  { skus: ['010-03650-00'], make: 'gmc', models: ['sierra'], from: 2007, to: 2013, note: 'Crew Cab; excludes Classic models.' },\n  { skus: ['010-03676-00'], make: 'chevrolet', models: ['silverado'], from: 2014, to: 2018, note: 'Gen 3 Crew Cab only.' },\n  { skus: ['010-03676-00'], make: 'gmc', models: ['sierra'], from: 2014, to: 2018, note: 'Gen 3 Crew Cab only.' },\n  { skus: ['010-03660-00'], make: 'chevrolet', models: ['silverado'], from: 2014, to: 2018, note: 'Double Cab with jet black or dark ash interior; does not fit Crew Cab or Standard Cab.' },\n  { skus: ['010-03660-00'], make: 'gmc', models: ['sierra'], from: 2014, to: 2018, note: 'Double Cab with jet black or dark ash interior; does not fit Crew Cab or Standard Cab.' },\n  { skus: ['010-03692-00'], make: 'chevrolet', models: ['silverado'], from: 2019, to: Infinity, note: 'Double Cab only; does not fit Silverado LD.' },\n  { skus: ['010-03692-00'], make: 'gmc', models: ['sierra'], from: 2019, to: Infinity, note: 'Double Cab only.' },\n  { skus: ['010-03649-00'], make: 'chevrolet', models: ['silverado'], from: 1999, to: 2007, note: 'Crew Cab; 2007 fit is early Crew Cab Classic only.' },\n  { skus: ['010-03649-00'], make: 'gmc', models: ['sierra'], from: 1999, to: 2007, note: 'Crew Cab; 2007 fit is early Crew Cab Classic only.' },\n  { skus: ['010-03615-00'], make: 'chevrolet', models: ['silverado','tahoe','suburban'], from: 2007, to: 2013, note: 'Front bucket seats and factory console required; JL excludes several vehicle variants. Verify model/equipment.' },\n  { skus: ['010-03615-00'], make: 'gmc', models: ['sierra','yukon','yukon xl'], from: 2007, to: 2013, note: 'Front bucket seats and factory console required; JL excludes several vehicle variants. Verify model/equipment.' },\n  { skus: ['010-03673-00'], make: 'chevrolet', models: ['tahoe','suburban'], from: 2015, to: 2020, note: 'Full-size SUV with front bucket seats and factory console.' },\n  { skus: ['010-03673-00'], make: 'gmc', models: ['yukon','yukon xl'], from: 2015, to: 2020, note: 'Full-size SUV with front bucket seats and factory console.' },\n  { skus: ['010-04666-00'], make: 'cadillac', models: ['escalade'], from: 2021, to: Infinity, note: 'Full-size SUV application.' },\n  { skus: ['010-04666-00'], make: 'chevrolet', models: ['tahoe','suburban'], from: 2021, to: Infinity, note: 'Full-size SUV application.' },\n  { skus: ['010-04666-00'], make: 'gmc', models: ['yukon','yukon xl'], from: 2021, to: Infinity, note: 'Full-size SUV application.' },\n  { skus: ['010-03632-00'], make: 'dodge', models: ['challenger'], from: 2009, to: Infinity, note: 'SRT audio package may require removal of the factory subwoofer.' },\n  { skus: ['010-03600-00'], make: 'dodge', models: ['ram 1500','1500'], from: 2002, to: 2018, note: 'Quad Cab; Crew Cab also fits 2009\u20132018. Does not fit Mega Cab.' },\n  { skus: ['010-03600-00'], make: 'ram', models: ['ram 1500','1500'], from: 2002, to: 2018, note: 'Quad Cab; Crew Cab also fits 2009\u20132018. Does not fit Mega Cab.' },\n  { skus: ['010-03600-00'], make: 'dodge', models: ['ram 2500','2500','ram 3500','3500'], from: 2003, to: Infinity, note: 'Quad Cab; Crew Cab also fits 2009-up. Does not fit Mega Cab.' },\n  { skus: ['010-03600-00'], make: 'ram', models: ['ram 2500','2500','ram 3500','3500'], from: 2003, to: Infinity, note: 'Quad Cab; Crew Cab also fits 2009-up. Does not fit Mega Cab.' },\n  { skus: ['010-03761-00'], make: 'ford', models: ['bronco'], from: 2021, to: Infinity, note: '2-door and 4-door; excludes Bronco Sport and slide-out tailgate option.' },\n  { skus: ['010-03682-00'], make: 'ford', models: ['f 150'], from: 2015, to: Infinity, note: 'SuperCab only.' },\n  { skus: ['010-03682-00'], make: 'ford', models: ['f 250','f 350','f 450','f 550','super duty'], from: 2017, to: Infinity, note: 'SuperDuty SuperCab only.' },\n  { skus: ['010-03635-00'], make: 'ford', models: ['f 150'], from: 2009, to: Infinity, note: 'SuperCrew only; does not fit SuperCab. Interior color must match.' },\n  { skus: ['010-03635-00'], make: 'ford', models: ['f 250','f 350','f 450','f 550','super duty'], from: 2017, to: Infinity, note: 'SuperDuty Crew Cab; interior color must match.' },\n  { skus: ['010-03762-00'], make: 'ford', models: ['maverick'], from: 2021, to: Infinity, note: 'Verify the under-seat storage configuration.' },\n  { skus: ['010-04685-00'], make: 'ford', models: ['ranger'], from: 2019, to: 2023, note: 'SuperCrew only; does not fit SuperCab.' },\n  { skus: ['010-03298-00'], make: 'ford', models: ['f 250','f 350','f 450','f 550','super duty'], from: 1998, to: 2007, note: 'Front bucket seats only; does not fit bench seat or specified console types.' },\n  { skus: ['010-03298-00'], make: 'ford', models: ['excursion'], from: 2000, to: 2007, note: 'Front bucket seats only; does not fit specified console types.' },\n  { skus: ['010-04660-00'], make: 'jeep', models: ['gladiator'], from: 2020, to: Infinity, note: 'JT application.' },\n  { skus: ['010-03100-00'], make: 'jeep', models: ['grand cherokee'], from: 2011, to: 2021, note: 'Black or light frost interior.' },\n  { skus: ['010-03948-00'], make: 'jeep', models: ['wrangler unlimited'], from: 2024, to: Infinity, note: '4-door only.' },\n  { skus: ['010-03302-00','010-03303-00','010-03304-00','010-03305-00','010-04681-00','010-04682-00'], make: 'jeep', models: ['wrangler unlimited'], from: 2018, to: 2023, note: '4-door; side and impedance vary by SKU. Premium factory audio may require additional trim parts.' },\n  { skus: ['010-04683-00','010-04684-00'], make: 'jeep', models: ['wrangler unlimited'], from: 2018, to: Infinity, note: '4-door, passenger side; impedance varies by SKU. Premium factory audio may require additional trim parts.' },\n  { skus: ['010-03698-00','010-03657-00','010-03699-00','010-03658-00'], make: 'jeep', models: ['wrangler unlimited'], from: 2007, to: 2017, note: '4-door; side and impedance vary by SKU.' },\n  { skus: ['010-03642-00','010-03643-00'], make: 'jeep', models: ['wrangler'], from: 2007, to: 2017, note: '2-door; interior color must match.' },\n  { skus: ['010-03101-00'], make: 'subaru', models: ['brz'], from: 2013, to: 2020, note: '' },\n  { skus: ['010-03101-00'], make: 'scion', models: ['fr s'], from: 2013, to: 2016, note: '' },\n  { skus: ['010-03101-00'], make: 'toyota', models: ['86'], from: 2016, to: 2020, note: '' },\n  { skus: ['010-03738-00'], make: 'tesla', models: ['model 3'], from: 2017, to: 2023, note: 'Installation requires permanent rear-deck modification.' },\n  { skus: ['010-03382-00'], make: 'tesla', models: ['model y'], from: 2020, to: 2023, note: 'Two-row, 5-seat vehicles only.' },\n  { skus: ['010-03700-00'], make: 'toyota', models: ['4runner'], from: 2010, to: 2024, note: 'Does not fit third-row seating.' },\n  { skus: ['010-03681-00'], make: 'toyota', models: ['tacoma'], from: 2016, to: Infinity, note: 'Access Cab only.' },\n  { skus: ['010-03739-00'], make: 'toyota', models: ['tacoma'], from: 2016, to: 2023, note: 'Double Cab only; factory subwoofer/trim may require additional parts.' },\n  { skus: ['010-03661-00'], make: 'toyota', models: ['tundra'], from: 2014, to: 2021, note: 'CrewMax only.' },\n  { skus: ['010-03626-00'], make: 'toyota', models: ['tundra'], from: 2007, to: 2013, note: 'CrewMax only.' },\n  { skus: ['010-04680-00'], make: 'toyota', models: [], from: 0, to: 0, note: 'JL dealer page did not provide a model-year application; no automatic match until confirmed.' },\n];\n\n// ---- Stealthbox amplifier pairing ----\n// Official JL Audio amp recommendation per Stealthbox SKU: `'<stealthbox sku>': '<JL amp sku>'`. Add an entry only\n// when a JL Audio source names the amp explicitly. Research 2026-10-15: none of JL's Stealthbox product pages\n// (garmin.com/en-US/p/pn/<sku>) names one, and the install manuals sit behind a bot check, so this is empty.\nconst JL_RECOMMENDED_AMPS = {};\n\n// Owner fallback when JL names no amp (or that amp isn't in the catalog): a JL XDM or HD amp matched to the\n// Stealthbox's JL-published power rating. [watts, wired ohms, channels] from each JL product page's Specs\n// (read 2026-10-15); split-impedance Jeep / Slingshot SKUs use the impedance in the SKU's own title.\n// A Stealthbox with no entry here (e.g. 010-03680-00, whose JL page no longer exists) gets no amp and isn't shown.\nconst JL_STEALTH_POWER = {\n  '010-03947-00': [400, 2], '010-03674-00': [300, 2], '010-03659-00': [600, 2], '010-03703-00': [300, 2],\n  '010-03946-00': [800, 2], '010-03165-00': [400, 2], '010-03763-00': [400, 2], '010-03653-00': [800, 2],\n  '010-03695-00': [60, 4, 2], '010-03628-00': [600, 2], '010-03671-00': [500, 2], '010-03689-00': [400, 2],\n  '010-03690-00': [400, 2], '010-03615-00': [300, 2], '010-03610-00': [300, 2], '010-03656-00': [400, 2],\n  '010-03655-00': [800, 2], '010-03665-00': [600, 2], '010-03667-00': [400, 2], '010-04652-00': [800, 2],\n  '010-03650-00': [800, 2], '010-03676-00': [800, 2], '010-03660-00': [600, 2], '010-03692-00': [600, 2],\n  '010-03649-00': [800, 2], '010-03673-00': [300, 2], '010-03632-00': [500, 2], '010-03600-00': [500, 2],\n  '010-03761-00': [300, 2], '010-03682-00': [400, 2], '010-03635-00': [600, 2], '010-03762-00': [300, 2],\n  '010-04685-00': [300, 2], '010-03298-00': [500, 2], '010-04666-00': [400, 2], '010-04660-00': [600, 2],\n  '010-03100-00': [500, 2], '010-03948-00': [400, 2], '010-03302-00': [300, 2], '010-03698-00': [300, 2],\n  '010-03303-00': [300, 4], '010-03657-00': [300, 4], '010-04681-00': [400, 2], '010-04682-00': [400, 4],\n  '010-03699-00': [300, 2], '010-03305-00': [300, 4], '010-03304-00': [300, 2], '010-03658-00': [300, 4],\n  '010-04683-00': [400, 2], '010-04684-00': [400, 4], '010-03642-00': [300, 2], '010-03643-00': [300, 2],\n  '010-03994-00': [400, 2], '010-03691-00': [400, 2], '010-03669-00': [500, 2], '010-03668-00': [500, 4],\n  '010-03670-00': [500, 4], '010-03306-00': [800, 2], '010-03693-00': [800, 2], '010-03727-00': [800, 2],\n  '010-03101-00': [400, 2], '010-03627-00': [600, 2], '010-03629-00': [600, 2], '010-03738-00': [300, 2],\n  '010-03382-00': [300, 2], '010-04680-00': [400, 2], '010-03700-00': [400, 2], '010-03681-00': [400, 2],\n  '010-03739-00': [400, 2], '010-03661-00': [800, 2], '010-03626-00': [600, 4], '010-04136-00': [400, 4],\n};\n\n// JL XDM / HD amps for the fallback, found in the loaded Amplifiers collection by SKU. `rms` is JL's rated\n// continuous power at 14.4 V by load in ohms (per channel for multi-channel amps), from JL's product Specs.\nconst JL_FALLBACK_AMPS = [\n  { sku: '010-03839-00', model: 'XDM300/1', channels: 1, rms: { 2: 300, 4: 200 } },\n  { sku: '010-03116-00', model: 'XDM600/1', channels: 1, rms: { 2: 600, 4: 400 } },\n  { sku: '010-03112-00', model: 'XDM1000/1', channels: 1, rms: { 2: 1000, 4: 600 } },\n  { sku: '010-03168-00', model: 'HD750/1', channels: 1, rms: { 2: 750, 4: 750 } },\n  { sku: '010-03170-00', model: 'HD1200/1', channels: 1, rms: { 2: 1200, 4: 1200 } },\n  { sku: '010-03114-00', model: 'XDM200/2', channels: 2, rms: { 2: 100, 4: 75 } },\n];\n\n// The JL amp to show with a Stealthbox: JL's named recommendation when present in the catalog, otherwise the XDM / HD\n// amp whose rated output at the box's impedance is closest to the box's power rating (a tie goes to the lower output).\n// Returns { amp, note } or null when no JL amp can be paired.\nfunction stealthAmpFor(box, amps) {\n  const bySku = new Map();\n  for (const amp of amps || []) {\n    const sku = String(amp.sku || '').trim();\n    if (sku && String(amp.vendor || '').toLowerCase() === 'jl audio') bySku.set(sku, amp);\n  }\n  const sku = String(box.sku || '').trim();\n  const official = JL_RECOMMENDED_AMPS[sku] ? bySku.get(JL_RECOMMENDED_AMPS[sku]) : null;\n  if (official) return { amp: official, note: \"JL Audio's recommended amplifier for this Stealthbox.\" };\n  const rating = JL_STEALTH_POWER[sku];\n  if (!rating) return null;\n  const [watts, ohms, channels = 1] = rating;\n  let best = null;\n  for (const spec of JL_FALLBACK_AMPS) {\n    const amp = spec.channels === channels ? bySku.get(spec.sku) : null;\n    const output = amp ? spec.rms[ohms] : 0;\n    if (!output) continue;\n    const diff = Math.abs(output - watts);\n    if (!best || diff < best.diff || (diff === best.diff && output < best.output)) best = { amp, diff, output };\n  }\n  if (!best) return null;\n  const rated = channels > 1 ? `${watts} W per channel at ${ohms} \u03A9` : `${watts} W at ${ohms} \u03A9`;\n  return { amp: best.amp, note: `Matched to this Stealthbox's JL power rating (${rated}).` };\n}\n\n\nfunction jlModelMatches(app, model) {\n  return app.models.some((candidate) => {\n    const wanted = normVehicle(candidate);\n    return model === wanted || model.startsWith(wanted + ' ') || wanted.startsWith(model + ' ');\n  });\n}\n\n// The verified JL application for this product and vehicle, or null. Requires a full 4-digit year, make and model.\nfunction jlVehicleApplication(item, vehicle) {\n  if (!vehicle || !/^(19|20)\\d{2}$/.test(vehicle.year) || !vehicle.make || !vehicle.model) return null;\n  const year = Number(vehicle.year);\n  const make = normVehicle(vehicle.make);\n  const model = normVehicle(vehicle.model);\n  const sku = String(item.sku || '').trim();\n  const fits = (app) => app.from > 0 && year >= app.from && year <= app.to && makeMatches(app.make, make) && jlModelMatches(app, model);\n  const skuApp = sku ? JL_SKU_VEHICLE_APPS.find((app) => app.skus.includes(sku) && fits(app)) : null;\n  if (skuApp) return skuApp;\n  return JL_VEHICLE_APPS.find((app) => app.handle.test(item.handle) && fits(app)) || null;\n}\n\nconst isJLStealthbox = (item) =>\n  String(item.vendor || '').toLowerCase() === 'jl audio' && /stealthbox/i.test(`${item.title} ${item.handle}`);\n\n// Matching Stealthboxes for the vehicle, each with its JL fit note and paired JL amp. Ordered lower to higher by\n// price, then JL power rating. A box without a pairable JL amp is left out, so every shown box has its amp.\nfunction stealthMatches(items, vehicle, amps) {\n  const seen = new Set();\n  const matches = [];\n  for (const item of items || []) {\n    if (seen.has(item.handle) || !isJLStealthbox(item)) continue;\n    const app = jlVehicleApplication(item, vehicle);\n    if (!app) continue;\n    const pairing = stealthAmpFor(item, amps);\n    if (!pairing) continue;\n    seen.add(item.handle);\n    matches.push({ item, note: app.note || '', amp: pairing.amp, ampNote: pairing.note });\n  }\n  const power = (match) => (JL_STEALTH_POWER[String(match.item.sku || '').trim()] || [0])[0];\n  return matches.sort((a, b) => a.item.price - b.item.price || power(a) - power(b) || a.item.title.localeCompare(b.item.title));\n}\n\n// Adds the vehicle's Stealthbox + amp to each Good / Better / Best tier. One match fills all three tiers; more matches\n// spread lowest \u2192 highest so the most premium fit is Best (two matches: Good = lower, Better and Best = higher).\nfunction addStealthToTiers(tiers, matches, budgetKey) {\n  if (!matches.length) return;\n  const last = matches.length - 1;\n  [0, Math.round(last / 2), last].forEach((matchIndex, tierIndex) => {\n    const match = matches[matchIndex];\n    const tier = tiers[tierIndex];\n    if (!match || !tier) return;\n    const entries = [\n      { slot: 'stealth', item: match.item, notes: [match.note] },\n      { slot: 'stealth-amp', labelSlot: 'amp', item: match.amp, notes: [match.ampNote] },\n    ];\n    for (const entry of entries) {\n      const over = isOverBudget(entry.item.price, budgetKey);\n      tier.picks.push({ ...entry, notes: entry.notes.filter(Boolean), over });\n      tier.total += entry.item.price;\n      if (over) tier.over = true;\n    }\n  });\n}\n\n// Budget buckets in cents, matching the labels (Under 300 / 300\u2013800 / 800\u20131500 / 1500 and up).\nconst BUDGETS = {\n  any: { lo: 0, hi: Infinity },\n  b1: { lo: 0, hi: 29999 },\n  b2: { lo: 30000, hi: 80000 },\n  b3: { lo: 80001, hi: 149999 },\n  b4: { lo: 150000, hi: Infinity },\n};\n\nfunction isOverBudget(price, budgetKey) {\n  if (!budgetKey || budgetKey === 'any' || !BUDGETS[budgetKey]) return false;\n  const { hi } = BUDGETS[budgetKey];\n  return Number.isFinite(hi) && Number.isFinite(price) && price > hi;\n}\n\n// ---- Product-type rules (pure; titles are lowercased by the data feed) ----\n\n// Vehicle-specific products are never auto-recommended: picking one would imply fit.\nconst VEHICLE_RE =\n  /\\b(harley|davidson|jeep|wrangler|gladiator|ram quad|ram crew|silverado|sierra|gm trucks?|ford|f-150|f-series|mustang|toyota|tacoma|tundra|chevy|chevrolet|dodge|polaris|rzr|can-am|yamaha|waverunner|kawasaki|honda|slingshot|bronco|road glide|street glide|cvo|stealthbox|lid kit|saddlebag|fairing|cut-in)\\b/;\nconst YEARS_RE = /\\b(19|20)\\d{2}\\s*(\\+|&\\s*up|[-\u2013]\\s*((19|20)?\\d{2})\\b)|\\b\\d{2}\\s*[-\u2013]\\s*\\d{2}\\b(?!\\s*(ga|awg|ft|feet|\"|in))|\\b\\d{2}\\+|\\bfor (select|19\\d{2}|20\\d{2})\\b/;\nconst isVehicleSpecific = (t) => VEHICLE_RE.test(t) || YEARS_RE.test(t);\nconst MONO_RE = /\\bmono|\\b1-channel|\\b1-ch\\b|\\/1(v\\d)?\\b|\\.1d?\\b|\\bx1\\b/;\nconst MULTI_RE = /\\b[2-8]-channel|\\b[2-8]-ch\\b|\\/[2-8](v\\d)?i?\\b|\\.[2-8]d?\\b|\\b[2-8] x \\d|\\b[2-8]x\\d|\\dx[2-8]\\b/;\nconst NOT_AMP_RE = /\\bkit\\b|enclosure|system|solution|harness|remote|controller/;\nconst isAmp = (t) => /amp|amplifier/.test(t) && !NOT_AMP_RE.test(t);\n// Amplifier collections hold only amps (some titles omit the word); Power Sports also holds kits and enclosures.\nconst ampOk = (t, pool) => (pool === 'power-sports-amps' ? isAmp(t) : !NOT_AMP_RE.test(t));\nconst isMonoAmp = (t, pool) => ampOk(t, pool) && MONO_RE.test(t);\nconst isMultiAmp = (t, pool) => ampOk(t, pool) && !MONO_RE.test(t) && MULTI_RE.test(t);\n// The Woofers collection holds only subwoofers (many titles omit the word); other pools need it.\nconst isSub = (t, pool) =>\n  (pool === 'woofers' || /sub|woofer/.test(t)) && !/grill|grille only|\\bring\\b|led light|cover|powered/.test(t);\nconst isSpeakerSet = (t) =>\n  /coax|component|2-way|3-way|speaker set|speakers?, pair/.test(t) &&\n  !/tweeter|midrange|mid-range|mid bass|diaphragm|replacement|horn|driver|throat|grill|enclosure|bullet|subwoofer/.test(t);\nconst speakerIsComponent = (title) => /\\bcomponent\\b/.test(String(title || '').toLowerCase());\nconst speakerIsCoax = (title) => { const text = String(title || '').toLowerCase(); return !speakerIsComponent(text) && (/coax(?:ial)?/.test(text) || /\\bjl\\s*audio\\s+c[1-7][ -]?\\d{3}x\\b/.test(text)); };\nfunction speakerSizes(title) {\n  let text = String(title || '').toLowerCase().replace(/[\u00D7\u2715]/g, 'x').replace(/[\u201D\u2033]/g, '\\\"');\n  text = text.replace(/(\\d)\\s*-\\s*1\\/2/g, '$1.5').replace(/(\\d)\\s+1\\/2/g, '$1.5').replace(/(\\d)\\s*-\\s*1\\/4/g, '$1.25').replace(/(\\d)\\s+1\\/4/g, '$1.25');\n  const sizes = new Set();\n  for (const match of text.matchAll(/\\b(\\d+(?:\\.\\d+)?)\\s*(?:in(?:ch(?:es)?)?\\s*)?\"?\\s*x\\s*(\\d+(?:\\.\\d+)?)/g)) sizes.add(`${Number(match[1])}x${Number(match[2])}`);\n  for (const match of text.matchAll(/\\b(\\d+(?:\\.\\d+)?)\\s*(?:-?\\s*(?:inch(?:es)?|in\\.?)|\")/g)) sizes.add(String(Number(match[1])));\n  for (const match of text.matchAll(/\\bC[1-7][ -]?(525|650|690)(?:x|cx|cs2)?\\b/gi)) sizes.add(match[1] === '525' ? '5.25' : match[1] === '650' ? '6.5' : '6x9');\n  return sizes;\n}\nfunction speakerLocationsFit(title, locations, front) {\n  const sizes = speakerSizes(title);\n  return (locations || []).some((entry) => {\n    const wanted = String(entry.size || '').toLowerCase().replace(/\\s+/g, '').replace(/\\.0/g, '');\n    const options = wanted.split(/\\s*(?:or|\\/)\\s*|\\s*&\\s*/).map((size) => size.replace(/[^0-9.x-]/g, ''));\n    if (options.some((size) => sizes.has(size))) return true;\n    if (options.some((size) => (size === '5' && sizes.has('5.25')) || (size === '6' && sizes.has('6.5')) || (size === '6.75' && sizes.has('6.5')))) return true;\n    return Boolean(front && options.includes('6x9') && /door/i.test(entry.location || '') && entry.adapter && sizes.has('6.5') && speakerIsComponent(title));\n  });\n}\nfunction hasSpeakerOpening(locations, wanted) {\n  const expected = String(wanted || '').toLowerCase().replace(/\\s+/g, '');\n  return (locations || []).some((entry) => {\n    const sizes = String(entry.size || '').toLowerCase().match(/(\\d+(?:\\.\\d+)?)\\s*(?:inches?|in\\.?|[\"\u201D])?\\s*x\\s*(\\d+(?:\\.\\d+)?)/g) || [];\n    return sizes.some((size) => size.replace(/[^0-9.x]/g, '').split('x').map((part) => String(Number(part))).join('x') === expected);\n  });\n}\nfunction speakerBrand(item) { return String(item?.vendor || item?.title?.split(' ')[0] || '').toLowerCase().replace(/\\baudio\\b/g, '').replace(/[^a-z0-9]/g, ''); }\nfunction jlComponent(item) { return speakerBrand(item) === 'jl' && speakerIsComponent(item.title) && isSpeakerSet(String(item.title || '').toLowerCase()) && !isMarineTitled(item.title); }\nfunction pairSpeakerRear(list, picks, fronts, budgetKey) {\n  for (let tier = 0; tier < picks.length; tier++) {\n    const front = fronts?.[tier]?.item; if (!front) { picks[tier] = null; continue; }\n    const same = list.filter((item) => speakerBrand(item) === speakerBrand(front));\n    const options = same.length ? same : list;\n    if (!options.length) { picks[tier] = null; continue; }\n    const reference = picks[tier]?.item?.price ?? front.price;\n    const choice = options.reduce((best, item) => !best || Math.abs(item.price - reference) < Math.abs(best.price - reference) ? item : best, null);\n    picks[tier] = { item: choice, over: isOverBudget(choice.price, budgetKey) };\n  }\n}\nconst isMarineSpeaker = (t) => /speaker/.test(t) && !/sub|woofer|tower|horn|grill|remote|pod/.test(t);\nconst isWiringKit = (t, pool) =>\n  pool === 'amp-kits' ||\n  /(amp|amplifier)[^\u2014]*\\b(install|installation|connection|wiring)\\b[^\u2014]*kit|power connection kit|connection kit/.test(t);\nconst isRca = (t) =>\n  /\\brca\\b|interconnect/.test(t) && /\\b\\d+\\s*(ft|feet)\\b/.test(t) && !/mini|optical|y-adapter|splitter|speaker-wire|usb|network/.test(t);\nconst rcaChannelCount = (item) => {\n  const match = String(item.title || '').match(/\\b(2|4|6)[ -]?channel\\b/i);\n  return match ? Number(match[1]) : 0;\n};\nconst isDeadening = (t) => !/roller|tape|license|frame/.test(t);\nconst isMarineTitled = (t) => /marine|tinned|abyc|water-resistant|waterproof|weatherproof|powersports/.test(t);\n\n// Builds the product types (\"slots\") a tier needs for the selected goals.\n// Marine / powersports switches bass, speaker and amplifier picks to the marine and powersports collections\n// (marine-rated only, so the car-only VX600/6i anchor never applies there).\n// `anchors` pin owner-approved models to a tier; `pairWith` matches an amp's brand to that slot's pick in each tier.\nfunction isCarPlayRadio(item) {\n  const text = (String(item.title || '') + ' ' + String(item.description || '')).toLowerCase();\n  const knownKenwoodCarPlay = /\\bkenwood\\b.*\\b(dmx1057xr|dmx1058xr|dmx1037s|dmx1038s)\\b/.test(text);\n  return (/apple\\s*carplay|carplay/.test(text) || knownKenwoodCarPlay) && !/single[- ]din|1[- ]din|marine|motorcycle|harley|powersports|utv|side[- ]by[- ]side|slingshot|direct replacement/.test(text);\n}\nconst KENWOOD_10IN_RE = /\\bkenwood\\b.*\\b(dmx1057xr|dmx1058xr)\\b/i;\n\nfunction buildSlots(goals, vehicle = null) {\n  const marine = goals.has('marine');\n  const marineAmpPools = ['power-sports-marine-amps', 'power-sports-amps'];\n  const slots = [];\n  if (goals.has('oem-carplay') && vehicle?.complete && !vehicle.manual) {\n    slots.push({ key: 'carplay-interface', labelText: 'ZZ2 OEM CarPlay Interface', pools: ['carplay-interfaces'], allowVehicleSpecific: true, single: true, message: 'No solution available for this vehicle in current ZZ2 compatibility listings. Contact Soundwaves to confirm the factory radio or screen system.', test: (item) => zz2VehicleMatch(item, vehicle) });\n  }\n  if (goals.has('carplay-radio') && vehicle?.complete && !vehicle.manual) {\n    if (vehicle.radioFitment?.status === 'confirmed') {\n      slots.push({ key: 'carplay-radio', labelText: 'CarPlay Radio', pools: ['head-units'], requiresProduct: true, anchors: { best: KENWOOD_10IN_RE, forceBest: true }, message: 'No listed CarPlay receiver has a confirmed double-DIN path for this selection. Contact Soundwaves to verify the dash and factory equipment.', test: isCarPlayRadio });\n    } else {\n      const status = vehicle.radioFitment?.status;\n      const message = status === 'no-kit'\n        ? 'No double-DIN installation path is listed in the Metra chart for this vehicle. No CarPlay radio fit is assumed.'\n        : status === 'unlisted'\n          ? 'This vehicle is not listed in the Metra double-DIN chart. No CarPlay radio fit is assumed.'\n          : status === 'confirm'\n            ? 'Metra has mixed double-DIN results for this vehicle. Contact Soundwaves to confirm the factory radio and dash.'\n            : 'Metra fitment could not be confirmed. Contact Soundwaves before choosing a CarPlay radio.';\n      slots.push({ key: 'carplay-radio', labelText: 'CarPlay Radio Fitment', pools: [], message, test: () => false });\n    }\n  }\n  // A factory-radio bass/power upgrade or Stealthbox needs the matching factory-signal interface.\n  // Power uses AmpPRO 4 / LC7i; bass-only and Stealthbox use AmpPRO SUB / LC2i. An aftermarket\n  // head unit replaces the factory signal source, while the marine flow remains unchanged.\n  const stealthOnlyGoal = goals.has('stealth-boxes') && goals.size === 1;\n  if ((goals.has('bass') || goals.has('power') || (goals.has('stealth-boxes') && !stealthOnlyGoal)) && vehicle?.complete && !vehicle.manual && !marine && !goals.has('carplay-radio')) {\n    const useAmpPro4 = goals.has('power');\n    slots.push({ key: 'factory-interface', labelText: 'FACTORY AUDIO INTERFACE', pools: ['installation-accessories', 'audio-processors'], allowProduct: true, single: true, useAmpPro4, test: (title) => /\\b(?:ap4|apsub)[- ]?[a-z]{2}\\d{2}\\b/i.test(String(title || '')) || new RegExp('\\\\b' + (useAmpPro4 ? 'lc7i' : 'lc2i') + '(?:\\\\s+pro)?\\\\b', 'i').test(String(title || '')) });\n  }\n  if (goals.has('bass')) {\n    slots.push(\n      marine\n        ? { key: 'marine-sub', pools: ['marine-woofers'], test: isSub }\n        : { key: 'sub', pools: ['woofers'], test: isSub, preferMarine: false, anchors: { better: NIGHTSHADE_RE, best: JL_W7_BEST_RE, forceBest: true }, goodCombo: true },\n      marine\n        ? { key: 'marine-bass-amp', pools: marineAmpPools, test: isMonoAmp, pairWith: 'marine-sub', distinct: true, skipAmplified: true }\n        : { key: 'bass-amp', pools: ['amplifiers'], test: isMonoAmp, preferMarine: false, pairWith: 'sub', pairRules: W7_AMP_PAIRS, skipAmplified: true },\n    );\n  }\n  if (goals.has('speakers') || marine) {\n    if (marine) slots.push({ key: 'marine-speakers', pools: ['marine-speakers'], test: isMarineSpeaker });\n    else if (vehicle?.complete) {\n      const front = vehicle.fitment?.front || [], rear = vehicle.fitment?.rear || [];\n      slots.push({ key: 'front-speakers', labelSlot: 'speakers', labelText: 'Front Speakers', pools: ['full-range-speakers'], test: (title) => isSpeakerSet(String(title || '').toLowerCase()) && speakerLocationsFit(title, front, true), forceJLComponentBest: true, anchors: hasSpeakerOpening(front, '6x9') ? { better: ROCKFORD_P2V2_69_RE } : undefined });\n      if (rear.length) slots.push({ key: 'rear-speakers', labelSlot: 'speakers', labelText: 'Rear Speakers', pools: ['full-range-speakers'], test: (title) => isSpeakerSet(String(title || '').toLowerCase()) && speakerIsCoax(title) && speakerLocationsFit(title, rear, false) });\n    } else slots.push({ key: 'speakers', pools: ['full-range-speakers'], test: isSpeakerSet, preferMarine: false });\n  }\n  if (goals.has('power') || marine) {\n    slots.push(\n      marine\n        ? { key: 'marine-amp', pools: marineAmpPools, test: isMultiAmp, pairWith: 'marine-speakers', distinct: true }\n        : { key: 'amp', pools: ['amplifiers'], test: isMultiAmp, preferMarine: false, anchors: { best: VX600_6I_RE, forceBest: true } },\n    );\n  } else if (goals.has('clarity')) {\n    // Cleaner sound on its own also gets a clean-power amp, with the VX600/6i as its Best.\n    slots.push({ key: 'amp', pools: ['amplifiers'], test: isMultiAmp, preferMarine: false, anchors: { best: VX600_6I_RE, forceBest: true } });\n  }\n  if (goals.has('cables')) {\n    slots.push(\n      { key: 'wiring', pools: ['amp-kits', 'installation-accessories'], test: isWiringKit, preferMarine: marine },\n      { key: 'rca', pools: ['installation-accessories'], test: isRca, preferMarine: marine },\n    );\n  }\n  if (goals.has('headlights')) {\n    slots.push({\n      key: 'headlights',\n      pools: ['upgraded-led-headlight-bulbs'],\n      test: (t) => /led headlight bulbs/.test(t),\n      fixedTiers: LUCAS_HEADLIGHT_TIERS,\n      tierNote: 'headlightNote',\n    });\n  }\n  if (goals.has('clarity')) {\n    slots.push(\n      marine\n        ? { key: 'processor', pools: ['audio-processors'], test: () => true }\n        : { key: 'deadening', pools: ['sound-deadner'], test: isDeadening },\n    );\n  }\n  return slots;\n}\n\nconst BRAND_FILTER_SLOT_KEYS = new Set([\n  'sub', 'bass-amp', 'marine-sub', 'marine-bass-amp',\n  'front-speakers', 'rear-speakers', 'speakers', 'marine-speakers',\n  'amp', 'marine-amp', 'wiring', 'rca',\n]);\n\n// Candidate list for one slot: filtered, de-duplicated, sorted by price.\nfunction candidatesFor(slot, poolItems, brand = '') {\n  const seen = new Set();\n  let list = [];\n  for (const pool of slot.pools) {\n    for (const item of poolItems[pool] || []) {\n      if (seen.has(item.handle)) continue;\n      const subject = slot.allowVehicleSpecific || slot.requiresProduct ? item : item.title;\n      if ((!slot.allowVehicleSpecific && isVehicleSpecific(item.title)) || !slot.test(subject, pool)) continue;\n      seen.add(item.handle);\n      list.push(item);\n    }\n  }\n  if (slot.preferMarine !== undefined) {\n    const preferred = list.filter((item) => isMarineTitled(item.title) === slot.preferMarine);\n    if (preferred.length >= 3) list = preferred;\n  }\n  if (brand && BRAND_FILTER_SLOT_KEYS.has(slot.key)) {\n    list = list.filter((item) => brandOf(item) === brand);\n    if (slot.key === 'wiring') list = list.filter((item) => !isSpeakerSet(String(item.title || '').toLowerCase()));\n  }\n  return list.sort((a, b) => a.price - b.price || a.title.localeCompare(b.title));\n}\n\nconst indexAt = (length, fraction) => Math.min(length - 1, Math.max(0, Math.round(fraction * (length - 1))));\n\n// Returns [good, better, best] (entries may be null), each `{ item, over }`.\n// No budget: 45th / 75th / 95th percentile. With a budget, Good and Better come from inside it\n// (preferring the chosen range), and Best is the next worthwhile step above it, marked as over budget.\nfunction pickTiers(list, budgetKey) {\n  const { lo, hi } = BUDGETS[budgetKey] || BUDGETS.any;\n  // A product is over budget only when a range is chosen and its own price is above that range's top.\n  // \"Any price\" has no ceiling, so nothing is ever marked; a cheaper pick inside a range is not \"over\".\n  const wrap = (item) => (item ? { item, over: isOverBudget(item.price, budgetKey) } : null);\n  if (!list.length) return [null, null, null];\n\n  // Percentile picks over distinct price points, so each tier is a real step up and never collides.\n  const percentilePicks = (pool, fractions) => {\n    const steps = pool.filter((item, index) => index === 0 || item.price > pool[index - 1].price);\n    const count = fractions.length;\n    if (steps.length <= count) return fractions.map((_, index) => steps[index] || null);\n    const picks = [];\n    let last = -1;\n    fractions.forEach((fraction, index) => {\n      const latest = steps.length - (count - index);\n      const position = Math.min(Math.max(indexAt(steps.length, fraction), last + 1), latest);\n      picks.push(steps[position]);\n      last = position;\n    });\n    return picks;\n  };\n\n  const within = list.filter((item) => item.price <= hi);\n  const inRange = within.filter((item) => item.price >= lo);\n  const above = list.filter((item) => item.price > hi);\n  const pool = inRange.length >= 2 ? inRange : within;\n\n  if (!above.length) {\n    // Too few in the chosen range (e.g. 1500 and up): lean to the top of everything that fits the budget.\n    const distinctPrices = new Set(pool.map((item) => item.price)).size;\n    if (distinctPrices < 3 || (inRange.length < 2 && lo > 0)) return percentilePicks(within, [0.75, 0.9, 1]).map(wrap);\n    return percentilePicks(pool, [0.45, 0.75, 0.95]).map(wrap);\n  }\n\n  const stepAbove = (from, ratio) => above.find((item) => item.price >= Math.max(from, hi) * ratio) || null;\n\n  if (pool.length >= 2) {\n    const [good, inBudgetBetter] = percentilePicks(pool, [0.4, 0.85]);\n    // Every in-budget option costs the same: step Better up to the closest option above the budget.\n    const better = inBudgetBetter || above[0];\n    let best = stepAbove(better.price, 1.25);\n    if (!best || best === better) best = above.find((item) => item.price > better.price) || null;\n    return [good, better, best].map(wrap);\n  }\n  if (pool.length === 1) {\n    const good = pool[0];\n    const better = stepAbove(good.price, 1.15) || above[0];\n    let best = stepAbove(better.price, 1.25);\n    if (!best || best === better) best = above.find((item) => item.price > better.price) || null;\n    return [good, better, best].map(wrap);\n  }\n  // Nothing within budget: show the closest options above it, each marked.\n  const good = above[0];\n  const better = above.find((item) => item.price >= good.price * 1.15 && item !== good) || above[1] || null;\n  const best = better ? above.find((item) => item.price >= better.price * 1.25) || above.find((item) => item.price > better.price) || null : null;\n  return [good, better, best].map(wrap);\n}\n\n// ---- Owner-approved anchors and brand pairing ----\n// Best multi-channel amp for More power / Cleaner sound: the JL Audio VX600/6i (exact model, premium clean-power reference).\nconst VX600_6I_RE = /\\bvx600\\/6i\\b/;\n// More bass: Better sub is a Sundown NightShade; Best is a JL Audio W7 (sold as W7AE), below.\n// More bass Best (owner-specified): a W7AE 10\", 12\" or 13.5\" driver (titled \"13-Inch\"), always Best whatever the budget,\n// paired with a fixed JL amp: 10\" \u2192 HD750/1; 12\" and 13.5\" \u2192 HD1200/1.\nconst JL_W7_BEST_RE = /\\bjl audio w7(ae)?\\b.*\\b(10|12|13(\\.5)?)-inch\\b/;\nconst W7_AMP_PAIRS = [\n  { lead: /\\bjl audio w7(ae)?\\b.*\\b10-inch\\b/, amp: /\\bhd750\\/1\\b/ },\n  { lead: /\\bjl audio w7(ae)?\\b.*\\b(12|13(\\.5)?)-inch\\b/, amp: /\\bhd1200\\/1\\b/ },\n];\nconst NIGHTSHADE_RE = /\\bsundown\\b.*\\bnightshade\\b/;\nconst ROCKFORD_P2V2_69_RE = /\\bp2v2-69\\b/i;\n// Sub with a built-in amp (powered / amplified / active enclosure): flagged from title, tags or description in Liquid,\n// with a title check as backup. Its tier gets no separate bass amp.\nconst AMPLIFIED_TITLE_RE = /\\b(amplified|powered|self-powered|active)\\b|built-in amp/;\nconst isAmplifiedSub = (item) => Boolean(item.amplified) || AMPLIFIED_TITLE_RE.test(item.title);\nconst isEnclosure = (t) => /enclosure|wedge|stealthbox|microsub|powerwedge|subwoofer system/.test(t);\n\n// Normalised brand: \"JL Audio\" \u2192 \"jl\", \"Sundown\" / \"Sundown Audio\" \u2192 \"sundown\", \"PowerBass\" / \"Powerbass\" \u2192 \"powerbass\".\nconst brandOf = (item) =>\n  (item.vendor || item.title.split(' ')[0] || '').toLowerCase().replace(/\\baudio\\b/g, '').replace(/[^a-z0-9]/g, '');\n\nconst closestTo = (list, target) =>\n  list.reduce((best, item) => (!best || Math.abs(item.price - target) < Math.abs(best.price - target) ? item : best), null);\n\n// Puts an anchor product into one tier when the catalog has it and the budget allows it.\n// Better must stay inside the budget; Best may be the next step up (at most 25% over the budget top).\nfunction applyAnchor(list, picks, tierIndex, re, budgetKey, force = false) {\n  const { hi } = BUDGETS[budgetKey] || BUDGETS.any;\n  let matches = list.filter((item) => re.test(item.title));\n  if (!matches.length) return;\n  const drivers = matches.filter((item) => !isEnclosure(item.title));\n  if (drivers.length) matches = drivers;\n  // force (VX600/6i): always Best whatever the budget, flagged over budget when it is.\n  const ceiling = force ? Infinity : tierIndex === 2 ? hi * 1.25 : hi;\n  matches = matches.filter((item) => item.price <= ceiling);\n  if (!matches.length) return;\n  const below = picks[tierIndex - 1]?.item;\n  const above = tierIndex < 2 ? picks[tierIndex + 1]?.item : null;\n  const ordered = matches.filter((item) => (!below || item.price >= below.price) && item.handle !== below?.handle);\n  if (ordered.length) matches = ordered;\n  const original = picks[tierIndex]?.item;\n  const inBudget = matches.filter((item) => item.price <= hi);\n  const choice = closestTo(inBudget.length ? inBudget : matches, original ? original.price : matches[0].price);\n  if (!choice) return;\n  picks[tierIndex] = { item: choice, over: isOverBudget(choice.price, budgetKey) };\n  // Keep the tier above a real step up from the new anchor.\n  if (above && above.price < choice.price) {\n    const next = list.find((item) => item.price >= choice.price && item.handle !== choice.handle);\n    if (next) picks[tierIndex + 1] = { item: next, over: isOverBudget(next.price, budgetKey) };\n  }\n}\n\n// After anchoring, keeps tiers ascending and distinct: a lower tier that now costs more than (or repeats) the tier\n// above is re-picked below it, inside the chosen range where possible, so Good stays mid-to-high rather than cheapest.\nfunction fixOrder(list, picks, budgetKey) {\n  const { lo } = BUDGETS[budgetKey] || BUDGETS.any;\n  for (const tierIndex of [1, 0]) {\n    const next = picks[tierIndex + 1]?.item;\n    const current = picks[tierIndex]?.item;\n    if (!next || !current) continue;\n    const taken = new Set(picks.filter(Boolean).map((pick) => pick.item.handle));\n    if (current.price <= next.price && !picks.some((pick, index) => index !== tierIndex && pick?.item.handle === current.handle)) continue;\n    let options = list.filter((item) => item.price <= next.price && !taken.has(item.handle));\n    const inRange = options.filter((item) => item.price >= lo);\n    if (inRange.length) options = inRange;\n    const choice = closestTo(options, next.price * (tierIndex === 1 ? 0.85 : 0.7));\n    if (choice) picks[tierIndex] = { item: choice, over: isOverBudget(choice.price, budgetKey) };\n  }\n}\n\n// Re-picks an amplifier slot so each tier's amp is the same brand as that tier's lead product\n// (sub \u2192 bass amp, marine sub \u2192 marine bass amp, marine speakers \u2192 marine amp), priced close to the lead product.\n// Never falls back to another brand: with no same-brand amp the tier's amp is left out and flagged so the tier shows\n// the \"ask Soundwaves to match an amp\" note. Good and Better prefer an amp inside the budget; if the brand only has\n// amps above it, that amp still shows with the over-budget badge. `distinct` (marine) never repeats an amp across tiers.\n// Returns which tiers had their amp left out.\n// pairRules pin an exact amp to an exact lead model (W7AE sizes \u2192 HD750/1 or HD1200/1) before the brand rule.\n// More bass Good tier (owner-specified): one complete setup totalling about $800\u2013$1,000. Prefers a passive sub plus a\n// same-brand mono amp with a balanced spend (sub 40\u201365% of the total), power that lines up where the catalog lists it\n// (amp watts 0.8\u20131.6\u00D7 the sub's RMS), and a bare driver over a loaded box. An amplified/powered all-in-one in range is\n// allowed only on its own (no separate amp) and ranks behind passive pairs. Applies at every budget; items above the\n// selected budget get the usual over-budget badge. Never reuses the Better or Best sub.\nconst GOOD_BASS_TOTAL = { min: 80000, max: 100000, target: 90000 };\nconst ampWatts = (item) => {\n  const match = item.title.match(/(\\d[\\d,]*)\\s*-?\\s*(?:w|watts?)\\b/);\n  return match ? Number(match[1].replace(/,/g, '')) : 0;\n};\nfunction pickGoodBassCombo(subs, amps, picks) {\n  const { min, max, target } = GOOD_BASS_TOTAL;\n  const taken = new Set(picks.slice(1).filter(Boolean).map((pick) => pick.item.handle));\n  let best = null;\n  const consider = (score, sub, amp) => {\n    if (!best || score < best.score) best = { score, sub, amp };\n  };\n  for (const sub of subs) {\n    if (taken.has(sub.handle)) continue;\n    if (isAmplifiedSub(sub)) {\n      if (sub.price >= min && sub.price <= max) consider(Math.abs(sub.price - target) + 4000, sub, null);\n      continue;\n    }\n    for (const amp of amps) {\n      if (brandOf(amp) !== brandOf(sub)) continue;\n      const total = sub.price + amp.price;\n      if (total < min || total > max) continue;\n      const share = sub.price / total;\n      if (share < 0.4 || share > 0.65) continue;\n      let score = Math.abs(total - target);\n      const rms = sub.rms || 0;\n      const watts = ampWatts(amp);\n      if (rms && watts) score += watts / rms >= 0.8 && watts / rms <= 1.6 ? -5000 : 10000;\n      else score += 2000;\n      if (isEnclosure(sub.title)) score += 3000;\n      consider(score, sub, amp);\n    }\n  }\n  return best;\n}\n\n// skipLead: leads that need no separate amp (amplified subs). That tier's amp is dropped with no note.\nfunction pairBrand(list, picks, leadPicks, budgetKey, distinct = false, pairRules = [], skipLead = null) {\n  const { hi } = BUDGETS[budgetKey] || BUDGETS.any;\n  const used = new Set();\n  const missing = [false, false, false];\n  let floor = 0;\n  picks.forEach((pick, tierIndex) => {\n    const lead = leadPicks[tierIndex]?.item;\n    if (!lead) {\n      if (pick) {\n        used.add(pick.item.handle);\n        floor = Math.max(floor, pick.item.price);\n      }\n      return;\n    }\n    if (skipLead && skipLead(lead)) {\n      picks[tierIndex] = null;\n      return;\n    }\n    const rule = pairRules.find((candidate) => candidate.lead.test(lead.title));\n    const fixed = rule ? list.find((item) => rule.amp.test(item.title) && !(distinct && used.has(item.handle))) : null;\n    if (fixed) {\n      used.add(fixed.handle);\n      floor = Math.max(floor, fixed.price);\n      picks[tierIndex] = { item: fixed, over: isOverBudget(fixed.price, budgetKey) };\n      return;\n    }\n    const brand = brandOf(lead);\n    let options = list.filter((item) => brandOf(item) === brand);\n    if (distinct) options = options.filter((item) => !used.has(item.handle));\n    if (!options.length) {\n      picks[tierIndex] = null;\n      missing[tierIndex] = true;\n      return;\n    }\n    if (tierIndex < 2 && Number.isFinite(hi)) {\n      const inBudget = options.filter((item) => item.price <= hi);\n      if (inBudget.length) options = inBudget;\n    }\n    const rising = options.filter((item) => item.price >= floor);\n    if (rising.length) options = rising;\n    const fresh = options.filter((item) => !used.has(item.handle));\n    const choice = closestTo(fresh.length ? fresh : options, lead.price);\n    used.add(choice.handle);\n    floor = Math.max(floor, choice.price);\n    picks[tierIndex] = { item: choice, over: isOverBudget(choice.price, budgetKey) };\n  });\n  return missing;\n}\n\n// Full recommendation: three tiers, each a list of `{ slot, item, over }` plus total and over flag.\nfunction recommend(goals, budgetKey, poolItems, vehicle = null, brand = '', brandNoOptionMessage = '', brandSlotLabels = {}) {\n  const slots = buildSlots(goals, vehicle);\n  const tiers = [0, 1, 2].map(() => ({ picks: [], messages: [], total: 0, over: false, ampNote: false, headlightNote: false }));\n  const bySlot = {};\n  const goodAmps = {};\n  for (const slot of slots) {\n    let list = candidatesFor(slot, poolItems, brand);\n    if ((slot.key === 'carplay-interface' || slot.key === 'carplay-radio') && !list.length && slot.message) tiers.forEach((tier) => tier.messages.push(slot.message));\n    if (slot.key === 'factory-interface') {\n      const pac = list.filter((item) => pacVehicleMatch(item, vehicle, slot.useAmpPro4));\n      list = pac.length ? pac : list.filter((item) => isAudioControl(item, slot.useAmpPro4 ? 'lc7i' : 'lc2i'));\n    }\n    if (slot.fixedTiers) {\n      // Owner-fixed product per tier; shown whatever the budget (marked over budget when it is), never substituted.\n      slot.fixedTiers.forEach((re, tierIndex) => {\n        if (slot.tierNote) tiers[tierIndex][slot.tierNote] = true;\n        const item = list.find((candidate) => re.test(candidate.title));\n        if (!item) return;\n        const over = isOverBudget(item.price, budgetKey);\n        tiers[tierIndex].picks.push({ slot: slot.key, item, over });\n        tiers[tierIndex].total += item.price;\n        if (over) tiers[tierIndex].over = true;\n      });\n      continue;\n    }\n    const singlePick = slot.single && list[0] ? { item: list[0], over: isOverBudget(list[0].price, budgetKey) } : null;\n    let picks = slot.single ? [singlePick, singlePick, singlePick] : pickTiers(list, budgetKey);\n    let rcaExtras = null;\n    // More Power + Amp Kits needs six RCA channels per tier: Good/Better use one 2-channel\n    // and one 4-channel cable; Best uses three distinct JL Audio Premium 2-channel cables.\n    if (slot.key === 'rca' && goals.has('power') && !goals.has('marine')) {\n      const twoChannel = list.filter((item) => rcaChannelCount(item) === 2);\n      const fourChannel = list.filter((item) => rcaChannelCount(item) === 4);\n      const twoTiers = pickTiers(twoChannel, budgetKey);\n      const fourTiers = pickTiers(fourChannel, budgetKey);\n      const premium = twoChannel.filter((item) => brandOf(item) === 'jl' && /\\bpremium\\b/i.test(item.title));\n      const premiumTiers = pickTiers(premium, 'any').map((pick) => pick?.item).filter(Boolean);\n      const bestTwoFallback = pickTiers(twoChannel, 'any').map((pick) => pick?.item).filter(Boolean);\n      const sets = [];\n      for (const tierIndex of [0, 1]) {\n        const two = twoTiers[tierIndex]?.item || twoTiers[0]?.item || null;\n        const four = fourTiers[tierIndex]?.item || fourTiers[0]?.item || null;\n        if (two && four) sets[tierIndex] = [two, four];\n        else {\n          const tierPicks = pickTiers(twoChannel, 'any').map((pick) => pick?.item).filter(Boolean);\n          sets[tierIndex] = tierPicks.length >= 3 ? tierPicks : [];\n        }\n      }\n      sets[2] = premiumTiers.length >= 3\n        ? premiumTiers.slice(0, 3)\n        : bestTwoFallback.length >= 3\n          ? bestTwoFallback.slice(0, 3)\n          : [];\n      if (sets.every((set) => set.length === 2 || set.length === 3)) {\n        picks = sets.map((set) => ({ item: set[0], over: isOverBudget(set[0].price, budgetKey) }));\n        rcaExtras = sets.map((set) => set.slice(1).map((item) => ({ item, over: isOverBudget(item.price, budgetKey) })));\n      } else if (brand) {\n        picks = sets.map((set) => set && (set.length === 2 || set.length === 3)\n          ? { item: set[0], over: isOverBudget(set[0].price, budgetKey) }\n          : null);\n        rcaExtras = sets.map((set) => (set?.length === 2 || set?.length === 3)\n          ? set.slice(1).map((item) => ({ item, over: isOverBudget(item.price, budgetKey) }))\n          : []);\n      }\n    }\n    // When the Better bass recommendation is a Kicker mono amp, prefer Kicker's\n    // dual-amplifier PKD1 kit if More Power is also selected; it matches the mono amp\n    // brand and is built for the combined two-amp setup. Otherwise use the closest\n    // same-brand Kicker kit. Other tier choices remain unchanged.\n    if (slot.key === 'wiring') {\n      const betterBassAmp = bySlot['bass-amp']?.[1]?.item;\n      if (betterBassAmp && brandOf(betterBassAmp) === 'kicker') {\n        const kickerKits = list.filter((item) => brandOf(item) === 'kicker');\n        const dualAmpKit = goals.has('power') ? kickerKits.find((item) => /\\bPKD1\\b/i.test(item.title)) : null;\n        const matchingKit = dualAmpKit || (kickerKits.length\n          ? closestTo(kickerKits, picks[1]?.item?.price ?? kickerKits[kickerKits.length - 1].price)\n          : null);\n        if (matchingKit) picks[1] = { item: matchingKit, over: isOverBudget(matchingKit.price, budgetKey) };\n      }\n      // Preserve the existing Best-tier same-brand match.\n      const bestAmpBrands = [...new Set(['bass-amp', 'amp', 'marine-bass-amp', 'marine-amp'].map((key) => bySlot[key]?.[2]?.item).filter(Boolean).map(brandOf))];\n      if (bestAmpBrands.length === 1) {\n        const matchingKits = list.filter((item) => brandOf(item) === bestAmpBrands[0]);\n        if (matchingKits.length) {\n          const kit = closestTo(matchingKits, picks[2]?.item?.price ?? matchingKits[matchingKits.length - 1].price);\n          picks[2] = { item: kit, over: isOverBudget(kit.price, budgetKey) };\n        }\n      }\n    }\n    if (slot.forceJLComponentBest) {\n      const jlOptions = list.filter(jlComponent).sort((a, b) => a.price - b.price || a.title.localeCompare(b.title));\n      const c6 = jlOptions.filter((item) => /\\bC6[ -]/i.test(item.title));\n      const best = c6[c6.length - 1] || jlOptions[jlOptions.length - 1];\n      if (best) { picks[2] = { item: best, over: isOverBudget(best.price, budgetKey) }; fixOrder(list, picks, budgetKey); }\n    }\n    if (slot.key === 'rear-speakers') pairSpeakerRear(list, picks, bySlot['front-speakers'], budgetKey);\n    if (slot.anchors?.better) applyAnchor(list, picks, 1, slot.anchors.better, budgetKey);\n    if (slot.anchors?.best) applyAnchor(list, picks, 2, slot.anchors.best, budgetKey, slot.anchors.forceBest);\n    if (slot.anchors) fixOrder(list, picks, budgetKey);\n    if (slot.goodCombo) {\n      const ampSlot = slots.find((candidate) => candidate.pairWith === slot.key);\n      const combo = ampSlot ? pickGoodBassCombo(list, candidatesFor(ampSlot, poolItems, brand), picks) : null;\n      if (combo) {\n        // Budget status for the Good setup uses the combined sub + amp total, so both cards (and the tier) are\n        // marked over budget when the pair together exceeds the selected budget.\n        const comboTotal = combo.sub.price + (combo.amp ? combo.amp.price : 0);\n        const comboOver = isOverBudget(comboTotal, budgetKey);\n        picks[0] = { item: combo.sub, over: comboOver || isOverBudget(combo.sub.price, budgetKey) };\n        goodAmps[ampSlot.key] = { amp: combo.amp, over: comboOver };\n      }\n    }\n    if (slot.pairWith && bySlot[slot.pairWith]) {\n      const missing = pairBrand(\n        list,\n        picks,\n        bySlot[slot.pairWith],\n        budgetKey,\n        Boolean(slot.distinct),\n        slot.pairRules,\n        slot.skipAmplified ? isAmplifiedSub : null\n      );\n      if (slot.key in goodAmps) {\n        const { amp: goodAmp, over: goodOver } = goodAmps[slot.key];\n        picks[0] = goodAmp ? { item: goodAmp, over: goodOver || isOverBudget(goodAmp.price, budgetKey) } : null;\n        missing[0] = false;\n      }\n      missing.forEach((isMissing, tierIndex) => {\n        if (isMissing) tiers[tierIndex].ampNote = true;\n      });\n    }\n    bySlot[slot.key] = picks;\n    picks.forEach((pick, tierIndex) => {\n      if (!pick) return;\n      tiers[tierIndex].picks.push({ slot: slot.key, labelSlot: slot.labelSlot, labelText: slot.labelText, ...pick });\n      tiers[tierIndex].total += pick.item.price;\n      if (pick.over) tiers[tierIndex].over = true;\n      for (const extra of rcaExtras?.[tierIndex] || []) {\n        tiers[tierIndex].picks.push({ slot: slot.key, labelSlot: slot.labelSlot, labelText: slot.labelText, ...extra });\n        tiers[tierIndex].total += extra.item.price;\n        if (extra.over) tiers[tierIndex].over = true;\n      }\n    });\n  }\n  // DSP amps already accept the factory speaker-level signal. Hide only the redundant LC7i in\n  // Better/Best; a compatible PAC AmpPRO remains visible, as requested.\n  if (goals.has('power')) {\n    for (let tierIndex = 1; tierIndex < tiers.length; tierIndex++) {\n      const amp = tiers[tierIndex].picks.find((pick) => pick.slot === 'amp')?.item;\n      if (!amp || !isDspAmp(amp)) continue;\n      const interfaceIndex = tiers[tierIndex].picks.findIndex((pick) => pick.slot === 'factory-interface' && isAudioControl(pick.item, 'lc7i'));\n      if (interfaceIndex >= 0) {\n        const [removed] = tiers[tierIndex].picks.splice(interfaceIndex, 1);\n        tiers[tierIndex].total -= removed.item.price;\n      }\n    }\n  }\n  if (brand) {\n    for (const slot of slots) {\n      if (!BRAND_FILTER_SLOT_KEYS.has(slot.key)) continue;\n      const slotLabel = slot.labelText || brandSlotLabels[slot.key] || slot.key.replace(/-/g, ' ');\n      for (const tier of tiers) {\n        if (tier.picks.some((pick) => pick.slot === slot.key)) continue;\n        tier.messages.push(`${slotLabel}: ${brandNoOptionMessage || 'No option available from this manufacturer. Contact us for options not listed.'}`);\n      }\n    }\n  }\n  return { slots, tiers };\n}\n\n// ---- Custom element ----\n\nclass SSoundGuide extends HTMLElement {\n  #controller = null;\n  #rafId = 0;\n  #renderToken = 0;\n  #pools = new Map();\n  #speakerVehicle = null;\n\n  connectedCallback() {\n    this.#controller = new AbortController();\n    const { signal } = this.#controller;\n    this.dataset.ready = '';\n    this.addEventListener('change', (event) => this.#onChange(event), { signal });\n    this.querySelector('form')?.addEventListener('reset', () => this.#onReset(), { signal });\n    // Back/forward cache restores checked inputs without firing change.\n    window.addEventListener('pageshow', () => this.#update(false), { signal });\n    // Warm the most common collections once the shopper shows interest.\n    this.addEventListener('pointerenter', () => this.#prefetch(), { signal, once: true });\n    this.addEventListener('focusin', () => this.#prefetch(), { signal, once: true });\n    // Year / Make / Model changes (from s-vehicle-picker) refresh the Stealth Boxes match.\n    this.addEventListener('vehicle-change', () => this.#onVehicleChange(), { signal });\n    this.addEventListener('speaker-fitment-change', (event) => { this.#speakerVehicle = event.detail || null; if (this.#selectedGoals().some((goal) => ['speakers', 'oem-carplay', 'carplay-radio'].includes(goal))) this.#update(false); }, { signal });\n\n    const linkedGoals = new URLSearchParams(window.location.search).getAll('goal');\n    for (const goal of linkedGoals) {\n      if (!GOALS.includes(goal)) continue;\n      const box = this.querySelector(`input[name=\"goal\"][value=\"${goal}\"]`);\n      if (box instanceof HTMLInputElement) box.checked = true;\n    }\n    this.#update(false);\n  }\n\n  disconnectedCallback() {\n    this.#controller?.abort();\n    cancelAnimationFrame(this.#rafId);\n  }\n\n  #selectedGoals() {\n    return [...this.querySelectorAll('input[name=\"goal\"]:checked')]\n      .map((input) => input.value)\n      .filter((goal) => GOALS.includes(goal));\n  }\n\n  #budget() {\n    const input = this.querySelector('input[name=\"budget\"]:checked');\n    return input instanceof HTMLInputElement && BUDGETS[input.value] ? input.value : 'any';\n  }\n\n  #selectedBrand() {\n    const select = this.querySelector('[data-guide-brand]');\n    return select instanceof HTMLSelectElement ? select.value : '';\n  }\n\n  #paintBrandFilter(slots, poolItems) {\n    const container = this.querySelector('[data-guide-brand-filter]');\n    const select = this.querySelector('[data-guide-brand]');\n    const brandSlots = slots.filter((slot) => BRAND_FILTER_SLOT_KEYS.has(slot.key));\n    if (!(container instanceof HTMLElement) || !(select instanceof HTMLSelectElement) || !brandSlots.length) return;\n\n    const currentValue = select.value;\n    const currentLabel = select.selectedOptions[0]?.textContent?.trim() || currentValue;\n    const brands = new Map();\n    for (const slot of brandSlots) {\n      for (const item of candidatesFor(slot, poolItems)) {\n        if (slot.key === 'wiring' && isSpeakerSet(String(item.title || '').toLowerCase())) continue;\n        const key = brandOf(item);\n        const label = String(item.vendor || item.title.split(' ')[0] || '').trim();\n        if (key && label && !brands.has(key)) brands.set(key, label);\n      }\n    }\n    // Sundown has full-range speaker products that may sit beyond the 250-item default feed.\n    // Keep it selectable for speaker goals so the selected-brand fetch can load its size-matched products.\n    if (brandSlots.some((slot) => ['front-speakers', 'rear-speakers', 'speakers'].includes(slot.key))) {\n      brands.set('sundown', 'Sundown');\n    }\n    if (currentValue && !brands.has(currentValue)) brands.set(currentValue, currentLabel);\n\n    const defaultOption = document.createElement('option');\n    defaultOption.value = '';\n    defaultOption.textContent = this.dataset.brandAll || 'All brands \u2014 default recommendations';\n    select.replaceChildren(defaultOption);\n    for (const [value, label] of [...brands.entries()].sort((a, b) => a[1].localeCompare(b[1]))) {\n      const option = document.createElement('option');\n      option.value = value;\n      option.textContent = label;\n      select.append(option);\n    }\n    select.value = currentValue;\n    select.disabled = brands.size === 0 && !currentValue;\n    container.hidden = false;\n  }\n\n  #choiceLabel(input) {\n    return input?.closest('label')?.querySelector('[data-choice-label]')?.textContent?.trim() || '';\n  }\n\n  #onChange(event) {\n    const target = event.target;\n    if (target instanceof HTMLSelectElement && target.matches('[data-guide-brand]')) {\n      this.#update(true);\n      return;\n    }\n    if (!(target instanceof HTMLInputElement)) return;\n    if (target.name !== 'goal' && target.name !== 'budget') return;\n    this.#update(true);\n  }\n\n  #onReset() {\n    // The form's reset runs after this event; read the restored state on the next frame.\n    requestAnimationFrame(() => {\n      this.#update(false);\n      this.#announce(this.dataset.clearedMessage || '');\n      const first = this.querySelector('input[name=\"goal\"]');\n      if (first instanceof HTMLElement) first.focus();\n    });\n  }\n\n  #update(announce) {\n    const goals = this.#selectedGoals();\n    const budget = this.#budget();\n    const brandFilter = this.querySelector('[data-guide-brand-filter]');\n    const brandSelect = this.querySelector('[data-guide-brand]');\n    const brandGoals = ['bass', 'speakers', 'power', 'cables', 'marine'];\n    if (!goals.some((goal) => brandGoals.includes(goal))) {\n      if (brandSelect instanceof HTMLSelectElement) brandSelect.value = '';\n      if (brandFilter instanceof HTMLElement) brandFilter.hidden = true;\n    } else if (brandFilter instanceof HTMLElement) {\n      brandFilter.hidden = false;\n    }\n    if (goals.length) this.dataset.goals = goals.join(' ');\n    else delete this.dataset.goals;\n    this.dataset.budget = budget;\n\n    const count = this.querySelector('[data-guide-count]');\n    if (count) {\n      if (!goals.length) count.textContent = this.dataset.countNone || '';\n      else if (goals.length === 1) count.textContent = this.dataset.countOne || '';\n      else count.textContent = (this.dataset.countOther || '').replace('%n', String(goals.length));\n    }\n\n    const goalLabels = goals.map((goal) => this.#choiceLabel(this.querySelector(`input[name=\"goal\"][value=\"${goal}\"]`)));\n    const budgetLabel = this.#choiceLabel(this.querySelector('input[name=\"budget\"]:checked'));\n    const summary = this.querySelector('[data-guide-summary]');\n    if (summary) summary.textContent = goals.length ? `${goalLabels.join(' + ')} \u00B7 ${budgetLabel}` : '';\n\n    if (!goals.includes('stealth-boxes')) this.#paintStealth(null);\n    // Stealth Boxes on its own shows only the Stealth result area, so the generic tier explanation is hidden.\n    const systemNote = this.querySelector('#guide-system-note');\n    if (systemNote instanceof HTMLElement) systemNote.hidden = goals.length === 1 && goals[0] === 'stealth-boxes';\n    if (!goals.length) {\n      this.#renderToken += 1;\n      return;\n    }\n    this.#render(new Set(goals), budget, announce ? [this.dataset.updatedMessage, `${goalLabels.join(', ')}, ${budgetLabel}`] : null);\n  }\n\n  #poolUrl(handle) {\n    const key = 'pool' + handle.replace(/(^|-)([a-z])/g, (_, __, c) => c.toUpperCase());\n    return this.dataset[key] || '';\n  }\n\n  // The `guide-picks` view lives only in this theme, so a preview request must name the previewed theme.\n  // The URL is absolute: inside the theme editor's embedded frame a relative path may resolve against the\n  // admin rather than the storefront, so it falls back to the storefront origin Liquid rendered the page for.\n  #feedUrl(base) {\n    const pageOrigin = /^https?:$/.test(window.location.protocol) ? window.location.origin : '';\n    const origin = pageOrigin && pageOrigin !== 'null' ? pageOrigin : this.dataset.shopOrigin || '';\n    const url = new URL(base, origin || document.baseURI);\n    url.searchParams.set('view', 'guide-picks');\n    const theme = window.Shopify?.theme;\n    const previewId =\n      new URLSearchParams(window.location.search).get('preview_theme_id') ||\n      (theme?.id && theme.role !== 'main' ? String(theme.id) : '');\n    if (previewId) url.searchParams.set('preview_theme_id', previewId);\n    return url.toString();\n  }\n\n  static #readPicks(root) {\n    return [...root.querySelectorAll('[data-pick]')].map((node) => ({\n      handle: node.getAttribute('data-handle') || '',\n      title: node.getAttribute('data-title') || '',\n      vendor: node.getAttribute('data-vendor') || '',\n      sku: node.getAttribute('data-sku') || '',\n      description: node.getAttribute('data-description') || '',\n      amplified: node.hasAttribute('data-amplified'),\n      rms: Number(node.getAttribute('data-rms')) || 0,\n      price: Number(node.getAttribute('data-price')) || 0,\n      node,\n    }));\n  }\n\n  async #fetchPool(base) {\n    const url = this.#feedUrl(base);\n    let response;\n    try {\n      response = await fetch(url, { headers: { Accept: 'text/html' }, credentials: 'include' });\n    } catch (error) {\n      throw new Error(`request blocked (${error?.message || error}) for ${url} from ${window.location.origin}`);\n    }\n    if (!response.ok) throw new Error(`HTTP ${response.status} for ${url}`);\n    const doc = new DOMParser().parseFromString(await response.text(), 'text/html');\n    // Anything other than the feed (e.g. a normal collection page from another theme) has no pool marker.\n    if (!doc.querySelector('[data-guide-pool]')) throw new Error(`not the guide feed: ${response.url || url}`);\n    return SSoundGuide.#readPicks(doc);\n  }\n\n  #loadPool(handle) {\n    if (this.#pools.has(handle)) return this.#pools.get(handle);\n    const base = this.#poolUrl(handle);\n    // In the theme editor the page carries its own pool, so no request is needed there.\n    const inline = this.querySelector(`template[data-guide-inline-pool=\"${handle}\"]`);\n    const request =\n      inline instanceof HTMLTemplateElement\n        ? Promise.resolve(SSoundGuide.#readPicks(inline.content))\n        : !base\n          ? Promise.resolve([])\n          : this.#fetchPool(base);\n    // Drop a failed request from the cache so a later change can retry it, and leave the reason visible to devtools.\n    request.catch((error) => {\n      this.#pools.delete(handle);\n      this.dataset.feedError = String(error?.message || error);\n      console.warn('[Find your sound] feed failed:', handle, error);\n    });\n    this.#pools.set(handle, request);\n    return request;\n  }\n\n  #loadFilteredPool(handle, filterName, filterValue) {\n    const cacheKey = `filter:${filterName}:${filterValue.toLowerCase()}:${handle}`;\n    if (this.#pools.has(cacheKey)) return this.#pools.get(cacheKey);\n    const base = this.#poolUrl(handle);\n    if (!base || !filterName || !filterValue) return Promise.resolve([]);\n    const url = new URL(base, window.location.origin);\n    url.searchParams.set(filterName, filterValue);\n    const request = this.#fetchPool(url.toString());\n    request.catch((error) => {\n      this.#pools.delete(cacheKey);\n      this.dataset.feedError = String(error?.message || error);\n      console.warn('[Find your sound] filtered feed failed:', handle, filterValue, error);\n    });\n    this.#pools.set(cacheKey, request);\n    return request;\n  }\n\n  #prefetch() {\n    for (const handle of ['woofers', 'amplifiers']) this.#loadPool(handle).catch(() => {});\n  }\n\n  async #render(goals, budget, announcement) {\n    const token = ++this.#renderToken;\n    const slots = buildSlots(goals, this.#speakerVehicle);\n    const tierHandles = [...new Set(slots.flatMap((slot) => slot.pools))];\n    const stealth = goals.has('stealth-boxes');\n    const stealthOnly = stealth && goals.size === 1;\n    // Stealthboxes are always shown with a JL amp, so the Amplifiers collection loads with them.\n    const stealthOnlyInterfaceHandles = stealthOnly ? ['installation-accessories', 'audio-processors'] : [];\n    const handles = stealth ? [...new Set([...tierHandles, ...stealthOnlyInterfaceHandles, 'stealth-boxes', 'amplifiers'])] : tierHandles;\n    const selectedBrand = this.#selectedBrand();\n    const addSundownWoofers = selectedBrand === 'sundown' && handles.includes('woofers');\n    const sundownWooferCacheKey = 'filter:vendor:sundown:woofers';\n    const addSundownSpeakers = selectedBrand === 'sundown' && handles.includes('full-range-speakers');\n    const sundownSpeakerCacheKey = 'filter:vendor:sundown:full-range-speakers';\n    const loading = this.querySelector('[data-guide-loading]');\n    const error = this.querySelector('[data-guide-error]');\n    const tiersList = this.querySelector('[data-guide-tiers]');\n    const pending = handles.some((handle) => !this.#pools.has(handle)) ||\n      (addSundownWoofers && !this.#pools.has(sundownWooferCacheKey)) ||\n      (addSundownSpeakers && !this.#pools.has(sundownSpeakerCacheKey));\n    if (loading) loading.hidden = !pending;\n    if (error) error.hidden = true;\n    // Don't flash empty tier frames on the first load.\n    if (pending && tiersList instanceof HTMLElement && !tiersList.querySelector('[data-pick]')) tiersList.hidden = true;\n    // Stealth Boxes alone never shows the tier display, not even earlier tiers while loading.\n    if (stealthOnly && tiersList instanceof HTMLElement) tiersList.hidden = true;\n    tiersList?.setAttribute('aria-busy', 'true');\n\n    let poolItems;\n    try {\n      const [results, sundownWoofers, sundownSpeakers] = await Promise.all([\n        Promise.all(handles.map((handle) => this.#loadPool(handle))),\n        addSundownWoofers\n          ? this.#loadFilteredPool('woofers', 'filter.p.vendor', 'Sundown').catch(() => [])\n          : Promise.resolve([]),\n        addSundownSpeakers\n          ? this.#loadFilteredPool('full-range-speakers', 'filter.p.vendor', 'Sundown').catch(() => [])\n          : Promise.resolve([]),\n      ]);\n      // Sundown subwoofers and full-range speakers can fall beyond their 250-product default feeds.\n      // Merge only Sundown's filtered collection results when that brand is selected, preserving all-brand picks.\n      poolItems = Object.fromEntries(handles.map((handle, index) => [handle, results[index]]));\n      if (sundownWoofers.length) {\n        const mergedWoofers = new Map([...(poolItems.woofers || []), ...sundownWoofers].map((item) => [item.handle, item]));\n        poolItems.woofers = [...mergedWoofers.values()];\n      }\n      if (sundownSpeakers.length) {\n        const mergedSpeakers = new Map([...(poolItems['full-range-speakers'] || []), ...sundownSpeakers].map((item) => [item.handle, item]));\n        poolItems['full-range-speakers'] = [...mergedSpeakers.values()];\n      }\n      // Stealth Boxes on its own may legitimately match nothing; only the tier collections must return products.\n      if (tierHandles.length && tierHandles.every((handle) => !poolItems[handle].length)) throw new Error('guide-picks returned no products');\n      if (!tierHandles.length && !poolItems['stealth-boxes'].length) throw new Error('guide-picks returned no products');\n    } catch (failure) {\n      if (token !== this.#renderToken) return;\n      if (loading) loading.hidden = true;\n      if (error) error.hidden = false;\n      // Theme editor only: show the exact reason so the preview can be diagnosed without devtools.\n      const detail = this.querySelector('[data-guide-error-detail]');\n      const previewing = this.hasAttribute('data-design-mode') || (window.Shopify?.theme?.role && window.Shopify.theme.role !== 'main');\n      if (detail instanceof HTMLElement && previewing) {\n        detail.textContent = String(failure?.message || failure);\n        detail.hidden = false;\n      }\n      if (tiersList instanceof HTMLElement) tiersList.hidden = true;\n      tiersList?.removeAttribute('aria-busy');\n      this.#paintStealth(null);\n      return;\n    }\n    if (token !== this.#renderToken) return;\n\n    this.#paintBrandFilter(slots, poolItems);\n    const brandSlotLabels = Object.fromEntries(slots.map((slot) => {\n      const slotDataKey = 'slot' + slot.key.replace(/(^|-)([a-z])/g, (_, __, c) => c.toUpperCase());\n      return [slot.key, slot.labelText || this.dataset[slotDataKey] || slot.key.replace(/-/g, ' ')];\n    }));\n    const { tiers } = recommend(goals, budget, poolItems, this.#speakerVehicle, selectedBrand, this.dataset.brandNoOption || '', brandSlotLabels);\n    // Stealth Boxes with other goals: the vehicle's Stealthbox + amp go inside the tiers and the standalone panel stays\n    // hidden. Stealth Boxes alone: only the standalone panel.\n    const stealthPicks = stealth ? stealthMatches(poolItems['stealth-boxes'], this.#vehicle(), poolItems.amplifiers) : [];\n    const stealthInterface = stealthOnly && hasCompleteVehicle(this.#vehicle())\n      ? compatibleFactoryInterfaces(poolItems, this.#vehicle(), false)[0] || null\n      : null;\n    if (stealth && !stealthOnly) addStealthToTiers(tiers, stealthPicks, budget);\n    this.#paint(tiers, budget);\n    this.#paintStealth(stealthOnly ? stealthPicks : null, budget, stealthInterface);\n    if (loading) loading.hidden = true;\n    // Stealth Boxes alone has no Good / Better / Best tiers to show.\n    if (tiersList instanceof HTMLElement) tiersList.hidden = !slots.length;\n    tiersList?.removeAttribute('aria-busy');\n    if (announcement) this.#announce(announcement.filter(Boolean).join(': '));\n  }\n\n  #paint(tiers, budget = 'any') {\n    const metaTemplate = this.querySelector('template[data-item-meta]');\n    const format = new Intl.NumberFormat(this.dataset.locale || undefined, {\n      style: 'currency',\n      currency: this.dataset.currency || 'USD',\n    });\n    const tierNodes = this.querySelectorAll('[data-tier]');\n    tiers.forEach((tier, index) => {\n      const tierNode = tierNodes[index];\n      if (!tierNode) return;\n      const list = tierNode.querySelector('[data-tier-items]');\n      const total = tierNode.querySelector('[data-tier-total]');\n      const over = tierNode.querySelector('[data-tier-over]');\n      const empty = tierNode.querySelector('[data-tier-empty]');\n      const ampNote = tierNode.querySelector('[data-tier-amp-note]');\n      if (!list) return;\n      let tierOver = false;\n      const items = tier.picks.map((pick) => {\n        const card = /** @type {HTMLElement} */ (pick.item.node.cloneNode(true));\n        // This product's own price vs the chosen budget, or (More bass Good setup) the sub + amp combined total.\n        const itemOver = pick.over === true || isOverBudget(pick.item.price, budget);\n        if (itemOver) tierOver = true;\n        if (metaTemplate instanceof HTMLTemplateElement) {\n          const meta = /** @type {DocumentFragment} */ (metaTemplate.content.cloneNode(true));\n          const slotLabel = meta.querySelector('[data-item-slot]');\n          const slotKey = 'slot' + (pick.labelSlot || pick.slot).replace(/(^|-)([a-z])/g, (_, __, c) => c.toUpperCase());\n          if (slotLabel) slotLabel.textContent = pick.labelText || this.dataset[slotKey] || '';\n          card.prepend(meta);\n        }\n        // Applied on the finished card, so it holds however the editor serialised the label template.\n        // At most one badge per card: the editor can leave more than one copy in the label row.\n        card.querySelectorAll('[data-item-over]').forEach((label, labelIndex) => {\n          if (itemOver && labelIndex === 0) label.hidden = false;\n          else label.remove();\n        });\n        // Stealthbox fit note / amp pairing note, styled like the Stealth panel's fit note.\n        for (const text of pick.notes || []) card.append(SSoundGuide.#noteNode(text));\n        return card;\n      });\n      for (const messageText of tier.messages || []) {\n        const message = document.createElement('li');\n        message.className = 'min-w-[16rem] max-w-[22rem] shrink-0 snap-start border border-border bg-surface p-4 type-body-sm text-on-surface/75';\n        message.textContent = messageText;\n        items.push(message);\n      }\n      list.replaceChildren(...items);\n      list.hidden = !items.length;\n      if (total) total.textContent = items.length ? format.format(tier.total / 100) : '';\n      if (over instanceof HTMLElement) over.hidden = !tierOver;\n      if (empty instanceof HTMLElement) empty.hidden = items.length > 0;\n      // A paired amp was left out (no same-brand / no distinct marine amp): point the shopper to Soundwaves.\n      if (ampNote instanceof HTMLElement) ampNote.hidden = !tier.ampNote;\n      // Upgraded LED headlight bulbs: bulb-size note and Lucas finder link on every tier.\n      const headlightNote = tierNode.querySelector('[data-tier-headlight-note]');\n      if (headlightNote instanceof HTMLElement) headlightNote.hidden = !tier.headlightNote;\n    });\n  }\n\n  #vehicleKey = '';\n  #vehicleFrame = 0;\n\n  #vehicle() {\n    const read = (name) => {\n      const input = this.querySelector(`input[name=\"${name}\"]`);\n      return input instanceof HTMLInputElement ? input.value.trim() : '';\n    };\n    return { year: read('year'), make: read('make'), model: read('model') };\n  }\n\n  #onVehicleChange() {\n    cancelAnimationFrame(this.#vehicleFrame);\n    this.#vehicleFrame = requestAnimationFrame(() => {\n      const vehicle = this.#vehicle();\n      const key = `${vehicle.year}|${normVehicle(vehicle.make)}|${normVehicle(vehicle.model)}`;\n      if (key === this.#vehicleKey) return;\n      this.#vehicleKey = key;\n      if (this.#selectedGoals().some((goal) => ['stealth-boxes', 'oem-carplay', 'carplay-radio'].includes(goal))) this.#update(false);\n    });\n  }\n\n  static #noteNode(text) {\n    const node = document.createElement('p');\n    node.className = 'mt-2 type-body-sm text-xs text-on-surface/75';\n    node.textContent = text;\n    return node;\n  }\n\n  // One card for the Stealth panel, with its slot label, budget badge and notes.\n  #stealthCard(item, slotLabel, notes, budget) {\n    const card = /** @type {HTMLElement} */ (item.node.cloneNode(true));\n    const itemOver = isOverBudget(item.price, budget);\n    const metaTemplate = this.querySelector('template[data-item-meta]');\n    if (metaTemplate instanceof HTMLTemplateElement) {\n      const meta = /** @type {DocumentFragment} */ (metaTemplate.content.cloneNode(true));\n      const label = meta.querySelector('[data-item-slot]');\n      if (label) label.textContent = slotLabel;\n      card.prepend(meta);\n    }\n    card.querySelectorAll('[data-item-over]').forEach((label, labelIndex) => {\n      if (itemOver && labelIndex === 0) label.hidden = false;\n      else label.remove();\n    });\n    for (const text of notes) if (text) card.append(SSoundGuide.#noteNode(text));\n    return card;\n  }\n\n  // Stealth Boxes panel (Stealth Boxes as the only goal): each verified JL fitment match for the entered vehicle with\n  // its paired JL amp, or one clear message. `matches` comes from stealthMatches(); null hides the panel.\n  #paintStealth(matches, budget = 'any', factoryInterface = null) {\n    const panel = this.querySelector('[data-stealth-panel]');\n    if (!(panel instanceof HTMLElement)) return;\n    if (!matches) {\n      panel.hidden = true;\n      return;\n    }\n    const list = panel.querySelector('[data-stealth-items]');\n    const message = panel.querySelector('[data-stealth-message]');\n    const note = panel.querySelector('[data-stealth-note]');\n    const vehicle = this.#vehicle();\n    const complete = /^(19|20)\\d{2}$/.test(vehicle.year) && Boolean(vehicle.make) && Boolean(vehicle.model);\n    const cards = complete\n      ? matches.flatMap(({ item, note: fitNote, amp, ampNote }) => [\n          this.#stealthCard(item, this.dataset.slotStealth || '', [fitNote], budget),\n          this.#stealthCard(amp, this.dataset.slotAmp || '', [ampNote], budget),\n        ]).concat(factoryInterface ? [this.#stealthCard(factoryInterface, 'FACTORY AUDIO INTERFACE', ['Confirm compatibility with the vehicle\u2019s factory audio system before ordering.'], budget)] : [])\n      : [];\n    if (list instanceof HTMLElement) {\n      list.replaceChildren(...cards);\n      list.hidden = !cards.length;\n    }\n    if (message instanceof HTMLElement) {\n      message.textContent = cards.length ? '' : complete ? 'No current option available' : message.dataset.needVehicle || '';\n      message.hidden = cards.length > 0;\n    }\n    if (note instanceof HTMLElement) note.hidden = !cards.length;\n    panel.hidden = false;\n  }\n\n  #announce(message) {\n    const status = this.querySelector('[data-guide-status]');\n    if (!status) return;\n    // Clear then set so a repeated identical message is still announced.\n    cancelAnimationFrame(this.#rafId);\n    status.textContent = '';\n    this.#rafId = requestAnimationFrame(() => {\n      status.textContent = message;\n    });\n  }\n}\n\nif (!customElements.get('s-sound-guide')) customElements.define('s-sound-guide', SSoundGuide);\n\n"],
  "mappings": "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AK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EACrG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EACrG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EACrG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EACrG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EACrG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EACrG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EACrG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EACrG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EACrG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EACrG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EACrG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,CAAC,IAAK,CAAC,EAAG,eAAgB,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",
  "names": ["sku", "pool", "good", "better", "best"]
}
