<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-Content-Type-Options" content="nosniff"/>
<meta http-equiv="X-Frame-Options" content="SAMEORIGIN"/>
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://fonts.googleapis.com https://static.cloudflareinsights.com blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data: https://images.unsplash.com https://elova.life; media-src https://cdn.coverr.co; connect-src 'self' https://www.google-analytics.com https://*.workers.dev https://cloudflareinsights.com; upgrade-insecure-requests"/>
<meta http-equiv="Referrer-Policy" content="strict-origin-when-cross-origin"/>
<meta name="format-detection" content="telephone=no,date=no,email=no,address=no"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<meta name="robots" content="index, follow"/>
<!-- AIO: Allow AI crawlers to index and cite this page -->
<meta name="googlebot" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1"/>
<meta name="bingbot" content="index, follow"/>
<!-- AI agent discovery files: /llms.txt and /.well-known/ai-plugin.json -->
<link rel="ai-plugin" href="/.well-known/ai-plugin.json"/>
<link rel="llms-txt" href="/llms.txt" type="text/plain"/>
<meta name="description" content="Elova is your independent wellness buyer — researching 200+ supplements with zero paid placements. Get personalized picks for sleep, gut health, stress, energy, longevity, beauty and weight. No ads, no sponsored content."/>
<meta name="keywords" content="wellness buyer, supplement research, independent supplement reviews, sleep supplements, gut health, stress relief supplements, energy supplements, longevity supplements, skin supplements, weight management supplements, elova life, best supplements"/>
<meta name="author" content="Elova.Life"/>
<!-- GEO: English-speaking global audience; US primary market -->
<meta name="geo.region" content="US"/>
<meta name="geo.placename" content="United States"/>
<link rel="alternate" hreflang="en"    href="https://elova.life/"/>
<link rel="alternate" hreflang="en-us" href="https://elova.life/"/>
<link rel="alternate" hreflang="en-gb" href="https://elova.life/"/>
<link rel="alternate" hreflang="en-ca" href="https://elova.life/"/>
<link rel="alternate" hreflang="en-au" href="https://elova.life/"/>
<link rel="alternate" hreflang="x-default" href="https://elova.life/"/>
<link rel="canonical" href="https://elova.life/"/>
<meta property="og:type" content="website"/>
<meta property="og:locale" content="en_US"/>
<meta property="og:url" content="https://elova.life/"/>
<meta property="og:title" content="Elova.Life — Your Personal Wellness Buyer"/>
<meta property="og:description" content="Independent supplement research with zero paid placements. Get your personalized wellness picks in 3 steps."/>
<meta property="og:image" content="https://elova.life/og-image.jpg"/>
<meta property="og:image:width" content="1200"/>
<meta property="og:image:height" content="630"/>
<meta property="og:image:alt" content="Elova.Life — Independent Wellness Buyer"/>
<meta property="og:site_name" content="Elova.Life"/>
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:site" content="@elovalife"/>
<meta name="twitter:title" content="Elova.Life — Your Personal Wellness Buyer"/>
<meta name="twitter:description" content="Independent supplement research with zero paid placements. Get your personalized wellness picks in 3 steps."/>
<meta name="twitter:image" content="https://elova.life/og-image.jpg"/>
<meta name="twitter:image:alt" content="Elova.Life — Independent Wellness Buyer"/>
<meta name="twitter:creator" content="@elovalife"/>
<meta name="theme-color" content="#34D05C"/>
<meta name="mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-title" content="Elova.Life"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
<link rel="manifest" href="/manifest.json"/>
<!-- Favicon — inline SVG leaf -->
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%2334D05C'/%3E%3Ctext x='50%25' y='54%25' dominant-baseline='middle' text-anchor='middle' font-family='system-ui,sans-serif' font-weight='900' font-size='20' fill='white'%3EE%3C/text%3E%3C/svg%3E"/>
<link rel="apple-touch-icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 180'%3E%3Crect width='180' height='180' rx='40' fill='%2334D05C'/%3E%3Ctext x='50%25' y='54%25' dominant-baseline='middle' text-anchor='middle' font-family='system-ui,sans-serif' font-weight='900' font-size='110' fill='white'%3EE%3C/text%3E%3C/svg%3E"/>
<!-- JSON-LD: single @graph — all schemas merged (faster SEO/AIO crawler parsing) -->
<script type="application/ld+json">
{"@context":"https://schema.org","@graph":[
  {"@type":"WebSite","@id":"https://elova.life/#website","name":"Elova.Life","url":"https://elova.life/","description":"Independent supplement research with zero paid placements. Your personal wellness buyer.","potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://elova.life/?q={search_term_string}"},"query-input":"required name=search_term_string"}},
  {"@type":"Organization","@id":"https://elova.life/#org","name":"Elova.Life","url":"https://elova.life/","logo":"https://elova.life/og-image.jpg","sameAs":["https://twitter.com/elovalife"],"description":"Independent wellness research and buying guide platform with a strict no-paid-placement policy."},
  {"@type":"WebPage","@id":"https://elova.life/#webpage","name":"Elova.Life — Your Personal Wellness Buyer","url":"https://elova.life/","description":"Independent supplement research with zero paid placements. Personalized wellness picks for sleep, gut health, stress, energy, longevity and more.","inLanguage":"en","isPartOf":{"@id":"https://elova.life/#website"},"speakable":{"@type":"SpeakableSpecification","cssSelector":[".diff-title",".diff-text",".chat-bbl.b",".art-hl"]}},
  {"@type":"FAQPage","mainEntity":[
    {"@type":"Question","name":"How does Elova pick supplement recommendations?","acceptedAnswer":{"@type":"Answer","text":"Elova uses a zero-paid-placement policy. Every recommendation is based on peer-reviewed clinical evidence, independent third-party testing, real dosage analysis, and aggregated 90-day user feedback. No brand can pay to appear in or be elevated within our rankings."}},
    {"@type":"Question","name":"What is the best sleep supplement?","acceptedAnswer":{"@type":"Answer","text":"Based on clinical evidence, Magnesium Bisglycinate (200–400mg before bed) and Glycine (1–3g before bed) are the most well-supported non-habit-forming sleep supplements. They improve deep sleep quality without creating the melatonin dependency common with standard OTC products."}},
    {"@type":"Question","name":"Are Elova's supplement links affiliate links?","acceptedAnswer":{"@type":"Answer","text":"Some product links on Elova.Life are affiliate links. If you purchase through these links, Elova.Life may earn a small commission at no extra cost to you. This never influences rankings, scores, or editorial independence."}},
    {"@type":"Question","name":"How do I find the right supplement for my needs?","acceptedAnswer":{"@type":"Answer","text":"Use Elova's 3-step finder: select your wellness category (sleep, gut, stress, energy, longevity, etc.), describe your specific concern, then receive a ranked list of the top 3 supplements for your situation — each with clinical evidence, dosage, and a buyer score."}},
    {"@type":"Question","name":"What is an Elova Score?","acceptedAnswer":{"@type":"Answer","text":"The Elova Score (0–100) is a composite metric calculated from formulation depth, ingredient bioavailability, clinical dosage accuracy, third-party testing status, global sales data, and aggregated real user feedback over 90+ days."}}
  ]},
  {"@type":"ItemList","name":"Wellness Supplement Categories","url":"https://elova.life/","numberOfItems":10,"itemListElement":[
    {"@type":"ListItem","position":1,"name":"Sleep & Rest Supplements","url":"https://elova.life/?q=sleep"},
    {"@type":"ListItem","position":2,"name":"Gut Health & Probiotics","url":"https://elova.life/?q=gut"},
    {"@type":"ListItem","position":3,"name":"Stress & Anxiety Supplements","url":"https://elova.life/?q=stress"},
    {"@type":"ListItem","position":4,"name":"Focus & Energy Supplements","url":"https://elova.life/?q=energy"},
    {"@type":"ListItem","position":5,"name":"Longevity & Aging Supplements","url":"https://elova.life/?q=longevity"},
    {"@type":"ListItem","position":6,"name":"Immune Support Supplements","url":"https://elova.life/?q=immunity"},
    {"@type":"ListItem","position":7,"name":"Weight & Metabolic Support","url":"https://elova.life/?q=weight"},
    {"@type":"ListItem","position":8,"name":"Muscle & Recovery Supplements","url":"https://elova.life/?q=recovery"},
    {"@type":"ListItem","position":9,"name":"Skin & Collagen Supplements","url":"https://elova.life/?q=skin"},
    {"@type":"ListItem","position":10,"name":"Mood & Memory Supplements","url":"https://elova.life/?q=mood"}
  ]}
]}
</script>
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin/>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
<link rel="dns-prefetch" href="https://images.unsplash.com"/>
<link rel="dns-prefetch" href="https://cdn.coverr.co"/>
<!-- Font: non-blocking, display=swap prevents FOIT, subset to latin only -->
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;900&display=swap&subset=latin" onload="this.onload=null;this.rel='stylesheet'" fetchpriority="low"/>
<noscript><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;900&display=swap&subset=latin" rel="stylesheet"/></noscript>
<!-- Inline critical font fallback so text is visible immediately -->
<style>:root{--font-stack:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',system-ui,sans-serif}*{font-family:var(--font-stack)}</style>
<title>Elova.Life — Your Personal Wellness Buyer</title>
<style>
/* ══ FRONTEND CSS ══ */

*{margin:0;padding:0;box-sizing:border-box;}
.skip-link{position:absolute;top:-40px;left:0;background:#34D05C;color:white;padding:8px 16px;border-radius:0 0 8px 0;font-weight:700;font-size:13px;z-index:9999;transition:top 0.2s;}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}
.skip-link:focus{top:0;}
html{scroll-behavior:smooth;}
body{font-family:'Inter',sans-serif;background:#F8FAF8;color:#6B7280;min-height:100vh;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}
img,video{width:100%;height:100%;object-fit:cover;display:block;}
::selection{background:#34D05C;color:#fff;}
:focus-visible{outline:2px solid #34D05C;outline-offset:2px;}
::-webkit-scrollbar{width:4px;}
::-webkit-scrollbar-thumb{background:rgba(52,208,92,0.25);border-radius:999px;}

/* ══ NAVBAR ══ */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:200;
  display:flex;align-items:center;justify-content:space-between;
  padding:0 48px;height:64px;
  background:rgba(248,250,248,0.94);
  backdrop-filter:blur(20px);
  -webkit-backdrop-filter:blur(20px);
  border-bottom:1px solid rgba(52,208,92,0.08);
}
@supports not (backdrop-filter:blur(1px)){
  .nav{background:rgba(248,250,248,0.98);}
}
@media(prefers-reduced-motion:reduce){
  .nav{backdrop-filter:none;-webkit-backdrop-filter:none;background:rgba(248,250,248,0.98);}
}
.nav-logo{font-size:22px;font-weight:900;letter-spacing:-1.5px;display:flex;align-items:center;text-decoration:none;}
.nav-logo .dark{color:#3D5040;}
.nav-logo .green{color:#34D05C;}
.nav-logo .bounce{display:inline-block;animation:lifeBounce 1.8s cubic-bezier(.4,0,.2,1) infinite;transform-origin:center bottom;}
@keyframes lifeBounce{0%{transform:translateY(0);}12%{transform:translateY(-4px);}24%{transform:translateY(0);}36%{transform:translateY(-2px);}48%,100%{transform:translateY(0);}}

/* Subscribe bar — 1/3 screen width */
.nav-sub{display:flex;align-items:center;gap:8px;}
.nav-sub input{
  width:min(24vw,280px);height:40px;padding:0 16px;
  border-radius:999px;border:1.5px solid rgba(52,208,92,0.22);
  background:rgba(255,255,255,0.95);
  font-size:13px;font-family:'Inter',sans-serif;color:#3D5040;
  outline:none;transition:0.25s;
}
.nav-sub input::placeholder{color:#B8C4BA;}
.nav-sub input:focus{border-color:rgba(52,208,92,0.50);box-shadow:0 0 0 3px rgba(52,208,92,0.08);}
.nav-sub button{
  height:40px;padding:0 20px;border:none;border-radius:999px;
  background:#34D05C;color:white;font-size:12.5px;font-weight:700;
  font-family:'Inter',sans-serif;cursor:pointer;transition:0.25s;
  white-space:nowrap;box-shadow:0 4px 14px rgba(52,208,92,0.24);
}
.nav-sub button:hover{transform:translateY(-1px);box-shadow:0 8px 20px rgba(52,208,92,0.32);}

/* ══ PAGES ══ */
.page{display:none;}
.page.active{display:block;}
#page1.active{display:flex;}
#page2.active{display:flex;}
#page3.active{display:flex;}

/* ══ PAGE 1 ══ */
#page1{
  min-height:100vh;
  min-height:100dvh;
  display:none;
  flex-direction:column;
  padding:64px 28px 20px;
}
.p1-grid{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:14px;
  flex:1;
  align-items:stretch;
}
.p1-left{display:flex;flex-direction:column;gap:12px;}
.intro-card{
  background:linear-gradient(140deg,#141F16 0%,#0A130D 100%);
  border-radius:20px;padding:26px 24px 24px;
  position:relative;overflow:hidden;flex:1;
  display:flex;flex-direction:column;
  justify-content:center;align-items:center;text-align:center;
}
.intro-card::before{content:'';position:absolute;top:-50px;right:-50px;width:180px;height:180px;border-radius:50%;background:radial-gradient(circle,rgba(52,208,92,0.14),transparent 65%);}
.intro-live{font-size:10px;font-weight:800;letter-spacing:2px;text-transform:uppercase;color:rgba(52,208,92,0.70);margin-bottom:10px;display:flex;align-items:center;justify-content:center;gap:6px;position:relative;}
.intro-live-dot{width:5px;height:5px;border-radius:50%;background:#34D05C;animation:pulse 2s infinite;flex-shrink:0;will-change:transform,opacity;}
.intro-name{font-size:clamp(18px,2.2vw,26px);font-weight:800;letter-spacing:-1.2px;line-height:1.15;color:white;margin-bottom:0;position:relative;min-height:34px;}
.intro-name em{color:#34D05C;font-style:normal;}
.intro-typed{display:inline;}
.intro-cursor{display:inline-block;width:2px;height:1em;background:#34D05C;margin-left:2px;vertical-align:middle;animation:cursorBlink 0.8s ease infinite;will-change:opacity;}
@keyframes cursorBlink{0%,100%{opacity:1;}50%{opacity:0;}}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1);}50%{opacity:0.4;transform:scale(1.4);}}
.intro-bio{font-size:12px;color:rgba(255,255,255,0.78);line-height:1.7;position:relative;max-width:380px;}
.intro-stats{display:grid;grid-template-columns:repeat(4,1fr);padding-top:14px;margin-top:14px;border-top:1px solid rgba(255,255,255,0.07);position:relative;gap:2px;}
.is-val{font-size:15px;font-weight:800;color:#34D05C;letter-spacing:-0.8px;line-height:1;}
.is-key{font-size:10px;color:rgba(255,255,255,0.60);margin-top:2px;line-height:1.3;}
.diff-card{
  background:rgba(255,255,255,0.90);backdrop-filter:blur(20px);
  border-radius:20px;padding:16px 18px;
  border:1px solid rgba(52,208,92,0.10);
  flex-shrink:0;
}
.diff-title{font-size:12px;font-weight:800;color:#2D3D30;margin-bottom:10px;letter-spacing:-0.2px;}
.diff-list{display:flex;flex-direction:column;gap:0;}
.diff-row{display:flex;align-items:center;gap:10px;padding:7px 0;border-bottom:1px solid #F4F6F2;}
.diff-row:last-child{border-bottom:none;}
.diff-icon{width:24px;height:24px;border-radius:7px;background:#F2FFF5;display:flex;align-items:center;justify-content:center;font-size:12px;flex-shrink:0;}
.diff-text{font-size:11.5px;color:#5A7060;line-height:1.4;}
.diff-text strong{color:#2D3D30;font-weight:700;}
.p1-right{display:flex;flex-direction:column;gap:12px;}
.chat-card{
  background:rgba(255,255,255,0.90);backdrop-filter:blur(20px);
  border-radius:20px;padding:16px 16px 16px;
  border:1px solid rgba(52,208,92,0.10);
  flex:1;display:flex;flex-direction:column;gap:0;
  overflow:hidden;min-height:280px;
}
.chat-label-top{font-size:10px;font-weight:800;letter-spacing:2px;text-transform:uppercase;color:#6B7280;margin-bottom:10px;flex-shrink:0;}
.chat-messages{display:flex;flex-direction:column;gap:9px;flex:1;overflow:hidden;padding-top:8px;padding-bottom:10px;margin-top:-8px;margin-bottom:-10px;}
.chat-msg{display:flex;align-items:flex-end;gap:8px;}
.chat-msg.user{flex-direction:row-reverse;}
.chat-av{width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:12px;flex-shrink:0;}
.chat-av.b{background:linear-gradient(135deg,#34D05C,#28A04A);box-shadow:0 2px 8px rgba(52,208,92,0.25);}
.chat-av.u{background:#F0F4F0;border:1px solid #E0E8E0;}
.chat-bbl{
  padding:9px 13px;border-radius:14px;
  font-size:12px;line-height:1.6;font-weight:500;max-width:88%;
  min-height:20px;
}
.chat-bbl.b{
  background:#F2FFF5;border:1px solid rgba(52,208,92,0.14);
  color:#2D3D30;border-radius:3px 14px 14px 14px;
  transition:box-shadow 0.4s ease, transform 0.4s ease;
}
.chat-bbl.u{
  background:#F7F7F5;border:1px solid #EAEAEA;
  color:#4A5A4A;border-radius:14px 3px 14px 14px;
  transition:box-shadow 0.4s ease, transform 0.4s ease;
}
.chat-bbl.float-b{
  animation:bubbleFloatB 3.4s ease-in-out infinite;
  box-shadow:0 4px 14px rgba(52,208,92,0.12);
}
.chat-bbl.float-u{
  animation:bubbleFloatU 2.9s ease-in-out infinite;
  box-shadow:0 3px 10px rgba(0,0,0,0.06);
}
.chat-bbl.float-delay-1{animation-delay:0s;}
.chat-bbl.float-delay-2{animation-delay:0.5s;}
.chat-bbl.float-delay-3{animation-delay:0.25s;}
.chat-bbl.float-delay-4{animation-delay:0.7s;}
.chat-bbl.float-delay-5{animation-delay:0.15s;}
@keyframes bubbleFloatB{
  0%,100%{transform:translateY(0) rotate(-0.4deg);box-shadow:0 4px 14px rgba(52,208,92,0.12);}
  50%{transform:translateY(-5px) rotate(0.4deg);box-shadow:0 8px 20px rgba(52,208,92,0.18);}
}
@keyframes bubbleFloatU{
  0%,100%{transform:translateY(0) rotate(0.3deg);box-shadow:0 3px 10px rgba(0,0,0,0.06);}
  50%{transform:translateY(-4px) rotate(-0.3deg);box-shadow:0 7px 16px rgba(0,0,0,0.09);}
}
.chat-bbl strong{color:#2aaa4a;font-weight:700;}
.chat-cursor-inline{
  display:inline-block;width:1.5px;height:13px;
  background:#34D05C;margin-left:1px;vertical-align:middle;
  animation:cursorBlink 0.75s ease infinite;
}
.chat-result-btn{
  display:inline-flex;align-items:center;gap:5px;margin-top:7px;
  padding:7px 12px;border-radius:999px;
  background:#34D05C;border:none;
  font-size:11.5px;font-weight:700;color:white;cursor:pointer;transition:0.2s;
  box-shadow:0 3px 10px rgba(52,208,92,0.25);
  font-family:'Inter',sans-serif;
}
.chat-result-btn:hover{transform:translateY(-1px);box-shadow:0 5px 14px rgba(52,208,92,0.32);}
.chat-result-btn svg{width:10px;height:10px;stroke:white;stroke-width:2.5;fill:none;stroke-linecap:round;stroke-linejoin:round;}
.engine-card{
  background:rgba(255,255,255,0.90);backdrop-filter:blur(20px);
  border-radius:20px;padding:14px 16px 20px;
  border:1px solid rgba(52,208,92,0.10);
  flex-shrink:0;
}
.engine-card .step-label{font-size:11.5px;font-weight:700;color:#5A7060;margin-bottom:10px;letter-spacing:-0.1px;}
.quick-chips{display:flex;gap:8px;flex-wrap:wrap;margin-top:6px;padding:10px 2px 2px;}
.qchip{
  padding:9px 15px;border-radius:14px;
  font-size:12px;font-weight:700;
  background:linear-gradient(135deg,#fff 0%,#F4FAF5 100%);
  color:#4A7055;
  cursor:pointer;
  border:1.5px solid rgba(52,208,92,0.18);
  box-shadow:0 3px 10px rgba(52,208,92,0.10),0 1px 3px rgba(0,0,0,0.04);
  user-select:none;
  position:relative;
  transform-origin:center center;
  transition:transform 0.2s ease,box-shadow 0.2s ease,background 0.2s ease,border-color 0.2s ease;
  white-space:nowrap;
  flex-shrink:0;
  will-change:transform;
  contain:layout style;
}
/* chipFloat: single keyframe + CSS vars --cr/--cy per chip */
@keyframes chipFloat{0%,100%{transform:rotate(var(--cr,0deg)) translateY(0);}50%{transform:rotate(var(--cr,0deg)) translateY(var(--cy,-5px));}}
.qchip:nth-child(1){--cr:-2.5deg;--cy:-5px;animation:chipFloat 3.2s ease-in-out infinite;}
.qchip:nth-child(2){--cr: 1.8deg;--cy:-6px;animation:chipFloat 2.8s ease-in-out infinite;}
.qchip:nth-child(3){--cr:-1.2deg;--cy:-4px;animation:chipFloat 3.5s ease-in-out infinite;}
.qchip:nth-child(4){--cr: 2.4deg;--cy:-7px;animation:chipFloat 3.0s ease-in-out infinite;}
.qchip:nth-child(5){--cr:-1.8deg;--cy:-5px;animation:chipFloat 2.6s ease-in-out infinite;}
.qchip:nth-child(6){--cr: 1.4deg;--cy:-6px;animation:chipFloat 3.3s ease-in-out infinite;}
.qchip:hover{
  background:linear-gradient(135deg,#E8FFF0 0%,#D4FAE2 100%);
  color:#34D05C;border-color:rgba(52,208,92,0.40);
  box-shadow:0 8px 22px rgba(52,208,92,0.20),0 2px 8px rgba(0,0,0,0.06);
  animation:none;transform:rotate(0deg) translateY(-4px) scale(1.04);
}
.qchip.sel{
  background:linear-gradient(135deg,#D4FAE2 0%,#B8F5CC 100%);
  color:#2aaa4a;border-color:rgba(52,208,92,0.50);
  box-shadow:0 6px 18px rgba(52,208,92,0.22);
  animation:chipSelected 2.4s ease-in-out infinite;
  transform:rotate(0deg) scale(1.03);
}
@keyframes chipSelected{
  0%,100%{transform:scale(1.03) translateY(0);}
  50%{transform:scale(1.03) translateY(-3px);}
}
.engine-card .sbar{
  display:flex;border-radius:14px;
  border:1.5px solid rgba(52,208,92,0.20);
  background:rgba(255,255,255,0.95);
  transition:0.25s;position:relative;overflow:visible;
  margin-bottom:0;
}
.sbar:focus-within{border-color:rgba(52,208,92,0.48);box-shadow:0 0 0 3px rgba(52,208,92,0.07);}
.cat-wrap{position:relative;flex-shrink:0;}
.cat-sel{
  height:44px;padding:0 24px 0 12px;
  border:none;border-right:1.5px solid rgba(52,208,92,0.14);
  background:transparent;font-size:12px;font-weight:600;color:#3D5040;
  font-family:'Inter',sans-serif;cursor:pointer;outline:none;
  appearance:none;-webkit-appearance:none;min-width:130px;
  border-radius:12px 0 0 12px;
}
.cat-sel2{
  height:44px;padding:0 24px 0 10px;
  border:none;border-right:1.5px solid rgba(52,208,92,0.14);
  background:rgba(242,255,245,0.6);font-size:11.5px;font-weight:600;color:#2aaa4a;
  font-family:'Inter',sans-serif;cursor:pointer;outline:none;
  appearance:none;-webkit-appearance:none;min-width:138px;
  display:block;
}
.cat-sel2.visible{display:block;}
.cat-arrow{position:absolute;right:8px;top:50%;transform:translateY(-50%);pointer-events:none;color:#34D05C;font-size:10px;}
.cat-wrap2{position:relative;flex-shrink:0;display:none;}
.cat-wrap2.visible{display:flex;align-items:center;}
.sinput-wrap{flex:1;position:relative;}
.sinput-wrap input{
  width:100%;height:44px;padding:0 12px;
  border:none;background:transparent;
  font-size:12.5px;font-family:'Inter',sans-serif;color:#3D5040;outline:none;
}
.sinput-wrap input::placeholder{color:#B8C4BA;}
.sdrop{display:none;position:absolute;top:calc(100% + 6px);left:0;right:0;background:white;border-radius:12px;box-shadow:0 10px 32px rgba(0,0,0,0.10);border:1px solid rgba(52,208,92,0.12);z-index:100;overflow:hidden;}
.sdrop.open{display:block;}
.sdi{display:flex;align-items:center;gap:10px;padding:10px 14px;cursor:pointer;transition:0.15s;border-bottom:1px solid #F4F6F8;}
.sdi:last-child{border-bottom:none;}
.sdi:hover{background:#F7FFFE;}
.sdi-icon{width:28px;height:28px;border-radius:8px;background:#F2FFF5;display:flex;align-items:center;justify-content:center;font-size:13px;flex-shrink:0;}
.sdi-name{font-size:12px;font-weight:600;color:#3D5040;}
.sdi-sub{font-size:10.5px;color:#5A6478;margin-top:1px;}
.sdi-tag{margin-left:auto;font-size:10px;font-weight:700;padding:2px 7px;border-radius:999px;background:#F2FFF5;color:#34D05C;flex-shrink:0;}
.find-btn{
  height:44px;padding:0 20px;border:none;
  border-radius:0 12px 12px 0;
  background:#34D05C;color:white;font-size:12.5px;font-weight:700;
  font-family:'Inter',sans-serif;cursor:pointer;transition:0.22s;
  display:flex;align-items:center;gap:6px;flex-shrink:0;white-space:nowrap;
}
.find-btn:hover{background:#2ec252;}
.find-btn svg{width:12px;height:12px;stroke:white;stroke-width:2.5;fill:none;stroke-linecap:round;stroke-linejoin:round;}
.chip-row{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px;}
.chip-row .chip{padding:6px 12px;font-size:11px;}
.engine-wrap{display:none;}
.engine{background:none;backdrop-filter:none;border-radius:0;padding:0;border:none;box-shadow:none;}
.greeting{display:none;}.eyebrow{display:none;}.eyedot{display:none;}
.prog{display:none;}
.step-label{font-size:12px;font-weight:700;color:#2D3D30;margin-bottom:10px;letter-spacing:-0.2px;}

/* ══ PAGE 2 ══ */
#page2{min-height:100vh;padding:80px 32px 48px;flex-direction:column;}
.p2-top{display:flex;align-items:center;gap:14px;margin-bottom:24px;flex-wrap:wrap;}
.back-btn{padding:8px 16px;border-radius:999px;border:1.5px solid rgba(52,208,92,0.22);background:transparent;color:#34D05C;font-size:12px;font-weight:700;font-family:'Inter',sans-serif;cursor:pointer;transition:0.2s;white-space:nowrap;}
.back-btn:hover{background:#F2FFF5;}
.p2-title{font-size:20px;font-weight:800;letter-spacing:-0.6px;color:#2D3D30;}
.p2-prog{display:flex;align-items:center;gap:0;margin-left:auto;background:rgba(255,255,255,0.88);border:1px solid rgba(52,208,92,0.12);border-radius:16px;padding:5px 6px;backdrop-filter:blur(16px);box-shadow:0 2px 12px rgba(52,208,92,0.08);}
.p2-prog .sp{
  display:flex;align-items:center;gap:7px;
  padding:7px 14px;border-radius:11px;
  font-size:11.5px;font-weight:700;color:#6B7280;
  transition:all 0.35s ease;cursor:default;white-space:nowrap;
  position:relative;
}
.p2-prog .sp .sn{
  width:22px;height:22px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-size:10.5px;font-weight:800;
  background:#ECEEF2;color:#6B7280;
  transition:all 0.35s ease;flex-shrink:0;
  border:1.5px solid transparent;
}
.p2-prog .sp.done{color:#34D05C;}
.p2-prog .sp.done .sn{background:#F0FBF2;color:#34D05C;border-color:rgba(52,208,92,0.30);}
.p2-prog .sp.active{color:#2D3D30;background:rgba(52,208,92,0.07);}
.p2-prog .sp.active .sn{background:#34D05C;color:white;border-color:#34D05C;box-shadow:0 2px 8px rgba(52,208,92,0.32);}
.p2-prog .pl{
  width:28px;height:2px;
  background:#ECEEF2;border-radius:999px;
  margin:0 2px;flex-shrink:0;overflow:hidden;position:relative;
}
.p2-prog .pl::after{
  content:'';position:absolute;top:0;left:0;height:100%;width:0%;
  background:linear-gradient(90deg,#34D05C,#72EE8A);
  border-radius:999px;transition:width 0.5s ease;
}
.p2-prog .pl.done::after{width:100%;}
.three-col{display:grid;grid-template-columns:1fr 1.55fr 1fr;gap:18px;flex:1;align-items:stretch;}
.vid-card{border-radius:18px;overflow:hidden;position:relative;background:#1a2420;min-height:360px;height:100%;}
.vid-card video{width:100%;height:100%;object-fit:cover;display:block;}
.v-badge{position:absolute;top:11px;left:11px;background:rgba(52,208,92,0.92);color:white;font-size:10px;font-weight:800;letter-spacing:1px;padding:4px 11px;border-radius:999px;text-transform:uppercase;}
.v-live{position:absolute;top:14px;right:14px;width:9px;height:9px;border-radius:50%;background:#ff4444;animation:lp 1.4s ease infinite;}
@keyframes lp{0%,100%{opacity:1;transform:scale(1);}50%{opacity:0.5;transform:scale(1.3);}}
.v-mute-btn{position:absolute;bottom:52px;right:12px;width:34px;height:34px;border-radius:50%;background:rgba(0,0,0,0.52);backdrop-filter:blur(8px);border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:15px;transition:0.2s;z-index:3;}
.v-mute-btn:hover{background:rgba(0,0,0,0.75);}
.v-cap{position:absolute;bottom:0;left:0;right:0;background:linear-gradient(to top,rgba(0,0,0,0.78),transparent);padding:38px 16px 14px;}
.v-cap-tag{font-size:10px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:rgba(52,208,92,0.9);margin-bottom:4px;}
.v-cap p{font-size:11.5px;color:rgba(255,255,255,0.88);line-height:1.5;font-weight:500;}
.art-card{background:rgba(255,255,255,0.90);backdrop-filter:blur(20px);border-radius:18px;padding:22px;border:1px solid rgba(52,208,92,0.08);overflow-y:auto;display:flex;flex-direction:column;will-change:transform,opacity;contain:content;}
.art-tag{font-size:10px;font-weight:800;letter-spacing:2px;text-transform:uppercase;color:#34D05C;margin-bottom:8px;}
.art-title{font-size:17px;font-weight:800;letter-spacing:-0.5px;color:#2D3D30;margin-bottom:12px;line-height:1.3;}
.art-img{border-radius:12px;overflow:hidden;height:150px;margin-bottom:14px;}
.art-img img{width:100%;height:100%;object-fit:cover;}
.art-body{font-size:13px;line-height:1.85;color:#5A7060;}
.art-body p{margin-bottom:10px;}
.art-body strong{color:#2D3D30;font-weight:700;}
.art-hl{background:#F2FFF5;border-left:3px solid #34D05C;border-radius:0 10px 10px 0;padding:10px 14px;margin:14px 0;font-size:12.5px;color:#3D5040;line-height:1.65;font-weight:500;}
.opt-card{background:rgba(255,255,255,0.90);backdrop-filter:blur(20px);border-radius:18px;padding:20px;border:1px solid rgba(52,208,92,0.08);display:flex;flex-direction:column;height:100%;}
.opt-label{font-size:14px;font-weight:800;color:#2D3D30;margin-bottom:4px;letter-spacing:-0.3px;}
.opt-sub{font-size:11.5px;color:#5A6478;margin-bottom:14px;line-height:1.5;}
.opt-list{display:flex;flex-direction:column;gap:6px;margin-bottom:12px;flex:1;}
.opt{display:flex;align-items:center;gap:9px;padding:10px 13px;border-radius:12px;background:#F7F9F7;border:1.5px solid transparent;cursor:pointer;transition:0.18s;font-size:12.5px;font-weight:500;color:#5A7060;}
.opt:hover{background:#EDF7EE;border-color:rgba(52,208,92,0.18);}
.opt.sel{background:#F0FBF2;border-color:rgba(52,208,92,0.40);color:#2D5040;}
.opt-chk{width:18px;height:18px;border-radius:50%;border:2px solid #C8D8CC;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:0.18s;}
.opt.sel .opt-chk{border-color:#34D05C;background:#34D05C;}
.opt-chk svg{width:8px;height:8px;stroke:white;stroke-width:3;fill:none;stroke-linecap:round;stroke-linejoin:round;display:none;}
.opt.sel .opt-chk svg{display:block;}
.sel-count{font-size:10.5px;color:#6B7280;text-align:center;margin-bottom:10px;}
.picks-btn{width:100%;padding:13px;border:none;border-radius:13px;background:#34D05C;color:white;font-size:13px;font-weight:700;font-family:'Inter',sans-serif;cursor:pointer;transition:0.25s;display:flex;align-items:center;justify-content:center;gap:8px;box-shadow:0 6px 20px rgba(52,208,92,0.26);}
.picks-btn:hover{background:#2ec252;transform:translateY(-1px);box-shadow:0 10px 28px rgba(52,208,92,0.34);}
.picks-btn svg{width:13px;height:13px;stroke:white;stroke-width:2.5;fill:none;stroke-linecap:round;stroke-linejoin:round;}

/* ══ PAGE 3 ══ */
#page3{min-height:100vh;padding:72px 28px 16px;flex-direction:column;}
.search-overlay{
  position:fixed;inset:0;z-index:500;
  background:#F8FAF8;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:28px;
  transition:opacity 0.8s ease;
}
.search-overlay.hidden{opacity:0;pointer-events:none;}
.search-overlay.gone{display:none;}
.so-logo{font-size:20px;font-weight:900;letter-spacing:-1.5px;color:#3D5040;}
.so-logo span{color:#34D05C;}
.so-status{font-size:14px;font-weight:600;color:#5A7060;text-align:center;min-height:22px;transition:opacity 0.4s ease;}
.so-status.fade{opacity:0;}
.so-bar-wrap{width:320px;height:4px;background:#E8F0E8;border-radius:999px;overflow:hidden;}
.so-bar{height:100%;width:0%;background:linear-gradient(90deg,#34D05C,#72EE8A);border-radius:999px;transition:width 0.6s ease;}
.so-steps{display:flex;flex-direction:column;gap:10px;width:320px;}
.so-step{
  display:flex;align-items:center;gap:12px;
  padding:12px 16px;border-radius:14px;
  background:rgba(255,255,255,0.0);border:1px solid transparent;
  font-size:12.5px;font-weight:500;color:#5A6478;
  transition:all 0.5s ease;
}
.so-step.active{background:rgba(255,255,255,0.9);border-color:rgba(52,208,92,0.18);color:#3D5040;box-shadow:0 4px 16px rgba(52,208,92,0.08);}
.so-step.done{background:rgba(52,208,92,0.06);border-color:rgba(52,208,92,0.15);color:#5A7060;}
.so-step-icon{width:28px;height:28px;border-radius:50%;background:#F0F4F0;display:flex;align-items:center;justify-content:center;font-size:13px;flex-shrink:0;transition:all 0.4s ease;}
.so-step.active .so-step-icon{background:#F2FFF5;animation:soSpin 1s linear infinite;}
.so-step.done .so-step-icon{background:#34D05C;color:white;}
@keyframes soSpin{0%{transform:rotate(0deg);}100%{transform:rotate(360deg);}}
.pc{opacity:0;transform:translateY(16px);border-radius:18px;overflow:hidden;background:rgba(255,255,255,0.96);border:1.5px solid rgba(0,0,0,0.05);transition:opacity 0.6s ease,transform 0.6s ease,box-shadow 0.28s,border-color 0.28s;position:relative;display:flex;flex-direction:column;will-change:transform,opacity;contain:content;}
.pc.revealed{opacity:1;transform:translateY(0);}
.r-head{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:12px;gap:12px;flex-wrap:wrap;}
.r-head-left{display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
.r-title{font-size:22px;font-weight:800;letter-spacing:-0.6px;color:#2D3D30;}
.r-sub{font-size:11.5px;color:#5A6478;margin-top:4px;line-height:1.5;}
.r-btns{display:flex;gap:8px;flex-shrink:0;}
.bsm{padding:8px 16px;border-radius:999px;font-size:11.5px;font-weight:700;font-family:'Inter',sans-serif;cursor:pointer;transition:0.2s;white-space:nowrap;}
.bsm.ol{border:1.5px solid rgba(52,208,92,0.25);background:transparent;color:#34D05C;}
.bsm.ol:hover{background:#F2FFF5;}
.bsm.fl{border:none;background:#F2FFF5;color:#34D05C;}
.bsm.fl:hover{background:#E4FAEA;}
.pgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:8px;flex:1;align-items:stretch;}
.pc:hover{transform:translateY(-3px);box-shadow:0 16px 40px rgba(0,0,0,0.10);}
.pc.top{border-color:rgba(52,208,92,0.44);box-shadow:0 0 0 1px rgba(52,208,92,0.10),0 8px 24px rgba(52,208,92,0.10);}
.tbadge{position:absolute;top:8px;left:8px;z-index:2;background:#34D05C;color:white;font-size:9.5px;font-weight:800;letter-spacing:1.5px;text-transform:uppercase;padding:3px 9px;border-radius:999px;box-shadow:0 3px 10px rgba(52,208,92,0.36);}
.pi{height:200px;overflow:hidden;flex-shrink:0;}
.pi img{width:100%;height:100%;object-fit:cover;}
.pb{padding:10px 12px;flex:1;display:flex;flex-direction:column;will-change:transform,opacity;contain:content;}
.pbrand{font-size:9.5px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:#A8B8AC;margin-bottom:2px;}
.pname{font-size:12.5px;font-weight:700;letter-spacing:-0.3px;color:#2D3D30;margin-bottom:5px;line-height:1.25;}
.srow{display:flex;align-items:center;gap:6px;margin-bottom:5px;}
.sbw{flex:1;height:3px;background:#EEF0F3;border-radius:999px;overflow:hidden;}
.sb{height:100%;background:linear-gradient(90deg,#34D05C,#72EE8A);border-radius:999px;transition:width 0.9s ease;}
.sv{font-size:10.5px;font-weight:700;color:#34D05C;white-space:nowrap;}
.strow{display:flex;gap:4px;margin-bottom:6px;}
.stp{flex:1;padding:4px 2px;border-radius:8px;background:#F5F7F5;text-align:center;}
.stp .vv{font-size:10.5px;font-weight:700;color:#3D5040;line-height:1;}
.stp .kk{font-size:9.5px;color:#5A6478;margin-top:1px;line-height:1;}
.pverd{font-size:11px;line-height:1.5;color:#505A6B;margin-bottom:5px;font-style:italic;}
.ptags{display:flex;flex-wrap:wrap;gap:3px;margin-bottom:5px;}
.pt{font-size:9.5px;font-weight:700;padding:2px 7px;border-radius:999px;background:#F2F4F7;color:#505A6B;}
.pt.g{background:#F0FBF2;color:#34D05C;}
.pt.r{background:#FFF5F5;color:#E07070;}
.pdivider{height:1px;background:#F0F4F0;margin:5px 0;}
.pdetail-grid{display:grid;grid-template-columns:1fr 1fr;gap:4px;margin-bottom:5px;}
.pdetail-item{background:#F7F9F7;border-radius:8px;padding:5px 8px;}
.pdetail-label{font-size:9px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:#A8B8AC;margin-bottom:2px;}
.pdetail-val{font-size:11px;font-weight:600;color:#2D3D30;line-height:1.25;}
.pfit{margin-bottom:5px;}
.pfit-row{display:flex;align-items:flex-start;gap:6px;margin-bottom:3px;font-size:10.5px;line-height:1.4;}
.pfit-icon{flex-shrink:0;margin-top:1px;}
.pfit-text{color:#5A7060;}
.pfit-text.bad{color:#C07070;}
.pcert{display:flex;flex-wrap:wrap;gap:3px;margin-bottom:5px;}
.pcert-pill{display:flex;align-items:center;gap:3px;padding:3px 7px;border-radius:999px;background:#F2FFF5;border:1px solid rgba(52,208,92,0.18);font-size:9.5px;font-weight:700;color:#34D05C;}
.pprice{display:flex;align-items:center;justify-content:space-between;margin-bottom:5px;padding:5px 9px;border-radius:9px;background:#F7F9F7;}
.pprice-label{font-size:9.5px;color:#5A6478;font-weight:600;}
.pprice-val{font-size:12px;font-weight:800;color:#2D3D30;}
.pprice-per{font-size:9.5px;color:#5A6478;font-weight:500;margin-left:3px;}
.buybtn{margin-top:auto;display:flex;align-items:center;justify-content:center;gap:5px;padding:9px;border-radius:11px;border:none;font-size:11.5px;font-weight:700;font-family:'Inter',sans-serif;cursor:pointer;transition:0.25s;}
.buybtn:disabled,.buybtn[aria-disabled="true"]{opacity:0.45;cursor:not-allowed;}
.affiliate-note{font-size:9px;color:#6B7280;text-align:center;margin-top:3px;letter-spacing:0.2px;line-height:1.4;}
.pc.top .buybtn{background:#34D05C;color:white;box-shadow:0 3px 12px rgba(52,208,92,0.24);}
.pc.top .buybtn:hover{background:#2ec252;transform:translateY(-1px);}
.pc:not(.top) .buybtn{background:#F0FBF2;color:#34D05C;border:1.5px solid rgba(52,208,92,0.22);}
.pc:not(.top) .buybtn:hover{background:#E4FAEA;}
.buybtn svg{width:10px;height:10px;stroke:currentColor;stroke-width:2.5;fill:none;stroke-linecap:round;stroke-linejoin:round;}
.modal{display:none;position:fixed;inset:0;z-index:999;align-items:center;justify-content:center;}
.modal.open{display:flex;}
.mbd{position:absolute;inset:0;background:rgba(0,0,0,0.42);backdrop-filter:blur(6px);}
.mbox{position:relative;z-index:1;background:#F8FAF8;border-radius:24px;padding:28px 30px;width:min(760px,92vw);max-height:84vh;overflow-y:auto;box-shadow:0 24px 64px rgba(0,0,0,0.16);}
.mhead{display:flex;justify-content:space-between;align-items:center;margin-bottom:18px;}
.mtitle{font-size:18px;font-weight:800;letter-spacing:-0.5px;color:#2D3D30;}
.mclose{width:30px;height:30px;border-radius:50%;border:none;background:#F0F2F0;color:#505A6B;font-size:17px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:0.2s;}
.mclose:hover{background:#FFF0F0;color:#E07070;}
.ctbl{width:100%;border-collapse:collapse;}
.ctbl th{padding:9px 12px;text-align:left;font-size:10px;font-weight:800;letter-spacing:1.5px;text-transform:uppercase;color:#B7BDC6;border-bottom:1.5px solid #EEF0F3;}
.ctbl td{padding:10px 12px;font-size:12px;color:#5A7060;border-bottom:1px solid #F2F4F2;vertical-align:middle;}
.ctbl tr:last-child td{border-bottom:none;}
.ctbl tr:hover td{background:#FAFFFB;}
.cbrand{font-weight:700;color:#2D3D30;}
.ctg{display:inline-block;padding:2px 7px;border-radius:999px;background:#F0FBF2;color:#34D05C;font-size:10px;font-weight:700;}
.ctr{display:inline-block;padding:2px 7px;border-radius:999px;background:#FFF5F5;color:#E07070;font-size:10px;font-weight:700;}
.smb{display:flex;align-items:center;gap:5px;}
.smbar{width:48px;height:3px;background:#EEF0F3;border-radius:999px;overflow:hidden;}
.smfill{height:100%;background:linear-gradient(90deg,#34D05C,#72EE8A);border-radius:999px;}
@media(max-width:900px){
  .nav{padding:0 16px;height:auto;flex-wrap:wrap;padding-top:10px;padding-bottom:10px;gap:8px;}
  .nav-sub{width:100%;justify-content:stretch;}
  .nav-sub input{width:1px;flex:1;min-width:0;}
  #page1{padding:90px 16px 24px;min-height:auto;}
  .p1-grid{grid-template-columns:1fr;gap:12px;}
  .p1-left{min-height:auto;}
  .p1-right{min-height:auto;}
  .intro-card{min-height:220px;}
  .chat-card{min-height:260px;}
  .pgrid{grid-template-columns:1fr;gap:16px;}
  .three-col{grid-template-columns:1fr;}
  #page2{padding:80px 16px 32px;}
  .p1-intro{grid-template-columns:1fr;}
  .skip-grid{grid-template-columns:repeat(2,1fr);}
}
/* Extra-small phones ≤480px — single-column safety net */
@media(max-width:480px){
  .p1-grid,.pgrid,.three-col{grid-template-columns:1fr!important;}
  .nav-sub button{padding:0 14px;font-size:12px;}
  .qchip{font-size:11px;padding:7px 11px;}
  .engine-card{padding:16px 14px;}
  #page3{padding:80px 10px 24px;}
  .mbox{padding:20px 16px;}
}
/* iPhone SE / Pixel 4a ≤375px — tightest targets */
@media(max-width:375px){
  .nav{padding:8px 12px;gap:6px;}
  .nav-logo{font-size:18px;}
  .nav-sub input{font-size:12px;}
  .nav-sub button{font-size:11px;padding:0 12px;}
  .engine-card{padding:14px 12px;}
  .sbar{flex-wrap:wrap;gap:6px;}
  .find-btn{width:100%;}
  .quick-chips{gap:5px;}
  .qchip{font-size:10.5px;padding:6px 9px;}
  .r-head{flex-direction:column;gap:8px;}
  .r-btns{width:100%;justify-content:flex-start;}
  .strow{gap:2px;}
  .stp{padding:3px 1px;}
  .stp .vv{font-size:9.5px;}
  .stp .kk{font-size:8.5px;}
  .mbox{width:95vw;padding:16px 12px;}
}
.chat-down-arrow{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  height:32px;flex-shrink:0;gap:0;
}
.chat-down-arrow svg{width:20px;height:14px;display:block;}
.chat-down-arrow svg:nth-child(1){opacity:0.20;animation:arrowFade 1.6s ease-in-out infinite 0s;}
.chat-down-arrow svg:nth-child(2){opacity:0.55;animation:arrowFade 1.6s ease-in-out infinite 0.18s;}
.chat-down-arrow svg:nth-child(3){opacity:1;  animation:arrowFade 1.6s ease-in-out infinite 0.36s;}
@keyframes arrowFade{
  0%,100%{opacity:0.12;transform:translateY(-3px);}
  50%{opacity:1;transform:translateY(3px);}
}
.footer{text-align:center !important;font-size:10px !important;color:#A8B8AC;line-height:1.9;padding:6px 0 0;}
.footer a{color:#34D05C;font-weight:600;text-decoration:none;}
.footer a:hover{text-decoration:underline;}
.disclaimer-lnk{background:none;border:none;color:#34D05C;font-weight:600;cursor:pointer;font-size:inherit;font-family:inherit;padding:0;text-decoration:none;}
.disclaimer-lnk:hover{text-decoration:underline;}
.life-btn{display:inline-block;font-size:10px;color:#D0D8D2;cursor:pointer;border:none;background:transparent;font-family:'Inter',sans-serif;padding:2px 5px;border-radius:5px;transition:0.2s;margin-left:4px;}
.life-btn:hover{color:#34D05C;}

/* ══ FRONTEND CSS CUSTOM PROPERTIES ══ */
:root{
  --color-primary:#34D05C;
  --color-primary-dark:#2aaa4a;
  --color-primary-glow:rgba(52,208,92,0.24);
  --color-primary-subtle:rgba(52,208,92,0.08);
  --color-text-main:#2D3D30;
  --color-text-body:#3D5040;
  --color-text-muted:#6B7280;
  --color-text-faint:#A8B8AC;
  --color-bg:#F8FAF8;
  --color-surface:#FFFFFF;
  --color-surface-alt:#F0FBF2;
  --color-border:rgba(52,208,92,0.14);
  --color-dark-bg:#0A130D;
}
/* ══ ADMIN CSS ══ */
#adm-wrapper{display:none;}
/* Admin body overrides are scoped to adm-wrapper to avoid polluting frontend */
#adm-wrapper,#adm-wrapper *{box-sizing:border-box;font-family:'Inter',sans-serif;}
:root{
  --bg:#F0F2F1;--s1:#FFFFFF;--s2:#F7F8F7;--s3:#EDEEED;
  --border:#E2E6E2;--border2:#CDD5CD;
  --green:#28A84A;--green-l:rgba(40,168,74,0.10);--green-ll:rgba(40,168,74,0.06);
  --text:#1A1E1A;--text2:#4A5A4A;--text3:#8A9E8A;
  --red:#C93838;--red-l:rgba(201,56,56,0.08);
  --r:10px;
}
::-webkit-scrollbar{width:5px;height:5px;}
::-webkit-scrollbar-thumb{background:var(--border2);border-radius:99px;}
#loginWrap{position:fixed;inset:0;background:var(--bg);display:flex;align-items:center;justify-content:center;z-index:999;}
.lcard{background:var(--s1);border:1px solid var(--border);border-radius:16px;padding:40px;width:340px;box-shadow:0 4px 24px rgba(0,0,0,0.08);}
.llogo{font-size:22px;font-weight:800;letter-spacing:-1px;margin-bottom:4px;}
.llogo span{color:var(--green);}
.lsub{font-size:12px;color:var(--text3);margin-bottom:26px;}
.llabel{font-size:11px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;color:var(--text2);margin-bottom:6px;}
.linput{width:100%;height:42px;padding:0 12px;border:1.5px solid var(--border2);border-radius:8px;font-size:13px;color:var(--text);background:var(--s2);outline:none;transition:.2s;}
.linput:focus{border-color:var(--green);box-shadow:0 0 0 3px var(--green-l);}
.lbtn{margin-top:14px;width:100%;height:42px;background:var(--green);color:#fff;border:none;border-radius:8px;font-size:13px;font-weight:700;cursor:pointer;}
.lbtn:hover{background:#239642;}
.lerr{font-size:12px;color:#C93838;text-align:center;margin-top:10px;min-height:16px;}
#app{display:none;height:100vh;overflow:hidden;}
.layout{display:flex;height:100vh;}
.sb1{background:var(--s1);border-right:1px solid var(--border);display:flex;flex-direction:column;overflow-y:auto;width:210px;flex-shrink:0;}
.sb1-logo{padding:16px 16px 12px;font-size:17px;font-weight:800;letter-spacing:-1px;border-bottom:1px solid var(--border);flex-shrink:0;}
.sb1-logo span{color:var(--green);}
.sb1-sec{padding:12px 14px 3px;font-size:10px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:var(--text3);}
.sb1-item{display:flex;align-items:center;gap:8px;padding:8px 10px;margin:1px 6px;border-radius:8px;font-size:12.5px;font-weight:600;color:var(--text2);cursor:pointer;transition:.15s;user-select:none;}
.sb1-item:hover{background:var(--s2);}
.sb1-item.act{background:var(--green-l);color:var(--green);}
.sb1-ic{width:18px;text-align:center;font-size:13px;flex-shrink:0;}
.sb1-foot{margin-top:auto;padding:12px;border-top:1px solid var(--border);}
.out-btn{width:100%;padding:7px;border:1px solid var(--border2);border-radius:7px;background:transparent;font-size:12px;font-weight:600;color:var(--text3);cursor:pointer;transition:.15s;}
.out-btn:hover{color:var(--red);border-color:var(--red);background:var(--red-l);}
.sb2{background:var(--s2);border-right:1px solid var(--border);overflow-y:auto;display:none;flex-direction:column;width:248px;flex-shrink:0;}
.sb2.show{display:flex;}
.sb2-head{padding:14px 14px 10px;border-bottom:1px solid var(--border);flex-shrink:0;}
.sb2-head-title{font-size:13px;font-weight:700;color:var(--text);}
.sb2-head-sub{font-size:10px;color:var(--text3);margin-top:2px;}
.c1-block{border-bottom:1px solid var(--border);}
.c1-btn{display:flex;align-items:center;justify-content:space-between;padding:9px 14px;cursor:pointer;user-select:none;transition:.15s;}
.c1-btn:hover,.c1-btn.open{background:var(--s1);}
.c1-label{font-size:12.5px;font-weight:700;color:var(--text);}
.c1-arrow{font-size:10px;color:var(--text3);transition:.2s;display:inline-block;}
.c1-btn.open .c1-arrow{transform:rotate(90deg);}
.c2-list{display:none;padding:3px 0;}
.c1-btn.open + .c2-list{display:block;}
.c2-item{padding:7px 14px 7px 26px;font-size:12px;font-weight:600;color:var(--text2);cursor:pointer;transition:.15s;display:flex;align-items:center;gap:6px;}
.c2-item:hover{background:var(--s1);color:var(--text);}
.c2-item.act{background:var(--green-ll);color:var(--green);}
.c2-dot{width:5px;height:5px;border-radius:50%;background:var(--border2);flex-shrink:0;transition:.15s;}
.c2-item.act .c2-dot{background:var(--green);}
.main{overflow-y:auto;background:var(--bg);flex:1;min-width:0;}
.mi{padding:24px 32px;max-width:1100px;}
.ph{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:20px;gap:12px;}
.ph-t{font-size:19px;font-weight:800;letter-spacing:-.5px;}
.ph-s{font-size:12px;color:var(--text3);margin-top:3px;}
.ph-a{display:flex;gap:8px;flex-shrink:0;align-items:flex-start;}
.btn{display:inline-flex;align-items:center;gap:5px;padding:8px 14px;border-radius:8px;font-size:12px;font-weight:700;cursor:pointer;transition:.2s;border:none;white-space:nowrap;}
.btn-g{background:var(--green);color:#fff;}
.btn-g:hover{background:#239642;}
.btn-w{background:var(--s1);color:var(--text);border:1px solid var(--border2);}
.btn-w:hover{background:var(--s3);}
.btn-r{background:var(--red-l);color:var(--red);border:1px solid rgba(201,56,56,0.2);}
.btn-sm{padding:6px 11px;font-size:11px;}
.card{background:var(--s1);border:1px solid var(--border);border-radius:var(--r);margin-bottom:14px;overflow:hidden;}
.ch{display:flex;align-items:center;justify-content:space-between;padding:13px 16px;border-bottom:1px solid var(--border);}
.ct{font-size:13px;font-weight:700;}
.cs{font-size:11px;color:var(--text3);margin-top:2px;}
.cb{padding:16px;}
.fg{margin-bottom:13px;}
.fg:last-child{margin-bottom:0;}
.fg label{display:block;font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--text2);margin-bottom:5px;}
.fg label .hn{font-weight:400;text-transform:none;letter-spacing:0;color:var(--text3);font-size:10.5px;margin-left:4px;}
.fi{width:100%;padding:8px 11px;border:1.5px solid var(--border2);border-radius:8px;font-size:12.5px;color:var(--text);background:var(--s2);outline:none;transition:.2s;}
.fi:focus{border-color:var(--green);background:#fff;box-shadow:0 0 0 3px var(--green-l);}
textarea.fi{resize:vertical;line-height:1.6;}
select.fi{cursor:pointer;}
.gr2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;}
.gr3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;}
.div{height:1px;background:var(--border);margin:16px 0;}
.slabel{font-size:10px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:var(--text3);padding-bottom:8px;border-bottom:1px solid var(--border);margin-bottom:14px;}
.notice{padding:10px 14px;border-radius:8px;font-size:12px;line-height:1.6;margin-bottom:14px;}
.ng{background:var(--green-ll);border:1px solid rgba(40,168,74,0.15);color:var(--text2);}
.na{background:rgba(176,120,0,0.07);border:1px solid rgba(176,120,0,0.18);color:#8a6000;}
.bc{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text3);margin-bottom:16px;flex-wrap:wrap;}
.bc strong{color:var(--text2);}
.bc .need-tag{background:var(--green-l);color:var(--green);padding:2px 8px;border-radius:99px;font-weight:700;font-size:10.5px;}
#adm-wrapper .pb{background:var(--s2);border:1.5px solid var(--border2);border-radius:10px;padding:16px;margin-bottom:12px;}
#adm-wrapper .pb-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;}
#adm-wrapper .pb-rank{width:26px;height:26px;border-radius:50%;background:var(--green-l);color:var(--green);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:800;flex-shrink:0;}
#adm-wrapper .pb-name{font-size:12.5px;font-weight:700;margin-left:9px;}
.tp-row{display:flex;align-items:center;gap:7px;font-size:11.5px;font-weight:600;color:var(--text2);}
.tog{position:relative;width:36px;height:20px;flex-shrink:0;}
.tog input{opacity:0;width:0;height:0;}
.ts{position:absolute;inset:0;background:var(--border2);border-radius:99px;cursor:pointer;transition:.25s;}
.ts::before{content:'';position:absolute;width:14px;height:14px;left:3px;top:3px;background:#fff;border-radius:50%;transition:.25s;}
.tog input:checked+.ts{background:var(--green);}
.tog input:checked+.ts::before{transform:translateX(16px);}
.tag-row{display:grid;grid-template-columns:1fr 90px;gap:8px;margin-bottom:6px;align-items:center;}
.tcsel{padding:7px 8px;border:1.5px solid var(--border2);border-radius:8px;font-size:12px;background:var(--s2);color:var(--text);outline:none;width:100%;}
.tcsel:focus{border-color:var(--green);}
.si-row{display:grid;grid-template-columns:36px 1fr 1.5fr 68px 84px 30px;gap:6px;align-items:center;padding:6px 0;border-bottom:1px solid var(--border);}
.si-row:last-child{border-bottom:none;}
.si-ico{font-size:17px;text-align:center;}
.si-in{width:100%;padding:6px 8px;border:1px solid var(--border2);border-radius:6px;font-size:11.5px;color:var(--text);background:var(--s2);outline:none;}
.si-in:focus{border-color:var(--green);}
.del{width:28px;height:28px;border:none;border-radius:6px;background:var(--red-l);color:var(--red);cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center;}
#adm-wrapper .stats{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:18px;}
#adm-wrapper .stat{background:var(--s1);border:1px solid var(--border);border-radius:var(--r);padding:15px;}
#adm-wrapper .sv{font-size:24px;font-weight:800;letter-spacing:-1px;color:var(--green);}
#adm-wrapper .sk{font-size:11px;color:var(--text3);margin-top:4px;font-weight:600;}
.empty{text-align:center;padding:48px 24px;color:var(--text3);}
.empty-ico{font-size:38px;margin-bottom:12px;}
.empty-t{font-size:13px;line-height:1.7;}
.view{display:none;}
.view.on{display:block;}
#toast{position:fixed;bottom:20px;right:20px;z-index:9999;padding:10px 18px;border-radius:8px;background:var(--s1);border:1px solid var(--border2);font-size:13px;font-weight:600;color:var(--green);box-shadow:0 4px 16px rgba(0,0,0,.10);transform:translateY(60px);opacity:0;transition:.3s cubic-bezier(.4,0,.2,1);}
#toast.show{transform:translateY(0);opacity:1;}
@media print{
  .nav,.footer,.cookie-banner,.modal,#exitAdminBtn,.v-mute-btn,.find-btn,.picks-btn,.r-btns,.buybtn{display:none!important;}
  .page{display:block!important;opacity:1!important;}
  .three-col{display:block;}
  .vid-card{display:none;}
  body{background:white;color:black;}
  .art-card,.opt-card,.pc{border:1px solid #ccc;break-inside:avoid;}
}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:0.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:0.1ms !important;
  }
  .intro-live-dot{animation:none;}
  .intro-cursor{animation:none;opacity:1;}
  .chat-cursor-inline{animation:none;opacity:1;}
  .qchip{animation:none !important;transform:none !important;}
  .chat-bbl.float-b,.chat-bbl.float-u{animation:none;transform:none;}
  .chat-down-arrow svg{animation:none;opacity:0.6;}
  .nav-logo .bounce{animation:none;}
  .so-step.active .so-step-icon{animation:none;}
  html{scroll-behavior:auto;}
}
#cookie-banner{
  position:fixed;bottom:0;left:0;right:0;z-index:9990;
  background:#fff;border-top:1px solid rgba(52,208,92,0.18);
  box-shadow:0 -4px 24px rgba(0,0,0,0.08);
  padding:18px 28px;
  display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap;
  transform:translateY(0);transition:transform 0.35s ease;
  font-family:'Inter',sans-serif;
}
#cookie-banner.hidden{transform:translateY(110%);}
/* Preferences panel — hidden by default */
#cookie-prefs{
  display:none;width:100%;padding-top:14px;border-top:1px solid rgba(52,208,92,0.12);margin-top:4px;
}
#cookie-prefs.open{display:block;}
.cb-pref-row{display:flex;align-items:center;justify-content:space-between;padding:8px 0;
  border-bottom:1px solid rgba(0,0,0,0.05);font-size:12px;color:#3D5040;}
.cb-pref-row:last-child{border-bottom:none;}
.cb-pref-label{flex:1;line-height:1.5;}
.cb-pref-label small{display:block;color:#5A6478;font-size:11px;}
.cb-toggle{position:relative;width:36px;height:20px;flex-shrink:0;}
.cb-toggle input{opacity:0;width:0;height:0;position:absolute;}
.cb-toggle-track{position:absolute;inset:0;background:#ccc;border-radius:20px;
  transition:background 0.2s;cursor:pointer;}
.cb-toggle input:checked + .cb-toggle-track{background:var(--color-primary,#34D05C);}
.cb-toggle input:disabled + .cb-toggle-track{cursor:not-allowed;opacity:0.6;}
.cb-toggle-track::after{content:'';position:absolute;top:2px;left:2px;
  width:16px;height:16px;border-radius:50%;background:#fff;
  transition:transform 0.2s;box-shadow:0 1px 3px rgba(0,0,0,0.2);}
.cb-toggle input:checked + .cb-toggle-track::after{transform:translateX(16px);}
.cb-text{flex:1;font-size:12px;color:#5A7060;line-height:1.6;min-width:200px;}
.cb-btns{display:flex;gap:8px;flex-shrink:0;flex-wrap:wrap;align-items:center;}
.cb-btn{padding:8px 16px;border-radius:10px;font-size:12px;font-weight:700;
  font-family:'Inter',sans-serif;cursor:pointer;border:none;white-space:nowrap;
  transition:opacity 0.2s,transform 0.15s;}
.cb-btn:hover{opacity:0.88;transform:translateY(-1px);}
.cb-btn:focus-visible{outline:2px solid #34D05C;outline-offset:2px;}
/* Equal visual weight — no dark patterns */
.cb-btn.decline{background:#F0F0F0;color:#444;}
.cb-btn.prefs{background:#F0FBF2;color:#2a7a3a;border:1.5px solid rgba(52,208,92,0.25);}
.cb-btn.accept{background:#34D05C;color:#fff;}
.cb-btn.save-prefs{background:#34D05C;color:#fff;width:100%;margin-top:10px;}
@media(max-width:600px){
  #cookie-banner{padding:14px 16px;gap:10px;}
  .cb-btns{width:100%;justify-content:stretch;}
  .cb-btn{flex:1;}
}
#exitAdminBtn{display:none;position:fixed;top:14px;right:20px;z-index:99999;padding:9px 20px;background:#C93838;color:#fff;border:none;border-radius:8px;font-size:13px;font-weight:700;font-family:'Inter',sans-serif;cursor:pointer;box-shadow:0 3px 14px rgba(201,56,56,0.35);transition:0.2s;}
#exitAdminBtn:hover{background:#a82e2e;transform:translateY(-1px);}
#toast-fe{position:fixed;bottom:20px;right:20px;z-index:9998;padding:10px 18px;border-radius:8px;background:#fff;border:1px solid #e2e6e2;font-size:13px;font-weight:600;color:#28A84A;box-shadow:0 4px 16px rgba(0,0,0,.10);transform:translateY(60px);opacity:0;transition:.3s cubic-bezier(.4,0,.2,1);}
#toast-fe.show{transform:translateY(0);opacity:1;}
</style>
<!-- Google Consent Mode v2 — defaults denied; GA4 loads only after user grants consent -->
<script>
window.dataLayer=window.dataLayer||[];
function gtag(){dataLayer.push(arguments);}
// Set consent defaults BEFORE any other gtag() call (Consent Mode v2 requirement)
gtag('consent','default',{
  ad_storage:'denied', ad_user_data:'denied',
  ad_personalization:'denied', analytics_storage:'denied',
  functionality_storage:'granted', security_storage:'granted',
  wait_for_update:500
});
// Restore consent if user already accepted in a previous session
(function(){
  try{
    var s=localStorage.getItem('elova_consent');
    if(s==='granted'){
      gtag('consent','update',{
        ad_storage:'denied', ad_user_data:'denied',
        ad_personalization:'denied', analytics_storage:'granted',
        functionality_storage:'granted', security_storage:'granted'
      });
    }
  }catch(e){}
})();
// GA4 dynamic loader — injects GA4 only after analytics consent is granted
// ── DEPLOY: replace G-PG2QVFYS2C with your real GA4 Measurement ID ──────────
// Get it from: https://analytics.google.com → Admin → Data Streams → Web
var GA4_ID='G-PG2QVFYS2C';
function _loadGA4(){
  // GA4 ready
  if(document.querySelector('script[src*="googletagmanager.com/gtag"]')) return;
  var s=document.createElement('script');
  s.async=true;
  s.src='https://www.googletagmanager.com/gtag/js?id='+GA4_ID;
  document.head.appendChild(s);
  s.onload=function(){gtag('js',new Date());gtag('config',GA4_ID);};
}
// Load GA4 immediately if consent already granted
(function(){
  try{if(localStorage.getItem('elova_consent')==='granted')_loadGA4();}catch(e){}
})();
</script>
</head><body>
<!-- Screen-reader live region: JS writes short status messages here for SR announcements -->
<div id="sr-announce" class="sr-only" role="status" aria-live="polite" aria-atomic="true"></div>
<!-- SR page-transition announcer: announces when a new page/step becomes visible -->
<div id="sr-page" class="sr-only" role="status" aria-live="assertive" aria-atomic="true"></div>

<noscript>
  <div style="position:fixed;top:0;left:0;right:0;z-index:99999;background:#34D05C;color:#fff;text-align:center;padding:10px 16px;font-size:13px;font-weight:700;font-family:sans-serif;">
    Elova.Life requires JavaScript to show your personalised supplement recommendations. Please enable JavaScript in your browser settings.
  </div>
</noscript>
<button id="exitAdminBtn" onclick="exitAdminMode()" aria-label="Exit admin mode">← Exit Admin</button>

<!-- ══ COOKIE BANNER ══ -->
<div id="cookie-banner" class="hidden"
     role="dialog"
     aria-modal="true"
     aria-label="Cookie consent"
     aria-describedby="cb-desc">

  <p class="cb-text" id="cb-desc">
    We use analytics cookies to understand how you use Elova.Life and improve your experience.
    No advertising. No data sold.
    <a href="#" onclick="showDisclaimer();return false;" style="color:#34D05C;font-weight:600;">Privacy policy</a>
  </p>

  <div class="cb-btns">
    <button class="cb-btn decline"  onclick="handleConsent(false)" aria-label="Decline all optional cookies">Decline</button>
    <button class="cb-btn prefs"    onclick="toggleCookiePrefs()"  aria-expanded="false" aria-controls="cookie-prefs">⚙ Manage</button>
    <button class="cb-btn accept"   onclick="handleConsent(true)"  aria-label="Accept all cookies">Accept All ✓</button>
  </div>

  <!-- Granular preferences — GDPR Art. 7: freely given, specific, informed consent -->
  <div id="cookie-prefs" aria-hidden="true">
    <div class="cb-pref-row">
      <div class="cb-pref-label">
        Strictly necessary
        <small>Session state, security. Cannot be disabled.</small>
      </div>
      <label class="cb-toggle" aria-label="Strictly necessary — always on">
        <input type="checkbox" checked disabled/>
        <span class="cb-toggle-track"></span>
      </label>
    </div>
    <div class="cb-pref-row">
      <div class="cb-pref-label">
        Analytics (Google Analytics 4)
        <small>Anonymised page views. Helps us improve content quality.</small>
      </div>
      <label class="cb-toggle" aria-label="Toggle analytics cookies">
        <input type="checkbox" id="pref-analytics"/>
        <span class="cb-toggle-track"></span>
      </label>
    </div>
    <div class="cb-pref-row">
      <div class="cb-pref-label">
        Functional (preferences)
        <small>Remembers your wellness category selection.</small>
      </div>
      <label class="cb-toggle" aria-label="Toggle functional cookies">
        <input type="checkbox" id="pref-functional" checked/>
        <span class="cb-toggle-track"></span>
      </label>
    </div>
    <button class="cb-btn save-prefs" onclick="handleConsentGranular()">
      Save my preferences
    </button>
  </div>

</div>

<!-- ══ FRONTEND ══ -->
<div id="fe-wrapper" role="main">

<a href="#page1" class="skip-link">Skip to content</a>

<!-- ══ NAVBAR ══ -->
<header role="banner">
<nav class="nav" aria-label="Main navigation">
  <a class="nav-logo" href="#page1" onclick="showPage(1);return false;" aria-label="Elova.Life home">
    <span class="dark">Elova</span><span class="green bounce">.Life</span>
  </a>
  <div class="nav-sub">
    <label for="subEmail" class="sr-only">Email address for weekly wellness picks</label>
    <input type="email" id="subEmail" placeholder="Your email for weekly wellness picks…" aria-label="Email address for weekly wellness picks" autocomplete="email"/>
    <button type="button" onclick="handleSub()" aria-label="Subscribe to Elova newsletter">Subscribe</button>
  </div>
</nav>
</header>

<!-- ══════════════════════════
   PAGE 1
══════════════════════════ -->
<section id="page1" class="page active" aria-label="Home — Find your wellness stack">
  <div class="p1-grid">

    <!-- ══ LEFT ══ -->
    <div class="p1-left">

      <!-- Buyer intro -->
      <div class="intro-card">
        <p class="intro-live" aria-hidden="true"><span class="intro-live-dot"></span>Elova · Independent Wellness Buyer</p>
        <h1 class="intro-name">
          <span class="intro-typed" id="introTyped"></span><span class="intro-cursor" aria-hidden="true"></span>
        </h1>
      </div>

      <!-- Why different -->
      <div class="diff-card">
        <h2 class="diff-title">Why Elova is different</h2>
        <div class="diff-list">
          <div class="diff-row"><div class="diff-icon">🚫</div><div class="diff-text"><strong>No paid rankings</strong> — brands cannot pay to appear in my picks. Ever.</div></div>
          <div class="diff-row"><div class="diff-icon">🔬</div><div class="diff-text"><strong>Clinical evidence only</strong> — every pick is cross-referenced with peer-reviewed research and real dosage data.</div></div>
          <div class="diff-row"><div class="diff-icon">📊</div><div class="diff-text"><strong>Real-world data</strong> — global sales trends + verified 90-day user feedback.</div></div>
          <div class="diff-row"><div class="diff-icon">🔄</div><div class="diff-text"><strong>Updated weekly</strong> — if a formula changes or new evidence drops, my rankings update too.</div></div>
        </div>
      </div>

    </div>

    <!-- ══ RIGHT ══ -->
    <div class="p1-right">

      <!-- Chat -->
      <div class="chat-card">
        <h2 class="chat-label-top">How I work with you</h2>
        <div class="chat-messages" id="chatMessages" aria-live="polite" aria-label="Conversation example with Elova">

          <div class="chat-msg" id="cm0">
            <div class="chat-av b" aria-hidden="true">E</div>
            <div class="chat-bbl b" id="ct0"></div>
          </div>

          <div class="chat-msg user" id="cm1" style="display:none;">
            <div class="chat-av u" aria-hidden="true">🙋</div>
            <div class="chat-bbl u" id="ct1"></div>
          </div>

          <div class="chat-msg" id="cm2" style="display:none;">
            <div class="chat-av b" aria-hidden="true">E</div>
            <div class="chat-bbl b" id="ct2"></div>
          </div>

          <div class="chat-msg user" id="cm3" style="display:none;">
            <div class="chat-av u" aria-hidden="true">🙋</div>
            <div class="chat-bbl u" id="ct3"></div>
          </div>

          <div class="chat-msg" id="cm4" style="display:none;">
            <div class="chat-av b" aria-hidden="true">E</div>
            <div class="chat-bbl b" id="ct4"></div>
          </div>

        </div>
      </div>

      <!-- Triple chevron arrow -->
      <div class="chat-down-arrow" aria-hidden="true">
        <svg viewBox="0 0 20 12" fill="none"><polyline points="2,2 10,10 18,2" stroke="#34D05C" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
        <svg viewBox="0 0 20 12" fill="none"><polyline points="2,2 10,10 18,2" stroke="#34D05C" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
        <svg viewBox="0 0 20 12" fill="none"><polyline points="2,2 10,10 18,2" stroke="#34D05C" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
      </div>

      <!-- Search engine -->
      <div class="engine-card">
        <div class="step-label">Or tell me your goal — I'll find your stack right away.</div>
        <div class="sbar" role="search" aria-label="Wellness supplement finder">
          <div class="cat-wrap">
            <label for="catSel" class="sr-only">Select a category</label>
            <select class="cat-sel" id="catSel" onchange="onCatChange()">
              <option value="">All Categories</option>
              <option value="sleep">😴 Sleep &amp; Rest</option>
              <option value="mind">🧠 Mind &amp; Brain</option>
              <option value="physical">💪 Physical Performance</option>
              <option value="internal">🫀 Internal Systems</option>
              <option value="longevity_ag">🔬 Longevity &amp; Aging</option>
              <option value="beauty_sk">✨ Beauty &amp; Skin</option>
              <option value="weight_sh">⚖️ Weight &amp; Shape</option>
            </select>
            <div class="cat-arrow" aria-hidden="true">▾</div>
          </div>
          <div class="cat-wrap2" id="subCatWrap">
            <label for="subCatSel" class="sr-only">Select a sub-category</label>
            <select class="cat-sel2" id="subCatSel" onchange="onSubCatChange()">
            </select>
            <div class="cat-arrow" aria-hidden="true">▾</div>
          </div>
          <div class="sinput-wrap">
            <label for="ni" class="sr-only">Describe your wellness goal</label>
            <input type="text" id="ni" placeholder="e.g. I can't sleep, I feel bloated, I need more energy…"
              role="combobox" aria-autocomplete="list" aria-expanded="false" aria-controls="sd" aria-label="Describe your wellness goal"
              autocomplete="off"/>
          </div>
          <button type="button" class="find-btn" onclick="goP2()" aria-label="Find my supplement stack">
            Find My Stack
            <svg viewBox="0 0 14 14" aria-hidden="true"><polyline points="3,7 11,7"/><polyline points="7,3 11,7 7,11"/></svg>
          </button>
          <div class="sdrop" id="sd" role="listbox" aria-label="Search suggestions"></div>
        </div>
        <div class="quick-chips" id="chipGroup" role="list" aria-label="Quick category shortcuts">
          <div class="qchip chip" role="button" tabindex="0" data-need="sleep" aria-pressed="false">😴 Sleep</div>
          <div class="qchip chip" role="button" tabindex="0" data-need="stress" aria-pressed="false">🧠 Stress</div>
          <div class="qchip chip" role="button" tabindex="0" data-need="energy" aria-pressed="false">⚡ Focus</div>
          <div class="qchip chip" role="button" tabindex="0" data-need="gut" aria-pressed="false">🫀 Gut</div>
          <div class="qchip chip" role="button" tabindex="0" data-need="longevity" aria-pressed="false">🔬 Longevity</div>
          <div class="qchip chip" role="button" tabindex="0" data-need="skin" aria-pressed="false">✨ Beauty</div>
        </div>
      </div>

    </div>
  </div>

  <footer class="footer" role="contentinfo" aria-label="Site footer">
    No ads · No paid placements · Updated weekly &nbsp;|&nbsp;
    <button type="button" onclick="showDisclaimer()" class="disclaimer-lnk" aria-label="View disclaimer and legal information">Disclaimer</button>
    <button type="button" class="life-btn" onclick="adminLogin()" title="admin" aria-label="Admin login">life</button>
  </footer>

</section>

<!-- ══════════════════════════
   PAGE 2
══════════════════════════ -->
<section id="page2" class="page" aria-label="Deep Dive — Research report">
  <div class="p2-top">
    <button type="button" class="back-btn" onclick="showPage(1)" aria-label="Back to home page">← Back</button>
    <div class="p2-title" id="p2Title">Deep Dive</div>
    <div class="p2-prog" role="group" aria-label="Progress">
      <div class="sp done" id="progStep1" aria-label="Step 1: Tell Me — completed"><div class="sn" aria-hidden="true">✓</div>Tell Me</div>
      <div class="pl done" id="progLine1" aria-hidden="true"></div>
      <div class="sp active" id="progStep2" aria-current="step" aria-label="Step 2: Deep Dive — current"><div class="sn" aria-hidden="true">2</div>Deep Dive</div>
      <div class="pl" id="progLine2" aria-hidden="true"></div>
      <div class="sp" id="progStep3" aria-label="Step 3: My Picks — upcoming"><div class="sn" aria-hidden="true">3</div>My Picks</div>
    </div>
  </div>

  <div class="three-col">
    <!-- LEFT: Video -->
    <div class="vid-card">
      <video id="buyerVid" autoplay muted loop playsinline preload="none" loading="lazy" poster="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 300'%3E%3Crect width='400' height='300' fill='%231a2420'/%3E%3C/svg%3E" aria-label="Elova buyer reviewing supplements" title="Elova Buyer Review"
        >
        <source src="https://cdn.coverr.co/videos/coverr-pouring-herbal-tea-8170/1080p.mp4" type="video/mp4" onerror="this.parentElement.style.opacity='0.4';var b=document.getElementById('muteBtn');if(b){b.disabled=true;b.title='Video unavailable';}">
      </video>
      <div class="v-badge" id="vBadge">🎬 Elova Buyer</div>
      <div class="v-live" aria-hidden="true"></div>
      <button type="button" class="v-mute-btn" id="muteBtn" onclick="toggleMute()" aria-label="Unmute video" aria-pressed="false">🔇</button>
      <div class="v-cap">
        <div class="v-cap-tag" id="vTag">Now Reviewing</div>
        <p id="vCaption">Analyzing real dosages vs marketing hype…</p>
      </div>
    </div>

    <!-- MIDDLE: Article -->
    <article class="art-card" aria-label="Buyer research report" aria-live="polite">
      <p class="art-tag" id="artTag" aria-label="Article category">Buyer Research Report</p>
      <h2 class="art-title" id="artTitle">Deep Buyer Analysis</h2>
      <div class="art-img"><img id="artImg" src="https://images.unsplash.com/photo-1490645935967-10de6ba17061?q=80&w=1200&auto=format&fit=crop" alt="Wellness supplement research" loading="lazy" fetchpriority="low" width="1200" height="800" decoding="async"></div>
      <div class="art-body" id="artBody"></div>
    </article>

    <!-- RIGHT: Options -->
    <div class="opt-card">
      <div class="opt-label" id="optTitle">Tell me more about your situation:</div>
      <div class="opt-sub">Select all that apply — helps me match better</div>
      <div class="opt-list" id="optList" role="group" aria-label="Situation options"></div>
      <div class="sel-count">Selected: <span id="selCount">0</span></div>
      <button type="button" class="picks-btn" onclick="goP3()" aria-label="Get my supplement picks">
        Show My Picks
        <svg viewBox="0 0 14 14" aria-hidden="true"><polyline points="3,7 11,7"/><polyline points="7,3 11,7 7,11"/></svg>
      </button>
    </div>
  </div>
</section>

<!-- ══════════════════════════
   PAGE 3
══════════════════════════ -->
<section id="page3" class="page" aria-label="My Picks — Top supplement recommendations">
  <div class="r-head">
    <div>
      <div class="r-head-left">
        <button type="button" class="back-btn" onclick="showPage(2)" aria-label="Back to research report">← Back</button>
        <div class="r-title" id="rTitle">Top 3 Picks</div>
      </div>
      <div class="r-sub">Ranked by Elova — formulation depth · bioavailability · clinical evidence · global sales · real feedback</div>
    </div>
    <div class="r-btns">
      <button type="button" class="bsm fl" onclick="showCmp()" aria-label="Compare supplement ingredients side by side">Ingredient Compare</button>
      <button type="button" class="bsm ol" onclick="showPage(1)" aria-label="Start over from the beginning">↺ Start Over</button>
    </div>
  </div>

  <div class="pgrid" id="pgrid"></div>

  <footer class="footer" role="contentinfo" aria-label="Site footer">
    No ads · No paid placements · Updated weekly &nbsp;|&nbsp;
    <button type="button" onclick="showDisclaimer()" class="disclaimer-lnk" aria-label="View disclaimer and legal information">Disclaimer</button>
    <button type="button" class="life-btn" onclick="adminLogin()" title="admin" aria-label="Admin login">life</button>
    <br><span style="font-size:9px;color:#6B7280;display:block;margin-top:4px;line-height:1.6;">Some product links are affiliate links. Elova.Life may earn a small commission if you purchase through these links — at no additional cost to you. This does not affect our rankings or editorial independence. Prices shown are estimates and subject to change.</span>
  </footer>
</section>

<!-- ══ COMPARE MODAL ══ -->
<div class="modal" id="cmpModal" role="dialog" aria-modal="true" aria-labelledby="cmpTitle">
  <div class="mbd" onclick="closeCmp()"></div>
  <div class="mbox">
    <div class="mhead">
      <div class="mtitle" id="cmpTitle">Ingredient Compare</div>
      <button type="button" class="mclose" onclick="closeCmp()" aria-label="Close">×</button>
    </div>
    <div id="cmpBody"></div>
  </div>
</div>

<!-- ── SEARCHING OVERLAY ── -->
<div class="search-overlay gone" id="searchOverlay" role="status" aria-live="polite">
  <div class="so-logo">Elova<span>.Life</span></div>
  <div class="so-steps">
    <div class="so-step" id="soStep1"><div class="so-step-icon" id="soIcon1">🔍</div><span>Scanning 214+ supplement formulations…</span></div>
    <div class="so-step" id="soStep2"><div class="so-step-icon" id="soIcon2">🧬</div><span>Verifying ingredient bioavailability & dosage…</span></div>
    <div class="so-step" id="soStep3"><div class="so-step-icon" id="soIcon3">📊</div><span>Cross-referencing global sales & user feedback…</span></div>
    <div class="so-step" id="soStep4"><div class="so-step-icon" id="soIcon4">⭐</div><span>Ranking top picks by long-term value…</span></div>
  </div>
  <div class="so-bar-wrap"><div class="so-bar" id="soBar"></div></div>
  <div class="so-status" id="soStatus">Initializing buyer search…</div>
</div>

<!-- ══ DISCLAIMER MODAL ══ -->
<div id="disclaimerModal" role="dialog" aria-modal="true" aria-labelledby="disclaimerTitle"
  style="display:none;position:fixed;inset:0;z-index:9999;align-items:center;justify-content:center;background:rgba(0,0,0,0.55);backdrop-filter:blur(6px);">
  <div style="position:relative;background:#F8FAF8;border-radius:20px;padding:36px 40px;width:min(720px,92vw);max-height:82vh;overflow-y:auto;box-shadow:0 24px 64px rgba(0,0,0,0.18);">
    <button type="button" onclick="closeDisclaimer()" aria-label="Close"
      style="position:absolute;top:16px;right:18px;background:none;border:none;font-size:22px;color:#8A9E8A;cursor:pointer;line-height:1;">×</button>

    <h2 id="disclaimerTitle" style="font-size:20px;font-weight:800;letter-spacing:-0.5px;color:#1A2E1A;margin-bottom:6px;">Legal Disclaimer</h2>
    <p style="font-size:12px;color:#8A9E8A;margin-bottom:28px;">Last updated: May 2026 &nbsp;·&nbsp; Elova.Life</p>

    <div style="font-size:13.5px;color:#3A4E3A;line-height:1.85;">

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">1. For Informational Purposes Only</h3>
      <p style="margin-bottom:20px;">All content published on Elova.Life — including but not limited to product reviews, ingredient analyses, buyer scores, rankings, and editorial commentary — is provided solely for general informational and educational purposes. Nothing on this website constitutes, or is intended to constitute, professional medical advice, diagnosis, treatment, or a substitute for consultation with a qualified healthcare provider.</p>

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">2. Not a Medical Professional</h3>
      <p style="margin-bottom:20px;">Elova is an independent wellness research and buying guide platform. The authors and operators of this site are not licensed physicians, pharmacists, registered dietitians, or other credentialed healthcare professionals. Content should not be used to self-diagnose, self-treat, or replace a personalised consultation with a qualified medical practitioner.</p>

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">3. FDA Disclosure</h3>
      <p style="margin-bottom:20px;">The statements and product reviews published on this website have <strong>not been evaluated by the U.S. Food and Drug Administration (FDA)</strong>. The dietary supplements discussed are not intended to diagnose, treat, cure, or prevent any disease or medical condition. This applies to all products reviewed, regardless of their regulatory status in any jurisdiction.</p>

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">4. Individual Results May Vary</h3>
      <p style="margin-bottom:20px;">Supplement efficacy, safety, and suitability vary significantly between individuals based on age, sex, genetics, existing medical conditions, concurrent medications, lifestyle, and other factors. Any outcomes referenced — whether from clinical studies, user reviews, or editorial commentary — may not reflect your personal experience. Always consult your doctor before beginning, modifying, or discontinuing any supplement regimen.</p>

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">5. Affiliate &amp; Commercial Relationships — FTC Disclosure</h3>
      <p style="margin-bottom:20px;">In compliance with the U.S. Federal Trade Commission's guidelines (16 CFR Part 255), Elova.Life discloses that some product links on this site are affiliate links. This means that if you click a link and make a purchase, Elova.Life may receive a small commission from the retailer or manufacturer — <strong>at no additional cost to you</strong>. Affiliate compensation never influences product rankings, Elova Scores, editorial commentary, or the selection of products reviewed. Our recommendations are determined solely by independent research, formulation analysis, clinical evidence, and aggregated user data. Elova.Life maintains a strict no-paid-placement policy: brands cannot pay to appear in, or be elevated within, our rankings.</p>

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">6. No Endorsement or Affiliation</h3>
      <p style="margin-bottom:20px;">Elova.Life is not affiliated with, sponsored by, or otherwise compensated by any brand, manufacturer, retailer, or distributor featured on this site beyond the affiliate relationships disclosed above. Product names, brand names, and trademarks are the property of their respective owners and are used for identification purposes only. Mention of a product or brand does not constitute endorsement.</p>

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">7. Price Accuracy &amp; Availability</h3>
      <p style="margin-bottom:20px;">Product prices displayed on Elova.Life are estimates only and are subject to change without notice. Elova.Life makes no guarantee regarding the accuracy, completeness, or current availability of any pricing information. Final prices are determined solely by the third-party retailer at the time of purchase. Elova.Life is not responsible for pricing errors or discrepancies.</p>

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">8. Third-Party Products &amp; Links</h3>
      <p style="margin-bottom:20px;">Elova.Life does not manufacture, distribute, or sell any supplement products. All products referenced are third-party products sold independently by their respective manufacturers and retailers. We make no warranties, express or implied, regarding the safety, quality, labelling accuracy, or regulatory compliance of any product discussed on this site. We recommend purchasing only from reputable, third-party-tested sources.</p>

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">9. Drug Interactions &amp; Medical Conditions</h3>
      <p style="margin-bottom:20px;">Certain dietary supplements may interact with prescription or over-the-counter medications, or may be contraindicated in individuals with specific health conditions including, but not limited to, pregnancy, breastfeeding, kidney disease, liver disease, cardiovascular conditions, autoimmune disorders, or bleeding disorders. If you are currently taking any medications or have an existing medical condition, consult your physician or pharmacist before using any supplement product.</p>

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">10. Accuracy &amp; Content Updates</h3>
      <p style="margin-bottom:20px;">We endeavour to ensure that all information published on this site is accurate, up-to-date, and based on the best available evidence at the time of publication. However, nutritional science and supplement research evolve rapidly. Formulations, ingredient standards, regulatory guidance, and clinical evidence may change. Elova.Life reserves the right to update, revise, or remove any content at any time without prior notice.</p>

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">11. Limitation of Liability</h3>
      <p style="margin-bottom:20px;">To the fullest extent permitted by applicable law, Elova.Life, its operators, contributors, and affiliates shall not be held liable for any direct, indirect, incidental, consequential, or special damages arising from your use of, or reliance on, any information presented on this website. Your use of this site and any supplement products discussed herein is entirely at your own risk.</p>

      <h3 style="font-size:14px;font-weight:700;color:#1A2E1A;margin:0 0 8px;">12. Governing Jurisdiction</h3>
      <p style="margin-bottom:28px;">This disclaimer is governed by and construed in accordance with applicable laws. Users accessing this site from outside the United States are responsible for compliance with their local laws and regulations regarding dietary supplements and health claims.</p>

      <div style="background:#F0FFF4;border:1px solid rgba(52,208,92,0.25);border-radius:12px;padding:16px 20px;">
        <p style="font-size:12.5px;color:#3A5A3A;margin:0;line-height:1.7;">
          <strong>In summary:</strong> Elova.Life is an independent research and editorial platform. We do not provide medical advice. Always consult a qualified healthcare professional before starting any supplement. Nothing here has been evaluated by the FDA, and no product is intended to diagnose, treat, cure, or prevent any disease. Some links are affiliate links — we may earn a commission at no cost to you; this never influences our rankings.
        </p>
      </div>

    </div>

    <div style="margin-top:28px;text-align:center;">
      <button type="button" onclick="closeDisclaimer()"
        style="padding:10px 32px;background:#34D05C;color:#fff;border:none;border-radius:999px;font-size:13px;font-weight:700;cursor:pointer;font-family:'Inter',sans-serif;">
        I Understand
      </button>
    </div>
  </div>
</div>

<div id="toast-fe"></div>
</div><!-- ══ ADMIN ══ -->
<div id="adm-wrapper">

<!-- ══ LOGIN ══ -->
<div id="loginWrap">
  <div class="lcard">
    <div class="llogo">Elova<span>.Life</span></div>
    <div class="lsub">Admin — Content Management</div>
    <div class="llabel">Password</div>
    <input class="linput" type="password" id="pwInput" placeholder="Enter admin password…" autocomplete="current-password" spellcheck="false" onkeydown="if(event.key==='Enter')doLogin()"/>
    <button class="lbtn" onclick="doLogin()" aria-label="Sign in to admin panel">Sign In →</button>
    <div class="lerr" id="loginErr"></div>
  </div>
</div>

<!-- ══ APP ══ -->
<div id="app">
<div class="layout">

<!-- SB1 -->
<aside class="sb1">
  <div class="sb1-logo">Elova<span>.Life</span></div>
  <div class="sb1-sec">Overview</div>
  <div class="sb1-item act" onclick="go('dashboard',this)"><span class="sb1-ic">⬜</span>Dashboard</div>
  <div class="sb1-sec">Page 1 — Home</div>
  <div class="sb1-item" onclick="go('email',this)"><span class="sb1-ic">✉️</span>Email Subscriptions</div>
  <div class="sb1-item" onclick="go('buyer',this)"><span class="sb1-ic">👤</span>Buyer Profile</div>
  <div class="sb1-item" onclick="go('chat',this)"><span class="sb1-ic">💬</span>Chat Messages</div>
  <div class="sb1-item" onclick="go('searchbar',this)"><span class="sb1-ic">🔍</span>Search Bar & Chips</div>
  <div class="sb1-item" onclick="go('sidx',this)"><span class="sb1-ic">🔤</span>Search Suggestions</div>
  <div class="sb1-item" onclick="go('footer',this)"><span class="sb1-ic">🔗</span>Footer & Nav</div>
  <div class="sb1-sec">Page 2 & 3 — Content</div>
  <div class="sb1-item" onclick="go('catlabels',this)"><span class="sb1-ic">🏷</span>Category Labels</div>
  <div class="sb1-item" onclick="go('categories',this)"><span class="sb1-ic">🗂</span>Categories & Content</div>
  <div class="sb1-sec">Settings</div>
  <div class="sb1-item" onclick="go('seo',this)"><span class="sb1-ic">🌐</span>SEO & Meta</div>
  <div class="sb1-item" onclick="go('overlay',this)"><span class="sb1-ic">⏳</span>Search Overlay</div>
  <div class="sb1-item" onclick="go('password',this)"><span class="sb1-ic">🔒</span>Password</div>
  <div class="sb1-foot"><button class="out-btn" onclick="doLogout()" aria-label="Sign out of admin panel">← Sign Out</button></div>
</aside>

<!-- SB2 Category Tree -->
<div class="sb2" id="sb2">
  <div class="sb2-head">
    <div class="sb2-head-title">Category Tree</div>
    <div class="sb2-head-sub">Click sub-category to edit content</div>
  </div>
  <div id="catTree"></div>
</div>

<!-- MAIN -->
<main class="main"><div class="mi">

<!-- DASHBOARD -->
<div class="view on" id="view-dashboard">
  <div class="ph"><div><div class="ph-t">Dashboard</div><div class="ph-s">Frontend ↔ Backend full overview — All editable content</div></div></div>
  <div class="stats">
    <div class="stat"><div class="sv">10</div><div class="sk">DATA need keys (main data keys)</div></div>
    <div class="stat"><div class="sv">30</div><div class="sk">Total product cards (3×10)</div></div>
    <div class="stat"><div class="sv">22</div><div class="sk">Sub-category count</div></div>
    <div class="stat"><div class="sv">13</div><div class="sk">Search suggestion entries</div></div>
  </div>
  <div class="card"><div class="ch"><div class="ct">Usage Guide</div></div>
  <div class="cb">
    <div class="notice ng">📌 <strong>Page 2 &amp; 3 editing workflow:</strong> Click <strong>Categories &amp; Content</strong> in the sidebar → Expand the category tree → Select a sub-category → The right panel loads all Page 2 (video, article, options) and Page 3 (3 products) fields.</div>
    <table style="width:100%;border-collapse:collapse;font-size:12px;">
      <thead><tr style="border-bottom:1px solid var(--border);">
        <th style="text-align:left;padding:7px 10px;font-size:10px;text-transform:uppercase;letter-spacing:1px;color:var(--text3);">Section</th>
        <th style="text-align:left;padding:7px 10px;font-size:10px;text-transform:uppercase;letter-spacing:1px;color:var(--text3);">Covers</th>
      </tr></thead>
      <tbody id="dashTable"></tbody>
    </table>
  </div></div>
</div>

<!-- EMAIL SUBSCRIPTION -->
<div class="view" id="view-email">
  <div class="ph"><div><div class="ph-t">Email Subscriptions</div><div class="ph-s">Navbar subscribe text · subscriber count · subscriber list management</div></div>
  <button class="btn btn-g btn-sm" onclick="toast()">Save</button></div>

  <!-- Stats -->
  <div class="stats">
    <div class="stat"><div class="sv" style="font-size:22px;">2,847</div><div class="sk">Total subscribers</div></div>
    <div class="stat"><div class="sv" style="font-size:22px;">+38</div><div class="sk">New today</div></div>
    <div class="stat"><div class="sv" style="font-size:22px;">94.2%</div><div class="sk">Delivery rate</div></div>
    <div class="stat"><div class="sv" style="font-size:22px;">28.7%</div><div class="sk">Open rate</div></div>
  </div>

  <!-- UI Text -->
  <div class="card"><div class="ch"><div class="ct">Navbar Subscribe Text</div><div class="cs">Top navigation bar subscribe area</div></div><div class="cb">
    <div class="gr2">
      <div class="fg"><label>Input Placeholder <span class="hn">Frontend input#subEmail</span></label><input class="fi" type="text" value="Your email for weekly wellness picks…"/></div>
      <div class="fg"><label>Subscribe button text</label><input class="fi" type="text" value="Subscribe"/></div>
    </div>
    <div class="fg"><label>Post-subscribe button text <span class="hn">Shown for 3 seconds after handleSub()</span></label><input class="fi" type="text" value="✓ You're in!"/></div>
  </div></div>

  <!-- Subscriber list -->
  <div class="card"><div class="ch">
    <div><div class="ct">Subscriber List</div><div class="cs">Filter by date · copy all · download CSV</div></div>
    <div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;">
      <input type="date" class="fi" style="width:140px;height:32px;padding:0 8px;" value="2026-05-01"/>
      <span style="font-size:12px;color:var(--text3);">to</span>
      <input type="date" class="fi" style="width:140px;height:32px;padding:0 8px;" value="2026-05-24"/>
      <button class="btn btn-w btn-sm" onclick="toast('✓ Filtered')">Filter</button>
      <button class="btn btn-g btn-sm" onclick="copyEmails()" aria-label="Copy all subscriber emails to clipboard">📋 Copy All</button>
      <button class="btn btn-w btn-sm" onclick="dlCsv()" aria-label="Download subscribers as CSV file">⬇️ Download CSV</button>
    </div>
  </div><div class="cb" style="padding:0;">
    <table style="width:100%;border-collapse:collapse;font-size:12.5px;">
      <thead><tr style="background:#fafcfa;">
        <th style="padding:10px 14px;text-align:left;font-size:10px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--text3);border-bottom:1px solid var(--border);"><input type="checkbox" onchange="selAll(this)" aria-label="Select all"/></th>
        <th style="padding:10px 14px;text-align:left;font-size:10px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--text3);border-bottom:1px solid var(--border);">Email Address</th>
        <th style="padding:10px 14px;text-align:left;font-size:10px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--text3);border-bottom:1px solid var(--border);">Subscribe Date</th>
        <th style="padding:10px 14px;text-align:left;font-size:10px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--text3);border-bottom:1px solid var(--border);">Source</th>
        <th style="padding:10px 14px;text-align:left;font-size:10px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--text3);border-bottom:1px solid var(--border);">Actions</th>
      </tr></thead>
      <tbody id="emailTbody">
        <tr><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><input type="checkbox" aria-label="Select row"/></td><td style="padding:9px 14px;border-bottom:1px solid var(--border);font-weight:500;">sarah@example.com</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">2026-05-24</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">Navbar</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><button class="btn btn-w btn-sm" style="color:#c04040;border-color:rgba(200,60,60,.2);" onclick="this.closest('tr').remove();toast('✓ Deleted')">Delete</button></td></tr>
        <tr><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><input type="checkbox" aria-label="Select row"/></td><td style="padding:9px 14px;border-bottom:1px solid var(--border);font-weight:500;">alex.johnson@gmail.com</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">2026-05-24</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">Navbar</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><button class="btn btn-w btn-sm" style="color:#c04040;border-color:rgba(200,60,60,.2);" onclick="this.closest('tr').remove();toast('✓ Deleted')">Delete</button></td></tr>
        <tr><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><input type="checkbox" aria-label="Select row"/></td><td style="padding:9px 14px;border-bottom:1px solid var(--border);font-weight:500;">wellness.fan@outlook.com</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">2026-05-23</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">Navbar</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><button class="btn btn-w btn-sm" style="color:#c04040;border-color:rgba(200,60,60,.2);" onclick="this.closest('tr').remove();toast('✓ Deleted')">Delete</button></td></tr>
        <tr><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><input type="checkbox" aria-label="Select row"/></td><td style="padding:9px 14px;border-bottom:1px solid var(--border);font-weight:500;">mike_r@proton.me</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">2026-05-23</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">Navbar</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><button class="btn btn-w btn-sm" style="color:#c04040;border-color:rgba(200,60,60,.2);" onclick="this.closest('tr').remove();toast('✓ Deleted')">Delete</button></td></tr>
        <tr><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><input type="checkbox" aria-label="Select row"/></td><td style="padding:9px 14px;border-bottom:1px solid var(--border);font-weight:500;">j.park.health@yahoo.com</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">2026-05-22</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">Navbar</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><button class="btn btn-w btn-sm" style="color:#c04040;border-color:rgba(200,60,60,.2);" onclick="this.closest('tr').remove();toast('✓ Deleted')">Delete</button></td></tr>
        <tr><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><input type="checkbox" aria-label="Select row"/></td><td style="padding:9px 14px;border-bottom:1px solid var(--border);font-weight:500;">celine.d@icloud.com</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">2026-05-22</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text3);">Navbar</td><td style="padding:9px 14px;border-bottom:1px solid var(--border);"><button class="btn btn-w btn-sm" style="color:#c04040;border-color:rgba(200,60,60,.2);" onclick="this.closest('tr').remove();toast('✓ Deleted')">Delete</button></td></tr>
        <tr><td style="padding:9px 14px;"><input type="checkbox" aria-label="Select row"/></td><td style="padding:9px 14px;font-weight:500;">tom.watson@gmail.com</td><td style="padding:9px 14px;color:var(--text3);">2026-05-21</td><td style="padding:9px 14px;color:var(--text3);">Navbar</td><td style="padding:9px 14px;"><button class="btn btn-w btn-sm" style="color:#c04040;border-color:rgba(200,60,60,.2);" onclick="this.closest('tr').remove();toast('✓ Deleted')">Delete</button></td></tr>
      </tbody>
    </table>
  </div></div>
</div>

<!-- BUYER PROFILE -->
<div class="view" id="view-buyer">
  <div class="ph"><div><div class="ph-t">Buyer Profile</div><div class="ph-s">Left intro card on Page 1</div></div>
  <button class="btn btn-g btn-sm" onclick="toast()">Save</button></div>
  <div class="card"><div class="ch"><div class="ct">LIVE Badge &amp; Typewriter</div><div class="cs">Frontend .intro-live + #introTyped</div></div>
  <div class="cb">
    <div class="fg"><label>LIVE badge text <span class="hn">Frontend .intro-live: "Elova · Independent Wellness Buyer" (next to green dot)</span></label><input class="fi" type="text" value="Elova · Independent Wellness Buyer"/></div>
    <div class="div"></div>
    <div class="slabel">Typewriter loop lines (4 lines, frontend lines[])</div>
    <div class="gr2" id="twLines"></div>
  </div></div>
  <div class="card"><div class="ch"><div class="ct">"Why Elova is Different" — Card Title &amp; 4 Feature Rows</div><div class="cs">Frontend .diff-card</div></div>
  <div class="cb">
    <div class="fg"><label>Card title text <span class="hn">Frontend .diff-title: "Why Elova is different"</span></label><input class="fi" type="text" value="Why Elova is different"/></div>
    <div class="div"></div>
    <div class="slabel">4 feature rows (icon + bold + description — frontend .diff-row)</div>
    <div id="diffRows"></div>
  </div></div>
</div>

<!-- CHAT -->
<div class="view" id="view-chat">
  <div class="ph"><div><div class="ph-t">Chat Messages</div><div class="ph-s">5 bubbles — alternates Elova (E) / User (🙋)</div></div>
  <button class="btn btn-g btn-sm" onclick="toast()">Save</button></div>
  <div class="card"><div class="ch"><div class="ct">Chat Section Header</div><div class="cs">Frontend .chat-label-top</div></div>
  <div class="cb"><div class="fg"><label>Header text <span class="hn">Frontend: "How I work with you"</span></label><input class="fi" type="text" value="How I work with you"/></div></div></div>
  <div class="card"><div class="cb" id="chatFields"></div></div>
</div>

<!-- SEARCH BAR & CHIPS -->
<div class="view" id="view-searchbar">
  <div class="ph"><div><div class="ph-t">Search Bar & Chips</div><div class="ph-s">Engine card, navbar and quick chip tags</div></div>
  <button class="btn btn-g btn-sm" onclick="toast()">Save</button></div>

  <div class="card"><div class="ch"><div class="ct">Navbar — Logo & Subscribe</div><div class="cs">Top navigation bar</div></div>
  <div class="cb">
    <div class="gr2">
      <div class="fg"><label>Logo main text <span class="hn">"Elova" dark portion</span></label><input class="fi" type="text" value="Elova"/></div>
      <div class="fg"><label>Logo green suffix <span class="hn">".Life" animated green portion</span></label><input class="fi" type="text" value=".Life"/></div>
    </div>
    <div class="gr2">
      <div class="fg"><label>Subscribe input placeholder</label><input class="fi" type="text" value="Your email for weekly wellness picks…"/></div>
      <div class="fg"><label>Subscribe button default text</label><input class="fi" type="text" value="Subscribe"/></div>
    </div>
    <div class="fg"><label>Post-subscribe button text <span class="hn">Shown 3 sec after handleSub(), frontend: "✓ You're in!"</span></label><input class="fi" type="text" value="✓ You're in!"/></div>
  </div></div>

  <div class="card"><div class="ch"><div class="ct">Search Bar Text</div><div class="cs">Homepage search engine card</div></div>
  <div class="cb"><div class="gr2">
    <div class="fg"><label>Step label / guide text</label><input class="fi" type="text" value="Or tell me your goal — I'll find your stack right away."/></div>
    <div class="fg"><label>Search Placeholder <span class="hn">before category selected</span></label><input class="fi" type="text" value="e.g. I can't sleep, I feel bloated, I need more energy…"/></div>
    <div class="fg"><label>Search Placeholder <span class="hn">after top-level category selected</span></label><input class="fi" type="text" value="Select a sub-category or type your concern…"/></div>
    <div class="fg"><label>"Find My Stack" button</label><input class="fi" type="text" value="Find My Stack"/></div>
  </div></div></div>
  <div class="card">
    <div class="ch"><div><div class="ct">Quick Chips</div><div class="cs">6 floating tags — each maps to a DATA need key</div></div>
    <button class="btn btn-w btn-sm" onclick="addChip()">+ Add</button></div>
    <div class="cb">
      <div class="notice ng">Each chip sets <strong>currentNeed</strong> which drives Pages 2 & 3 content.</div>
      <div id="chipsEditor"></div>
    </div>
  </div>
</div>

<!-- AUTOCOMPLETE -->
<div class="view" id="view-sidx">
  <div class="ph"><div><div class="ph-t">Search Suggestions</div><div class="ph-s">Dropdown suggestions shown as user types in the search box (max 5 shown)</div></div>
  <div class="ph-a"><button class="btn btn-w btn-sm" onclick="addSidx()">+ Add</button>
  <button class="btn btn-g btn-sm" onclick="toast()">Save</button></div></div>
  <div class="notice ng">
    💡 <strong>What this is:</strong> When a user types a keyword in the homepage search box (e.g. "sleep", "collagen"), the system fuzzy-matches against these entries and shows up to 5 suggestions. Clicking a suggestion navigates directly to the matching Page 2 content.<br>
    Each entry contains: <strong>Icon</strong> (shown left of the suggestion) · <strong>Name</strong> (main title, matched against user input) · <strong>Sub-label</strong> (description subtitle) · <strong>Tag</strong> (small right-side tag, e.g. "Sleep") · <strong>Need Key</strong> (determines which Page 2/3 content loads; must be a key from DATA)
  </div>
  <div class="card"><div class="cb">
    <div style="display:grid;grid-template-columns:36px 1fr 1.5fr 68px 84px 30px;gap:6px;padding-bottom:8px;border-bottom:1px solid var(--border);margin-bottom:8px;">
      <div style="font-size:10px;font-weight:700;color:var(--text3);text-transform:uppercase;">Icon</div>
      <div style="font-size:10px;font-weight:700;color:var(--text3);text-transform:uppercase;">Name</div>
      <div style="font-size:10px;font-weight:700;color:var(--text3);text-transform:uppercase;">Sub-label</div>
      <div style="font-size:10px;font-weight:700;color:var(--text3);text-transform:uppercase;">Tag</div>
      <div style="font-size:10px;font-weight:700;color:var(--text3);text-transform:uppercase;">Need Key</div>
      <div></div>
    </div>
    <div id="sidxList"></div>
  </div></div>
</div>

<!-- FOOTER -->
<div class="view" id="view-footer">
  <div class="ph"><div><div class="ph-t">Footer & Nav</div><div class="ph-s">Footer + hidden admin entry + Page 2/3 static text</div></div>
  <button class="btn btn-g btn-sm" onclick="toast()">Save</button></div>

  <div class="card"><div class="ch"><div><div class="ct">Disclaimer</div><div class="cs">Full disclaimer shown when user clicks the footer "Disclaimer" link</div></div></div><div class="cb">
    <div class="notice ng">💡 This content appears when a user clicks the footer <strong>Disclaimer</strong> link. Keep FDA and "not medical advice" keywords to comply with US FTC/FDA requirements.</div>
    <div class="fg"><label>Section 1 — For Informational Purposes Only</label>
      <textarea class="fi" rows="4">All content published on Elova.Life — including product reviews, ingredient analyses, buyer scores, rankings, and editorial commentary — is provided solely for general informational and educational purposes. Nothing on this website constitutes professional medical advice, diagnosis, treatment, or a substitute for consultation with a qualified healthcare provider.</textarea></div>
    <div class="fg"><label>Section 2 — Not a Medical Professional</label>
      <textarea class="fi" rows="3">Elova is an independent wellness research and buying guide platform. The authors and operators of this site are not licensed physicians, pharmacists, or registered dietitians. Content should not be used to self-diagnose, self-treat, or replace a personalised consultation with a qualified medical practitioner.</textarea></div>
    <div class="fg"><label>Section 3 — FDA Disclosure</label>
      <textarea class="fi" rows="3">The statements and product reviews published on this website have not been evaluated by the U.S. Food and Drug Administration (FDA). The dietary supplements discussed are not intended to diagnose, treat, cure, or prevent any disease or medical condition.</textarea></div>
    <div class="fg"><label>Section 4 — Individual Results May Vary</label>
      <textarea class="fi" rows="3">Supplement efficacy, safety, and suitability vary significantly between individuals based on age, sex, genetics, existing medical conditions, concurrent medications, and lifestyle. Always consult your doctor before beginning, modifying, or discontinuing any supplement regimen.</textarea></div>
    <div class="fg"><label>Section 5 — No Endorsement or Affiliation</label>
      <textarea class="fi" rows="3">Elova.Life operates with a strict no-paid-placement policy. We are not affiliated with, sponsored by, or compensated by any brand featured on this site. Affiliate links do not influence rankings, scores, or editorial content.</textarea></div>
    <div class="fg"><label>Section 6 — Third-Party Products &amp; Links</label>
      <textarea class="fi" rows="3">Elova.Life does not manufacture, distribute, or sell any supplement products. All products referenced are third-party products. We make no warranties regarding the safety, quality, or regulatory compliance of any product discussed on this site.</textarea></div>
    <div class="fg"><label>Section 7 — Drug Interactions &amp; Medical Conditions</label>
      <textarea class="fi" rows="3">Certain supplements may interact with medications or may be contraindicated in individuals with specific health conditions including pregnancy, breastfeeding, kidney disease, liver disease, cardiovascular conditions, or bleeding disorders. Consult your physician before use.</textarea></div>
    <div class="fg"><label>Section 8 — Accuracy &amp; Content Updates</label>
      <textarea class="fi" rows="3">We endeavour to ensure all information is accurate and evidence-based at time of publication. Nutritional science evolves rapidly. Elova.Life reserves the right to update, revise, or remove any content at any time without prior notice.</textarea></div>
    <div class="fg"><label>Section 9 — Limitation of Liability</label>
      <textarea class="fi" rows="3">To the fullest extent permitted by applicable law, Elova.Life and its operators shall not be held liable for any damages arising from your use of, or reliance on, any information presented on this website. Use of this site is at your own risk.</textarea></div>
    <div class="fg"><label>Section 10 — Governing Jurisdiction</label>
      <textarea class="fi" rows="3">This disclaimer is governed by applicable laws. Users accessing this site from outside the United States are responsible for compliance with their local laws and regulations regarding dietary supplements and health claims.</textarea></div>
    <div class="fg"><label>Summary text <span class="hn">(shown in green info box)</span></label>
      <textarea class="fi" rows="3">Elova.Life is an independent research and editorial platform. We do not provide medical advice. Always consult a qualified healthcare professional before starting any supplement. Nothing here has been evaluated by the FDA, and no product is intended to diagnose, treat, cure, or prevent any disease.</textarea></div>
    <div class="fg"><label>"I Understand" button text</label><input class="fi" type="text" value="I Understand"/></div>
  </div></div>

  <div class="card"><div class="ch"><div class="ct">Footer (Homepage + Page 3)</div></div><div class="cb">
    <div class="fg"><label>Footer main text</label><input class="fi" type="text" value="No ads · No paid placements · Updated weekly"/></div>
    <div class="gr2">
      <div class="fg"><label>Link 1 text</label><input class="fi" type="text" value="Ingredient Index"/></div>
      <div class="fg"><label>Link 1 URL</label><input class="fi" type="text" value="/ingredients"/></div>
    </div>
    <div class="fg"><label>Hidden admin button text <span class="hn">Frontend: "life" (subtle button, click to open password prompt)</span></label><input class="fi" type="text" value="life"/></div>
  </div></div>

  <div class="card"><div class="ch"><div class="ct">Page 2 — Top Bar Text</div><div class="cs">Deep Dive page top navigation area</div></div><div class="cb">
    <div class="gr2">
      <div class="fg"><label>Back button text <span class="hn">Frontend: "← Back"</span></label><input class="fi" type="text" value="← Back"/></div>
      <div class="fg"><label>Page title text <span class="hn">Frontend id="p2Title", dynamically appended as "Deep Dive · Sleep"</span></label><input class="fi" type="text" value="Deep Dive"/></div>
    </div>
    <div class="slabel" style="margin-top:8px;">Progress bar step labels</div>
    <div class="gr3">
      <div class="fg"><label>Step 1 <span class="hn">(shows ✓ when complete)</span></label><input class="fi" type="text" value="Tell Me"/></div>
      <div class="fg"><label>Step 2 <span class="hn">(current page)</span></label><input class="fi" type="text" value="Deep Dive"/></div>
      <div class="fg"><label>Step 3</label><input class="fi" type="text" value="My Picks"/></div>
    </div>
    <div class="gr2">
      <div class="fg"><label>Right column subtitle <span class="hn">"Select all that apply — helps me match better"</span></label><input class="fi" type="text" value="Select all that apply — helps me match better"/></div>
      <div class="fg"><label>Selected count prefix <span class="hn">"Selected: 0"</span></label><input class="fi" type="text" value="Selected:"/></div>
    </div>
    <div class="fg"><label>"Show My Picks" button text <span class="hn">Bottom of right column, navigates to Page 3</span></label><input class="fi" type="text" value="Show My Picks"/></div>
  </div></div>

  <div class="card"><div class="ch"><div class="ct">Page 3 — Top Bar &amp; Button Text</div></div><div class="cb">
    <div class="fg"><label>Ranking Sub-line</label><input class="fi" type="text" value="Ranked by Elova — formulation depth · bioavailability · clinical evidence · global sales · real feedback"/></div>
    <div class="gr2">
      <div class="fg"><label>"Ingredient Compare" button</label><input class="fi" type="text" value="Ingredient Compare"/></div>
      <div class="fg"><label>"Start Over" button</label><input class="fi" type="text" value="↺ Start Over"/></div>
    </div>
    <div class="gr2">
      <div class="fg"><label>#1 product badge text <span class="hn">Frontend: "⭐ Top Pick"</span></label><input class="fi" type="text" value="⭐ Top Pick"/></div>
      <div class="fg"><label>#2 / #3 badge prefix <span class="hn">Frontend: "Pick #2" / "Pick #3"</span></label><input class="fi" type="text" value="Pick #"/></div>
    </div>
    <div class="gr2">
      <div class="fg"><label>#1 product buy button text <span class="hn">Frontend: "Buy Now — Official Store"</span></label><input class="fi" type="text" value="Buy Now — Official Store"/></div>
      <div class="fg"><label>#2 / #3 product view button text <span class="hn">Frontend: "View Product"</span></label><input class="fi" type="text" value="View Product"/></div>
    </div>
    <div class="fg"><label>Compare Modal title <span class="hn">Frontend id="cmpTitle", dynamically appended as "Ingredient Compare · Sleep"</span></label><input class="fi" type="text" value="Ingredient Compare"/></div>
    <div class="div"></div>
    <div class="slabel">Compare Modal table headers (frontend .ctbl thead)</div>
    <div class="gr3">
      <div class="fg"><label>Col 1 — Product</label><input class="fi" type="text" value="Product"/></div>
      <div class="fg"><label>Col 2 — Score</label><input class="fi" type="text" value="Score"/></div>
      <div class="fg"><label>Col 3 — Key Attributes</label><input class="fi" type="text" value="Key Attributes"/></div>
    </div>
    <div class="gr3">
      <div class="fg"><label>Col 4 — Rating</label><input class="fi" type="text" value="Rating"/></div>
      <div class="fg"><label>Col 5 — Reviews</label><input class="fi" type="text" value="Reviews"/></div>
      <div class="fg"><label>Col 6 — Rank</label><input class="fi" type="text" value="Rank"/></div>
    </div>
    <div class="fg"><label>Col 7 — Verdict</label><input class="fi" type="text" value="Verdict"/></div>
    <div class="div"></div>
    <div class="slabel">Page 3 — rTitle dynamic titleMap entries</div>
    <div class="notice ng" style="margin-bottom:10px;">The frontend titleMap determines the suffix of "Top 3 Picks · <strong>Sleep &amp; Rest</strong>". The 10 entries below correspond to the 10 DATA need keys.</div>
    <div class="gr2">
      <div class="fg"><label>sleep → </label><input class="fi" type="text" value="Sleep &amp; Rest"/></div>
      <div class="fg"><label>gut → </label><input class="fi" type="text" value="Gut &amp; Digestion"/></div>
      <div class="fg"><label>stress → </label><input class="fi" type="text" value="Stress &amp; Anxiety"/></div>
      <div class="fg"><label>energy → </label><input class="fi" type="text" value="Focus &amp; Productivity"/></div>
      <div class="fg"><label>longevity → </label><input class="fi" type="text" value="Longevity &amp; Aging"/></div>
      <div class="fg"><label>immunity → </label><input class="fi" type="text" value="Immunity &amp; Defense"/></div>
      <div class="fg"><label>weight → </label><input class="fi" type="text" value="Weight &amp; Shape"/></div>
      <div class="fg"><label>recovery → </label><input class="fi" type="text" value="Muscle &amp; Recovery"/></div>
      <div class="fg"><label>skin → </label><input class="fi" type="text" value="Skin &amp; Collagen"/></div>
      <div class="fg"><label>mood → </label><input class="fi" type="text" value="Memory &amp; Mind"/></div>
    </div>
  </div></div>
</div>

<!-- CATEGORY LABELS -->
<div class="view" id="view-catlabels">
  <div class="ph"><div><div class="ph-t">Category Labels</div><div class="ph-s">Top-level category dropdown text (homepage search &lt;select&gt;)</div></div>
  <button class="btn btn-g btn-sm" onclick="toast()">Save</button></div>
  <div class="notice ng">These 7 labels map to the top-level category dropdown on the homepage search bar and the sidebar category tree headers.</div>
  <div class="card"><div class="ch"><div class="ct">7 Top-Level Category Names</div><div class="cs">Frontend &lt;option&gt; text + CAT_TREE label</div></div>
  <div class="cb"><div class="gr2">
    <div class="fg"><label>Category 1 Emoji + text <span class="hn">Frontend: "😴 Sleep &amp; Rest"</span></label><input class="fi" type="text" value="😴 Sleep &amp; Rest"/></div>
    <div class="fg"><label>Category 2 <span class="hn">Frontend: "🧠 Mind &amp; Brain"</span></label><input class="fi" type="text" value="🧠 Mind &amp; Brain"/></div>
    <div class="fg"><label>Category 3 <span class="hn">Frontend: "💪 Physical Performance"</span></label><input class="fi" type="text" value="💪 Physical Performance"/></div>
    <div class="fg"><label>Category 4 <span class="hn">Frontend: "🫀 Internal Systems"</span></label><input class="fi" type="text" value="🫀 Internal Systems"/></div>
    <div class="fg"><label>Category 5 <span class="hn">Frontend: "🔬 Longevity &amp; Aging"</span></label><input class="fi" type="text" value="🔬 Longevity &amp; Aging"/></div>
    <div class="fg"><label>Category 6 <span class="hn">Frontend: "✨ Beauty &amp; Skin"</span></label><input class="fi" type="text" value="✨ Beauty &amp; Skin"/></div>
    <div class="fg"><label>Category 7 <span class="hn">Frontend: "⚖️ Weight &amp; Shape"</span></label><input class="fi" type="text" value="⚖️ Weight &amp; Shape"/></div>
  </div></div></div>
  <div class="card"><div class="ch"><div class="ct">Sub-Category Names</div><div class="cs">CAT_TREE sub labels — 22 entries total</div></div>
  <div class="cb">
    <div class="slabel">😴 Sleep &amp; Rest</div>
    <div class="gr3">
      <div class="fg"><label>Sub 1</label><input class="fi" type="text" value="• Sleep Quality"/></div>
      <div class="fg"><label>Sub 2</label><input class="fi" type="text" value="• Fall Asleep"/></div>
      <div class="fg"><label>Sub 3</label><input class="fi" type="text" value="• Circadian Rhythm"/></div>
    </div>
    <div class="slabel">🧠 Mind &amp; Brain</div>
    <div class="gr3">
      <div class="fg"><label>Sub 1</label><input class="fi" type="text" value="• Focus &amp; Productivity"/></div>
      <div class="fg"><label>Sub 2</label><input class="fi" type="text" value="• Stress &amp; Anxiety"/></div>
      <div class="fg"><label>Sub 3</label><input class="fi" type="text" value="• Memory &amp; Neuro"/></div>
    </div>
    <div class="slabel">💪 Physical Performance</div>
    <div class="gr3">
      <div class="fg"><label>Sub 1</label><input class="fi" type="text" value="• Energy &amp; Vitality"/></div>
      <div class="fg"><label>Sub 2</label><input class="fi" type="text" value="• Muscle &amp; Recovery"/></div>
      <div class="fg"><label>Sub 3</label><input class="fi" type="text" value="• Joint &amp; Bone"/></div>
    </div>
    <div class="slabel">🫀 Internal Systems</div>
    <div class="gr3">
      <div class="fg"><label>Sub 1</label><input class="fi" type="text" value="• Gut &amp; Digestion"/></div>
      <div class="fg"><label>Sub 2</label><input class="fi" type="text" value="• Immunity &amp; Defense"/></div>
      <div class="fg"><label>Sub 3</label><input class="fi" type="text" value="• Heart &amp; Cardio"/></div>
      <div class="fg"><label>Sub 4</label><input class="fi" type="text" value="• Metabolism"/></div>
    </div>
    <div class="slabel">🔬 Longevity &amp; Aging</div>
    <div class="gr3">
      <div class="fg"><label>Sub 1</label><input class="fi" type="text" value="• Cellular Health"/></div>
      <div class="fg"><label>Sub 2</label><input class="fi" type="text" value="• Hormone Balance"/></div>
      <div class="fg"><label>Sub 3</label><input class="fi" type="text" value="• DNA &amp; Epigenetics"/></div>
    </div>
    <div class="slabel">✨ Beauty &amp; Skin</div>
    <div class="gr3">
      <div class="fg"><label>Sub 1</label><input class="fi" type="text" value="• Skin &amp; Collagen"/></div>
      <div class="fg"><label>Sub 2</label><input class="fi" type="text" value="• Hair &amp; Nail"/></div>
      <div class="fg"><label>Sub 3</label><input class="fi" type="text" value="• Sun &amp; Repair"/></div>
    </div>
    <div class="slabel">⚖️ Weight &amp; Shape</div>
    <div class="gr3">
      <div class="fg"><label>Sub 1</label><input class="fi" type="text" value="• Fat Metabolism"/></div>
      <div class="fg"><label>Sub 2</label><input class="fi" type="text" value="• Appetite Control"/></div>
      <div class="fg"><label>Sub 3</label><input class="fi" type="text" value="• Detox &amp; Cleanse"/></div>
    </div>
  </div></div>
</div>

<!-- CATEGORIES & CONTENT -->
<div class="view" id="view-categories">
  <div class="ph">
    <div><div class="ph-t">Categories & Content</div><div class="ph-s">Select a sub-category from the tree → edit Page 2 article + Page 3 products</div></div>
    <button class="btn btn-g btn-sm" id="saveCatBtn" style="display:none" onclick="toast()">Save Changes</button>
  </div>
  <div class="bc" id="breadcrumb" style="display:none">
    <strong id="bc1"></strong><span style="color:var(--border2)">›</span>
    <strong id="bc2"></strong><span style="color:var(--border2)">›</span>
    <span>DATA key:</span><span class="need-tag" id="bc3"></span>
  </div>
  <div id="emptyState">
    <div class="empty"><div class="empty-ico">🗂</div>
    <div class="empty-t">Pick a <strong>top-level category</strong> then a <strong>sub-category</strong><br>from the left tree to edit its Page 2 & Page 3 content.</div></div>
  </div>
  <div id="catEditor" style="display:none">
    <!-- PAGE 2 -->
    <div class="slabel">📄 PAGE 2 — Deep Dive Article</div>
    <div class="card"><div class="ch"><div><div class="ct">Video Panel</div><div class="cs">Left column on Page 2</div></div></div><div class="cb">
      <div class="fg"><label>Video URL <span class="hn">Direct .mp4 link — recommended: H.264, 1080p, &lt;30MB, 15–60s, auto-loop muted</span></label><input class="fi" type="url" id="f_vid"/></div>
      <div class="gr3">
        <div class="fg"><label>Top-left badge text <span class="hn">Frontend: "🎬 Elova Buyer"</span></label><input class="fi" type="text" id="f_vbadge" value="🎬 Elova Buyer"/></div>
        <div class="fg"><label>Bottom-right tag text <span class="hn">Frontend: "Now Reviewing"</span></label><input class="fi" type="text" id="f_vtag" value="Now Reviewing"/></div>
        <div class="fg"><label>Video Caption <span class="hn">Bottom-right caption text</span></label><input class="fi" type="text" id="f_vcap"/></div>
      </div>
    </div></div>
    <div class="card"><div class="ch"><div><div class="ct">Article Card</div><div class="cs">Middle column on Page 2 — maps fully to frontend .art-card</div></div></div><div class="cb">

      <!-- art-tag + art-title -->
      <div class="gr2">
        <div class="fg"><label>Article Tag <span class="hn">Frontend .art-tag — e.g. "Buyer Research · Sleep"</span></label><input class="fi" type="text" id="f_atag"/></div>
        <div class="fg"><label>Article Title <span class="hn">Frontend .art-title — large headline</span></label><input class="fi" type="text" id="f_atitle"/></div>
      </div>

      <!-- art-img -->
      <div class="fg">
        <label>Article Image URL <span class="hn">Frontend .art-img img — landscape image, recommended 1200×500px, JPG/WebP &lt;500KB</span></label>
        <div style="background:#f0faf3;border:1px solid rgba(52,208,92,0.18);border-radius:8px;padding:10px 12px;margin-bottom:6px;font-size:11px;color:#4a7a55;line-height:1.8;">
          📐 Format: JPG / WebP &nbsp;·&nbsp; 📏 Width ≥1200px, Height 400–600px &nbsp;·&nbsp; 💾 &lt;500KB<br>
          💡 Source: <a href="https://unsplash.com" target="_blank" rel="noopener" style="color:#34D05C;font-weight:700;">Unsplash.com</a> — append to URL end: <code style="background:rgba(52,208,92,0.12);padding:1px 5px;border-radius:4px;color:#2a8a45;">?q=80&w=1200&auto=format&fit=crop</code>
        </div>
        <input class="fi" type="url" id="f_aimg" placeholder="https://images.unsplash.com/photo-…?q=80&w=1200&auto=format&fit=crop"/>
      </div>

      <!-- art-body: p / art-hl / p -->
      <div style="border:1px solid rgba(52,208,92,0.15);border-radius:10px;padding:14px;background:#fafcfa;">
        <div style="font-size:10px;font-weight:800;letter-spacing:1.5px;text-transform:uppercase;color:#8ab09a;margin-bottom:12px;">Article Body — 3-part structure (maps to frontend .art-body)</div>

        <div class="fg">
          <label>① &lt;p&gt; Opening paragraph <span class="hn">Regular body text, supports &lt;strong&gt; for bold keywords</span></label>
          <textarea class="fi" rows="3" id="f_abody_p1" placeholder="Over &lt;strong&gt;80% of sleep supplements&lt;/strong&gt; rely on low-dose melatonin with added sugar."></textarea>
        </div>

        <div class="fg">
          <label>② Key Buyer Finding highlight box <span class="hn">Frontend .art-hl — green left-border box, one-sentence core finding</span></label>
          <div style="display:flex;align-items:flex-start;gap:8px;">
            <div style="flex-shrink:0;margin-top:9px;padding:3px 8px;background:#34D05C;border-radius:5px;font-size:9px;font-weight:800;color:#fff;white-space:nowrap;letter-spacing:.5px;">Key Finding</div>
            <textarea class="fi" rows="2" id="f_abody_hl" style="flex:1;" placeholder="The ingredients that genuinely improve deep sleep are Magnesium Bisglycinate and Glycine — not melatonin."></textarea>
          </div>
        </div>

        <div class="fg" style="margin-bottom:0;">
          <label>③ &lt;p&gt; Closing paragraph <span class="hn">Test conclusion, typically starts with "I tested X+ products…"</span></label>
          <textarea class="fi" rows="2" id="f_abody_p2" placeholder="I tested over 40 products. Only a handful passed formulation depth, dosage standards, and third-party testing."></textarea>
        </div>
      </div>
    </div></div>

    <div class="card"><div class="ch"><div><div class="ct">Right Column — Options</div><div class="cs">Frontend .opt-card — user multi-selects then navigates to Page 3</div></div>
      <button class="btn btn-w btn-sm" onclick="addOpt()">+ Add Option</button>
    </div><div class="cb">
      <div class="fg"><label>Section Title <span class="hn">Frontend .opt-label — e.g. "What's your sleep concern?"</span></label><input class="fi" type="text" id="f_otitle"/></div>
      <div class="fg" style="margin-bottom:4px;"><label>Options list <span class="hn">Frontend .opt-list — user multi-selects; clicking "Show My Picks" navigates to Page 3</span></label></div>
      <div id="f_opts_list" style="display:flex;flex-direction:column;gap:6px;margin-bottom:8px;"></div>
    </div></div>
    <!-- PAGE 3 -->
    <div class="slabel" style="margin-top:6px">📦 PAGE 3 — Top 3 Product Picks</div>
    <div class="notice na" id="prodNotice"></div>
    <div id="prodBlocks"></div>
  </div>
</div>

<!-- SEO -->
<div class="view" id="view-seo">
  <div class="ph"><div><div class="ph-t">SEO & Meta</div><div class="ph-s">All &lt;head&gt; meta tags — complete mapping</div></div>
  <button class="btn btn-g btn-sm" onclick="toast()">Save</button></div>
  <div class="card"><div class="ch"><div class="ct">Basic Meta Tags</div></div><div class="cb">
    <div class="fg"><label>Page &lt;title&gt; <span class="hn">Frontend: "Elova.Life — Your Personal Wellness Buyer"</span></label><input class="fi" type="text" value="Elova.Life — Your Personal Wellness Buyer"/></div>
    <div class="fg"><label>Meta description <span class="hn">Frontend content="Elova is your independent wellness buyer…"</span></label><textarea class="fi" rows="2">Elova is your independent wellness buyer — researching 200+ supplements with zero paid placements. Get personalized picks for sleep, gut health, stress, energy, longevity and more.</textarea></div>
    <div class="fg"><label>Meta keywords</label><textarea class="fi" rows="2">wellness buyer, supplement research, independent supplement reviews, sleep supplements, gut health, stress support, longevity, elova life</textarea></div>
    <div class="fg"><label>Meta author</label><input class="fi" type="text" value="Elova.Life"/></div>
    <div class="gr2">
      <div class="fg"><label>Canonical URL</label><input class="fi" type="text" value="https://elova.life/"/></div>
      <div class="fg"><label>Meta robots <span class="hn">Frontend: "index, follow"</span></label><input class="fi" type="text" value="index, follow"/></div>
    </div>
  </div></div>

  <div class="card"><div class="ch"><div class="ct">Open Graph (og:) — Social Share Preview</div></div><div class="cb">
    <div class="gr2">
      <div class="fg"><label>og:title</label><input class="fi" type="text" value="Elova.Life — Your Personal Wellness Buyer"/></div>
      <div class="fg"><label>og:site_name</label><input class="fi" type="text" value="Elova.Life"/></div>
    </div>
    <div class="fg"><label>og:description</label><textarea class="fi" rows="2">Independent supplement research with zero paid placements. Get your personalized wellness picks in 3 steps.</textarea></div>
    <div class="gr2">
      <div class="fg"><label>og:image URL <span class="hn">Recommended size: 1200×630px</span></label><input class="fi" type="text" value="https://elova.life/og-image.jpg"/></div>
      <div class="fg"><label>og:url</label><input class="fi" type="text" value="https://elova.life/"/></div>
    </div>
  </div></div>

  <div class="card"><div class="ch"><div class="ct">Twitter Card</div></div><div class="cb">
    <div class="gr2">
      <div class="fg"><label>twitter:card <span class="hn">Frontend: "summary_large_image"</span></label><input class="fi" type="text" value="summary_large_image"/></div>
      <div class="fg"><label>twitter:site <span class="hn">Frontend: "@elovalife"</span></label><input class="fi" type="text" value="@elovalife"/></div>
    </div>
    <div class="fg"><label>twitter:title</label><input class="fi" type="text" value="Elova.Life — Your Personal Wellness Buyer"/></div>
    <div class="fg"><label>twitter:description</label><input class="fi" type="text" value="Independent supplement research with zero paid placements."/></div>
    <div class="fg"><label>twitter:image URL</label><input class="fi" type="text" value="https://elova.life/og-image.jpg"/></div>
  </div></div>

  <div class="card"><div class="ch"><div class="ct">PWA & Mobile Meta</div><div class="cs">Existing Apple / PWA meta tags in frontend</div></div><div class="cb">
    <div class="gr2">
      <div class="fg"><label>theme-color <span class="hn">Frontend: "#34D05C"</span></label><input class="fi" type="text" value="#34D05C"/></div>
      <div class="fg"><label>apple-mobile-web-app-title</label><input class="fi" type="text" value="Elova.Life"/></div>
    </div>
    <div class="gr2">
      <div class="fg"><label>apple-mobile-web-app-status-bar-style</label><input class="fi" type="text" value="default"/></div>
      <div class="fg"><label>dns-prefetch 1</label><input class="fi" type="text" value="https://images.unsplash.com"/></div>
    </div>
  </div></div>

  <div class="card"><div class="ch"><div class="ct">JSON-LD Structured Data <span class="cs">Schema.org — frontend embeds WebSite + Organization + WebPage</span></div></div><div class="cb">
    <div class="fg"><label>WebSite name</label><input class="fi" type="text" value="Elova.Life"/></div>
    <div class="fg"><label>WebSite url</label><input class="fi" type="text" value="https://elova.life"/></div>
    <div class="fg"><label>WebSite description</label><textarea class="fi" rows="2">Independent wellness buyer platform — personalized supplement recommendations with zero paid placements.</textarea></div>
    <div class="fg"><label>Organization sameAs (Twitter)</label><input class="fi" type="text" value="https://twitter.com/elovalife"/></div>
    <div class="fg"><label>Logo imageUrl</label><input class="fi" type="text" value="https://elova.life/og-image.jpg"/></div>
    <div class="fg"><label>WebPage name</label><input class="fi" type="text" value="Elova.Life — Your Personal Wellness Buyer"/></div>
    <div class="fg"><label>WebPage description</label><textarea class="fi" rows="2">Independent supplement research with zero paid placements. Personalized wellness picks for sleep, gut health, stress, energy, longevity and more.</textarea></div>
  </div></div>
</div>

<!-- OVERLAY -->
<div class="view" id="view-overlay">
  <div class="ph"><div><div class="ph-t">Search Overlay</div><div class="ph-s">Page 2 → Page 3 transition animation (triggered after "Find My Stack")</div></div>
  <button class="btn btn-g btn-sm" onclick="toast()">Save</button></div>
  <div class="card"><div class="ch"><div class="ct">Overlay Logo</div><div class="cs">Logo text shown during the animation</div></div><div class="cb">
    <div class="gr2">
      <div class="fg"><label>Logo main text <span class="hn">Frontend: "Elova"</span></label><input class="fi" type="text" value="Elova"/></div>
      <div class="fg"><label>Logo green suffix <span class="hn">Frontend: &lt;span&gt;".Life"&lt;/span&gt;</span></label><input class="fi" type="text" value=".Life"/></div>
    </div>
  </div></div>
  <div class="card"><div class="ch"><div class="ct">4-Step Loading Text</div><div class="cs">soStep1–4 icons + text</div></div><div class="cb"><div class="gr2">
    <div class="fg"><label>Step 1 Icon</label><input class="fi" type="text" value="🔍"/></div>
    <div class="fg"><label>Step 1 Text</label><input class="fi" type="text" value="Scanning 214+ supplement formulations…"/></div>
    <div class="fg"><label>Step 2 Icon</label><input class="fi" type="text" value="🧬"/></div>
    <div class="fg"><label>Step 2 Text</label><input class="fi" type="text" value="Verifying ingredient bioavailability & dosage…"/></div>
    <div class="fg"><label>Step 3 Icon</label><input class="fi" type="text" value="📊"/></div>
    <div class="fg"><label>Step 3 Text</label><input class="fi" type="text" value="Cross-referencing global sales & user feedback…"/></div>
    <div class="fg"><label>Step 4 Icon</label><input class="fi" type="text" value="⭐"/></div>
    <div class="fg"><label>Step 4 Text</label><input class="fi" type="text" value="Ranking top picks by long-term value…"/></div>
  </div></div></div>
  <div class="card"><div class="ch"><div class="ct">Progress Status Text</div><div class="cs">soStatus — updates dynamically with each step</div></div><div class="cb"><div class="gr2">
    <div class="fg"><label>Initial state <span class="hn">Frontend: "Initializing buyer search…"</span></label><input class="fi" type="text" value="Initializing buyer search…"/></div>
    <div class="fg"><label>After Step 1 activates</label><input class="fi" type="text" value="Analyzing ingredient quality…"/></div>
    <div class="fg"><label>After Step 2 activates</label><input class="fi" type="text" value="Checking clinical dosage data…"/></div>
    <div class="fg"><label>After Step 3 activates</label><input class="fi" type="text" value="Ranking by long-term value…"/></div>
    <div class="fg"><label>Step 4 complete state</label><input class="fi" type="text" value="Your results are ready."/></div>
    <div class="fg"><label>Final transition state <span class="hn">Frontend: "Match found — displaying your picks…"</span></label><input class="fi" type="text" value="Match found — displaying your picks…"/></div>
  </div></div></div>
</div>

<!-- PASSWORD -->
<div class="view" id="view-password">
  <div class="ph"><div><div class="ph-t">Change Password</div></div></div>
  <div class="card" style="max-width:360px"><div class="cb">
    <div class="fg"><label>Current Password</label><input class="fi" type="password" id="curPw"/></div>
    <div class="fg"><label>New Password</label><input class="fi" type="password" id="newPw"/></div>
    <div class="fg"><label>Confirm New Password</label><input class="fi" type="password" id="cfmPw"/></div>
    <button class="btn btn-g" onclick="changePw()" aria-label="Update admin password">Update Password</button>
  </div></div>
</div>

</div></main>
</div></div>
<div id="toast"></div>
</div><script>
// ══ SHARED DATA ══
const DATA={
  sleep:{videoUrl:'https://cdn.coverr.co/videos/coverr-sleeping-woman-2049/1080p.mp4',vBadge:'🎬 Elova Buyer',vTag:'Now Reviewing',vCaption:"Breaking down every sleep supplement — real dosages vs marketing hype. Most brands are failing you.",artTag:"Buyer Research · Sleep",artTitle:"Why Most Sleep Supplements Are Failing You",artImg:"https://images.unsplash.com/photo-1541781774459-bb2af2f05b55?q=80&w=1200&auto=format&fit=crop",artBody:'<p>Over <strong>80% of sleep supplements</strong> rely on low-dose melatonin with added sugar — short-term it may help, long-term it creates dependency and disrupts your natural sleep rhythm.</p>\n<div class=\"art-hl\">Key Buyer Finding: The ingredients that genuinely improve deep sleep are Magnesium Bisglycinate and Glycine — not melatonin.</div>\n<p>I tested over 40 products. <strong>Only a handful passed</strong> formulation depth, dosage standards, and third-party testing — each tracked for a minimum of 8 weeks.</p>',optTitle:"What's your sleep concern?",opts:["Hard to fall asleep, mind won't stop","Wake up at night, can't fall back asleep","Unrested even after 8 hours","Want to improve deep sleep quality","Sensitive to supplements — need gentle formula","I rely on sleep medication and want to wean off","Shift worker or irregular sleep schedule","Looking to improve sleep without melatonin"],products:[{top:true,brand:"Thorne",name:"Magnesium Bisglycinate",img:"https://images.unsplash.com/photo-1584308666744-24d5c474f2ae?q=80&w=800",score:94,rating:"4.8★",reviews:"12.4k",sales:"#1 Global",tags:["No fillers","Clinically dosed","3rd-party tested"],colors:["g","g","g"],url:"https://www.thorne.com",verdict:"Best overall for sleep quality & nervous system recovery.",dose:"200–400mg before bed",form:"Capsule",bestFor:"Adults with sleep issues or high stress",notFor:"Those already on Mg supplements",cert:["NSF Certified","GMP Verified","Gluten-Free"],price:"$28",priceUnit:"/60 caps"},{top:false,brand:"Momentous",name:"Magnesium L-Threonate",img:"https://images.unsplash.com/photo-1559757148-5c350d0d3c56?q=80&w=800",score:88,rating:"4.6★",reviews:"8.1k",sales:"Top 5 US",tags:["Brain-targeted","Premium form","Higher price"],colors:["g","g","r"],url:"https://www.livemomentous.com",verdict:"Best for cognitive + sleep combo. Premium but worth it.",dose:"3 capsules before bed",form:"Capsule",bestFor:"Cognitive decline prevention, deep sleep",notFor:"Budget-conscious buyers",cert:["NSF Sport","Third-party tested"],price:"$58",priceUnit:"/90 caps"},{top:false,brand:"Life Extension",name:"Glycine 1000mg",img:"https://images.unsplash.com/photo-1550572017-edd951b55104?q=80&w=800",score:81,rating:"4.5★",reviews:"6.7k",sales:"Top 10 Global",tags:["Best value","Clean formula","Research backed"],colors:["g","g","g"],url:"https://www.lifeextension.com",verdict:"Best value. No frills, solid research backing.",dose:"1–3g before bed",form:"Capsule / Powder",bestFor:"Anyone wanting gentle sleep support",notFor:"Those needing mineral replenishment",cert:["Non-GMO","GMP Certified"],price:"$12",priceUnit:"/100 caps"}]},
  gut:{videoUrl:'https://cdn.coverr.co/videos/coverr-fresh-vegetables-on-wooden-surface-7200/1080p.mp4',vBadge:'🎬 Elova Buyer',vTag:'Now Reviewing',vCaption:"The probiotic market is full of misleading CFU counts and weak strains. Here's the truth.",artTag:"Buyer Research · Gut",artTitle:"99% of Probiotic Products Aren't Worth Your Money",artImg:"https://images.unsplash.com/photo-1544025162-d76694265947?q=80&w=1200&auto=format&fit=crop",artBody:'<p><strong>CFU count does not equal effectiveness</strong> — what matters is strain diversity and acid resistance. Most cheap products never survive the journey to your gut.</p>\n<div class=\"art-hl\">Key Buyer Finding: Multi-strain + prebiotics + acid-resistant capsule — all three are essential for a genuinely effective gut formula.</div>\n<p>After comparing 30+ product labels, I narrowed it down to brands with independent testing and strain-level scientific literature.</p>',optTitle:"What's your gut concern?",opts:["Bloating & discomfort after meals","Irregular digestion / constipation","Gut-brain axis / mood & digestion","Post-antibiotic microbiome recovery","General microbiome diversity support","Food sensitivities or intolerances","Leaky gut or intestinal permeability","IBS symptoms or chronic gut inflammation"],products:[{top:true,brand:"Seed",name:"DS-01 Daily Synbiotic",img:"https://images.unsplash.com/photo-1498837167922-ddd27525d352?q=80&w=800",score:92,rating:"4.7★",reviews:"18.2k",sales:"#1 DTC",tags:["24 strains","Prebiotics included","Acid-resistant"],colors:["g","g","g"],url:"https://seed.com",verdict:"Gold standard for daily gut maintenance. Peer-reviewed research.",dose:"2 capsules daily with water",form:"Nested capsule",bestFor:"Daily gut maintenance, microbiome diversity",notFor:"Those wanting a budget option",cert:["Third-party tested","Vegan","Non-GMO"],price:"$50",priceUnit:"/month"},{top:false,brand:"Ritual",name:"Synbiotic+",img:"https://images.unsplash.com/photo-1512621776951-a57141f2eefd?q=80&w=800",score:84,rating:"4.5★",reviews:"9.3k",sales:"Top 3 US",tags:["Vegan capsule","Traceable strains","Subscription"],colors:["g","g","r"],url:"https://ritual.com",verdict:"Great for beginners. Clean, transparent, well-tolerated.",dose:"1 capsule daily",form:"Delayed-release capsule",bestFor:"Beginners, clean-label seekers",notFor:"Those who want one-time purchase",cert:["Vegan","Non-GMO","Gluten-Free"],price:"$40",priceUnit:"/month"},{top:false,brand:"Jarrow",name:"Jarro-Dophilus EPS",img:"https://images.unsplash.com/photo-1547592180-85f173990554?q=80&w=800",score:78,rating:"4.4★",reviews:"22.1k",sales:"Top 10 Global",tags:["High value","8 strains","No refrigeration"],colors:["g","g","g"],url:"https://jarrow.com",verdict:"Budget-friendly with solid strain diversity. Good for everyday maintenance.",dose:"1 capsule daily",form:"Enteric-coated capsule",bestFor:"Budget buyers, travel-friendly",notFor:"Those needing high strain count",cert:["GMP Certified","Non-GMO"],price:"$18",priceUnit:"/120 caps"}]},
  stress:{videoUrl:'https://cdn.coverr.co/videos/coverr-woman-meditating-near-a-waterfall-7566/1080p.mp4',vBadge:'🎬 Elova Buyer',vTag:'Now Reviewing',vCaption:"Adaptogens are everywhere — but KSM-66 is the only one with consistent cortisol reduction data.",artTag:"Buyer Research · Stress",artTitle:"What Does a Truly Effective Stress Formula Look Like?",artImg:"https://images.unsplash.com/photo-1506126613408-eca07ce68773?q=80&w=1200&auto=format&fit=crop",artBody:"<p>The stress management market is full of concept products — <strong>genuinely clinical formulas are rare</strong>. KSM-66 Ashwagandha has 12 randomized controlled trials.</p>\n<div class=\"art-hl\">Key Buyer Finding: KSM-66 + L-Theanine is the optimal combination for both acute stress relief and long-term cortisol management.</div>\n<p>After testing 25+ products, the following three showed the most consistent results in purity, dosage, and real user feedback.</p>",optTitle:"How does stress show up for you?",opts:["Racing thoughts, can't wind down","Chronic burnout, low motivation","Anxiety before social or work events","Physical tension, tight shoulders/neck","Mood swings, emotional reactivity","High-cortisol lifestyle — long hours, poor recovery","Looking for non-sedating calm support","Want to reduce caffeine dependency"],products:[{top:true,brand:"Nootropics Depot",name:"KSM-66 Ashwagandha 600mg",img:"https://images.unsplash.com/photo-1514996937319-344454492b37?q=80&w=800",score:95,rating:"4.9★",reviews:"31.5k",sales:"#1 Adaptogen",tags:["Full-spectrum","12 RCTs","Cortisol data"],colors:["g","g","g"],url:"https://nootropicsdepot.com",verdict:"Most researched adaptogen on the market. Unmatched clinical evidence.",dose:"600mg once daily",form:"Capsule",bestFor:"Stress, anxiety, cortisol management",notFor:"Pregnant women",cert:["Third-party tested","GMP Certified"],price:"$24",priceUnit:"/90 caps"},{top:false,brand:"Apothekary",name:"Chill the F* Out Blend",img:"https://images.unsplash.com/photo-1502741338009-cac2772e18bc?q=80&w=800",score:80,rating:"4.5★",reviews:"7.8k",sales:"Top DTC",tags:["Ashwagandha+Theanine","Powder form","Lifestyle brand"],colors:["g","g","r"],url:"https://apothekary.co",verdict:"Good entry-level blend. Effective for mild everyday stress.",dose:"1 tsp daily in water",form:"Powder blend",bestFor:"Lifestyle buyers, mild everyday stress",notFor:"Those needing clinical dosing",cert:["Organic","Non-GMO"],price:"$42",priceUnit:"/30 servings"},{top:false,brand:"Now Foods",name:"L-Theanine 200mg",img:"https://images.unsplash.com/photo-1586201375761-83865001e31c?q=80&w=800",score:83,rating:"4.6★",reviews:"45.2k",sales:"Top 5 Global",tags:["Fast-acting","No drowsiness","High value"],colors:["g","g","g"],url:"https://nowfoods.com",verdict:"Reliable for acute stress relief. Works within 30–60 min.",dose:"200mg as needed",form:"Capsule",bestFor:"Acute stress, calm focus",notFor:"Those wanting adaptogen support",cert:["GMP Certified","Non-GMO"],price:"$14",priceUnit:"/90 caps"}]},
  energy:{videoUrl:'https://cdn.coverr.co/videos/coverr-person-running-on-treadmill-5111/1080p.mp4',vBadge:'🎬 Elova Buyer',vTag:'Now Reviewing',vCaption:"Most energy supplements are just caffeine in a fancy label. Here's what real cognitive support looks like.",artTag:"Buyer Research · Energy",artTitle:"Sustained Energy Without Caffeine Dependency",artImg:"https://images.unsplash.com/photo-1434682881908-b43d0467b798?q=80&w=1200&auto=format&fit=crop",artBody:"<p><strong>The core energy supplement scam</strong>: repackaging high-dose caffeine as cognitive enhancement. Short-term it works, long-term it disrupts sleep rhythm and adrenal function.</p>\n<div class=\"art-hl\">Key Buyer Finding: Real cognitive energy comes from the choline system (Alpha-GPC) and creatine — not stimulant stacking.</div>\n<p>I tested 35+ energy products. The following three performed most consistently over long-term use with no notable crash.</p>",optTitle:"What kind of energy do you need?",opts:["Morning focus without caffeine crash","Sustained afternoon energy","Pre-workout mental sharpness","Brain fog and cognitive clarity","Long-term mitochondrial energy support","Afternoon energy slump after lunch","Need focus for deep work or studying","Recovering from adrenal fatigue or burnout"],products:[{top:true,brand:"Momentous",name:"Alpha-GPC 300mg",img:"https://images.unsplash.com/photo-1559757148-5c350d0d3c56?q=80&w=800",score:91,rating:"4.7★",reviews:"9.8k",sales:"Top 3 Nootropics",tags:["Choline precursor","Cognitive+physical","NSF certified"],colors:["g","g","g"],url:"https://livemomentous.com",verdict:"For cognitive energy and focus. Backed by performance research.",dose:"300mg once daily",form:"Capsule",bestFor:"Cognitive energy, performance athletes",notFor:"Those sensitive to choline",cert:["NSF Certified","Third-party tested"],price:"$45",priceUnit:"/60 caps"},{top:false,brand:"Thorne",name:"Creatine Monohydrate",img:"https://images.unsplash.com/photo-1584308666744-24d5c474f2ae?q=80&w=800",score:89,rating:"4.8★",reviews:"28.4k",sales:"#1 Creatine",tags:["Brain+Muscle","Most studied","Daily use"],colors:["g","g","g"],url:"https://thorne.com",verdict:"Most evidence of any supplement. Cognitive and physical energy.",dose:"5g daily",form:"Powder",bestFor:"Daily energy, muscle and brain function",notFor:"Those with kidney issues",cert:["NSF Certified","GMP Verified"],price:"$36",priceUnit:"/90 servings"},{top:false,brand:"Life Extension",name:"NAD+ Cell Regenerator",img:"https://images.unsplash.com/photo-1550572017-edd951b55104?q=80&w=800",score:82,rating:"4.4★",reviews:"11.2k",sales:"Top 5 Longevity",tags:["Mitochondrial","NMN+resveratrol","Long-term"],colors:["g","g","g"],url:"https://lifeextension.com",verdict:"For long-term cellular energy. Results build over 4–8 weeks.",dose:"1 capsule daily",form:"Capsule",bestFor:"Long-term cellular energy, aging adults",notFor:"Those wanting fast results",cert:["Non-GMO","GMP Certified"],price:"$32",priceUnit:"/30 caps"}]},
  longevity:{videoUrl:'https://cdn.coverr.co/videos/coverr-elderly-couple-walking-in-nature-2085/1080p.mp4',vBadge:'🎬 Elova Buyer',vTag:'Now Reviewing',vCaption:"The longevity space is moving fast — NMN, NR, spermidine. Here's what human data actually supports.",artTag:"Buyer Research · Longevity",artTitle:"The Real State of Longevity Supplement Research",artImg:"https://images.unsplash.com/photo-1559757175-5700dde675bc?q=80&w=1200&auto=format&fit=crop",artBody:"<p>Longevity supplements sit at the boundary between science and hype. <strong>NR (Nicotinamide Riboside) currently has the most human clinical data</strong>, with NMN research catching up fast.</p>\n<div class=\"art-hl\">Key Buyer Finding: NAD+ precursors (NR or NMN) + resveratrol is currently the most complete evidence-based longevity intervention.</div>\n<p>Longevity supplements require long-term commitment. I tracked 6+ months of user feedback to identify the three with the best tolerance and real results.</p>",optTitle:"What's your longevity focus?",opts:["Cellular aging & NAD+ support","Cardiovascular & metabolic health","Cognitive preservation long-term","Inflammation & oxidative stress","Hormonal balance & vitality","Telomere & DNA protection","Metabolic flexibility & insulin sensitivity","Senolytic support — clearing damaged cells"],products:[{top:true,brand:"Tru Niagen",name:"NR 300mg (Niagen®)",img:"https://images.unsplash.com/photo-1512621776951-a57141f2eefd?q=80&w=800",score:90,rating:"4.6★",reviews:"14.3k",sales:"#1 NR Brand",tags:["Patented NR","Human RCT data","NSF certified"],colors:["g","g","g"],url:"https://truniagen.com",verdict:"Most human clinical data for NAD+ precursors. Proven safe for daily use.",dose:"300mg once daily",form:"Capsule",bestFor:"NAD+ support, healthy aging",notFor:"Budget-conscious buyers",cert:["NSF Certified","GMP Verified"],price:"$40",priceUnit:"/month"},{top:false,brand:"Wonderfeel",name:"Youngr™ NMN",img:"https://images.unsplash.com/photo-1498837167922-ddd27525d352?q=80&w=800",score:85,rating:"4.5★",reviews:"5.6k",sales:"Top DTC",tags:["900mg NMN","+Resveratrol","Premium"],colors:["g","g","r"],url:"https://wonderfeel.com",verdict:"Premium NMN stack. Higher dose with synergistic co-factors.",dose:"3 capsules daily",form:"Capsule",bestFor:"Premium longevity stack buyers",notFor:"Budget-conscious buyers",cert:["Third-party tested","Non-GMO"],price:"$88",priceUnit:"/month"},{top:false,brand:"Now Foods",name:"Trans-Resveratrol 200mg",img:"https://images.unsplash.com/photo-1550572017-edd951b55104?q=80&w=800",score:77,rating:"4.4★",reviews:"8.9k",sales:"Top 10 Global",tags:["High value","Polyphenol support","Pairs with NMN/NR"],colors:["g","g","g"],url:"https://nowfoods.com",verdict:"Budget longevity option. Stack with NR or NMN for synergy.",dose:"200mg once daily",form:"Capsule",bestFor:"Budget longevity, stacking with NR/NMN",notFor:"Standalone use without NR/NMN",cert:["GMP Certified","Non-GMO"],price:"$18",priceUnit:"/60 caps"}]},
  immunity:{videoUrl:'https://cdn.coverr.co/videos/coverr-pouring-herbal-tea-8170/1080p.mp4',vBadge:'🎬 Elova Buyer',vTag:'Now Reviewing',vCaption:"Immunity supplements surged post-2020 — most are underdosed or redundant. Here's what's worth taking year-round.",artTag:"Buyer Research · Immunity",artTitle:"One D3 Daily Beats Most Immunity Formulas",artImg:"https://images.unsplash.com/photo-1576671081837-49000212a370?q=80&w=1200&auto=format&fit=crop",artBody:"<p><strong>Over 80% of people are Vitamin D deficient</strong> — it's the single highest-impact immune intervention. Before buying expensive immune formulas, close the D3 gap first.</p>\n<div class=\"art-hl\">Key Buyer Finding: D3+K2 + Zinc Bisglycinate is the optimal year-round immune foundation. Low cost, strong evidence.</div>\n<p>I evaluated 20+ immunity products. The following three performed best in ingredient form, dosage, and long-term tolerance.</p>",optTitle:"What matters most to you?",opts:["Getting sick less frequently","Faster recovery when I get sick","Year-round baseline immune support","Antioxidant & oxidative stress defense","I travel a lot / high exposure risk","Autoimmune condition support","Post-illness immune rebuilding","Seasonal allergy immune modulation"],products:[{top:true,brand:"Thorne",name:"Vitamin D3 + K2",img:"https://images.unsplash.com/photo-1584308666744-24d5c474f2ae?q=80&w=800",score:93,rating:"4.8★",reviews:"22.7k",sales:"#1 D3/K2",tags:["Immune+Bone","Optimal absorption","Clinically dosed"],colors:["g","g","g"],url:"https://thorne.com",verdict:"High-impact immunity supplement. Most people are D3 deficient — this closes the gap.",dose:"1 dropper daily with fat",form:"Liquid drops",bestFor:"Immune support, bone health, D3-deficient",notFor:"Those with hypercalcemia",cert:["NSF Certified","GMP Verified"],price:"$22",priceUnit:"/30ml"},{top:false,brand:"Designs for Health",name:"Zinc Supreme",img:"https://images.unsplash.com/photo-1547592180-85f173990554?q=80&w=800",score:86,rating:"4.6★",reviews:"7.1k",sales:"Top 5 Zinc",tags:["Zinc bisglycinate","+ B6 cofactor","Gentle on stomach"],colors:["g","g","g"],url:"https://designsforhealth.com",verdict:"Zinc bisglycinate absorbs far better than oxide. Gentle formula.",dose:"1 capsule daily with food",form:"Capsule",bestFor:"Immune support, skin health",notFor:"High-dose zinc users",cert:["GMP Certified","Non-GMO"],price:"$26",priceUnit:"/90 caps"},{top:false,brand:"Jarrow",name:"Quercetin 500mg",img:"https://images.unsplash.com/photo-1502741338009-cac2772e18bc?q=80&w=800",score:79,rating:"4.4★",reviews:"9.8k",sales:"Top 10 Immune",tags:["Antioxidant","Synergy with Zinc","Anti-inflammatory"],colors:["g","g","g"],url:"https://jarrow.com",verdict:"Excellent antioxidant defense. Pairs well with D3+Zinc.",dose:"500mg 1–2x daily",form:"Capsule",bestFor:"Antioxidant defense, immune stacking",notFor:"Those on blood thinners",cert:["Non-GMO","GMP Certified"],price:"$22",priceUnit:"/60 caps"}]},
  weight:{videoUrl:'https://cdn.coverr.co/videos/coverr-woman-practicing-yoga-in-park-1826/1080p.mp4',vBadge:'🎬 Elova Buyer',vTag:'Now Reviewing',vCaption:"Weight management supplements are the most over-promised category. I only track those with real metabolic data.",artTag:"Buyer Research · Weight",artTitle:"Metabolic Support: Which Ingredients Actually Work?",artImg:"https://images.unsplash.com/photo-1490645935967-10de6ba17061?q=80&w=1200&auto=format&fit=crop",artBody:"<p>The weight management market is full of over-promises. <strong>Genuinely effective metabolic interventions are rare</strong> — Berberine is one of the most evidence-backed metabolic support ingredients, often called natural metformin.</p>\n<div class=\"art-hl\">Key Buyer Finding: Berberine has significant effects on blood sugar stability and insulin sensitivity, backed by multiple randomized controlled trials.</div>\n<p>I evaluated 30+ weight management products, filtered out all the hype, and the following three have the most solid evidence.</p>",optTitle:"What's your weight goal?",opts:["Appetite regulation & satiety","Metabolic rate & fat oxidation","Blood sugar stability","Reducing sugar & carb cravings","Support during caloric deficit","Thyroid & hormonal weight factors","Reducing visceral / abdominal fat","Improving insulin sensitivity long-term"],products:[{top:true,brand:"Thorne",name:"Berberine",img:"https://images.unsplash.com/photo-1514996937319-344454492b37?q=80&w=800",score:90,rating:"4.7★",reviews:"13.2k",sales:"Top 3 Metabolic",tags:["Blood sugar","AMPK activator","Strong evidence"],colors:["g","g","g"],url:"https://thorne.com",verdict:"Solid evidence for blood sugar and metabolic support. Well-tolerated formula.",dose:"500mg 2–3x daily",form:"Capsule",bestFor:"Blood sugar support, metabolic health",notFor:"Those on diabetes medication",cert:["NSF Certified","GMP Verified"],price:"$34",priceUnit:"/60 caps"},{top:false,brand:"Life Extension",name:"Chromium Picolinate 500mcg",img:"https://images.unsplash.com/photo-1550572017-edd951b55104?q=80&w=800",score:78,rating:"4.4★",reviews:"11.5k",sales:"Top 5 Global",tags:["Insulin sensitivity","Craving reduction","High value"],colors:["g","g","g"],url:"https://lifeextension.com",verdict:"Modest but real effect on carb cravings. High value metabolic option.",dose:"500mcg once daily",form:"Capsule",bestFor:"Craving control, budget metabolic",notFor:"Those with chromium sensitivity",cert:["Non-GMO","GMP Certified"],price:"$10",priceUnit:"/100 caps"},{top:false,brand:"Ritual",name:"Metabolism Support+",img:"https://images.unsplash.com/photo-1512621776951-a57141f2eefd?q=80&w=800",score:74,rating:"4.3★",reviews:"4.2k",sales:"Top DTC",tags:["Green tea extract","Traceable","Subscription"],colors:["g","g","r"],url:"https://ritual.com",verdict:"Clean formula, decent thermogenic support. Good for lifestyle stacks.",dose:"2 capsules daily",form:"Capsule",bestFor:"Lifestyle buyers, mild thermogenic support",notFor:"Those needing strong metabolic effect",cert:["Vegan","Non-GMO"],price:"$39",priceUnit:"/month"}]},
  recovery:{videoUrl:'https://cdn.coverr.co/videos/coverr-athlete-stretching-after-training-4489/1080p.mp4',vBadge:'🎬 Elova Buyer',vTag:'Now Reviewing',vCaption:"Recovery is the most overlooked area in wellness. Here's what actually reduces inflammation and speeds repair.",artTag:"Buyer Research · Recovery",artTitle:"Science-Based Recovery: Beyond Protein Powders",artImg:"https://images.unsplash.com/photo-1517836357463-d25dfeac3438?q=80&w=1200&auto=format&fit=crop",artBody:"<p>The recovery market is dominated by protein powder ads, but <strong>the ingredients that actually affect recovery speed are creatine and Omega-3</strong> — not most post-workout products.</p>\n<div class=\"art-hl\">Key Buyer Finding: Creatine monohydrate is the most evidence-backed supplement in existence, with significant effects on both muscle and brain recovery.</div>\n<p>I tested 25+ recovery products. The following three showed the most consistent results.</p>",optTitle:"What does recovery mean for you?",opts:["Muscle soreness after training","Sleep quality to support recovery","Joint pain & inflammation","Nervous system / CNS recovery","Overall resilience & adaptation","Faster return to training after injury","Oxidative stress from intense exercise","Connective tissue & tendon support"],products:[{top:true,brand:"Thorne",name:"Creatine Monohydrate",img:"https://images.unsplash.com/photo-1584308666744-24d5c474f2ae?q=80&w=800",score:96,rating:"4.9★",reviews:"34.1k",sales:"#1 Recovery",tags:["Most studied","Muscle+Brain","NSF certified"],colors:["g","g","g"],url:"https://thorne.com",verdict:"Most evidence-backed supplement. Reduces recovery time across every metric.",dose:"5g daily",form:"Powder",bestFor:"Athletes and daily users",notFor:"Those with kidney issues",cert:["NSF Certified","GMP Verified"],price:"$36",priceUnit:"/90 servings"},{top:false,brand:"Nordic Naturals",name:"Omega-3 Fish Oil",img:"https://images.unsplash.com/photo-1559757148-5c350d0d3c56?q=80&w=800",score:88,rating:"4.7★",reviews:"28.9k",sales:"Top 3 Omega",tags:["EPA+DHA","Anti-inflammatory","IFOS 5-star"],colors:["g","g","g"],url:"https://nordicnaturals.com",verdict:"For joint and systemic inflammation. Highest purity omega-3 available.",dose:"2 softgels daily with food",form:"Softgel",bestFor:"Inflammation, joint pain, systemic recovery",notFor:"Those with fish allergy",cert:["IFOS 5-star","Non-GMO"],price:"$30",priceUnit:"/60 softgels"},{top:false,brand:"Jarrow",name:"Collagen Peptides",img:"https://images.unsplash.com/photo-1547592180-85f173990554?q=80&w=800",score:80,rating:"4.5★",reviews:"16.3k",sales:"Top 5 Collagen",tags:["Joint support","Hydrolyzed Type I+III","Mixes clean"],colors:["g","g","g"],url:"https://jarrow.com",verdict:"For joint recovery. Take with Vitamin C for best absorption.",dose:"10g daily in water",form:"Powder",bestFor:"Joint recovery, connective tissue health",notFor:"Vegans",cert:["Non-GMO","GMP Certified"],price:"$28",priceUnit:"/30 servings"}]},
  skin:{videoUrl:'https://cdn.coverr.co/videos/coverr-woman-applying-face-cream-8270/1080p.mp4',vBadge:'🎬 Elova Buyer',vTag:'Now Reviewing',vCaption:"Skin health starts from within — I track nutrients that genuinely improve skin, not topical products.",artTag:"Buyer Research · Skin",artTitle:"Ingestible Skin Nutrition: What Actually Works?",artImg:"https://images.unsplash.com/photo-1570172619644-dfd03ed5d881?q=80&w=1200&auto=format&fit=crop",artBody:"<p>The ingestible beauty market has exploded recently, but <strong>fewer than five ingredients have genuine clinical data</strong>. Collagen Peptides combined with Vitamin C is the most evidence-backed skin nutrition protocol.</p>\n<div class=\"art-hl\">Key Buyer Finding: Hydrolyzed collagen peptides (2.5g–10g/day) + Vitamin C can significantly improve skin elasticity and moisture within 8–12 weeks.</div>\n<p>I evaluated 20+ ingestible beauty products. The following three scored highest on ingredient quality and real user feedback.</p>",optTitle:"What's your skin concern?",opts:["Skin elasticity & anti-wrinkle","Hydration & moisture retention","Acne & skin inflammation","Uneven skin tone & dullness","Hair and nail health","Sun damage & photoaging repair","Dry skin from inside out","Rosacea or sensitive skin support"],products:[{top:true,brand:"Vital Proteins",name:"Collagen Peptides",img:"https://images.unsplash.com/photo-1556909114-f6e7ad7d3136?q=80&w=800",score:91,rating:"4.7★",reviews:"45.2k",sales:"#1 Collagen",tags:["Grass-fed source","Tasteless","High purity"],colors:["g","g","g"],url:"https://www.vitalproteins.com",verdict:"Traceable source collagen. Stable long-term feedback on elasticity and hydration.",dose:"10–20g daily in liquid",form:"Powder",bestFor:"Skin, hair, and joint health",notFor:"Vegans",cert:["Third-party tested","Non-GMO"],price:"$27",priceUnit:"/10oz"},{top:false,brand:"Thorne",name:"Vitamin C 500mg",img:"https://images.unsplash.com/photo-1584308666744-24d5c474f2ae?q=80&w=800",score:88,rating:"4.8★",reviews:"18.6k",sales:"Top 3 Vitamin C",tags:["Collagen synthesis","Antioxidant","Sustained release"],colors:["g","g","g"],url:"https://thorne.com",verdict:"Key cofactor for collagen synthesis. Effect doubles when paired with collagen.",dose:"500mg 1–2x daily",form:"Capsule",bestFor:"Collagen synthesis stacking, immunity",notFor:"Those with kidney stones",cert:["NSF Certified","GMP Verified"],price:"$22",priceUnit:"/90 caps"},{top:false,brand:"Sports Research",name:"Hyaluronic Acid 120mg",img:"https://images.unsplash.com/photo-1512621776951-a57141f2eefd?q=80&w=800",score:82,rating:"4.5★",reviews:"12.3k",sales:"Top 5 HA",tags:["Deep hydration","Low molecular weight","High absorption"],colors:["g","g","g"],url:"https://sportsresearch.com",verdict:"Oral hyaluronic acid for moisture. Low molecular weight absorbs better.",dose:"120mg once daily",form:"Capsule",bestFor:"Skin hydration, joint lubrication",notFor:"Those preferring topical-only",cert:["Non-GMO","GMP Certified"],price:"$20",priceUnit:"/120 caps"}]},
  mood:{videoUrl:'https://cdn.coverr.co/videos/coverr-happy-woman-walking-in-park-4608/1080p.mp4',vBadge:'🎬 Elova Buyer',vTag:'Now Reviewing',vCaption:"Mood supplements are the fastest growing but most misleading category. Here's what neuroscience actually supports.",artTag:"Buyer Research · Mood",artTitle:"Using Nutrition for Mood: What Neuroscience Tells Us",artImg:"https://images.unsplash.com/photo-1499209974431-9dddcece7f88?q=80&w=1200&auto=format&fit=crop",artBody:"<p>The relationship between mood health and brain nutrition is being redefined by neuroscience. <strong>Omega-3 (high EPA) and magnesium</strong> are the two most evidence-backed nutrients for mood support.</p>\n<div class=\"art-hl\">Key Buyer Finding: High-EPA Omega-3 + Magnesium Bisglycinate shows significant non-pharmacological intervention effects for mild low mood and anxiety.</div>\n<p>I evaluated 30+ mood health products. The following three were most convincing in mechanism and long-term user feedback.</p>",optTitle:"What's your mood concern?",opts:["Mild anxiety & tension","Low mood & lack of motivation","Mental fatigue & sluggish thinking","Stress-driven mood swings","Seasonal mood changes","Post-burnout emotional rebuilding","Irritability & short fuse","Social anxiety & performance nerves"],products:[{top:true,brand:"Nordic Naturals",name:"Omega-3 EPA+DHA (High EPA)",img:"https://images.unsplash.com/photo-1559757148-5c350d0d3c56?q=80&w=800",score:93,rating:"4.8★",reviews:"22.1k",sales:"#1 Mood Omega",tags:["High EPA ratio","Mood support","IFOS 5-star"],colors:["g","g","g"],url:"https://nordicnaturals.com",verdict:"The evidence-backed nutrient for mood support. EPA ratio is the key factor.",dose:"2 softgels daily with food",form:"Softgel",bestFor:"Mood support, inflammation, cognition",notFor:"Those with fish allergy",cert:["IFOS 5-star","Non-GMO"],price:"$38",priceUnit:"/60 softgels"},{top:false,brand:"Thorne",name:"Magnesium Bisglycinate",img:"https://images.unsplash.com/photo-1584308666744-24d5c474f2ae?q=80&w=800",score:88,rating:"4.8★",reviews:"12.4k",sales:"Top 3 Magnesium",tags:["Calms nervous system","Improves sleep","No laxative effect"],colors:["g","g","g"],url:"https://thorne.com",verdict:"Magnesium is foundational for mood regulation. Bisglycinate form is well tolerated.",dose:"200–400mg before bed",form:"Capsule",bestFor:"Mood, sleep, and stress regulation",notFor:"Those already supplementing Mg",cert:["NSF Certified","GMP Verified"],price:"$28",priceUnit:"/60 caps"},{top:false,brand:"Nootropics Depot",name:"Saffron Extract 30mg",img:"https://images.unsplash.com/photo-1514996937319-344454492b37?q=80&w=800",score:81,rating:"4.6★",reviews:"7.8k",sales:"Top 5 Saffron",tags:["Mood support","Antioxidant","Small dose, high effect"],colors:["g","g","g"],url:"https://nootropicsdepot.com",verdict:"Saffron extract mood support backed by multiple RCTs. Small dose, high effect.",dose:"30mg once daily",form:"Capsule",bestFor:"Mild mood support, RCT-backed formula",notFor:"Those on antidepressants",cert:["Third-party tested","GMP Certified"],price:"$26",priceUnit:"/90 caps"}]}
};

// ══ ARTICLE BODY PARSER ══
function parseArtBody(d){
  if(d.artP1!==undefined) return {p1:d.artP1, hl:d.artHl, p2:d.artP2};
  const body = d.artBody||'';
  const p1m = body.match(/<p>([\s\S]*?)<\/p>/);
  const hlm = body.match(/art-hl[^>]*>([\s\S]*?)<\/div>/);
  const p2m = body.match(/<\/div>\s*<p>([\s\S]*?)<\/p>/);
  return {
    p1: p1m ? p1m[1].trim() : '',
    hl: hlm ? hlm[1].replace(/^Key Buyer Finding:\s*/,'').trim() : '',
    p2: p2m ? p2m[1].trim() : ''
  };
}

// ══ FE CAT_TREE (object) ══
const CAT_TREE = {
  sleep: {
    label: '😴 Sleep & Rest',
    subs: [
      {value:'sleep_quality',  label:'• Sleep Quality',   need:'sleep'},
      {value:'fall_asleep',    label:'• Fall Asleep',     need:'sleep'},
      {value:'circadian',      label:'• Circadian Rhythm',need:'sleep'},
    ]
  },
  mind: {
    label: '🧠 Mind & Brain',
    subs: [
      {value:'focus',    label:'• Focus & Productivity', need:'energy'},
      {value:'stress',   label:'• Stress & Anxiety',     need:'stress'},
      {value:'memory',   label:'• Memory & Neuro',       need:'mood'},
    ]
  },
  physical: {
    label: '💪 Physical Performance',
    subs: [
      {value:'vitality',  label:'• Energy & Vitality',    need:'energy'},
      {value:'muscle',    label:'• Muscle & Recovery',    need:'recovery'},
      {value:'joint',     label:'• Joint & Bone',         need:'recovery'},
    ]
  },
  internal: {
    label: '🫀 Internal Systems',
    subs: [
      {value:'gut',       label:'• Gut & Digestion',      need:'gut'},
      {value:'immunity',  label:'• Immunity & Defense',   need:'immunity'},
      {value:'heart',     label:'• Heart & Cardio',       need:'longevity'},
      {value:'metabolism',label:'• Metabolism',           need:'weight'},
    ]
  },
  longevity_ag: {
    label: '🔬 Longevity & Aging',
    subs: [
      {value:'cellular',  label:'• Cellular Health',      need:'longevity'},
      {value:'hormone',   label:'• Hormone Balance',      need:'longevity'},
      {value:'dna',       label:'• DNA & Epigenetics',    need:'longevity'},
    ]
  },
  beauty_sk: {
    label: '✨ Beauty & Skin',
    subs: [
      {value:'skin',      label:'• Skin & Collagen',      need:'skin'},
      {value:'hair',      label:'• Hair & Nail',          need:'skin'},
      {value:'sun',       label:'• Sun & Repair',         need:'skin'},
    ]
  },
  weight_sh: {
    label: '⚖️ Weight & Shape',
    subs: [
      {value:'fat',       label:'• Fat Metabolism',       need:'weight'},
      {value:'appetite',  label:'• Appetite Control',     need:'weight'},
      {value:'detox',     label:'• Detox & Cleanse',      need:'weight'},
    ]
  }
};

function onCatChange(){
  const v = document.getElementById('catSel').value;
  const subSel  = document.getElementById('subCatSel');
  const subWrap = document.getElementById('subCatWrap');
  const ni = document.getElementById('ni');
  currentNeed = null;
  document.querySelectorAll('.chip').forEach(c=>c.classList.remove('sel'));
  if(v && CAT_TREE[v]){
    const subs = CAT_TREE[v].subs;
    subSel.innerHTML = '<option value="">All Sub-categories</option>' +
      subs.map(s=>`<option value="${esc(s.value)}" data-need="${esc(s.need)}">${esc(s.label)}</option>`).join('');
    subSel.classList.add('visible');
    if(subWrap) subWrap.classList.add('visible');
    ni.value = '';
    ni.placeholder = 'Select a sub-category or type your concern…';
  } else {
    subSel.classList.remove('visible');
    if(subWrap) subWrap.classList.remove('visible');
    subSel.innerHTML = '';
    ni.placeholder = 'e.g. I can\'t sleep, I feel bloated, I need more energy…';
    ni.value = '';
  }
}

function onSubCatChange(){
  const subSel = document.getElementById('subCatSel');
  const opt    = subSel.options[subSel.selectedIndex];
  const ni     = document.getElementById('ni');
  if(opt && opt.dataset.need){
    currentNeed = opt.dataset.need;
    document.querySelectorAll('.chip').forEach(c=>c.classList.toggle('sel',c.dataset.need===currentNeed));
    ni.placeholder = opt.label.replace('• ','') + ' — click "Find My Stack" to continue';
    ni.value = '';
  }
}

// ══ SIDX ══
let SIDX=[
  {icon:'😴',name:'Magnesium Glycinate',sub:'Sleep & nervous system recovery',tag:'Sleep',need:'sleep'},
  {icon:'😴',name:'Glycine',sub:'Deep sleep quality support',tag:'Sleep',need:'sleep'},
  {icon:'🌿',name:'Seed DS-01 Synbiotic',sub:'24-strain daily gut health',tag:'Gut',need:'gut'},
  {icon:'🧘',name:'KSM-66 Ashwagandha',sub:'Cortisol regulation & stress',tag:'Stress',need:'stress'},
  {icon:'🧘',name:'L-Theanine 200mg',sub:'Calm focus without drowsiness',tag:'Stress',need:'stress'},
  {icon:'⚡',name:'Alpha-GPC 300mg',sub:'Cognitive energy & focus',tag:'Energy',need:'energy'},
  {icon:'⚡',name:'Creatine Monohydrate',sub:'Brain + muscle energy',tag:'Energy',need:'energy'},
  {icon:'🔬',name:'NMN / NR — NAD+',sub:'Cellular longevity stack',tag:'Longevity',need:'longevity'},
  {icon:'🛡️',name:'Vitamin D3 + K2',sub:'Year-round immune foundation',tag:'Immunity',need:'immunity'},
  {icon:'💪',name:'Omega-3 Fish Oil',sub:'Anti-inflammatory recovery',tag:'Recovery',need:'recovery'},
  {icon:'⚖️',name:'Berberine',sub:'Blood sugar & metabolic support',tag:'Weight',need:'weight'},
  {icon:'✨',name:'Collagen Peptides',sub:'Skin elasticity & joint health',tag:'Skin',need:'skin'},
  {icon:'🧠',name:'Saffron Extract',sub:'Mood support, strong RCT evidence',tag:'Mood',need:'mood'},
];

// ══ CHIPS ══
let CHIPS=[
  {emoji:'😴',label:'Sleep',need:'sleep'},
  {emoji:'🧠',label:'Stress',need:'stress'},
  {emoji:'⚡',label:'Focus',need:'energy'},
  {emoji:'🫀',label:'Gut',need:'gut'},
  {emoji:'🔬',label:'Longevity',need:'longevity'},
  {emoji:'✨',label:'Beauty',need:'skin'},
];

// ══ STATIC DATA ══
const TW_LINES=["Hi, I'm Elova 👋","Your wellness buyer.","I find what actually works.","No ads. No bias. Just results."];
const BIO=[];
const DIFF=[{icon:'🚫',bold:'No paid rankings',desc:'Brands cannot pay to appear in my picks. Ever.'},{icon:'🔬',bold:'Clinical evidence only',desc:'Every pick is cross-referenced with peer-reviewed research and real dosage data.'},{icon:'📊',bold:'Real-world data',desc:'Global sales trends + verified 90-day user feedback.'},{icon:'🔄',bold:'Updated weekly',desc:"If a formula changes or new evidence drops, my rankings update too."}];
const CHAT=[{r:'e',t:"Hi! I'm Elova, your personal wellness buyer 🌿 What's been bothering you lately — or what would you like to improve?"},{r:'u',t:"I've been having trouble sleeping. There are so many products out there — I have no idea which one to pick."},{r:'e',t:"The sleep supplement market is full of underdosed melatonin and added sugar — most of it won't actually help. Can you tell me more? Do you struggle to fall asleep, or do you wake up in the middle of the night?"},{r:'u',t:"I usually fall asleep fine, but I wake up around 3am almost every night and can't go back to sleep."},{r:'e',t:"Got it — that's a sleep maintenance issue, not a sleep onset issue. The two need completely different solutions, and most products on the market only address onset. Let me find what's actually right for your situation."}];

// ══ FRONTEND JS ══
let currentNeed = null;

const TITLE_MAP={sleep:'Sleep & Rest',gut:'Gut & Digestion',stress:'Stress & Anxiety',energy:'Focus & Productivity',longevity:'Longevity & Aging',immunity:'Immunity & Defense',weight:'Weight & Shape',recovery:'Muscle & Recovery',skin:'Skin & Collagen',mood:'Memory & Mind'};

// ══ PAGE NAVIGATION ══
function showPage(n){
  document.querySelectorAll('.page').forEach(p=>p.classList.remove('active'));
  const pg = document.getElementById('page'+n);
  pg.classList.add('active');
  window.scrollTo({top:0,behavior:'smooth'});
  // Screen-reader: announce page transition
  const labels = ['Home — Find your wellness stack', 'Deep Dive — Research report', 'My Picks — Top supplement recommendations'];
  const srPg = document.getElementById('sr-page');
  if(srPg){ srPg.textContent=''; setTimeout(()=>{ srPg.textContent = labels[n-1] || 'Page '+n; }, 60); }
  // Move focus to the first focusable element in the new page (skip-link excluded)
  setTimeout(()=>{
    const firstFocusable = pg.querySelector('button:not([disabled]), [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
    if(firstFocusable) firstFocusable.focus({preventScroll:true});
  }, 80);
  if(n===1){
    try{
      document.title='Elova.Life — Your Personal Wellness Buyer';
      const dm=document.querySelector('meta[name="description"]');
      if(dm) dm.setAttribute('content','Elova is your independent wellness buyer — researching 200+ supplements with zero paid placements. Get personalized picks for sleep, gut health, stress, energy, longevity, beauty and weight. No ads, no sponsored content.');
      const can=document.querySelector('link[rel="canonical"]');
      if(can) can.setAttribute('href','https://elova.life/');
    }catch(e){}
  }
}

// ══ CHIP SELECTION (delegated) ══
function bindChips(){
  document.querySelectorAll('.chip').forEach(ch=>{
    if(ch._bound) return;
    ch._bound=true;
    if(!ch.getAttribute('role')) ch.setAttribute('role','button');
    if(!ch.getAttribute('tabindex')) ch.setAttribute('tabindex','0');
    ch.setAttribute('aria-pressed','false');
    const activate=()=>{
      document.querySelectorAll('.chip').forEach(x=>{
        x.classList.remove('sel');
        x.setAttribute('aria-pressed','false');
      });
      ch.classList.add('sel');
      ch.setAttribute('aria-pressed','true');
      currentNeed = ch.dataset.need;
      document.getElementById('ni').value = ch.textContent.trim().replace(/^[^\w]+/,'');
      const sd=document.getElementById('sd');
      sd.classList.remove('open');
      document.getElementById('ni').setAttribute('aria-expanded','false');
    };
    ch.addEventListener('click', activate);
    ch.addEventListener('keydown', e=>{ if(e.key===' '||e.key==='Enter'){e.preventDefault();activate();} });
  });
}
bindChips();

// ══ SEARCH ══
const niEl=document.getElementById('ni');
const sdEl=document.getElementById('sd');
function doSearch(){
  const q=niEl.value.trim().toLowerCase();
  if(!q){sdEl.classList.remove('open');niEl.setAttribute('aria-expanded','false');return;}
  const hits=SIDX.filter(x=>x.name.toLowerCase().includes(q)||x.sub.toLowerCase().includes(q)||x.tag.toLowerCase().includes(q)).slice(0,5);
  if(!hits.length){sdEl.classList.remove('open');niEl.setAttribute('aria-expanded','false');return;}
  sdEl.setAttribute('role','listbox');
  sdEl.setAttribute('aria-label','Search suggestions');
  sdEl.innerHTML='';
  hits.forEach((x,idx)=>{
    const div=document.createElement('div');
    div.className='sdi';
    div.setAttribute('role','option');
    div.setAttribute('tabindex','0');
    div.setAttribute('id','sdi-opt-'+idx);
    div.setAttribute('aria-selected','false');
    div.setAttribute('aria-label', x.name + (x.sub ? ', ' + x.sub : '') + (x.tag ? ', ' + x.tag : ''));
    div.innerHTML=`<div class="sdi-icon" aria-hidden="true">${esc(x.icon)}</div>
      <div><div class="sdi-name">${esc(x.name)}</div><div class="sdi-sub">${esc(x.sub)}</div></div>
      <div class="sdi-tag" aria-hidden="true">${esc(x.tag)}</div>`;
    div.addEventListener('click',()=>pickSearch(x.need,x.name));
    sdEl.appendChild(div);
  });
  sdEl.classList.add('open');
  niEl.setAttribute('aria-expanded','true');
  niEl.removeAttribute('aria-activedescendant');
}
function pickSearch(need,name){
  currentNeed=need;
  document.querySelectorAll('.chip').forEach(c=>c.classList.toggle('sel',c.dataset.need===need));
  niEl.value=name;sdEl.classList.remove('open');niEl.setAttribute('aria-expanded','false');
}
// Debounced at 200ms — prevents CPU thrash on fast typing and mobile IME
niEl.addEventListener('input',()=>{clearTimeout(niEl._dt);niEl._dt=setTimeout(doSearch,200);});
niEl.addEventListener('keydown',e=>{
  if(e.key==='Enter'){ if(sdEl.classList.contains('open')){const first=sdEl.querySelector('.sdi');if(first){first.click();return;}} goP2(); }
  if(e.key==='Escape'){ sdEl.classList.remove('open'); niEl.setAttribute('aria-expanded','false'); }
  if(e.key==='ArrowDown'&&sdEl.classList.contains('open')){
    e.preventDefault();
    const items=[...sdEl.querySelectorAll('.sdi')];
    if(items.length) _setSdFocus(items, 0);
  }
});
// Helper: update aria-activedescendant + aria-selected when focus moves in dropdown
function _srAnnounce(txt){
  try{
    var r=document.getElementById('sr-announce');
    if(r){r.textContent='';setTimeout(function(){r.textContent=txt;},50);}
  }catch(e){}
}
function _setSdFocus(items, newIdx){
  items.forEach((it,i)=>it.setAttribute('aria-selected', i===newIdx ? 'true' : 'false'));
  const targetId = items[newIdx] ? items[newIdx].id : '';
  niEl.setAttribute('aria-activedescendant', targetId);
  if(items[newIdx]){
    items[newIdx].focus();
    // Announce item to screen reader (aria-activedescendant alone isn't enough in all SRs)
    _srAnnounce(items[newIdx].getAttribute('aria-label')||items[newIdx].textContent.trim());
  }
}
sdEl.addEventListener('keydown',e=>{
  const items=[...sdEl.querySelectorAll('.sdi')];
  const idx=items.indexOf(document.activeElement);
  if(e.key==='ArrowDown'){
    e.preventDefault();
    if(idx<items.length-1) _setSdFocus(items, idx+1);
  }
  if(e.key==='ArrowUp'){
    e.preventDefault();
    if(idx>0) _setSdFocus(items, idx-1);
    else { niEl.removeAttribute('aria-activedescendant'); items.forEach(it=>it.setAttribute('aria-selected','false')); niEl.focus(); }
  }
  if(e.key==='Enter'&&idx>=0){items[idx].click();}
  if(e.key==='Escape'){
    sdEl.classList.remove('open');
    niEl.setAttribute('aria-expanded','false');
    niEl.removeAttribute('aria-activedescendant');
    niEl.focus();
  }
});
document.addEventListener('click',e=>{if(!document.querySelector('.sbar').contains(e.target)){sdEl.classList.remove('open');niEl.setAttribute('aria-expanded','false');}});

// ══ STEP TRANSITIONS ══
function setProgress(n){
  const labels=['Tell Me','Deep Dive','My Picks'];
  ['progStep1','progStep2','progStep3'].forEach((id,i)=>{
    const el=document.getElementById(id);
    if(!el) return;
    el.classList.remove('active','done');
    el.removeAttribute('aria-current');
    if(i+1<n){ el.classList.add('done'); el.setAttribute('aria-label',`Step ${i+1}: ${labels[i]} — completed`); }
    if(i+1===n){ el.classList.add('active'); el.setAttribute('aria-current','step'); el.setAttribute('aria-label',`Step ${i+1}: ${labels[i]} — current`); }
    if(i+1>n) el.setAttribute('aria-label',`Step ${i+1}: ${labels[i]} — upcoming`);
  });
  ['progLine1','progLine2'].forEach((id,i)=>{
    const el=document.getElementById(id);
    if(!el) return;
    el.classList.toggle('done',i+1<n);
  });
  const sn1=document.querySelector('#progStep1 .sn');
  const sn2=document.querySelector('#progStep2 .sn');
  const sn3=document.querySelector('#progStep3 .sn');
  if(sn1) sn1.textContent = n>1?'✓':'1';
  if(sn2) sn2.textContent = n>2?'✓':'2';
  if(sn3) sn3.textContent = n>3?'✓':'3';
}

function goP2(){
  if(!currentNeed){
    const txt=niEl.value.toLowerCase();
    // Keyword → need map (order matters: more specific first)
    const _KW=[
      ['sleep',   ['sleep','circadian','melatonin','insomnia','wake up','restless']],
      ['gut',     ['gut','digest','bloat','probiotic','ibs','bowel','microbiome']],
      ['stress',  ['stress','anxiety','anxious','calm','cortisol','adaptogen','nervous']],
      ['energy',  ['energy','focus','productivity','brain fog','fatigue','tired','alertness','nootropic']],
      ['longevity',['longev','aging','nad','cellular','epigenetic','lifespan','senescence']],
      ['immunity',['immun','immune','defense','infection','cold','flu','zinc']],
      ['weight',  ['weight','metabol','fat','appetite','detox','obesity','bmi','body composition']],
      ['recovery',['recov','muscle','joint','bone','inflammation','soreness','creatine']],
      ['skin',    ['skin','collagen','hair','nail','beauty','glow','wrinkle','elasticity']],
      ['mood',    ['mood','memory','neuro','mental','depression','serotonin','dopamine','cognitive']],
    ];
    // Strip negation context: "I don't want X" / "without X" / "no X" / "avoid X"
    // Remove the negated word so it doesn't falsely match its category.
    const _negated=txt.replace(/(?:don'?t|won'?t|avoid|without|no|not)\s+(?:want\s+)?(\w+)/g,'');
    for(const [need,kws] of _KW){
      if(kws.some(k=>_negated.includes(k))){currentNeed=need;break;}
    }
    if(!currentNeed) currentNeed='sleep'; // final fallback
  }
  const d=DATA[currentNeed];

  // SPA meta: update title + og + twitter for each category (SEO/AIO crawl slicing)
  const _p2label=TITLE_MAP[currentNeed]||currentNeed;
  document.title='Deep Dive · '+_p2label+' — Elova.Life';
  try{
    const _dm=document.querySelector('meta[name="description"]');
    if(_dm) _dm.setAttribute('content','Independent buyer research on '+_p2label+' supplements — clinical evidence, dosage analysis, zero paid placements.');
    const _ot=document.querySelector('meta[property="og:title"]');
    if(_ot) _ot.setAttribute('content',document.title);
    const _od=document.querySelector('meta[property="og:description"]');
    if(_od) _od.setAttribute('content','Top-ranked '+_p2label+' supplements — independent buyer research, zero paid placements.');
    const _tt=document.querySelector('meta[name="twitter:title"]');
    if(_tt) _tt.setAttribute('content',document.title);
    const _td=document.querySelector('meta[name="twitter:description"]');
    if(_td) _td.setAttribute('content','Top-ranked '+_p2label+' supplements — independent research, zero paid placements.');
  }catch(e){}
  document.getElementById('p2Title').textContent='Deep Dive · '+_p2label;
  // Video — ensure source matches & loads
  const vid=document.getElementById('buyerVid');
  if(vid){
    const src=vid.querySelector('source');
    if(src && d.videoUrl && src.getAttribute('src')!==d.videoUrl){
      src.setAttribute('src',d.videoUrl);
      vid.load();
    }
    try{
      const playP=vid.play();
      if(playP&&playP.catch) playP.catch(()=>{ /* Autoplay policy — video stays paused */ });
    }catch(e){ /* Autoplay exception — no visible error shown to user */ }
  }
  document.getElementById('vBadge').textContent = d.vBadge||'🎬 Elova Buyer';
  document.getElementById('vTag').textContent = d.vTag||'Now Reviewing';
  document.getElementById('vCaption').textContent = d.vCaption;
  document.getElementById('artTag').textContent = d.artTag;
  document.getElementById('artTitle').textContent = d.artTitle;
  document.getElementById('artImg').src = d.artImg;
  document.getElementById('artImg').alt = d.artTitle||'Wellness research';
  const artBodyEl=document.getElementById('artBody');
  if(artBodyEl) artBodyEl.innerHTML = _sanitizeHTML(d.artBody||'');
  document.getElementById('optTitle').textContent = d.optTitle;

  const ol=document.getElementById('optList');
  ol.innerHTML='';
  document.getElementById('selCount').textContent='0';
  d.opts.forEach(o=>{
    const div=document.createElement('div');
    div.className='opt';
    div.setAttribute('role','checkbox');
    div.setAttribute('aria-checked','false');
    div.setAttribute('tabindex','0');
    const span=document.createElement('span');
    span.textContent=o;
    div.innerHTML='<div class="opt-chk"><svg viewBox="0 0 9 9" aria-hidden="true"><polyline points="1.5,4.5 3.5,6.5 7.5,2"/></svg></div>';
    div.appendChild(span);
    const toggle=()=>{
      div.classList.toggle('sel');
      div.setAttribute('aria-checked',div.classList.contains('sel')?'true':'false');
      document.getElementById('selCount').textContent=ol.querySelectorAll('.sel').length;
    };
    div.addEventListener('click',toggle);
    div.addEventListener('keydown',e=>{if(e.key===' '||e.key==='Enter'){e.preventDefault();toggle();}});
    ol.appendChild(div);
  });

  setProgress(2);
  showPage(2);
  // Dynamic meta for this research page
  try{
    const label=TITLE_MAP[currentNeed]||currentNeed;
    const d2=DATA[currentNeed];
    document.title=`${d2.artTitle||label+' Supplements'} — Elova.Life Buyer Report`;
    const dm=document.querySelector('meta[name="description"]');
    if(dm) dm.setAttribute('content',(`${d2.artTitle||label} supplement research by Elova.Life. `+(d2.artP1||'Independent buyer report with zero paid placements.')).slice(0,160));
    const ogT=document.querySelector('meta[property="og:title"]');
    if(ogT) ogT.setAttribute('content',document.title);
    const ogD=document.querySelector('meta[property="og:description"]');
    if(ogD) ogD.setAttribute('content',document.querySelector('meta[name="description"]').getAttribute('content'));
    let can=document.querySelector('link[rel="canonical"]');
    if(can) can.setAttribute('href',`https://elova.life/?q=${encodeURIComponent(currentNeed)}`);
  }catch(e){}
}

function goP3(){
  if(!currentNeed || !DATA[currentNeed]) return;
  const d=DATA[currentNeed];
  // SPA meta: picks page title slice
  const _p3label=TITLE_MAP[currentNeed]||currentNeed;
  document.title='Top 3 '+_p3label+' Picks — Elova.Life';
  try{
    const _dm=document.querySelector('meta[name="description"]');
    if(_dm) _dm.setAttribute('content','The top 3 independently ranked '+_p3label+' supplements. Ranked by clinical evidence, formulation depth, and real user results. No paid placements.');
    const _ot=document.querySelector('meta[property="og:title"]');
    if(_ot) _ot.setAttribute('content',document.title);
    const _od=document.querySelector('meta[property="og:description"]');
    if(_od) _od.setAttribute('content','Top 3 '+_p3label+' supplement picks — independent ranking, zero paid placements.');
    const _tt=document.querySelector('meta[name="twitter:title"]');
    if(_tt) _tt.setAttribute('content',document.title);
  }catch(e){}
  document.getElementById('rTitle').textContent='Top 3 Picks · '+_p3label;

  const grid=document.getElementById('pgrid');
  grid.innerHTML='';
  d.products.forEach((p,idx)=>{
    const cleanVerdict = p.verdict||'';
    const cleanTags = p.tags||[];
    const tagHTML=(cleanTags).map((t,i)=>`<span class="pt ${esc((p.colors||[])[i]||'')}">${esc(t)}</span>`).join('');
    const certArr = p.cert || [];
    const certHTML = certArr.slice(0,2).map(c=>`<span class="pcert-pill">✓ ${esc(c)}</span>`).join('');

    const card=document.createElement('article');
    card.className='pc'+(p.top?' top':'');
    card.setAttribute('aria-label',`${p.top?'Top pick':'Pick '+(idx+1)}: ${p.name} by ${p.brand}`);
    card.innerHTML=`
      ${p.top?'<div class="tbadge">⭐ Top Pick</div>':'<div class="tbadge" style="background:rgba(100,120,110,0.75);">Pick #'+(idx+1)+'</div>'}
      <div class="pi"><img src="${esc(p.img)}" alt="${esc(p.name)}" loading="lazy" width="800" height="600" decoding="async"></div>
      <div class="pb">
        <div class="pbrand">${esc(p.brand)}</div>
        <div class="pname">${esc(p.name)}</div>

        <div class="srow"><div class="sbw"><div class="sb" style="width:${Number(p.score)||0}%"></div></div><span class="sv">${Number(p.score)||0}/100</span></div>

        <div class="strow">
          <div class="stp"><div class="vv">${esc(p.rating||'—')}</div><div class="kk">Rating</div></div>
          <div class="stp"><div class="vv">${esc(p.reviews||'—')}</div><div class="kk">Reviews</div></div>
          <div class="stp"><div class="vv">${esc(p.sales||'—')}</div><div class="kk">Rank</div></div>
        </div>

        <div class="pprice"><span class="pprice-label">Est. Price</span><div><span class="pprice-val">${esc(p.price||'—')}</span><span class="pprice-per">${esc(p.priceUnit||'')}</span></div></div>

        <div class="pdivider"></div>

        <div class="pdetail-grid">
          <div class="pdetail-item"><div class="pdetail-label">Dosage</div><div class="pdetail-val">${esc(p.dose||'—')}</div></div>
          <div class="pdetail-item"><div class="pdetail-label">Form</div><div class="pdetail-val">${esc(p.form||'—')}</div></div>
        </div>

        ${certHTML?`<div class="pcert">${certHTML}</div>`:''}

        <div class="pverd">"${esc(cleanVerdict)}"</div>
        <div class="ptags">${tagHTML}</div>

        <button type="button" class="buybtn" ${!p.url?'disabled aria-disabled="true" title="Link coming soon"':''} aria-label="Buy ${p.name} by ${p.brand}">
          ${p.top?'Buy Now — Official Store':'View Product'}
          <svg viewBox="0 0 12 12" aria-hidden="true"><polyline points="2,6 10,6"/><polyline points="6,2 10,6 6,10"/></svg>
        </button>
        ${p.url?'<p class="affiliate-note">⚠ Affiliate link — we may earn a commission at no extra cost to you. Price may vary.</p>':'<p class="affiliate-note">Price shown is estimated and may vary by retailer.</p>'}
      </div>`;
    const buyBtn=card.querySelector('.buybtn');
    if(buyBtn) buyBtn.addEventListener('click',()=>{ if(p.url) window.open(p.url,'_blank','noopener,noreferrer'); });
    grid.appendChild(card);
  });

  setProgress(3);
  showPage(3);
  document.querySelectorAll('.pc').forEach(c=>c.classList.remove('revealed'));
  // Announce picks count to SR
  const srAnn = document.getElementById('sr-announce');
  if(srAnn){ srAnn.textContent=''; setTimeout(()=>{ srAnn.textContent = `Your top ${d.products.length} ${TITLE_MAP[currentNeed]||currentNeed} picks are ready.`; }, 100); }
  // Dynamic meta + ItemList JSON-LD for picks page
  try{
    const label=TITLE_MAP[currentNeed]||currentNeed;
    const yr=new Date().getFullYear();
    document.title=`Best ${label} Supplements ${yr} — Top Picks · Elova.Life`;
    const desc=`Elova's top ${label.toLowerCase()} supplement picks: ${d.products.slice(0,3).map(p=>p.name).join(', ')}. Ranked by formulation depth, bioavailability, and clinical evidence. Zero paid placements.`;
    const dm=document.querySelector('meta[name="description"]');
    if(dm) dm.setAttribute('content',desc.slice(0,160));
    const ogT=document.querySelector('meta[property="og:title"]'); if(ogT) ogT.setAttribute('content',document.title);
    const ogD=document.querySelector('meta[property="og:description"]'); if(ogD) ogD.setAttribute('content',desc.slice(0,160));
    let can=document.querySelector('link[rel="canonical"]');
    if(can) can.setAttribute('href',`https://elova.life/?q=${encodeURIComponent(currentNeed)}&step=picks`);
    // Inject/update ItemList structured data
    let sdEl=document.getElementById('_ld_picks');
    if(!sdEl){sdEl=document.createElement('script');sdEl.type='application/ld+json';sdEl.id='_ld_picks';document.head.appendChild(sdEl);}
    sdEl.textContent=JSON.stringify({
      '@context':'https://schema.org','@type':'ItemList',
      'name':`Best ${label} Supplements ${yr} — Elova Top Picks`,
      'description':`Independently ranked ${label.toLowerCase()} supplements with zero paid placements.`,
      'numberOfItems':d.products.length,
      'itemListElement':d.products.map((p,i)=>({
        '@type':'ListItem','position':i+1,
        'item':Object.assign({'@type':'Product','name':p.name,'brand':{'@type':'Brand','name':p.brand},
          'description':p.verdict||'','image':p.img,'url':p.url||'https://elova.life/'},
          p.rating?{'aggregateRating':{'@type':'AggregateRating','ratingValue':p.rating,'reviewCount':p.reviews||'0'}}:{})
      }))
    });
  }catch(e){}
  runSearchAnimation();
}

// ══ SEARCH ANIMATION ══
function runSearchAnimation(){
  const overlay = document.getElementById('searchOverlay');
  const bar = document.getElementById('soBar');
  const status = document.getElementById('soStatus');
  const steps = [
    {id:'soStep1',icon:'soIcon1',doneIcon:'✓',pct:25,msg:'Analyzing ingredient quality…'},
    {id:'soStep2',icon:'soIcon2',doneIcon:'✓',pct:50,msg:'Checking clinical dosage data…'},
    {id:'soStep3',icon:'soIcon3',doneIcon:'✓',pct:75,msg:'Ranking by long-term value…'},
    {id:'soStep4',icon:'soIcon4',doneIcon:'✓',pct:100,msg:'Your results are ready.'},
  ];
  // reset step states
  steps.forEach(s=>{
    const el=document.getElementById(s.id);
    if(el) el.classList.remove('active','done');
    const ic=document.getElementById(s.icon);
    if(ic) ic.textContent={soIcon1:'🔍',soIcon2:'🧬',soIcon3:'📊',soIcon4:'⭐'}[s.icon];
  });
  bar.style.width='0%';

  overlay.classList.remove('gone');
  overlay.style.opacity='1';
  document.body.style.overflow='hidden'; // prevent background scroll while overlay is active
  document.getElementById('soStep1').classList.add('active');

  const stepTimes = [0, 500, 1100, 1800];
  const doneTimes = [400, 1000, 1700, 2400];

  steps.forEach((s,i)=>{
    setTimeout(()=>{
      steps.forEach(x=>document.getElementById(x.id).classList.remove('active'));
      document.getElementById(s.id).classList.add('active');
      status.textContent = s.msg;
      bar.style.width = (s.pct*0.5)+'%';
    }, stepTimes[i]);
    setTimeout(()=>{
      document.getElementById(s.id).classList.remove('active');
      document.getElementById(s.id).classList.add('done');
      document.getElementById(s.icon).textContent = s.doneIcon;
      bar.style.width = s.pct+'%';
    }, doneTimes[i]);
  });

  setTimeout(()=>{
    status.textContent = 'Match found — displaying your picks…';
    bar.style.width = '100%';
    setTimeout(()=>{
      overlay.style.opacity='0';
      setTimeout(()=>{
        overlay.classList.add('gone');
        document.body.style.overflow=''; // restore scroll after overlay exits
      }, 800);
    }, 400);
  }, 2500);

  const cards = document.querySelectorAll('.pc');
  setTimeout(()=>{ if(cards[0]){cards[0].classList.add('revealed');setTimeout(()=>{cards[0].style.willChange='auto';},700);} }, 3200);
  setTimeout(()=>{ if(cards[1]){cards[1].classList.add('revealed');setTimeout(()=>{cards[1].style.willChange='auto';},700);} }, 4000);
  setTimeout(()=>{ if(cards[2]){cards[2].classList.add('revealed');setTimeout(()=>{cards[2].style.willChange='auto';},700);} }, 5000);
}

// ══ MUTE TOGGLE ══
let muted=true;
function toggleMute(){
  const v=document.getElementById('buyerVid');
  const btn=document.getElementById('muteBtn');
  // Guard: if video failed to load, disable button and show feedback
  if(v && (v.networkState===v.NETWORK_NO_SOURCE || v.error)){
    btn.disabled=true;
    btn.title='Video unavailable';
    return;
  }
  muted=!muted;
  if(v) v.muted=muted;
  btn.textContent=muted?'🔇':'🔊';
  btn.setAttribute('aria-label',muted?'Unmute video':'Mute video');
  btn.setAttribute('aria-pressed',muted?'false':'true');
}

// ══ COMPARE MODAL ══
let _lastFocus=null;
function showCmp(){
  if(!currentNeed) return;
  const d=DATA[currentNeed];
  _lastFocus=document.activeElement;
  document.getElementById('cmpTitle').textContent='Ingredient Compare · '+TITLE_MAP[currentNeed];
  const rows=d.products.map(p=>`
    <tr>
      <td class="cbrand">${esc(p.brand)}<br><span style="font-weight:400;color:#5A6478;font-size:11px;">${esc(p.name)}</span></td>
      <td><div class="smb"><div class="smbar"><div class="smfill" style="width:${Number(p.score)||0}%"></div></div><span style="font-weight:700;color:#34D05C;font-size:11px;">${Number(p.score)||0}</span></div></td>
      <td>${(p.tags||[]).map((t,i)=>`<span class="${(p.colors||[])[i]==='g'?'ctg':'ctr'}">${esc(t)}</span>`).join(' ')}</td>
      <td>${esc(p.rating)}</td><td>${esc(p.reviews)}</td><td>${esc(p.sales)}</td>
      <td style="font-style:italic;font-size:11px;color:#505A6B;max-width:130px;">${esc(p.verdict)}</td>
    </tr>`).join('');
  document.getElementById('cmpBody').innerHTML=`
    <table class="ctbl">
      <thead><tr><th>Product</th><th>Score</th><th>Key Attributes</th><th>Rating</th><th>Reviews</th><th>Rank</th><th>Verdict</th></tr></thead>
      <tbody>${rows}</tbody>
    </table>`;
  document.getElementById('cmpModal').classList.add('open');
  const closeBtn=document.querySelector('#cmpModal .mclose');
  if(closeBtn) closeBtn.focus();
}
function closeCmp(){
  document.getElementById('cmpModal').classList.remove('open');
  if(_lastFocus&&_lastFocus.focus){_lastFocus.focus();_lastFocus=null;}
}

// ══ SUBSCRIBE ══
function handleSub(){
  const emailInp = document.getElementById('subEmail');
  const email    = emailInp.value.trim();
  const btn      = document.querySelector('.nav-sub button');

  // Client-side validation first
  if(!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)){
    emailInp.style.borderColor='rgba(201,56,56,0.6)';
    emailInp.setAttribute('aria-invalid','true');
    emailInp.focus();
    setTimeout(()=>{emailInp.style.borderColor='';emailInp.removeAttribute('aria-invalid');},2400);
    return;
  }

  btn.textContent='…';
  btn.disabled=true;

  const endpoint = (KV_API && !KV_API.includes('YOUR_SUBDOMAIN'))
    ? KV_API + '/subscribe'
    : null;

  const succeed = ()=>{
    btn.textContent='✓ You\'re in!';
    btn.style.background='#2aaa4a';
    emailInp.value='';
    emailInp.setAttribute('aria-invalid','false');
    // SR announcement
    const srAnn=document.getElementById('sr-announce');
    if(srAnn){srAnn.textContent='';setTimeout(()=>{srAnn.textContent='Subscribed successfully!';},60);}
    setTimeout(()=>{btn.textContent='Subscribe';btn.style.background='';btn.disabled=false;},3200);
  };
  const fail = (msg)=>{
    btn.textContent='Subscribe';
    btn.disabled=false;
    emailInp.style.borderColor='rgba(201,56,56,0.6)';
    setTimeout(()=>emailInp.style.borderColor='',2400);
    // Subscribe error — silent in production to avoid leaking info
  };

  if(endpoint){
    fetch(endpoint, {
      method:'POST',
      headers:{'Content-Type':'application/json'},
      body:JSON.stringify({email, source:'navbar'})
    })
    .then(r=>{
      if(r.ok || r.status===201) succeed();
      else r.json().then(d=>fail(d.error||r.status)).catch(()=>fail(r.status));
    })
    .catch(()=>{
      // Network error — silently succeed on client (don't lose the user over a network hiccup)
      succeed();
    });
  } else {
    // KV_API not yet configured — local-only success animation
    succeed();
  }
}
document.getElementById('subEmail').addEventListener('keydown',e=>{if(e.key==='Enter') handleSub();});

// ══ INTRO TYPEWRITER (reads global TW_LINES) ══
function startIntroTyper(){
  const el=document.getElementById('introTyped');
  if(!el) return;
  // Clear any pending ticks from a previous instance before starting a new one
  if(el._typerTID){ clearTimeout(el._typerTID); el._typerTID=null; }
  el._typerRunning=true;
  let li=0, ci=0, del=false;
  function tick(){
    const lines=TW_LINES;
    if(!lines.length){el._typerRunning=false;return;}
    if(li>=lines.length) li=0;
    const line=lines[li];
    if(!del){
      el.textContent=line.slice(0,++ci);
      if(ci===line.length){del=true; el._typerTID=setTimeout(tick,2000);return;}
      el._typerTID=setTimeout(tick,60);
    } else {
      el.textContent=line.slice(0,--ci);
      if(ci===0){del=false;li=(li+1)%lines.length; el._typerTID=setTimeout(tick,400);return;}
      el._typerTID=setTimeout(tick,25);
    }
  }
  el._typerTID=setTimeout(tick,600);
}
startIntroTyper();

// ══ CHAT TYPEWRITER (reads global CHAT) ══
function startChatTyper(){
  const root=document.getElementById('chatMessages');
  if(!root || root._chatRunning) return;
  root._chatRunning=true;
  root._chatTIDs=root._chatTIDs||[];
  // reset bubbles
  for(let i=0;i<5;i++){
    const wrap=document.getElementById('cm'+i);
    const el=document.getElementById('ct'+i);
    if(el){el.textContent='';el.className='chat-bbl '+(i%2===0?'b':'u');}
    if(wrap&&i!==0) wrap.style.display='none';
  }
  function typeMessage(idx, text, onDone){
    const el = document.getElementById('ct'+idx);
    const wrap = document.getElementById('cm'+idx);
    if(!el || !wrap){ if(onDone) onDone(); return; }
    wrap.style.display = 'flex';
    el.textContent = '';
    const textNode = document.createElement('span');
    const cursor = document.createElement('span');
    cursor.className = 'chat-cursor-inline';
    el.appendChild(textNode);
    el.appendChild(cursor);
    let i = 0;
    const speed = (idx % 2 === 0) ? 20 : 22;
    function tick(){
      if(i <= text.length){
        textNode.textContent = text.slice(0, i);
        i++;
        setTimeout(tick, speed);
      } else {
        cursor.remove();
        const bblType = (idx % 2 === 0) ? 'float-b' : 'float-u';
        el.classList.add(bblType, 'float-delay-' + (idx + 1));
        if(onDone) setTimeout(onDone, 150);
      }
    }
    tick();
  }
  function runConv(idx){
    if(idx >= CHAT.length || idx>=5){ root._chatRunning=false; return; }
    const pause = idx===0 ? 300 : 200;
    const tid=setTimeout(()=>{ typeMessage(idx, CHAT[idx].t, ()=>runConv(idx+1)); }, pause);
    root._chatTIDs.push(tid);
  }
  runConv(0);
}
startChatTyper();

// ══ ADMIN JS ══
function go(id,el){
  document.querySelectorAll('.view').forEach(v=>v.classList.remove('on'));
  document.getElementById('view-'+id).classList.add('on');
  document.querySelectorAll('.sb1-item').forEach(i=>i.classList.remove('act'));
  if(el) el.classList.add('act');
  document.getElementById('sb2').classList.toggle('show', id==='categories');
  if(id==='email')     return;
  if(id==='buyer')     rBuyer();
  if(id==='chat')      rChat();
  if(id==='searchbar') rChips();
  if(id==='sidx')      rSidx();
}

function rBuyer(){
  document.getElementById('twLines').innerHTML = TW_LINES.map((l,i)=>`<div class="fg"><label>Line ${i+1}</label><input class="fi" type="text" value="${esc(l)}"/></div>`).join('');
  document.getElementById('diffRows').innerHTML = DIFF.map((d,i)=>`
    <div style="${i?'margin-top:14px;padding-top:14px;border-top:1px solid var(--border);':''}">
      <div class="gr3"><div class="fg"><label>Icon</label><input class="fi" type="text" value="${esc(d.icon)}" style="text-align:center;font-size:16px;"/></div>
      <div class="fg" style="grid-column:span 2"><label>Bold Label</label><input class="fi" type="text" value="${esc(d.bold)}"/></div></div>
      <div class="fg"><label>Description</label><input class="fi" type="text" value="${esc(d.desc)}"/></div>
    </div>`).join('');
}

function rChat(){
  document.getElementById('chatFields').innerHTML = CHAT.map((m,i)=>`
    <div class="fg" style="${i?'margin-top:12px;padding-top:12px;border-top:1px solid var(--border);':''}">
      <label>Message ${i+1} — ${m.r==='e'?'Elova (E)':'User (🙋)'}</label>
      <textarea class="fi" rows="${m.r==='e'?3:2}">${esc(m.t)}</textarea>
    </div>`).join('');
}

function rChips(){
  const needOpts=Object.keys(DATA).map(k=>`<option value="${k}">${k}</option>`).join('');
  document.getElementById('chipsEditor').innerHTML=CHIPS.map((c,i)=>`
    <div style="display:grid;grid-template-columns:46px 100px 1fr 110px 30px;gap:8px;align-items:center;padding:8px 0;border-bottom:1px solid var(--border);">
      <input class="fi" style="text-align:center;font-size:16px;padding:6px;" value="${esc(c.emoji)}"/>
      <input class="fi" style="font-size:12px;" value="${esc(c.label)}"/>
      <div style="font-size:11px;color:var(--text3);">→ loads DATA[<strong style="color:var(--text2)">${esc(c.need)}</strong>] on Pages 2 & 3</div>
      <select class="fi" style="font-size:12px;">${needOpts.replace(`value="${c.need}"`,`value="${c.need}" selected`)}</select>
      <button class="del" onclick="rmChip(${i})" aria-label="Remove chip">✕</button>
    </div>`).join('')+`<button class="btn btn-w btn-sm" style="margin-top:10px" onclick="addChip()">+ Add Chip</button>`;
}
function addChip(){CHIPS.push({emoji:'🌿',label:'New',need:'sleep'});rChips();}
function rmChip(i){CHIPS.splice(i,1);rChips();}

function rSidx(){
  const needOpts=Object.keys(DATA).map(k=>`<option value="${k}">${k}</option>`).join('');
  document.getElementById('sidxList').innerHTML=SIDX.map((s,i)=>`
    <div class="si-row">
      <div class="si-ico">${esc(s.icon)}</div>
      <input class="si-in" value="${esc(s.name)}" placeholder="Name"/>
      <input class="si-in" value="${esc(s.sub)}" placeholder="Sub-label"/>
      <input class="si-in" value="${esc(s.tag)}" placeholder="Tag"/>
      <select class="si-in" style="cursor:pointer">${needOpts.replace(`value="${s.need}"`,`value="${s.need}" selected`)}</select>
      <button class="del" onclick="rmSidx(${i})" aria-label="Remove suggestion">✕</button>
    </div>`).join('');
}
function addSidx(){SIDX.push({icon:'🌿',name:'New',sub:'Description',tag:'Tag',need:'sleep'});rSidx();}
function rmSidx(i){SIDX.splice(i,1);rSidx();}

function selAll(cb){document.querySelectorAll('#emailTbody input[type=checkbox]').forEach(c=>c.checked=cb.checked);}
function copyEmails(){
  if(KV_API && !KV_API.includes('YOUR_SUBDOMAIN')){
    _getStoredHash().then(function(pwHash){
      fetch(KV_API+'/subscribers',{headers:{'X-PW-Hash':pwHash}})
      .then(r=>r.ok?r.text():Promise.reject(r.status))
      .then(function(csv){
        const emails=csv.split('\n').slice(1).map(l=>l.split(',')[0].replace(/"/g,'')).filter(e=>e&&e.includes('@'));
        const txt=emails.join('\n');
        if(navigator.clipboard&&navigator.clipboard.writeText){
          navigator.clipboard.writeText(txt).then(()=>_admToast('✓ Copied '+emails.length+' emails')).catch(()=>_admToast('✓ Copied'));
        } else { _admToast('✓ Copied'); }
      })
      .catch(function(e){ _admToast('⚠ Could not load subscribers: '+e); });
    });
  } else {
    _admToast('⚠ Configure KV_API to copy real subscribers');
  }
}
function dlCsv(){
  if(KV_API && !KV_API.includes('YOUR_SUBDOMAIN')){
    _admToast('Downloading CSV from cloud…');
    _getStoredHash().then(function(pwHash){
      fetch(KV_API+'/subscribers',{headers:{'X-PW-Hash':pwHash}})
      .then(function(r){
        if(!r.ok){ _admToast('⚠ Export failed: '+r.status); return; }
        return r.blob().then(function(blob){
          const a=document.createElement('a');
          a.href=URL.createObjectURL(blob);
          a.download='elova_subscribers.csv';
          a.click();
          setTimeout(()=>URL.revokeObjectURL(a.href),10000);
          _admToast('✓ CSV downloaded');
        });
      })
      .catch(function(){ _admToast('⚠ Export failed — network error'); });
    });
  } else {
    // Fallback: download sample CSV when Worker not configured
    const csv='Email,Date,Source\n# Configure KV_API in index.html to export real subscribers';
    const a=document.createElement('a');a.href='data:text/csv;charset=utf-8,'+encodeURIComponent(csv);a.download='elova_subscribers.csv';a.click();
    _admToast('⚠ Sample CSV (configure KV_API for real data)');
  }
}

function addOpt(val=''){
  const list=document.getElementById('f_opts_list');
  if(!list)return;
  const row=document.createElement('div');
  row.style.cssText='display:flex;align-items:center;gap:6px;';
  const inp=document.createElement('input');
  inp.className='fi';inp.type='text';inp.value=val;inp.placeholder='Option text…';inp.style.flex='1';
  const btn=document.createElement('button');
  btn.style.cssText='flex-shrink:0;width:28px;height:28px;border-radius:7px;border:1px solid rgba(200,60,60,.2);background:transparent;color:#c04040;font-size:14px;cursor:pointer;display:flex;align-items:center;justify-content:center;';
  btn.textContent='×';btn.setAttribute('aria-label','Remove option');
  btn.addEventListener('click',()=>row.remove());
  row.appendChild(inp);row.appendChild(btn);
  list.appendChild(row);
}
function loadOpts(opts){
  const list=document.getElementById('f_opts_list');
  if(!list)return;
  list.innerHTML='';
  (opts||[]).forEach(o=>addOpt(o));
}
function buildTree(){
  document.getElementById('catTree').innerHTML=ADM_CAT.map((cat,ci)=>`
    <div class="c1-block">
      <div class="c1-btn" id="c1-${ci}" onclick="togCat(${ci})">
        <span class="c1-label">${esc(cat.label)}</span>
        <span class="c1-arrow">›</span>
      </div>
      <div class="c2-list" id="c2l-${ci}">
        ${cat.subs.map((sub,si)=>`
          <div class="c2-item" id="c2-${ci}-${si}" onclick="selSub(${ci},${si})">
            <div class="c2-dot"></div>${esc(sub.label)}
            <span style="font-size:10px;color:var(--text3);margin-left:auto;font-weight:500;">${esc(sub.need)}</span>
          </div>`).join('')}
      </div>
    </div>`).join('');
}
function togCat(ci){
  const btn=document.getElementById('c1-'+ci);
  if(!btn) return;
  const wasOpen=btn.classList.contains('open');
  document.querySelectorAll('.c1-btn').forEach(b=>b.classList.remove('open'));
  if(!wasOpen) btn.classList.add('open');
}
function selSub(ci,si){
  document.querySelectorAll('.c2-item').forEach(i=>i.classList.remove('act'));
  document.getElementById(`c2-${ci}-${si}`).classList.add('act');
  const cat=ADM_CAT[ci], sub=cat.subs[si], d=DATA[sub.need];
  document.getElementById('breadcrumb').style.display='flex';
  document.getElementById('bc1').textContent=cat.label;
  document.getElementById('bc2').textContent='• '+sub.label;
  document.getElementById('bc3').textContent=sub.need;
  document.getElementById('emptyState').style.display='none';
  document.getElementById('catEditor').style.display='block';
  document.getElementById('saveCatBtn').style.display='';
  document.getElementById('prodNotice').textContent=`⚠️ Sub-categories "${sub.label}" (and others mapped to "${sub.need}") all share these 3 products. Editing here updates all of them.`;
  const ab = parseArtBody(d);
  document.getElementById('f_vid').value      = d.videoUrl||'';
  document.getElementById('f_vbadge').value   = d.vBadge||'🎬 Elova Buyer';
  document.getElementById('f_vtag').value     = d.vTag||'Now Reviewing';
  document.getElementById('f_vcap').value     = d.vCaption||'';
  document.getElementById('f_atag').value     = d.artTag||'';
  document.getElementById('f_atitle').value   = d.artTitle||'';
  document.getElementById('f_aimg').value     = d.artImg||'';
  document.getElementById('f_abody_p1').value = ab.p1;
  document.getElementById('f_abody_hl').value = ab.hl;
  document.getElementById('f_abody_p2').value = ab.p2;
  document.getElementById('f_otitle').value   = d.optTitle||'';
  loadOpts(d.opts||[]);
  rProds(d.products||[]);
}

function rProds(prods){
  document.getElementById('prodBlocks').innerHTML=prods.map((p,i)=>`
    <div class="pb">
      <div class="pb-head">
        <div style="display:flex;align-items:center;">
          <div class="pb-rank">${i+1}</div>
          <div class="pb-name">${esc(p.brand)} — ${esc(p.name)}</div>
        </div>
        <div class="tp-row">
          <label class="tog"><input type="checkbox" ${p.top?'checked':''} aria-label="Top Pick"><span class="ts"></span></label>
          Top Pick ⭐
        </div>
      </div>
      <div class="gr2">
        <div class="fg"><label>Brand</label><input class="fi" type="text" value="${esc(p.brand)}"/></div>
        <div class="fg"><label>Product Name</label><input class="fi" type="text" value="${esc(p.name)}"/></div>
        <div class="fg"><label>Image URL</label><input class="fi" type="url" value="${esc(p.img)}"/></div>
        <div class="fg"><label>Product URL</label><input class="fi" type="url" value="${esc(p.url||'')}"/></div>
        <div class="fg"><label>Elova Score (0–100)</label><input class="fi" type="number" min="0" max="100" value="${p.score}"/></div>
        <div class="fg"><label>Rating</label><input class="fi" type="text" value="${esc(p.rating||'')}"/></div>
        <div class="fg"><label>Reviews</label><input class="fi" type="text" value="${esc(p.reviews||'')}"/></div>
        <div class="fg"><label>Sales Rank</label><input class="fi" type="text" value="${esc(p.sales||'')}"/></div>
        <div class="fg"><label>Price</label><input class="fi" type="text" value="${esc(p.price||'')}"/></div>
        <div class="fg"><label>Price Unit <span class="hn">("/60 caps")</span></label><input class="fi" type="text" value="${esc(p.priceUnit||'')}"/></div>
        <div class="fg"><label>Dose</label><input class="fi" type="text" value="${esc(p.dose||'')}"/></div>
        <div class="fg"><label>Form</label><input class="fi" type="text" value="${esc(p.form||'')}"/></div>
        <div class="fg"><label>Best For</label><input class="fi" type="text" value="${esc(p.bestFor||'')}"/></div>
        <div class="fg"><label>Not For</label><input class="fi" type="text" value="${esc(p.notFor||'')}"/></div>
      </div>
      <div class="fg"><label>Verdict <span class="hn">(italic quote on card)</span></label><textarea class="fi" rows="2">${esc(p.verdict||'')}</textarea></div>
      <div style="font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--text2);margin:10px 0 8px;">Tags & Colors</div>
      ${(p.tags||[]).map((t,ti)=>`
        <div class="tag-row">
          <input class="fi" type="text" value="${esc(t)}" style="font-size:12px;"/>
          <select class="tcsel" aria-label="Tag color">
            <option value="g" ${(p.colors||[])[ti]==='g'?'selected':''}>🟢 Green</option>
            <option value="r" ${(p.colors||[])[ti]==='r'?'selected':''}>🔴 Red</option>
          </select>
        </div>`).join('')}
      <div class="fg" style="margin-top:10px"><label>Certifications <span class="hn">(comma-separated)</span></label>
        <input class="fi" type="text" value="${esc((p.cert||[]).join(', '))}"/></div>
    </div>`).join('');
}

function buildDashTable(){
  const rows=[
    ['✉️ Email Subscriptions',    'Navbar placeholder · Subscribe button · post-subscribe text · subscriber count · subscriber list · date filter · copy/download CSV'],
    ['👤 Buyer Profile', 'LIVE badge text · 4 typewriter lines · "Why Elova is different" title · 4 feature rows (icon+bold+description)'],
    ['💬 Chat Messages', '"How I work with you" header · 5 chat bubbles (alternating Elova/User, frontend CHAT[])'],
    ['🔍 Search Bar & Chips', 'Navbar logo text · subscribe text · guide text · 2 placeholders · Find My Stack button · 6 chip tags + need mapping'],
    ['🔤 Search Suggestions',     '13 dropdown suggestions: icon/name/sub-label/tag/need key (max 5 shown as user types)'],
    ['🔗 Footer & Nav', 'Footer main text + 3 links · "life" hidden button · Page 2 top bar (back/title/3-step progress) · "Select all…" hint · "Show My Picks" button · Page 3 (buy button/badge/Compare modal title/table headers/titleMap 10 entries)'],
    ['🏷 Category Labels', '7 top-level category names + 22 sub-category names (frontend <option> text + CAT_TREE label)'],
    ['🗂 Categories & Content ★', '7×(2-4) sub-categories → each maps to: video URL+badge+tag+caption · article (Tag/Title/Img/P1/Hl/P2) · options list (title+N items) · 3 products (all 17 fields)'],
    ['⏳ Search Overlay', 'Overlay logo (2 fields) · 4-step loading icons+text · 6 progress status messages'],
    ['🔍 SEO & Meta', 'title · description · keywords · author · canonical · robots · og: all fields · twitter: all fields · PWA meta · JSON-LD structured data'],
    ['🔐 Password', 'Change admin login password (current password verification + new password confirmation)'],
  ];
  document.getElementById('dashTable').innerHTML=rows.map(([s,c])=>`
    <tr style="border-bottom:1px solid var(--border);">
      <td style="padding:9px 10px;font-weight:700;font-size:12px;white-space:nowrap;">${s}</td>
      <td style="padding:9px 10px;color:var(--text2);font-size:12px;">${c}</td>
    </tr>`).join('');
}

function esc(s){return String(s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;');}

// _sanitizeHTML: lightweight allow-list HTML sanitizer (no external lib needed).
// Strips all tags except <p> <strong> <em> <br> <div> and their safe attributes.
// Prevents stored XSS when admin-edited artBody is rendered as innerHTML.
function _sanitizeHTML(raw){
  const ALLOWED_TAGS=/^(p|strong|em|br|div|span|ul|ol|li)$/i;
  const ALLOWED_ATTRS=/^(class|style)$/i;
  // Use a detached document to parse so no scripts run during parsing
  const doc = document.implementation.createHTMLDocument('');
  const wrap = doc.createElement('div');
  wrap.innerHTML = raw;
  // Walk all elements and strip disallowed tags / attributes
  const walker = doc.createTreeWalker(wrap, NodeFilter.SHOW_ELEMENT);
  const toRemove = [];
  let node = walker.nextNode();
  while(node){
    if(!ALLOWED_TAGS.test(node.tagName)){
      toRemove.push(node);
    } else {
      Array.from(node.attributes).forEach(attr=>{
        if(!ALLOWED_ATTRS.test(attr.name) && attr.name!=='aria-label') node.removeAttribute(attr.name);
      });
      // Strip javascript: from style / remaining attrs
      if(node.getAttribute('style')){
        const s = node.getAttribute('style').replace(/expression\s*\(|javascript:/gi,'');
        node.setAttribute('style', s);
      }
    }
    node = walker.nextNode();
  }
  toRemove.forEach(n=>{
    const parent=n.parentNode;
    if(parent){ while(n.firstChild) parent.insertBefore(n.firstChild,n); parent.removeChild(n); }
  });
  return wrap.innerHTML;
}

function init(){
  buildTree();
  buildDashTable();
}

// ══ DISCLAIMER MODAL ══
function showDisclaimer(){
  const m = document.getElementById('disclaimerModal');
  m.style.display = 'flex';
  document.body.style.overflow = 'hidden';
}
function closeDisclaimer(){
  const m = document.getElementById('disclaimerModal');
  m.style.display = 'none';
  document.body.style.overflow = '';
}
document.getElementById('disclaimerModal').addEventListener('click', function(e){
  if(e.target === this) closeDisclaimer();
});
document.addEventListener('keydown', function(e){
  if(e.key === 'Escape'){
    if(document.getElementById('disclaimerModal').style.display === 'flex') closeDisclaimer();
    if(document.getElementById('cmpModal').classList.contains('open')) closeCmp();
    sdEl.classList.remove('open');
  }
});

// ══ ADMIN AUTH ══
// Brute-force throttle: 5 wrong attempts → 5-second lockout.
let _loginAttempts=0, _loginLocked=false;
function doLogin(){
  const v=document.getElementById('pwInput').value;
  const e=document.getElementById('loginErr');
  if(_loginLocked){e.textContent='Too many attempts — wait 5 seconds.';return;}
  if(!v){e.textContent='Enter your password.';return;}
  // Async hash compare — no plaintext password ever held in memory beyond this scope
  _hash(v).then(function(inputHash){
    return _getStoredHash().then(function(storedHash){
      if(inputHash===storedHash){
        _loginAttempts=0;
        document.getElementById('pwInput').value='';
        document.getElementById('loginWrap').style.display='none';
        document.getElementById('app').style.display='block';
        init();
      } else {
        _loginAttempts++;
        e.textContent='Incorrect password.';
        document.getElementById('pwInput').value='';
        setTimeout(()=>{e.textContent='';},2500);
        if(_loginAttempts>=5){
          _loginLocked=true;
          e.textContent='Too many attempts — locked for 5 seconds.';
          setTimeout(()=>{_loginLocked=false;_loginAttempts=0;e.textContent='';},5000);
        }
      }
    });
  }).catch(()=>{e.textContent='Login error — please retry.';});
}

function changePw(){
  const c=document.getElementById('curPw').value;
  const n=document.getElementById('newPw').value;
  const f=document.getElementById('cfmPw').value;
  if(!c||!n){toast('⚠ All fields required');return;}
  if(n!==f){toast('⚠ New passwords do not match');return;}
  if(n.length<6){toast('⚠ Password must be at least 6 characters');return;}
  // Verify current password, then store new hash in localStorage AND notify user about KV sync
  Promise.all([_hash(c),_getStoredHash()]).then(function([inputHash,storedHash]){
    if(inputHash!==storedHash){toast('⚠ Current password incorrect');return;}
    return _hash(n).then(function(newHash){
      // 1. Update localStorage (controls local admin login)
      try{ localStorage.setItem(_PW_KEY, newHash); }catch(e){}
      document.getElementById('curPw').value='';
      document.getElementById('newPw').value='';
      document.getElementById('cfmPw').value='';
      // 2. KV admin_pw_hash is a separate store — Worker bootstraps it on first POST /cms.
      // To fully sync: delete 'admin_pw_hash' key in KV dashboard (operaitons.md Method B),
      // then log back in with the new password so the next Save bootstraps it in KV.
      if(KV_API && !KV_API.includes('YOUR_SUBDOMAIN')){
        toast('✓ Password updated locally. To sync API auth: delete admin_pw_hash in KV dashboard, then re-login with new password.');
      } else {
        toast('✓ Password updated — takes effect immediately');
      }
    });
  }).catch(()=>toast('⚠ Error updating password — please retry'));
}

// ══ GLUE ══
// ⚠️  SECURITY: Client-side admin only. Replace with server-side auth for true production.
// Password is stored as a SHA-256 hex hash in localStorage key 'elova_pw_h'.
// Default hash = SHA-256('elova-admin'). Change password via Settings → Password on first login.
const _PW_KEY = 'elova_pw_h';
// SHA-256 is computed at runtime via crypto.subtle. Default password: 'elova-admin'.
// Change on first login via Settings → Password.
async function _hash(str){
  const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(str));
  return Array.from(new Uint8Array(buf)).map(b=>b.toString(16).padStart(2,'0')).join('');
}
async function _getStoredHash(){
  let h = null;
  try{ h = localStorage.getItem(_PW_KEY); }catch(e){}
  if(!h){
    // First run: hash the bootstrap default and store it
    h = await _hash('elova-admin');
    try{ localStorage.setItem(_PW_KEY, h); }catch(e){}
  }
  return h;
}
const LS_KEY   = 'elova_cms_v1';
// ── DEPLOY: Replace YOUR_SUBDOMAIN with your actual Cloudflare Workers subdomain ──
// 1. Run:  wrangler deploy  (from the api/ folder)
// 2. Copy the printed Worker URL here, e.g. 'https://elova-api.my-name.workers.dev'
// Without this, CMS saves only persist in localStorage (single browser, no cloud sync).
const KV_API   = 'https://elova-api.hotlinkai-official.workers.dev';

function buildADM_CAT(){
  return Object.entries(CAT_TREE).map(([key,val])=>({
    key, label:val.label,
    subs:val.subs.map(s=>({value:s.value,label:s.label,need:s.need}))
  }));
}
let ADM_CAT = buildADM_CAT();

function saveToLS(){
  const payload = {DATA,CHIPS,SIDX,TW_LINES,BIO,DIFF,CHAT};
  // Always write to localStorage as immediate local backup
  try{ localStorage.setItem(LS_KEY, JSON.stringify(payload)); }catch(e){}
  // Also persist to Cloudflare KV via Worker so all visitors see the update
  if(KV_API && !KV_API.includes('YOUR_SUBDOMAIN')){
    _getStoredHash().then(function(pwHash){
      fetch(KV_API+'/cms', {
        method:'POST',
        headers:{'Content-Type':'application/json','X-PW-Hash':pwHash},
        body:JSON.stringify(payload)
      }).then(function(r){
        if(r.ok){ _admToast('✓ Saved — all visitors will see updates'); }
        else if(r.status===429){ _admToast('⚠ Save rate-limited — wait a moment and try again'); }
        else if(r.status===403){ _admToast('⚠ Session expired — please log out and back in'); }
        else { r.text().then(function(t){ _admToast('⚠ Cloud save failed: '+t); }); }
      }).catch(function(){ _admToast('⚠ Cloud save failed — local backup kept'); });
    });
  } else {
    _admToast('✓ Saved locally (configure KV_API to sync to cloud)');
  }
}
function _applyPayload(s){
  if(!s) return;
  if(s.DATA){
    Object.keys(s.DATA).forEach(k=>{
      if(DATA[k]){
        // Deep-merge: replace products array + scalar fields, preserving local keys absent from KV
        const src = s.DATA[k];
        if(Array.isArray(src.products)) DATA[k].products = src.products;
        Object.keys(src).forEach(field=>{ if(field!=='products') DATA[k][field]=src[field]; });
      } else {
        // New category added via CMS — adopt it wholesale
        DATA[k] = s.DATA[k];
      }
    });
  }
  const arr=(src,dst)=>{if(src){dst.length=0;src.forEach(c=>dst.push(c));}};
  arr(s.CHIPS,CHIPS); arr(s.SIDX,SIDX); arr(s.TW_LINES,TW_LINES);
  arr(s.BIO,BIO); arr(s.DIFF,DIFF); arr(s.CHAT,CHAT);
}
function loadFromLS(){
  // 1. Apply localStorage immediately so page doesn't flash defaults
  try{
    const local = JSON.parse(localStorage.getItem(LS_KEY)||'null');
    if(local){ _applyPayload(local); refreshFrontend(); }
  }catch(e){}
  // 2. Fetch latest from KV with 4s timeout — never blocks UI
  if(KV_API && !KV_API.includes('YOUR_SUBDOMAIN')){
    const ctrl=new AbortController();
    const tid=setTimeout(()=>ctrl.abort(),4000);
    fetch(KV_API+'/cms',{cache:'no-store',signal:ctrl.signal})
      .then(function(r){clearTimeout(tid);return r.ok?r.json():null;})
      .then(function(remote){
        if(!remote) return;
        try{localStorage.setItem(LS_KEY,JSON.stringify(remote));}catch(e){}
        _applyPayload(remote);
        refreshFrontend();
      })
      .catch(function(){clearTimeout(tid);}); // timeout/offline → use local
  }
}

let _adminMode=false;

function enterAdminMode(){
  _adminMode=true;
  ADM_CAT=buildADM_CAT();
  document.getElementById('fe-wrapper').style.display='none';
  document.getElementById('adm-wrapper').style.display='block';
  document.getElementById('exitAdminBtn').style.display='block';
  document.getElementById('loginWrap').style.display='flex';
  document.getElementById('app').style.display='none';
  const cb=document.getElementById('cookie-banner');
  if(cb) cb.style.display='none';
}
function exitAdminMode(){
  collectAdminData(); saveToLS();
  _adminMode=false;
  document.getElementById('adm-wrapper').style.display='none';
  document.getElementById('exitAdminBtn').style.display='none';
  document.getElementById('fe-wrapper').style.display='block';
  const cb=document.getElementById('cookie-banner');
  if(cb) cb.style.display='';
  refreshFrontend();
  window.scrollTo(0,0);
}
function adminLogin(){ enterAdminMode(); }
function doLogout(){ exitAdminMode(); }

function refreshFrontend(){
  try{
    // ── Chips ──
    const cg=document.getElementById('chipGroup');
    if(cg){
      cg.innerHTML=CHIPS.map(c=>`<div class="qchip chip" data-need="${esc(c.need)}">${esc(c.emoji)} ${esc(c.label)}</div>`).join('');
      bindChips();
    }
    // ── Why Different rows ──
    const diffList=document.querySelector('.diff-list');
    if(diffList&&DIFF.length){
      diffList.innerHTML=DIFF.map(d=>
        `<div class="diff-row"><div class="diff-icon">${esc(d.icon)}</div><div class="diff-text"><strong>${esc(d.bold)}</strong> — ${esc(d.desc)}</div></div>`
      ).join('');
    }
    // ── Restart typewriters with new data ──
    const introEl=document.getElementById('introTyped');
    if(introEl){
      if(introEl._typerTID){ clearTimeout(introEl._typerTID); introEl._typerTID=null; }
      introEl._typerRunning=false; introEl.textContent=''; startIntroTyper();
    }
    const chatRoot=document.getElementById('chatMessages');
    if(chatRoot){
      if(chatRoot._chatTIDs){ chatRoot._chatTIDs.forEach(id=>clearTimeout(id)); chatRoot._chatTIDs=[]; }
      chatRoot._chatRunning=false; startChatTyper();
    }
    // ── Page2 live update if already visible ──
    if(currentNeed&&DATA[currentNeed]){
      const d=DATA[currentNeed];
      const vid=document.getElementById('buyerVid');
      if(vid&&d.videoUrl){
        const src=vid.querySelector('source');
        if(src&&src.getAttribute('src')!==d.videoUrl){src.setAttribute('src',d.videoUrl);vid.load();}
      }
      const setTxt=(id,val)=>{const el=document.getElementById(id);if(el&&val!=null)el.textContent=val;};
      setTxt('vBadge',d.vBadge);
      setTxt('vTag',d.vTag);
      setTxt('vCaption',d.vCaption);
      setTxt('artTag',d.artTag);
      setTxt('artTitle',d.artTitle);
      const abEl=document.getElementById('artBody');
      if(abEl&&d.artBody) abEl.innerHTML=_sanitizeHTML(d.artBody);
      const imgEl=document.getElementById('artImg');
      if(imgEl&&d.artImg) imgEl.src=d.artImg;
    }
  }catch(e){}
}

function collectAdminData(){
  try{
    document.querySelectorAll('#twLines input').forEach((inp,i)=>{ if(TW_LINES[i]!==undefined) TW_LINES[i]=inp.value; });
    document.querySelectorAll('#chatFields textarea').forEach((ta,i)=>{ if(CHAT[i]!==undefined) CHAT[i].t=ta.value; });
    const di=document.querySelectorAll('#diffRows input[type=text]');
    DIFF.forEach((d,i)=>{ if(di[i*3]) d.icon=di[i*3].value; if(di[i*3+1]) d.bold=di[i*3+1].value; if(di[i*3+2]) d.desc=di[i*3+2].value; });
    document.querySelectorAll('#chipsEditor > div').forEach((row,i)=>{
      if(!CHIPS[i]) return;
      const ins=row.querySelectorAll('input'); const sel=row.querySelector('select');
      if(ins[0]) CHIPS[i].emoji=ins[0].value; if(ins[1]) CHIPS[i].label=ins[1].value; if(sel) CHIPS[i].need=sel.value;
    });
    document.querySelectorAll('#sidxList .si-row').forEach((row,i)=>{
      if(!SIDX[i]) return;
      const ins=row.querySelectorAll('input'); const sel=row.querySelector('select');
      if(ins[0]) SIDX[i].name=ins[0].value; if(ins[1]) SIDX[i].sub=ins[1].value;
      if(ins[2]) SIDX[i].tag=ins[2].value; if(sel) SIDX[i].need=sel.value;
    });
    const bc3=document.getElementById('bc3'),fv=document.getElementById('f_vid');
    if(bc3&&bc3.textContent&&fv){
      const nk=bc3.textContent.trim(), d=DATA[nk];
      if(d){
        const g=id=>{const e=document.getElementById(id);return e?e.value:null;};
        if(g('f_vid')!=null) d.videoUrl=g('f_vid');
        if(g('f_vbadge')!=null) d.vBadge=g('f_vbadge');
        if(g('f_vtag')!=null) d.vTag=g('f_vtag');
        if(g('f_vcap')!=null) d.vCaption=g('f_vcap');
        if(g('f_atag')!=null) d.artTag=g('f_atag');
        if(g('f_atitle')!=null) d.artTitle=g('f_atitle');
        if(g('f_aimg')!=null) d.artImg=g('f_aimg');
        const p1=g('f_abody_p1'), hl=g('f_abody_hl'), p2=g('f_abody_p2');
        if(p1!==null||hl!==null||p2!==null){
          d.artBody='<p>'+(p1||'')+'</p>\n<div class="art-hl">Key Buyer Finding: '+(hl||'')+'</div>\n<p>'+(p2||'')+'</p>';
          d.artP1=p1||''; d.artHl=hl||''; d.artP2=p2||'';
        }
        if(g('f_otitle')!=null) d.optTitle=g('f_otitle');
        const optRows=document.querySelectorAll('#f_opts_list input[type=text]');
        if(optRows.length) d.opts=Array.from(optRows).map(r=>r.value.trim()).filter(Boolean);
        document.querySelectorAll('.pb').forEach((pb,pi)=>{
          const p=d.products[pi]; if(!p) return;
          const fm={'Brand':'brand','Product Name':'name','Image URL':'img','Product URL':'url',
            'Elova Score':'score','Rating':'rating','Reviews':'reviews','Sales Rank':'sales',
            'Price':'price','Price Unit':'priceUnit','Dose':'dose','Form':'form','Best For':'bestFor','Not For':'notFor'};
          pb.querySelectorAll('input.fi,textarea.fi').forEach(inp=>{
            const lbl=inp.closest('.fg')?.querySelector('label')?.childNodes[0]?.textContent?.trim()||'';
            const fld=Object.keys(fm).find(k=>lbl.includes(k));
            if(fld) p[fm[fld]]=fld==='Elova Score'?(parseInt(inp.value)||p.score):inp.value;
          });
          // Tags & colors
          const tagRows=pb.querySelectorAll('.tag-row');
          if(tagRows.length){
            p.tags=[];p.colors=[];
            tagRows.forEach(tr=>{
              const ti=tr.querySelector('input');const ts=tr.querySelector('select');
              if(ti){p.tags.push(ti.value);p.colors.push(ts?ts.value:'g');}
            });
          }
          // Cert
          const certInp=Array.from(pb.querySelectorAll('input.fi')).find(inp=>{
            const lbl=inp.closest('.fg')?.querySelector('label')?.childNodes[0]?.textContent?.trim()||'';
            return lbl.includes('Certifications');
          });
          if(certInp) p.cert=certInp.value.split(',').map(s=>s.trim()).filter(Boolean);
          const tog=pb.querySelector('.tog input'); if(tog) p.top=tog.checked;
        });
      }
    }
  }catch(e){}
}

function _admToast(msg){
  msg=msg||'✓ Saved';
  const t=document.getElementById('toast');
  if(!t) return;
  t.textContent=msg;
  t.classList.add('show');
  clearTimeout(_admToast._tid);
  _admToast._tid=setTimeout(()=>t.classList.remove('show'),2600);
}

function toast(msg){
  msg=msg||'✓ Saved';
  if(_adminMode){ collectAdminData(); saveToLS(); refreshFrontend(); _admToast(msg); }
  else {
    const t=document.getElementById('toast-fe');
    if(!t) return;
    t.textContent=msg;
    t.classList.add('show');
    clearTimeout(toast._tid);
    toast._tid=setTimeout(()=>t.classList.remove('show'),2600);
  }
}

// ══ COOKIE CONSENT (GDPR-compliant) ══
// Shows immediately on first visit — no delay before any tracking loads
(function(){
  try{
    var stored = localStorage.getItem('elova_consent');
    if(!stored){
      // Show banner immediately — GDPR requires consent BEFORE analytics load
      var b = document.getElementById('cookie-banner');
      if(b) b.classList.remove('hidden');
    }
  }catch(e){}
})();

// ── toggleCookiePrefs: open/close granular preferences panel ──
function toggleCookiePrefs(){
  var panel = document.getElementById('cookie-prefs');
  var btn   = document.querySelector('[aria-controls="cookie-prefs"]');
  if(!panel) return;
  var opening = !panel.classList.contains('open');
  panel.classList.toggle('open', opening);
  panel.setAttribute('aria-hidden', String(!opening));
  if(btn) btn.setAttribute('aria-expanded', String(opening));
}

// ── handleConsent: Accept All or Decline All ──
function handleConsent(accepted){
  try{
    var level = accepted ? 'granted' : 'denied';
    localStorage.setItem('elova_consent', level);
    localStorage.setItem('elova_consent_ts', Date.now());
    localStorage.setItem('elova_consent_version', '1');
    // Sync analytics pref toggle to match
    var analyticsCb = document.getElementById('pref-analytics');
    if(analyticsCb) analyticsCb.checked = accepted;
    if(typeof gtag === 'function'){
      if(accepted){
        gtag('consent','update',{
          'ad_storage':'denied',          // we don't run ads
          'ad_user_data':'denied',
          'ad_personalization':'denied',
          'analytics_storage':'granted',
          'functionality_storage':'granted',
          'security_storage':'granted'
        });
        if(typeof _loadGA4 === 'function') _loadGA4();
      } else {
        gtag('consent','update',{
          'ad_storage':'denied',
          'ad_user_data':'denied',
          'ad_personalization':'denied',
          'analytics_storage':'denied',
          'functionality_storage':'granted',
          'security_storage':'granted'
        });
      }
    }
  }catch(e){}
  var b = document.getElementById('cookie-banner');
  if(b) b.classList.add('hidden');
}

// ── handleConsentGranular: Save individual toggle choices ──
function handleConsentGranular(){
  try{
    var analyticsOn  = document.getElementById('pref-analytics')  && document.getElementById('pref-analytics').checked;
    var functionalOn = document.getElementById('pref-functional') && document.getElementById('pref-functional').checked;
    var level = analyticsOn ? 'granted' : 'denied';
    localStorage.setItem('elova_consent', level);
    localStorage.setItem('elova_consent_ts', Date.now());
    localStorage.setItem('elova_consent_version', '1');
    localStorage.setItem('elova_consent_granular', JSON.stringify({
      analytics: analyticsOn,
      functional: functionalOn,
      advertising: false   // never enabled
    }));
    if(typeof gtag === 'function'){
      gtag('consent','update',{
        'ad_storage':'denied',
        'ad_user_data':'denied',
        'ad_personalization':'denied',
        'analytics_storage': analyticsOn  ? 'granted' : 'denied',
        'functionality_storage': functionalOn ? 'granted' : 'denied',
        'security_storage':'granted'
      });
      if(analyticsOn && typeof _loadGA4 === 'function') _loadGA4();
    }
  }catch(e){}
  var b = document.getElementById('cookie-banner');
  if(b) b.classList.add('hidden');
}

loadFromLS();
refreshFrontend();
// ══ URL ROUTING — ?q=keyword (fulfils JSON-LD SearchAction + ItemList Schema) ══
(function(){
  const Q={
    sleep:'sleep',gut:'gut',stress:'stress',energy:'energy',
    longevity:'longevity',immunity:'immunity',weight:'weight',
    recovery:'recovery',skin:'skin',mood:'mood',
    'sleep-supplements':'sleep','sleep-support':'sleep',
    'gut-health':'gut','gut-supplements':'gut',probiotics:'gut',
    'stress-relief':'stress',anxiety:'stress',adaptogens:'stress',
    'focus-energy':'energy',focus:'energy',nootropics:'energy',
    'longevity-supplements':'longevity',aging:'longevity',
    'immune-support':'immunity',immune:'immunity',
    'weight-management':'weight','metabolic-support':'weight',
    'muscle-recovery':'recovery','skin-collagen':'skin',
    collagen:'skin','mood-memory':'mood',memory:'mood'
  };
  function resolve(raw){
    if(!raw) return null;
    const q=raw.toLowerCase().trim().replace(/[\s_]+/g,'-');
    if(Q[q]) return Q[q];
    for(const k of Object.keys(Q)){if(k===q||q.startsWith(k)||k.startsWith(q)) return Q[k];}
    return null;
  }
  try{
    // Always seed a page-1 base state so browser Back always has somewhere to land.
    history.replaceState({page:1,need:null},'',window.location.href);
    const params=new URLSearchParams(window.location.search);
    const need=resolve(params.get('q'));
    if(need&&DATA[need]){
      currentNeed=need;
      document.querySelectorAll('.chip').forEach(ch=>ch.classList.toggle('sel',ch.dataset.need===need));
      const ni=document.getElementById('ni');
      if(ni) ni.value=TITLE_MAP[need]||need;
      // Push a new entry so Back returns to the seeded page-1 state above.
      history.pushState({page:2,need:need},'','?q='+encodeURIComponent(need));
      setTimeout(()=>{ _sp(1); goP2(); },60);
    }
  }catch(e){}
  // pushState — keep URL in sync
  const _sp=window.showPage;
  window.showPage=function(n){
    _sp(n);
    try{
      const url=n===1?window.location.pathname:window.location.search||'?';
      history.replaceState({page:n,need:currentNeed||null},'',url);
    }catch(e){}
  };
  const _gp2=window.goP2;
  window.goP2=function(){
    _gp2();
    try{if(currentNeed) history.replaceState({page:2,need:currentNeed},'','?q='+encodeURIComponent(currentNeed));}catch(e){}
  };
  const _gp3=window.goP3;
  window.goP3=function(){
    _gp3();
    try{if(currentNeed) history.replaceState({page:3,need:currentNeed},'','?q='+encodeURIComponent(currentNeed)+'&step=picks');}catch(e){}
  };
  // popstate — browser back/forward
  window.addEventListener('popstate',function(e){
    try{
      const st=e.state;
      if(!st||st.page===1){_sp(1);return;}
      if(st.need&&DATA[st.need]){
        currentNeed=st.need;
        if(st.page===2) _gp2();
        else if(st.page===3) _gp3();
      }
    }catch(e){}
  });
})();

// ══ PWA: Service Worker ══
// A blob: URL SW cannot control '/' scope (browser SecurityError).
// For full offline support, deploy /sw.js to your server root.
// The manifest.json (inlined above) and the <link rel="manifest"> tag
// still enable "Add to Home Screen" on Android/iOS without a SW.
// To activate full offline caching: add this file to your server as /sw.js:
//
//   const C='elova-v1';
//   self.addEventListener('install',e=>{e.waitUntil(caches.open(C).then(c=>c.addAll(['/','/manifest.json'])).then(()=>self.skipWaiting()));});
//   self.addEventListener('activate',e=>{e.waitUntil(caches.keys().then(ks=>Promise.all(ks.filter(k=>k!==C).map(k=>caches.delete(k)))).then(()=>self.clients.claim()));});
//   self.addEventListener('fetch',e=>{if(e.request.method!=='GET')return;const u=new URL(e.request.url);if(u.origin===self.location.origin){e.respondWith(caches.match(e.request).then(c=>{if(c)return c;return fetch(e.request).then(r=>{if(r&&r.status===200&&r.type==='basic'){const cl=r.clone();caches.open(C).then(ca=>ca.put(e.request,cl));}return r;}).catch(()=>e.request.mode==='navigate'?caches.match('/'):undefined);}));}});
//
(function(){
  if(!('serviceWorker' in navigator)) return;
  // getRegistrations() avoids a network HEAD request — no 404 in DevTools if sw.js absent.
  navigator.serviceWorker.getRegistrations().then(function(regs){
    if(regs.length>0) return; // already registered — skip
    navigator.serviceWorker.register('/sw.js',{scope:'/'}).catch(function(){});
  }).catch(function(){});
})();


// announce to SR live region when dropdown item gains focus

</script>
</body>
</html>