{"id":7152,"date":"2026-08-31T03:12:39","date_gmt":"2026-08-31T07:12:39","guid":{"rendered":"https:\/\/www.visionpros.com\/pro\/?p=7152"},"modified":"2026-08-31T03:12:40","modified_gmt":"2026-08-31T07:12:40","slug":"halloween-contact-lens-matcher","status":"publish","type":"post","link":"https:\/\/www.visionpros.com\/pro\/halloween-contact-lens-matcher\/","title":{"rendered":"Halloween Contact Lens Matcher"},"content":{"rendered":"\n<meta charset=\"UTF-8\">\n<title>VisionPros Halloween Costume + Lens Finder<\/title>\n<style>\n  @import url('https:\/\/fonts.googleapis.com\/css2?family=Libre+Baskerville:wght@400;700&family=Source+Sans+3:wght@400;500;600;700&display=swap');\n\n  :root {\n    --navy: #1a3a6b;\n    --accent-blue: #0057a8;\n    --amber: #e8a13c;\n    --amber-soft: #e8a13c1a;\n    --bg: #faf9f6;\n    --card: #ffffff;\n    --line: #e2ded4;\n    --ink: #232323;\n    --muted: #6f6a5e;\n    --page-max: 1600px;\n  }\n  * { box-sizing: border-box; }\n  body {\n    margin: 0;\n    min-height: 100vh;\n    background: var(--bg);\n    color: var(--ink);\n    font-family: 'Source Sans 3', -apple-system, sans-serif;\n  }\n\n  .wrap {\n    width: 100%;\n    max-width: var(--page-max);\n    margin: 0 auto;\n    padding: 40px clamp(20px, 4vw, 64px);\n  }\n  h3 {\n    font-family: 'Libre Baskerville', Georgia, serif;\n    font-weight: 700;\n    font-size: 1.5rem;\n    margin: 0 0 8px;\n    color: var(--navy);\n  }\n  .sub {\n    color: var(--muted);\n    font-size: 0.98rem;\n    margin: 0 0 30px;\n    max-width: 640px;\n    line-height: 1.55;\n  }\n\n  .page { display: none; }\n  .page.active { display: block; }\n\n  \/* ---------- Page 1: costume input + autocomplete ---------- *\/\n  form {\n    display: flex;\n    gap: 10px;\n    background: var(--card);\n    border: 1px solid var(--line);\n    border-radius: 8px;\n    padding: 6px 6px 6px 18px;\n    box-shadow: 0 1px 3px rgba(0,0,0,0.05);\n    max-width: 720px;\n  }\n  .search-field { position: relative; flex: 1; }\n  input[type=\"text\"] {\n    width: 100%;\n    border: none;\n    background: transparent;\n    font-size: 1.05rem;\n    font-family: 'Source Sans 3', sans-serif;\n    padding: 12px 2px;\n    outline: none;\n    color: var(--ink);\n  }\n  input[type=\"text\"]::placeholder { color: #a39d8c; }\n  button {\n    border: none;\n    background: var(--navy);\n    color: #ffffff;\n    font-family: 'Source Sans 3', sans-serif;\n    font-weight: 700;\n    font-size: 0.82rem;\n    letter-spacing: 0.03em;\n    text-transform: uppercase;\n    padding: 12px 22px;\n    border-radius: 6px;\n    cursor: pointer;\n    transition: background 0.15s ease;\n  }\n  button:hover { background: var(--accent-blue); }\n  button.ghost {\n    background: #ffffff;\n    color: var(--navy);\n    border: 1px solid var(--line);\n  }\n  button.ghost:hover { background: #f2f0ea; }\n\n  .hint { margin-top: 10px; font-size: 0.78rem; color: var(--muted); }\n\n  .suggest-list {\n    position: absolute;\n    top: calc(100% + 8px);\n    left: 0;\n    right: 0;\n    background: var(--card);\n    border: 1px solid var(--line);\n    border-radius: 8px;\n    list-style: none;\n    margin: 0;\n    padding: 6px;\n    max-height: 320px;\n    overflow-y: auto;\n    display: none;\n    z-index: 20;\n    box-shadow: 0 12px 28px rgba(0,0,0,0.12);\n  }\n  .suggest-list.active { display: block; }\n  .suggest-group-label {\n    font-size: 0.66rem;\n    text-transform: uppercase;\n    letter-spacing: 0.06em;\n    color: var(--muted);\n    padding: 8px 10px 4px;\n  }\n  .suggest-item {\n    padding: 10px 12px;\n    border-radius: 6px;\n    font-size: 0.92rem;\n    color: var(--ink);\n    cursor: pointer;\n    display: flex;\n    align-items: center;\n    gap: 9px;\n  }\n  .suggest-item .icon { opacity: 0.85; }\n  .suggest-item mark { background: transparent; color: var(--accent-blue); font-weight: 700; }\n  .suggest-item:hover,\n  .suggest-item.highlighted { background: var(--amber-soft); }\n\n  \/* ---------- Page 2: color builder ---------- *\/\n  .builder-title {\n    font-family: 'Libre Baskerville', Georgia, serif;\n    font-weight: 700;\n    font-size: 1.6rem;\n    color: var(--navy);\n    margin: 0 0 26px;\n  }\n  .builder-layout {\n  display: grid;\n  grid-template-columns: 257px 520px;\n  gap: 24px;\n  justify-content: center;\n  align-items: start;\n  width: 100%;\n}\n\n.frames-grid {\n  display: grid;\n  grid-template-columns: 1fr;\n  gap: 14px;\n  width: 257px;\n  max-width: 257px;\n}\n\n.frame {\n  width: 257px;\n  height: 180px;\n}\n  @media (max-width: 900px) {\n  .builder-layout {\n    grid-template-columns: 1fr;\n    justify-items: center;\n    gap: 18px;\n  }\n\n  .sliders {\n    width: 100%;\n    max-width: 520px;\n  }\n}\n\n  \/* --- Placeholder PNG frames --- *\/\n  .frames-grid {\n  display: grid;\n  grid-template-columns: 1fr;\n  gap: 14px;\n  max-width: 180px;\n}\n\n.frame {\n  position: relative;\n  width: 257px;\n  height: 180px;\n  border-radius: 12px;\n  border: 2px dashed var(--line);\n  overflow: hidden;\n  background-color: var(--card);\n  transition: opacity 0.15s ease;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n  \/*\n    ============================================================\n    DROP YOUR PNGs IN HERE.\n    Replace each url('') below with the path to your PNG\n    (e.g. url('headwear.png')). Your PNG needs a TRANSPARENT\n    background -- the frame's fill color shows through the\n    transparent areas, which is how the \"whole frame recolors\"\n    effect works. An opaque background on the PNG will just\n    hide the color behind the photo.\n    ============================================================\n  *\/\n  .frame-headwear .frame-photo { background-image: url('https:\/\/www.visionpros.com\/pro\/wp-content\/uploads\/2026\/08\/ChatGPT-Image-Aug-27-2026-03_19_09-PM.png'); \/* <-- headwear.png *\/ }\n  .frame-top      .frame-photo { background-image: url('https:\/\/www.visionpros.com\/pro\/wp-content\/uploads\/2026\/08\/ChatGPT-Image-Aug-27-2026-03_19_18-PM.png'); \/* <-- top.png      *\/ }\n  .frame-bottom   .frame-photo { background-image: url('https:\/\/www.visionpros.com\/pro\/wp-content\/uploads\/2026\/08\/ChatGPT-Image-Aug-27-2026-03_19_25-PM.png'); \/* <-- bottom.png   *\/ }\n  .frame-footwear .frame-photo { background-image: url('https:\/\/www.visionpros.com\/pro\/wp-content\/uploads\/2026\/08\/ChatGPT-Image-Aug-27-2026-03_19_29-PM.png'); \/* <-- footwear.png *\/ }\n\n  .frame-photo {\n  position: absolute;\n  inset: 0;\n  z-index: 0;\n  background-size: contain;\n  background-position: center;\n  background-repeat: no-repeat;\n  filter: contrast(1.1); brightness(0.6);\n}\n  .frame-color-overlay {\n    position: absolute;\n    inset: 0;\n    z-index: 1;\n    background-color: hsl(220, 70%, 50%); \/* set on load \/ by the slider *\/\n    opacity: 1.0;\n    mix-blend-mode: color;\n    pointer-events: none;\n    transition: background-color 0.05s linear;\n  }\n  .frame-placeholder-label {\n    position: relative;\n    z-index: 2;\n    text-align: center;\n    color: var(--muted);\n    font-size: 0.8rem;\n    font-weight: 700;\n    text-transform: uppercase;\n    letter-spacing: 0.04em;\n    padding: 10px;\n    pointer-events: none;\n  }\n  .frame-part-name {\n    display: block;\n    margin-top: 12px;\n    text-align: center;\n    font-size: 0.72rem;\n    text-transform: uppercase;\n    letter-spacing: 0.06em;\n    color: var(--muted);\n  }\n\n  .part-overlay {\n    position: absolute;\n    top: 8px;\n    left: 8px;\n    right: 8px;\n    bottom: 8px;\n    display: none;\n    align-items: center;\n    justify-content: center;\n    background: rgba(255,255,255,0.35);\n    pointer-events: none;\n    z-index: 3;\n  }\n  .part-overlay.active { display: flex; }\n  .part-overlay .x-mark {\n    font-size: 2.4rem;\n    font-weight: 700;\n    color: #c11414;\n    line-height: 1;\n    text-shadow: 0 0 4px rgba(255,255,255,0.9), 0 0 2px rgba(255,255,255,0.9);\n  }\n  .frame.is-na { opacity: 0.45; }\n\n  \/* --- Sliders --- *\/\n  .sliders {\n  width: 520px;\n  max-width: 100%;\n}\n  .slider-row {\n  height: 180px;\n  background: var(--card);\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  padding: 16px 18px;\n  margin-bottom: 14px;\n  box-shadow: 0 1px 3px rgba(0,0,0,0.05);\n}\n  .slider-head {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    margin-bottom: 10px;\n  }\n  .slider-label {\n    font-size: 0.72rem;\n    text-transform: uppercase;\n    letter-spacing: 0.08em;\n    color: var(--navy);\n    font-weight: 700;\n  }\n  .slider-value {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    font-size: 0.78rem;\n    color: var(--muted);\n  }\n  .slider-swatch {\n    width: 20px;\n    height: 20px;\n    border-radius: 50%;\n    border: 2px solid var(--line);\n    flex-shrink: 0;\n  }\n  .na-btn {\n    border: 1px solid var(--line);\n    background: #ffffff;\n    color: var(--muted);\n    font-family: 'Source Sans 3', sans-serif;\n    font-weight: 700;\n    font-size: 0.68rem;\n    letter-spacing: 0.03em;\n    text-transform: uppercase;\n    padding: 5px 10px;\n    border-radius: 999px;\n    cursor: pointer;\n    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n  }\n  .na-btn:hover { border-color: var(--muted); color: var(--ink); }\n  .na-btn.active {\n    background: var(--navy);\n    border-color: var(--navy);\n    color: #ffffff;\n  }\n  .slider-row.is-na { opacity: 0.55; }\n  .slider-row.is-na input[type=\"range\"] {\n    pointer-events: none;\n    filter: grayscale(1);\n  }\n  input[type=\"range\"] {\n    -webkit-appearance: none;\n    appearance: none;\n    width: 100%;\n    height: 10px;\n    border-radius: 999px;\n    background: linear-gradient(to right,\n      hsl(0,75%,55%), hsl(60,75%,55%), hsl(120,75%,55%),\n      hsl(180,75%,55%), hsl(240,75%,55%), hsl(300,75%,55%), hsl(360,75%,55%));\n    outline: none;\n  }\n  input[type=\"range\"]::-webkit-slider-thumb {\n    -webkit-appearance: none;\n    width: 22px;\n    height: 22px;\n    border-radius: 50%;\n    background: #ffffff;\n    border: 3px solid var(--navy);\n    cursor: pointer;\n    box-shadow: 0 1px 4px rgba(0,0,0,0.3);\n  }\n  input[type=\"range\"]::-moz-range-thumb {\n    width: 22px;\n    height: 22px;\n    border-radius: 50%;\n    background: #ffffff;\n    border: 3px solid var(--navy);\n    cursor: pointer;\n    box-shadow: 0 1px 4px rgba(0,0,0,0.3);\n  }\n\n  .builder-actions { display: flex; gap: 10px; margin-top: 22px; }\n\n\/* ---------- Combined hue + brightness picker ---------- *\/\n\n.color-picker {\n  position: relative;\n  width: 100%;\n  height: 64px;\n  border-radius: 10px;\n  cursor: crosshair;\n  overflow: hidden;\n  border: 1px solid var(--line);\n\n  background:\n    linear-gradient(\n      to bottom,\n      rgba(255,255,255,1) 0%,\n      rgba(255,255,255,0) 50%,\n      rgba(0,0,0,1) 100%\n    ),\n    linear-gradient(\n      to right,\n      hsl(0,75%,55%),\n      hsl(60,75%,55%),\n      hsl(120,75%,55%),\n      hsl(180,75%,55%),\n      hsl(240,75%,55%),\n      hsl(300,75%,55%),\n      hsl(360,75%,55%)\n    );\n}\n\n.color-picker-handle {\n  position: absolute;\n  width: 20px;\n  height: 20px;\n  border-radius: 50%;\n  border: 3px solid #ffffff;\n  box-shadow:\n    0 0 0 2px rgba(5,36,50,0.8),\n    0 2px 5px rgba(0,0,0,0.3);\n\n  transform: translate(-50%, -50%);\n  pointer-events: none;\n}\n\n.color-picker-labels {\n  display: none;\n}\n\n.color-picker.is-disabled {\n  pointer-events: none;\n  filter: grayscale(1);\n  opacity: 0.5;\n}\n\n\n  \/* ---------- Page 3: lens recommendations ---------- *\/\n  .lens-intro {\n    background: var(--card);\n    border: 1px solid var(--line);\n    border-radius: 8px;\n    padding: 14px 18px;\n    margin: 0 auto 22px;\n    margin-bottom: 22px;\n    font-size: 0.9rem;\n    color: var(--muted);\n    line-height: 1.55;\n    width: 100%;\n    max-width: 1100px;\n    text-align: left;\n    box-shadow: 0 1px 3px rgba(0,0,0,0.05);\n  }\n  .lens-intro strong { color: var(--navy); }\n\n  .lens-cards {\n    display: grid;\n  grid-template-columns: repeat(3, minmax(300px, 380px));\n  justify-content: center;\n  gap: 24px;\n  width: 100%;\n  }\n@media (max-width: 900px) {\n  .lens-cards {\n    grid-template-columns: 1fr;\n  }\n}\n  .lens-card {\n    display: flex;\n    gap: 16px;\n    background: var(--card);\n    border: 1px solid var(--line);\n    border-left: 3px solid var(--accent-blue);\n    border-radius: 8px;\n    padding: 18px 20px;\n    box-shadow: 0 1px 3px rgba(0,0,0,0.05);\n  }\n  .lens-swatch {\n    width: 48px;\n    height: 48px;\n    border-radius: 50%;\n    flex-shrink: 0;\n    border: 2px solid var(--line);\n    box-shadow: inset 0 0 0 3px rgba(0,0,0,0.08);\n  }\n  .lens-body { flex: 1; }\n  .lens-name {\n    font-family: 'Libre Baskerville', Georgia, serif;\n    font-weight: 700;\n    font-size: 1.1rem;\n    color: var(--navy);\n    margin: 0 0 4px;\n  }\n  .lens-line {\n    font-size: 0.7rem;\n    text-transform: uppercase;\n    letter-spacing: 0.05em;\n    color: var(--amber);\n    font-weight: 700;\n    margin: 0 0 8px;\n  }\n  .lens-desc { font-size: 0.9rem; line-height: 1.5; color: var(--ink); margin: 0 0 12px; }\n  .lens-link {\n    display: inline-block;\n    font-size: 0.82rem;\n    color: var(--accent-blue);\n    text-decoration: none;\n    font-weight: 700;\n  }\n  .lens-link:hover { text-decoration: underline; }\n\n\/* Page 3 bottom row *\/\n#page3 .page3-bottom-row {\n  width: 100%;\n  max-width: 900px;\n  margin: 20px auto 0;\n  display: flex;\n  align-items: center;\n  gap: 18px;\n  text-align: left;\n}\n\n#page3 .page3-bottom-row #backBtn2 {\n  flex: 0 0 auto;\n  margin: 0;\n}\n\n#page3 .page3-bottom-row .safety-note {\n  flex: 1;\n  width: auto;\n  max-width: none;\n  margin: 0;\n  padding: 0;\n  border-top: none;\n\n  font-size: 0.78rem;\n  line-height: 1.5;\n  color: var(--muted);\n  text-align: left;\n}\n@media (max-width: 700px) {\n  #page3 .page3-bottom-row {\n    flex-direction: column;\n    align-items: flex-start;\n  }\n}\n<\/style>\n\n\n<div class=\"wrap\">\n\n  <!-- PAGE 1: costume input -->\n  <div class=\"page active\" id=\"page1\">\n    <h3>Who are you going to be this Halloween?<\/h3>\n    <p class=\"sub\">Type a character, theme, or vibe. We'll suggest matches as you go. If it looks misspelled, we'll offer the closest costume ideas we know.<\/p>\n\n    <form id=\"searchForm\">\n      <div class=\"search-field\">\n        <input type=\"text\" id=\"queryInput\" placeholder=\"e.g. 'witch' or 'zombie' or 'group costume for 4 coworkers'\" autocomplete=\"off\">\n        <ul class=\"suggest-list\" id=\"suggestList\"><\/ul>\n      <\/div>\n      <button type=\"submit\" id=\"submitBtn\">Next<\/button>\n    <\/form>\n    <div class=\"hint\">Try a character, a pun, a group theme, or just a mood.<\/div>\n  <\/div>\n\n  <!-- PAGE 2: color builder -->\n  <div class=\"page\" id=\"page2\">\n    <h2 class=\"builder-title\" id=\"costumeTitle\">Costume<\/h2>\n\n    <div class=\"builder-layout\">\n      <div class=\"frames-grid\">\n\n        <div class=\"frame-wrap\">\n          <div class=\"frame frame-headwear\" id=\"frameHeadwear\">\n            <div class=\"frame-photo\"><\/div>\n            <div class=\"frame-color-overlay\" id=\"overlayColorHeadwear\"><\/div>\n            <div class=\"part-overlay\" id=\"overlayHeadwear\"><span class=\"x-mark\">\u00d7<\/span><\/div>\n          <\/div>\n        <\/div>\n\n        <div class=\"frame-wrap\">\n          <div class=\"frame frame-top\" id=\"frameTop\">\n            <div class=\"frame-photo\"><\/div>\n            <div class=\"frame-color-overlay\" id=\"overlayColorTop\"><\/div>\n            <div class=\"part-overlay\" id=\"overlayTop\"><span class=\"x-mark\">\u00d7<\/span><\/div>\n          <\/div>\n        <\/div>\n\n        <div class=\"frame-wrap\">\n          <div class=\"frame frame-bottom\" id=\"frameBottom\">\n            <div class=\"frame-photo\"><\/div>\n            <div class=\"frame-color-overlay\" id=\"overlayColorBottom\"><\/div>\n            <div class=\"part-overlay\" id=\"overlayBottom\"><span class=\"x-mark\">\u00d7<\/span><\/div>\n          <\/div>\n        <\/div>\n\n        <div class=\"frame-wrap\">\n          <div class=\"frame frame-footwear\" id=\"frameFootwear\">\n            <div class=\"frame-photo\"><\/div>\n            <div class=\"frame-color-overlay\" id=\"overlayColorFootwear\"><\/div>\n            <div class=\"part-overlay\" id=\"overlayFootwear\"><span class=\"x-mark\">\u00d7<\/span><\/div>\n          <\/div>\n        <\/div>\n\n      <\/div>\n\n      <div class=\"sliders\" id=\"slidersBox\"><\/div>\n    <\/div>\n\n    <div class=\"builder-actions\">\n      <button type=\"button\" class=\"ghost\" id=\"backBtn\">\u2190 Back<\/button>\n      <button type=\"button\" id=\"doneBtn\">Find my contact lenses \u2192<\/button>\n    <\/div>\n  <\/div>\n\n  <!-- PAGE 3: lens recommendations -->\n  <div class=\"page\" id=\"page3\">\n    <h2 id=\"lensHeading\">Contact lenses for your costume<\/h2>\n    <div class=\"lens-intro\" id=\"lensIntro\"><\/div>\n\n    <div class=\"lens-cards\" id=\"lensCards\"><\/div>\n\n    <div style=\"font-family: Georgia, 'Times New Roman', serif; max-width: 1200px; margin: 40px auto; border: 1px solid #e0e0e0; border-radius: 8px; overflow: hidden;\">\n  <div style=\"display: flex; align-items: stretch;\">\n    <div style=\"flex: 1; display: flex; flex-direction: column; justify-content: center; padding: 40px 44px; background: #ffffff;\">\n      <p style=\"font-family: Arial, sans-serif; font-size: 14px; color: #7ba9d1; letter-spacing: 0.08em; text-transform: uppercase; margin: 0 0 10px 0; font-weight: 700;\">See the world more clearly<\/p>\n      <p style=\"font-family: Georgia, 'Times New Roman', serif; font-size: 38px; font-weight: 700; color: #0e4773; margin: 0 0 10px 0; line-height: 1.3;\">Premium contacts,<br>delivered to you.<\/p>\n      <p style=\"font-family: Arial, sans-serif; font-size: 16px; color: #555; margin: 0 0 24px 0; line-height: 1.6;\">Shop top brands like Acuvue, Bausch + Lomb, and Air Optix at trusted low prices.<\/p>\n      <a href=\"https:\/\/www.visionpros.com\/contact-lenses\/\" style=\"display: inline-block; font-family: Arial, sans-serif; font-size: 14px; font-weight: 600; color: #ffffff; background: #3176b4; text-decoration: none; padding: 11px 24px; border-radius: 4px; width: fit-content; letter-spacing: 0.03em;\">Shop Contact Lenses \u2192<\/a>\n    <\/div>\n    <div style=\"flex: 0 0 45%; overflow: hidden;\">\n      <img decoding=\"async\" class=\"lazyload\" data-src=\"https:\/\/www.visionpros.com\/pro\/wp-content\/uploads\/2026\/06\/Contact-Lenses-1.png\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" alt=\"Contact lens boxes with lifestyle props\" style=\"width: 100%; height: 100%; object-fit: cover; object-position: 100% center; display: block;\"><noscript><img decoding=\"async\" src=\"https:\/\/www.visionpros.com\/pro\/wp-content\/uploads\/2026\/06\/Contact-Lenses-1.png\" alt=\"Contact lens boxes with lifestyle props\" style=\"width: 100%; height: 100%; object-fit: cover; object-position: 100% center; display: block;\"><\/noscript>\n    <\/div>\n  <\/div>\n<\/div>\n\n    <div class=\"page3-bottom-row\">\n  <button type=\"button\" class=\"ghost\" id=\"backBtn2\">\u2190 Back to colors<\/button>\n\n  <p class=\"safety-note\">\n    These are cosmetic suggestions based on VisionPros' current colored and costume lens lineup. Even\n    plano (no-correction) costume lenses are medical devices. Only wear FDA-approved lenses, get a\n    proper fit from an eye doctor, and never share lenses with anyone else.\n  <\/p>\n<\/div>\n\n<\/div>\n\n<script>\n\/* ==================== Page 1: costume input + autocomplete\/autospell ==================== *\/\nconst form = document.getElementById('searchForm');\nconst input = document.getElementById('queryInput');\nconst suggestList = document.getElementById('suggestList');\nconst page1 = document.getElementById('page1');\nconst page2 = document.getElementById('page2');\nconst page3 = document.getElementById('page3');\nconst costumeTitle = document.getElementById('costumeTitle');\nconst backBtn = document.getElementById('backBtn');\nconst backBtn2 = document.getElementById('backBtn2');\nconst doneBtn = document.getElementById('doneBtn');\n\nconst SUGGESTIONS = [\n  \"witch\", \"vampire\", \"zombie\", \"ghost\", \"mummy\", \"werewolf\", \"skeleton\", \"devil\",\n  \"grim reaper\", \"frankenstein's monster\", \"headless horseman\", \"banshee\", \"phantom\",\n  \"pirate\", \"ninja\", \"gladiator\", \"knight\", \"viking\", \"cowboy\", \"astronaut\", \"clown\",\n  \"mad scientist\", \"superhero\", \"supervillain\", \"fairy\", \"mermaid\", \"unicorn\", \"dragon\",\n  \"angel\", \"cat\", \"black cat\", \"dog\", \"spider\", \"bat\", \"bee\",\n  \"butterfly\", \"fox\", \"wolf\", \"bear\", \"dinosaur\", \"shark\", \"octopus\",\n  \"80s costume\", \"90s costume\", \"disco costume\", \"greek goddess\", \"roman soldier\",\n  \"medieval princess\", \"renaissance fair costume\", \"steampunk costume\", \"cyberpunk costume\",\n  \"video game character\", \"anime character\", \"cartoon character\", \"movie character\",\n  \"horror movie character\", \"sitcom character\", \"80s rockstar\", \"rapper costume\",\n  \"cheerleader\", \"referee\", \"mailman\", \"firefighter\", \"police officer\", \"doctor\",\n  \"nurse\", \"chef\", \"flight attendant\", \"sailor\", \"cowgirl\", \"wizard\", \"sorceress\",\n  \"genie\", \"pharaoh\", \"cleopatra\", \"bonnie and clyde couple\",\n  \"salt and pepper couple\", \"ketchup and mustard couple\", \"day and night couple\",\n  \"group costume for 3\", \"group costume for 4\", \"group costume for coworkers\",\n  \"family costume idea\", \"costume for toddlers\", \"costume for a baby\",\n  \"couples costume idea\", \"office group costume\", \"pun costume idea\",\n  \"scary costume\", \"funny costume\", \"cute costume idea\", \"last minute costume\",\n  \"diy costume on a budget\", \"no-sew costume idea\", \"costume using stuff at home\",\n  \"plus size costume idea\", \"pregnant halloween costume\", \"wheelchair-friendly costume\",\n  \"pet costume idea\", \"dog halloween costume\", \"scarecrow costume\", \"voodoo doll costume\",\n  \"corpse bride costume\", \"creepy doll costume\", \"circus performer costume\",\n  \"carnival ringmaster costume\", \"queen of hearts costume\", \"mad hatter costume\",\n  \"alice in wonderland costume\", \"wizard of oz group costume\", \"addams family costume\",\n  \"greek mythology costume\", \"zombie bride costume\", \"plague doctor costume\",\n  \"grim reaper couple costume\", \"80s workout costume\", \"punk rock costume\",\n  \"hippie costume\", \"disco ball costume\", \"roaring 20s costume\", \"pop star costume\",\n  \"internet meme costume\"\n];\n\n\/* ---- Levenshtein distance, used to power the \"closest match\" suggestions ---- *\/\nfunction levenshtein(a, b) {\n  a = a.toLowerCase(); b = b.toLowerCase();\n  const m = a.length, n = b.length;\n  const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));\n  for (let i = 0; i <= m; i++) dp[i][0] = i;\n  for (let j = 0; j <= n; j++) dp[0][j] = j;\n  for (let i = 1; i <= m; i++) {\n    for (let j = 1; j <= n; j++) {\n      dp[i][j] = a[i - 1] === b[j - 1]\n        ? dp[i - 1][j - 1]\n        : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);\n    }\n  }\n  return dp[m][n];\n}\n\nfunction getSuggestions(query) {\n  const q = query.toLowerCase().trim();\n  if (!q) return { mode: 'none', items: [] };\n\n  const substringMatches = SUGGESTIONS\n    .filter(s => s.toLowerCase().includes(q))\n    .sort((a, b) => a.toLowerCase().indexOf(q) - b.toLowerCase().indexOf(q))\n    .slice(0, 8);\n\n  if (substringMatches.length > 0) {\n    return { mode: 'match', items: substringMatches };\n  }\n\n  const scored = SUGGESTIONS\n    .map(s => ({ term: s, dist: levenshtein(q, s) }))\n    .sort((a, b) => a.dist - b.dist)\n    .slice(0, 5)\n    .map(s => s.term);\n\n  return { mode: 'spell', items: scored };\n}\n\nfunction renderSuggestions(query) {\n  const { mode, items } = getSuggestions(query);\n  suggestList.innerHTML = \"\";\n\n  if (!items.length) {\n    suggestList.classList.remove('active');\n    return;\n  }\n\n  if (mode === 'spell') {\n    const label = document.createElement('li');\n    label.className = 'suggest-group-label';\n    label.textContent = \"Did you mean...?\";\n    suggestList.appendChild(label);\n  }\n\n  items.forEach((s) => {\n    const li = document.createElement(\"li\");\n    li.className = \"suggest-item\";\n\n    const icon = document.createElement(\"span\");\n    icon.className = \"icon\";\n    icon.textContent = mode === 'spell' ? \"\\u{1F50E}\" : \"\\u{1F383}\";\n\n    const label = document.createElement(\"span\");\n    if (mode === 'match') {\n      const idx = s.toLowerCase().indexOf(query.toLowerCase());\n      const before = s.slice(0, idx);\n      const match = s.slice(idx, idx + query.length);\n      const after = s.slice(idx + query.length);\n      label.appendChild(document.createTextNode(before));\n      const markEl = document.createElement(\"mark\");\n      markEl.textContent = match;\n      label.appendChild(markEl);\n      label.appendChild(document.createTextNode(after));\n    } else {\n      label.textContent = s;\n    }\n\n    li.appendChild(icon);\n    li.appendChild(label);\n    li.addEventListener(\"mousedown\", (e) => {\n      e.preventDefault();\n      input.value = s;\n      suggestList.classList.remove('active');\n      form.requestSubmit();\n    });\n    suggestList.appendChild(li);\n  });\n\n  suggestList.classList.add('active');\n}\n\nlet highlightedIndex = -1;\nfunction updateHighlight(items) {\n  items.forEach((item, i) => item.classList.toggle('highlighted', i === highlightedIndex));\n  if (highlightedIndex >= 0 && items[highlightedIndex]) {\n    items[highlightedIndex].scrollIntoView({ block: 'nearest' });\n  }\n}\n\ninput.addEventListener('input', () => {\n  highlightedIndex = -1;\n  const query = input.value.trim();\n  if (!query) { suggestList.classList.remove('active'); return; }\n  renderSuggestions(query);\n});\n\ninput.addEventListener('keydown', (e) => {\n  const items = Array.from(suggestList.querySelectorAll('.suggest-item'));\n  if (!items.length || !suggestList.classList.contains('active')) return;\n  if (e.key === 'ArrowDown') {\n    e.preventDefault();\n    highlightedIndex = (highlightedIndex + 1) % items.length;\n    updateHighlight(items);\n  } else if (e.key === 'ArrowUp') {\n    e.preventDefault();\n    highlightedIndex = (highlightedIndex - 1 + items.length) % items.length;\n    updateHighlight(items);\n  } else if (e.key === 'Enter') {\n    if (highlightedIndex >= 0) {\n      e.preventDefault();\n      items[highlightedIndex].dispatchEvent(new Event('mousedown'));\n    }\n  } else if (e.key === 'Escape') {\n    suggestList.classList.remove('active');\n  }\n});\n\ndocument.addEventListener('click', (e) => {\n  if (!suggestList.contains(e.target) && e.target !== input) {\n    suggestList.classList.remove('active');\n  }\n});\n\n\/* ==================== Page 2: slider-based color builder ==================== *\/\nfunction hslToHex(h, s, l) {\n  s \/= 100; l \/= 100;\n  const k = n => (n + h \/ 30) % 12;\n  const a = s * Math.min(l, 1 - l);\n  const f = n => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));\n  const toHex = x => Math.round(255 * x).toString(16).padStart(2, '0');\n  return `#${toHex(f(0))}${toHex(f(8))}${toHex(f(4))}`;\n}\n\nconst PARTS = [\n  { key: \"headwear\", label: \"Headwear\", frameId: \"frameHeadwear\", colorOverlayId: \"overlayColorHeadwear\", overlayId: \"overlayHeadwear\", defaultHue: 220 },\n  { key: \"top\", label: \"Top\", frameId: \"frameTop\", colorOverlayId: \"overlayColorTop\", overlayId: \"overlayTop\", defaultHue: 260 },\n  { key: \"bottom\", label: \"Bottom\", frameId: \"frameBottom\", colorOverlayId: \"overlayColorBottom\", overlayId: \"overlayBottom\", defaultHue: 0 },\n  { key: \"footwear\", label: \"Footwear\", frameId: \"frameFootwear\", colorOverlayId: \"overlayColorFootwear\", overlayId: \"overlayFootwear\", defaultHue: 40 }\n];\n\nconst slidersBox = document.getElementById('slidersBox');\nconst chosenHues = {};\nconst chosenLightness = {};\nconst inactiveParts = new Set();\n\nfunction applyColor(part, hue, lightness) {\n  chosenHues[part.key] = hue;\n  chosenLightness[part.key] = lightness;\n\n  const colorOverlay = document.getElementById(part.colorOverlayId);\n\n  if (colorOverlay) {\n    colorOverlay.style.backgroundColor =\n      `hsl(${hue}, 70%, ${lightness}%)`;\n  }\n}\n\nfunction setPartActive(part, active, els) {\n  const { row, picker, naBtn } = els;\n  const frame = document.getElementById(part.frameId);\n  const overlay = document.getElementById(part.overlayId);\n\n  if (active) {\n    inactiveParts.delete(part.key);\n\n    row.classList.remove('is-na');\n    picker.classList.remove('is-disabled');\n\n    naBtn.classList.remove('active');\n    naBtn.textContent = 'N\/A';\n\n    if (frame) frame.classList.remove('is-na');\n    if (overlay) overlay.classList.remove('active');\n\n  } else {\n    inactiveParts.add(part.key);\n\n    row.classList.add('is-na');\n    picker.classList.add('is-disabled');\n\n    naBtn.classList.add('active');\n    naBtn.textContent = 'N\/A \u2713';\n\n    if (frame) frame.classList.add('is-na');\n    if (overlay) overlay.classList.add('active');\n  }\n}\n\nfunction buildSliders() {\n  slidersBox.innerHTML = \"\";\n  inactiveParts.clear();\n\n  PARTS.forEach(part => {\n    const defaultLightness = 50;\n\n    chosenHues[part.key] = part.defaultHue;\n    chosenLightness[part.key] = defaultLightness;\n\n    applyColor(\n      part,\n      part.defaultHue,\n      defaultLightness\n    );\n\n    const row = document.createElement('div');\n    row.className = 'slider-row';\n\n    \/* ---------- Header ---------- *\/\n\n    const head = document.createElement('div');\n    head.className = 'slider-head';\n\n    const label = document.createElement('span');\n    label.className = 'slider-label';\n    label.textContent = part.label;\n\n    const valueBox = document.createElement('span');\n    valueBox.className = 'slider-value';\n\n    const swatch = document.createElement('span');\n    swatch.className = 'slider-swatch';\n\n    swatch.style.background =\n      `hsl(${part.defaultHue}, 70%, ${defaultLightness}%)`;\n\n    const hexLabel = document.createElement('span');\n\n    hexLabel.textContent =\n      hslToHex(\n        part.defaultHue,\n        70,\n        defaultLightness\n      );\n\n    const naBtn = document.createElement('button');\n    naBtn.type = 'button';\n    naBtn.className = 'na-btn';\n    naBtn.textContent = 'N\/A';\n\n    valueBox.appendChild(swatch);\n    valueBox.appendChild(hexLabel);\n    valueBox.appendChild(naBtn);\n\n    head.appendChild(label);\n    head.appendChild(valueBox);\n\n    \/* ---------- 2D color picker ---------- *\/\n\n    const picker = document.createElement('div');\n    picker.className = 'color-picker';\n\n    const handle = document.createElement('div');\n    handle.className = 'color-picker-handle';\n\n    picker.appendChild(handle);\n\n    \/* Initial handle position *\/\n\n    handle.style.left =\n      `${(part.defaultHue \/ 360) * 100}%`;\n\n    handle.style.top =\n      `${100 - defaultLightness}%`;\n\n    const labels = document.createElement('div');\n    labels.className = 'color-picker-labels';\n\n    const lightLabel = document.createElement('span');\n    lightLabel.textContent = 'White \u2191';\n\n    const darkLabel = document.createElement('span');\n    darkLabel.textContent = '\u2193 Black';\n\n    labels.appendChild(lightLabel);\n    labels.appendChild(darkLabel);\n\n    \/* ---------- Picker movement ---------- *\/\n\n    function updatePicker(clientX, clientY) {\n      const rect = picker.getBoundingClientRect();\n\n      let x = clientX - rect.left;\n      let y = clientY - rect.top;\n\n      x = Math.max(0, Math.min(rect.width, x));\n      y = Math.max(0, Math.min(rect.height, y));\n\n      const xPercent = x \/ rect.width;\n      const yPercent = y \/ rect.height;\n\n      const hue = Math.round(xPercent * 360);\n\n      const lightness = Math.round(\n        100 - (yPercent * 100)\n      );\n\n      applyColor(\n        part,\n        hue,\n        lightness\n      );\n\n      handle.style.left =\n        `${xPercent * 100}%`;\n\n      handle.style.top =\n        `${yPercent * 100}%`;\n\n      swatch.style.background =\n        `hsl(${hue}, 70%, ${lightness}%)`;\n\n      hexLabel.textContent =\n        hslToHex(\n          hue,\n          70,\n          lightness\n        );\n    }\n\n    let dragging = false;\n\n    picker.addEventListener('pointerdown', (e) => {\n      dragging = true;\n\n      picker.setPointerCapture(e.pointerId);\n\n      updatePicker(\n        e.clientX,\n        e.clientY\n      );\n    });\n\n    picker.addEventListener('pointermove', (e) => {\n      if (!dragging) return;\n\n      updatePicker(\n        e.clientX,\n        e.clientY\n      );\n    });\n\n    picker.addEventListener('pointerup', () => {\n      dragging = false;\n    });\n\n    picker.addEventListener('pointercancel', () => {\n      dragging = false;\n    });\n\n    \/* ---------- N\/A ---------- *\/\n\n    const els = {\n      row,\n      picker,\n      naBtn\n    };\n\n    naBtn.addEventListener('click', () => {\n      setPartActive(\n        part,\n        inactiveParts.has(part.key),\n        els\n      );\n    });\n\n    \/* ---------- Assemble ---------- *\/\n\n    row.appendChild(head);\n    row.appendChild(picker);\n    \n    slidersBox.appendChild(row);\n  });\n}\n\nfunction goToBuilder(query) {\n  costumeTitle.textContent = query;\n  buildSliders();\n  page1.classList.remove('active');\n  page2.classList.add('active');\n}\n\nform.addEventListener('submit', (e) => {\n  e.preventDefault();\n  const query = input.value.trim();\n  if (!query) return;\n  suggestList.classList.remove('active');\n  goToBuilder(query);\n});\n\nbackBtn.addEventListener('click', () => {\n  page2.classList.remove('active');\n  page1.classList.add('active');\n});\n\n\/* ==================== Page 3: VisionPros contact lens matching ==================== *\/\nconst HALLOWEEN_CATEGORY_URL = \"https:\/\/www.visionpros.com\/contact-lenses\/pure-colors-hd-halloween-edition\/\";\nconst NATURAL_CATEGORY_URL = \"https:\/\/www.visionpros.com\/contact-lenses\/pure-colors-hd\/\";\n\nconst HALLOWEEN_LENSES = [\n  { name: \"White Out\", hex: \"#f2f2ef\", desc: \"A fully opaque, all-white lens that erases your natural eye color for a hollow, undead stare.\", keywords: [\"zombie\",\"ghost\",\"corpse\",\"possessed\",\"exorcist\",\"mummy\",\"skeleton\",\"banshee\",\"dead\",\"undead\",\"phantom\"] },\n  { name: \"Black Out\", hex: \"#1a1a1a\", desc: \"Covers the entire eye in solid black for a demonic, void-eyed look with no visible white or iris.\", keywords: [\"demon\",\"devil\",\"possessed\",\"shadow\",\"void\",\"dark\",\"grim reaper\",\"plague doctor\",\"witch\",\"alien\",\"evil\"] },\n  { name: \"Psycho\", hex: \"#e8dede\", desc: \"A cracked, bloodshot white design built for an unhinged, horror-movie killer stare.\", keywords: [\"clown\",\"killer\",\"psycho\",\"horror\",\"chaos\",\"joker\",\"serial killer\",\"asylum\"] },\n  { name: \"Spider Web\", hex: \"#e9e6df\", desc: \"A web pattern radiating across the iris \u2014 an easy way to sell a creepy, crawly costume.\", keywords: [\"spider\",\"web\",\"witch\",\"halloween\",\"arachnid\",\"creepy\"] },\n  { name: \"Yellow Wolf\", hex: \"#e0b23a\", desc: \"A vertical-pupil, amber-yellow lens built for a feral, werewolf stare.\", keywords: [\"wolf\",\"werewolf\",\"beast\",\"monster\",\"feral\"] },\n  { name: \"White Cat\", hex: \"#eef0e8\", desc: \"A pale, vertical-pupil cat-eye lens for a ghostly or albino feline look.\", keywords: [\"cat\",\"white cat\",\"kitten\",\"feline\"] },\n  { name: \"Yellow Cat\", hex: \"#d9b23c\", desc: \"A vertical-pupil amber cat-eye lens for a sharper, predator feline look.\", keywords: [\"cat\",\"black cat\",\"fox\",\"feline\",\"predator\"] },\n  { name: \"Devil\", hex: \"#8a0f0f\", desc: \"A deep blood-red lens for a classic devil, demon, or vampire stare.\", keywords: [\"devil\",\"demon\",\"vampire\",\"horror\",\"hell\",\"satan\"] },\n  { name: \"Hot Red\", hex: \"#c11414\", desc: \"A vivid, saturated red lens \u2014 one of the most requested Halloween colors for vampire and horror looks.\", keywords: [\"vampire\",\"devil\",\"horror\",\"red\",\"dracula\"] }\n];\n\nconst NATURAL_LENSES = [\n  { name: \"Amethyst\", hex: \"#8a5fc7\", desc: \"A rich violet tone that reads as fantasy or magic rather than horror.\", keywords: [\"witch\",\"sorceress\",\"fairy\",\"mystic\",\"galaxy\",\"magic\"] },\n  { name: \"Emerald Green\", hex: \"#1f7a4c\", desc: \"A saturated green for witch, elf, or nature-themed costumes without any FX effect.\", keywords: [\"witch\",\"elf\",\"mermaid\",\"dragon\",\"envy\",\"nature\",\"goblin\"] },\n  { name: \"Ocean Blue\", hex: \"#1f6f9c\", desc: \"A deep aqua-blue that pairs naturally with water or ice-themed costumes.\", keywords: [\"mermaid\",\"water\",\"ice queen\",\"elsa\",\"ocean\",\"siren\"] },\n  { name: \"Sapphire Blue\", hex: \"#2b4fa0\", desc: \"A vivid, jewel-toned blue for angelic or regal costumes.\", keywords: [\"angel\",\"ice queen\",\"fairy\",\"royal\",\"queen\",\"princess\"] },\n  { name: \"Sky Blue\", hex: \"#7ec6e6\", desc: \"A light, airy blue suited to soft, ethereal costumes.\", keywords: [\"angel\",\"fairy\",\"cloud\",\"ethereal\",\"ghostly\"] },\n  { name: \"Turquoise\", hex: \"#2fb5a0\", desc: \"A bright teal that reads as mystical or aquatic without full FX intensity.\", keywords: [\"mermaid\",\"fairy\",\"peacock\",\"siren\",\"aquatic\"] },\n  { name: \"Vivid Green\", hex: \"#57c23a\", desc: \"A saturated, slightly unnatural green suited to alien or witchy looks.\", keywords: [\"alien\",\"witch\",\"elf\",\"toxic\",\"poison ivy\",\"zombie\"] },\n  { name: \"Jade\", hex: \"#3f9e77\", desc: \"A muted green-blue for elf, mermaid, or nature-spirit costumes.\", keywords: [\"elf\",\"mermaid\",\"witch\",\"nature\",\"forest\"] },\n  { name: \"Honey\", hex: \"#c58a3a\", desc: \"A warm amber-brown for a natural but slightly enhanced look.\", keywords: [\"cowboy\",\"pirate\",\"wizard\",\"werewolf\",\"natural\"] },\n  { name: \"Hazel\", hex: \"#a97c4f\", desc: \"A warm, natural hazel tone for a subtly brighter, defined eye look.\", keywords: [\"cowgirl\",\"doctor\",\"nurse\",\"natural\",\"everyday\"] },\n  { name: \"Chestnut Brown\", hex: \"#6b4226\", desc: \"A natural warm brown for costumes that don't call for a dramatic eye change.\", keywords: [\"pirate\",\"cowboy\",\"wizard\",\"natural\"] },\n  { name: \"Grey\", hex: \"#9a9a9a\", desc: \"A cool, pale grey that reads as otherworldly or lifeless without full opaque coverage.\", keywords: [\"ghost\",\"zombie\",\"robot\",\"elder\",\"alien\",\"statue\"] }\n];\n\nconst ALL_LENSES = [\n  ...HALLOWEEN_LENSES.map(l => ({ ...l, line: \"Pure Colors HD \u2014 Costume Halloween Edition\", url: HALLOWEEN_CATEGORY_URL })),\n  ...NATURAL_LENSES.map(l => ({ ...l, line: \"Pure Colors HD\", url: NATURAL_CATEGORY_URL }))\n];\n\nfunction hexToRgb(hex) {\n  const h = hex.replace('#', '');\n  return {\n    r: parseInt(h.substring(0, 2), 16),\n    g: parseInt(h.substring(2, 4), 16),\n    b: parseInt(h.substring(4, 6), 16)\n  };\n}\nfunction colorDistance(hexA, hexB) {\n  const a = hexToRgb(hexA), b = hexToRgb(hexB);\n  return Math.sqrt((a.r - b.r) ** 2 + (a.g - b.g) ** 2 + (a.b - b.b) ** 2);\n}\n\nfunction recommendLenses(costumeName, hues) {\n  const nameLower = costumeName.toLowerCase();\n  const activeParts = PARTS.filter(p => !inactiveParts.has(p.key));\n  const relevantParts = activeParts.length > 0 ? activeParts : PARTS; \/\/ fallback if everything is N\/A\n  const outfitHexes = relevantParts.map(\n  p => hslToHex(\n    hues[p.key],\n    70,\n    chosenLightness[p.key] ?? 50\n  )\n);\n\n  const scored = ALL_LENSES.map(lens => {\n    let score = 0;\n    lens.keywords.forEach(kw => {\n      if (nameLower.includes(kw)) score += 10;\n    });\n    const avgDist = outfitHexes.reduce((sum, hex) => sum + colorDistance(lens.hex, hex), 0) \/ outfitHexes.length;\n    score += Math.max(0, 15 - avgDist \/ 20);\n    return { ...lens, score };\n  });\n\n  scored.sort((a, b) => b.score - a.score);\n\n  let picks = scored.slice(0, 3);\n  const hasHalloween = picks.some(p => p.line.includes('Halloween'));\n  const hasNatural = picks.some(p => p.line === 'Pure Colors HD');\n  if (!hasNatural) {\n    const bestNatural = scored.find(p => p.line === 'Pure Colors HD');\n    if (bestNatural) picks[picks.length - 1] = bestNatural;\n  } else if (!hasHalloween) {\n    const bestHalloween = scored.find(p => p.line.includes('Halloween'));\n    if (bestHalloween) picks[picks.length - 1] = bestHalloween;\n  }\n  return picks;\n}\n\nfunction buildLensPage() {\n  const lensIntro = document.getElementById('lensIntro');\n  const lensCards = document.getElementById('lensCards');\n  const heading = document.getElementById('lensHeading');\n\n  heading.textContent = \"Contact lenses for your: \" + costumeTitle.textContent;\n  lensIntro.innerHTML = `Based on <strong>${costumeTitle.textContent}<\/strong> and the outfit colors you picked, here are the top 3 contact lenses from VisionPros' colored &amp; costume lens lineup that we would recommend.`;\n\n  const picks = recommendLenses(costumeTitle.textContent, chosenHues);\n\n  lensCards.innerHTML = \"\";\n  picks.forEach(lens => {\n    const card = document.createElement('div');\n    card.className = 'lens-card';\n\n    const swatch = document.createElement('div');\n    swatch.className = 'lens-swatch';\n    swatch.style.background = lens.hex;\n\n    const body = document.createElement('div');\n    body.className = 'lens-body';\n\n    const line = document.createElement('p');\n    line.className = 'lens-line';\n    line.textContent = lens.line;\n\n    const name = document.createElement('p');\n    name.className = 'lens-name';\n    name.textContent = lens.name;\n\n    const desc = document.createElement('p');\n    desc.className = 'lens-desc';\n    desc.textContent = lens.desc;\n\n    const link = document.createElement('a');\n    link.className = 'lens-link';\n    link.href = lens.url;\n    link.target = '_blank';\n    link.rel = 'noopener noreferrer';\n    link.textContent = \"View on VisionPros \u2192\";\n\n    body.appendChild(line);\n    body.appendChild(name);\n    body.appendChild(desc);\n    body.appendChild(link);\n\n    card.appendChild(swatch);\n    card.appendChild(body);\n    lensCards.appendChild(card);\n  });\n}\n\ndoneBtn.addEventListener('click', () => {\n  buildLensPage();\n  page2.classList.remove('active');\n  page3.classList.add('active');\n});\n\nbackBtn2.addEventListener('click', () => {\n  page3.classList.remove('active');\n  page2.classList.add('active');\n});\n<\/script><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>VisionPros Halloween Costume + Lens Finder Who are you going to be this Halloween? Type a character, theme, or vibe. We&#8217;ll suggest matches as you go. If it looks misspelled, we&#8217;ll offer the closest costume ideas we know. Next Try a character, a pun, a group theme, or just a mood. Costume \u00d7 \u00d7 \u00d7 [&hellip;]<\/p>\n","protected":false},"author":15,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"_themeisle_gutenberg_block_has_review":false,"footnotes":""},"categories":[398],"tags":[],"semantictags":[],"class_list":["post-7152","post","type-post","status-publish","format-standard","hentry","category-cosplay"],"_links":{"self":[{"href":"https:\/\/www.visionpros.com\/pro\/wp-json\/wp\/v2\/posts\/7152","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.visionpros.com\/pro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.visionpros.com\/pro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.visionpros.com\/pro\/wp-json\/wp\/v2\/users\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/www.visionpros.com\/pro\/wp-json\/wp\/v2\/comments?post=7152"}],"version-history":[{"count":81,"href":"https:\/\/www.visionpros.com\/pro\/wp-json\/wp\/v2\/posts\/7152\/revisions"}],"predecessor-version":[{"id":7344,"href":"https:\/\/www.visionpros.com\/pro\/wp-json\/wp\/v2\/posts\/7152\/revisions\/7344"}],"wp:attachment":[{"href":"https:\/\/www.visionpros.com\/pro\/wp-json\/wp\/v2\/media?parent=7152"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.visionpros.com\/pro\/wp-json\/wp\/v2\/categories?post=7152"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.visionpros.com\/pro\/wp-json\/wp\/v2\/tags?post=7152"},{"taxonomy":"semantictags","embeddable":true,"href":"https:\/\/www.visionpros.com\/pro\/wp-json\/wp\/v2\/semantictags?post=7152"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}