<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">

<title>Nairobi Escorts Directory | Verified VIP & Signature Escorts Nairobi</title>
<meta name="description" content="Nairobi Sweets is a Nairobi escorts directory for verified escorts Nairobi, VIP escorts Nairobi and Signature escorts Nairobi across Roysambu, Kasarani, Ruiru, Kiambu, Westlands, Kilimani and Ruaka.">
<meta name="keywords" content="roysambu escorts, kasarani escorts, ruiru escorts, kiambu escorts, westlands escorts, kilimani escorts, ruaka escorts, nairobi escorts directory, verified escorts nairobi, vip escorts nairobi, signature escorts nairobi">
<meta name="robots" content="index,follow">
<link rel="canonical" href="https://nairobi-sweets.com/">

<meta property="og:title" content="Nairobi Escorts Directory | Verified Nairobi Escorts">
<meta property="og:description" content="Browse verified escorts Nairobi, VIP escorts Nairobi and Signature escorts Nairobi across Roysambu, Kasarani, Ruiru, Kiambu, Westlands, Kilimani and Ruaka.">
<meta property="og:url" content="https://nairobi-sweets.com/">
<meta property="og:type" content="website">
<meta property="og:image" content="https://nairobi-sweets.com/assets/logo/logo-badge.png">

<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Nairobi Escorts Directory | Nairobi Sweets">
<meta name="twitter:description" content="Verified escorts Nairobi, VIP escorts Nairobi and Signature escorts Nairobi by location.">
<meta name="twitter:image" content="https://nairobi-sweets.com/assets/logo/logo-badge.png">

<link rel="icon" href="/assets/logo/logo-badge.png">

<!-- PWA APP SUPPORT: Android + iPhone/iPad -->
<link rel="manifest" href="/manifest.webmanifest">
<meta name="theme-color" content="#ffd54a">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta name="background-color" content="#000814">
<meta name="mobile-web-app-capable" content="yes">
<meta name="application-name" content="Nairobi Sweets">

<!-- iOS Safari PWA support -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="Nairobi Sweets">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="apple-touch-icon" sizes="180x180" href="/assets/pwa/icon-180.png">
<link rel="apple-touch-icon" sizes="152x152" href="/assets/pwa/icon-152.png">
<link rel="apple-touch-icon" sizes="144x144" href="/assets/pwa/icon-144.png">
<link rel="apple-touch-icon" sizes="120x120" href="/assets/pwa/icon-128.png">

<!-- Android/Chrome icons -->
<link rel="icon" type="image/png" sizes="192x192" href="/assets/pwa/icon-192.png">
<link rel="icon" type="image/png" sizes="512x512" href="/assets/pwa/icon-512.png">
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
<link rel="preconnect" href="https://dkjlvyynvgtijccitvvd.supabase.co" crossorigin>
<link rel="preload" as="image" href="/assets/logo/logo-badge.png">
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>

<script type="application/ld+json">
{
  "@context":"https://schema.org",
  "@type":"WebSite",
  "name":"Nairobi Escorts Directory | Nairobi Sweets",
  "url":"https://nairobi-sweets.com/",
  "potentialAction":{
    "@type":"SearchAction",
    "target":"https://nairobi-sweets.com/?q={search_term_string}",
    "query-input":"required name=search_term_string"
  }
}
</script>

<style>
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  background:radial-gradient(circle at top,#0c1148 0%,#000 45%);
  color:white;
  font-family:Arial,Helvetica,sans-serif;
  overflow-x:hidden;
  padding-bottom:120px;
}
a{text-decoration:none;color:inherit}

.topbar{
  position:sticky;
  top:0;
  z-index:999;
  background:rgba(0,0,0,.96);
  backdrop-filter:blur(20px);
  border-bottom:1px solid rgba(255,213,74,.08);
  display:flex;
  align-items:center;
  justify-content:space-between;
  padding:14px 18px;
  gap:14px;
}

.brand{
  display:flex;
  align-items:center;
  gap:16px;
  min-width:0;
}

.brand-logo{
  width:88px;
  height:88px;
  min-width:88px;
  object-fit:cover;
  border-radius:24px;
  background:#050505;
  border:2px solid rgba(255,190,70,.18);
  box-shadow:
    0 0 25px rgba(255,140,0,.45),
    0 0 60px rgba(255,80,0,.22);
}

.brand-text{
  display:flex;
  flex-direction:column;
  line-height:.88;
}

.brand-text span{
  color:#ffd54a;
  font-size:clamp(2rem,5vw,3.6rem);
  font-weight:900;
  letter-spacing:-2px;
}

.menu-btn{
  width:72px;
  height:72px;
  min-width:72px;
  border-radius:22px;
  background:linear-gradient(180deg,#07145f,#02083d);
  border:1px solid rgba(255,213,74,.12);
  display:flex;
  align-items:center;
  justify-content:center;
  cursor:pointer;
}

.menu-btn span{
  color:#ffd54a;
  font-size:38px;
  font-weight:900;
}

.mobile-menu{
  position:fixed;
  inset:0;
  background:rgba(0,0,0,.98);
  z-index:2000;
  transform:translateX(100%);
  transition:.35s ease;
  padding:34px;
}

.mobile-menu.active{transform:translateX(0)}

.menu-close{
  text-align:right;
  color:#ffd54a;
  font-size:44px;
  margin-bottom:30px;
  cursor:pointer;
}

.menu-links{
  display:flex;
  flex-direction:column;
  gap:16px;
}

.menu-links a{
  background:linear-gradient(180deg,#07145f,#02083d);
  border:1px solid rgba(255,213,74,.08);
  border-radius:20px;
  padding:18px;
  font-size:18px;
  font-weight:900;
}

.hero{padding:20px 18px 12px}

.hero-box{
  background:linear-gradient(180deg,#020a56,#010633);
  border-radius:32px;
  padding:34px 24px;
  border:1px solid rgba(255,213,74,.08);
  box-shadow:0 0 30px rgba(255,0,128,.12),0 25px 80px rgba(0,0,0,.5);
}

.hero-box h2{
  color:#ffd54a;
  font-size:clamp(52px,13vw,100px);
  line-height:.9;
  font-weight:900;
  margin-bottom:18px;
}

.hero-box p{
  color:#d9d9d9;
  font-size:18px;
  line-height:1.7;
}

.search-box{
  width:100%;
  margin-top:24px;
  background:#020926;
  border:1px solid rgba(255,255,255,.08);
  color:white;
  border-radius:18px;
  padding:18px;
  font-size:15px;
  outline:none;
}

.install-app-btn{
  width:100%;
  margin-top:18px;
  border:none;
  border-radius:18px;
  padding:18px;
  background:linear-gradient(145deg,#ffd54a,#ff9f1c);
  color:#000;
  font-size:16px;
  font-weight:900;
  cursor:pointer;
  box-shadow:0 12px 30px rgba(255,180,0,.22);
}

.install-app-btn:hover{
  filter:brightness(1.05);
  transform:translateY(-1px);
}

.filters{
  display:flex;
  gap:12px;
  overflow-x:auto;
  padding:14px 18px;
  scrollbar-width:none;
}

.filters::-webkit-scrollbar{display:none}

.filters button{
  border:none;
  background:linear-gradient(145deg,#1d243f,#08114f);
  color:white;
  border-radius:16px;
  padding:14px 20px;
  font-size:12px;
  font-weight:900;
  min-width:max-content;
  border:1px solid rgba(255,255,255,.06);
  cursor:pointer;
}

.filters button.active{
  background:linear-gradient(145deg,#1db954,#117336);
}


.seo-locations{
  padding:0 18px 24px;
}

.seo-locations-box{
  background:linear-gradient(180deg,#020a56,#010633);
  border:1px solid rgba(255,213,74,.08);
  border-radius:26px;
  padding:22px;
  box-shadow:0 18px 50px rgba(0,0,0,.28);
}

.seo-locations-box h2{
  color:#ffd54a;
  font-size:24px;
  font-weight:900;
  margin-bottom:10px;
}

.seo-locations-box p{
  color:#d8d8d8;
  font-size:14px;
  line-height:1.6;
  margin-bottom:16px;
}

.seo-location-links{
  display:flex;
  flex-wrap:wrap;
  gap:10px;
}

.seo-location-links a{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-height:40px;
  padding:10px 15px;
  border-radius:999px;
  background:linear-gradient(145deg,#1d243f,#08114f);
  border:1px solid rgba(255,213,74,.12);
  color:white;
  font-size:12px;
  font-weight:900;
}

.seo-location-links a.primary-location{
  background:linear-gradient(145deg,#ffd54a,#ff9f1c);
  color:#000;
}



/* =========================
SEO TARGET KEYWORDS BLOCK
========================= */
.seo-keyword-intro{
  margin-top:18px;
  background:rgba(255,213,74,.08);
  border:1px solid rgba(255,213,74,.14);
  border-radius:22px;
  padding:18px;
}

.seo-keyword-intro h1{
  color:#ffd54a;
  font-size:clamp(30px,6vw,56px);
  line-height:1;
  font-weight:950;
  margin-bottom:12px;
}

.seo-keyword-intro p{
  color:#e6e6e6;
  font-size:15px;
  line-height:1.8;
  margin:0;
}


/* =========================
JOIN / MEMBERSHIP CTA
========================= */
.hero-cta-row{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:12px;
  margin-top:16px;
}

.hero-join-btn,
.hero-login-btn{
  min-height:54px;
  border:none;
  border-radius:18px;
  display:flex;
  align-items:center;
  justify-content:center;
  font-size:14px;
  font-weight:950;
  cursor:pointer;
  text-align:center;
}

.hero-join-btn{
  background:linear-gradient(145deg,#ffd54a,#ff9f1c);
  color:#000;
  box-shadow:0 12px 30px rgba(255,180,0,.20);
}

.hero-login-btn{
  background:linear-gradient(145deg,#1d243f,#08114f);
  border:1px solid rgba(255,213,74,.14);
  color:#fff;
}

.join-pricing-wrap{
  padding:0 18px 28px;
}

.join-pricing-box{
  background:linear-gradient(135deg,#07145f,#02083d,#140022);
  border:1px solid rgba(255,213,74,.12);
  border-radius:30px;
  padding:22px;
  box-shadow:0 20px 70px rgba(0,0,0,.42),0 0 38px rgba(255,213,74,.08);
}

.join-pricing-header{
  display:flex;
  align-items:flex-end;
  justify-content:space-between;
  gap:14px;
  flex-wrap:wrap;
  margin-bottom:18px;
}

.join-pricing-header h2{
  color:#ffd54a;
  font-size:30px;
  font-weight:950;
  line-height:1;
}

.join-pricing-header p{
  color:#dedede;
  font-size:14px;
  line-height:1.6;
  max-width:680px;
}

.join-pricing-grid{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:14px;
}

.join-price-card{
  background:rgba(255,255,255,.055);
  border:1px solid rgba(255,213,74,.12);
  border-radius:22px;
  padding:18px;
}

.join-price-card h3{
  font-size:18px;
  color:white;
  margin-bottom:8px;
  font-weight:950;
}

.join-price-card strong{
  display:block;
  color:#ffd54a;
  font-size:24px;
  font-weight:950;
  margin-bottom:12px;
}

.join-price-card p{
  color:#d8d8d8;
  font-size:12px;
  line-height:1.6;
  min-height:58px;
}

.join-price-card a{
  display:flex;
  justify-content:center;
  align-items:center;
  min-height:42px;
  margin-top:14px;
  border-radius:999px;
  background:linear-gradient(145deg,#ffd54a,#ff9f1c);
  color:#000;
  font-size:12px;
  font-weight:950;
}

.join-main-link{
  display:flex;
  align-items:center;
  justify-content:center;
  min-height:54px;
  margin-top:18px;
  border-radius:18px;
  background:linear-gradient(145deg,#ff4d8d,#a855f7);
  color:white;
  font-size:14px;
  font-weight:950;
  box-shadow:0 14px 32px rgba(255,77,141,.18);
}

@media(max-width:1100px){
  .join-pricing-grid{
    grid-template-columns:repeat(2,minmax(0,1fr));
  }
}

@media(max-width:650px){
  .hero-cta-row,
  .join-pricing-grid{
    grid-template-columns:1fr;
  }
}

.stats-wrap{
  padding:0 18px 20px;
}

.stats-box{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:12px;
}

.stat-mini{
  background:linear-gradient(180deg,#020a56,#010633);
  border:1px solid rgba(255,213,74,.08);
  border-radius:24px;
  padding:18px;
  min-height:100px;
}

.stats-label{
  color:#d8d8d8;
  font-size:13px;
  font-weight:800;
}

.stats-number{
  color:#ffd54a;
  font-size:38px;
  font-weight:900;
  margin-top:6px;
}

@media(max-width:760px){
  .stats-box{grid-template-columns:repeat(2,minmax(0,1fr))}
  .stat-mini{padding:16px;min-height:86px}
  .stats-number{font-size:30px}
}

/* =========================
SIGNATURE PROFILES BANNER
========================= */
.signature-wrap{
  padding:0 18px 26px;
}

.signature-box{
  background:linear-gradient(135deg,#2a103d,#0b0f2c,#3b184d);
  border-radius:30px;
  border:1px solid rgba(255,213,74,.18);
  overflow:hidden;
  box-shadow:
    0 0 40px rgba(255,213,74,.12),
    0 25px 90px rgba(0,0,0,.45);
}

.signature-header{
  padding:22px;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:14px;
}

.signature-header h2{
  color:#ffd54a;
  font-size:28px;
  font-weight:900;
}

.signature-header span{
  color:#e6d7ff;
  font-size:13px;
  font-weight:800;
}

.signature-row{
  display:flex;
  gap:18px;
  overflow-x:auto;
  padding:0 22px 22px;
  scrollbar-width:none;
  scroll-snap-type:x mandatory;
  scroll-padding:22px;
  scroll-behavior:smooth;
}

.signature-row::-webkit-scrollbar{display:none}

.signature-card{
  position:relative;
  min-width:100%;
  width:100%;
  aspect-ratio:16/9;
  border-radius:28px;
  overflow:hidden;
  cursor:pointer;
  background:#000;
  border:1px solid rgba(255,213,74,.15);
  flex-shrink:0;
  scroll-snap-align:center;
  box-shadow:0 18px 50px rgba(0,0,0,.5);
}

.signature-card img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
  image-rendering:auto;
  backface-visibility:hidden;
  transform:translateZ(0);
  filter:contrast(1.03) saturate(1.04);
}

.card-image.poster-image{
  aspect-ratio:16/9;
  object-fit:contain;
  background:#020617;
}

@media(max-width:650px){
  .signature-row{
    padding:0 12px 18px;
    scroll-padding:12px;
  }

  .signature-card{
    min-width:100%;
    width:100%;
    aspect-ratio:16/9;
    border-radius:24px;
  }
}

@media(max-width:600px){
  .signature-header h2{
    font-size:30px;
    line-height:1.05;
  }
}

.shorts-section{padding:4px 18px 26px}

.shorts-header{
  display:flex;
  align-items:center;
  justify-content:space-between;
  margin-bottom:18px;
}

.shorts-header h2{
  color:#ffd54a;
  font-size:28px;
  font-weight:900;
}

.shorts-header a{
  color:#ff4d8d;
  font-size:13px;
  font-weight:900;
}

.shorts-row{
  display:flex;
  gap:16px;
  overflow-x:auto;
  scrollbar-width:none;
  scroll-behavior:auto;
  -webkit-overflow-scrolling:touch;
}

.shorts-row::-webkit-scrollbar{display:none}

.shorts-row.auto-moving{
  cursor:grab;
}

.shorts-row.auto-moving:hover{
  scroll-behavior:smooth;
}

.short-card{
  position:relative;
  min-width:190px;
  width:190px;
  height:330px;
  overflow:hidden;
  border-radius:26px;
  background:#020617;
  border:1px solid rgba(255,255,255,.06);
  flex-shrink:0;
  cursor:pointer;
}

.short-card video{
  width:100%;
  height:100%;
  object-fit:cover;
  image-rendering:auto;
  backface-visibility:hidden;
  transform:translateZ(0);
}

.short-card img{display:none !important;}

.short-overlay{
  position:absolute;
  left:0;
  right:0;
  bottom:0;
  padding:16px;
  background:linear-gradient(to top,rgba(0,0,0,.95),transparent);
}

.short-name{
  font-size:18px;
  font-weight:900;
}

.short-location{
  color:#d5d5d5;
  margin-top:5px;
  font-size:12px;
}

.profiles{
  display:grid;
  grid-template-columns:repeat(4,minmax(220px,1fr));
  gap:22px;
  padding:10px 18px 70px;
}

.card{
  position:relative;
  overflow:hidden;
  border-radius:28px;
  backdrop-filter:blur(12px);
  background:linear-gradient(180deg,#020a56,#010633);
  border:1px solid rgba(255,213,74,.08);
  box-shadow:0 0 28px rgba(255,0,128,.08),0 18px 50px rgba(0,0,0,.45);
  cursor:pointer;
}

.card-image{
  width:100%;
  aspect-ratio:4/4.4;
  object-fit:cover;
  display:block;
  background:#020617;
  image-rendering:auto;
  backface-visibility:hidden;
  transform:translateZ(0);
  filter:contrast(1.03) saturate(1.04);
}

.card-body{padding:16px}

.card-name{
  font-size:14px;
  font-weight:900;
  margin-bottom:8px;
}

.online{
  color:#31ff71;
  font-size:11px;
  font-weight:900;
  margin-bottom:10px;
}

.location{
  color:#d5d5d5;
  font-size:10px;
  margin-bottom:10px;
}

.phone{
  color:#ffd54a;
  font-size:11px;
  font-weight:900;
  margin-bottom:12px;
}

.bio{
  color:#d2d2d2;
  font-size:10px;
  line-height:1.55;
  margin-bottom:14px;
}

.engagement{
  display:flex;
  gap:8px;
  color:#d0d0d0;
  font-size:10px;
  margin-bottom:14px;
  flex-wrap:wrap;
}

.ranking-score{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:4px;
  background:rgba(255,213,74,.12);
  border:1px solid rgba(255,213,74,.18);
  color:#ffd54a;
  border-radius:999px;
  padding:5px 8px;
  font-weight:900;
}


.live-location-btn{
  grid-column:1/-1;
  min-height:34px;
  border-radius:16px;
  display:flex;
  align-items:center;
  justify-content:center;
  gap:6px;
  font-size:10px;
  font-weight:950;
  background:linear-gradient(145deg,#22c55e,#16a34a);
  color:#fff;
  box-shadow:0 8px 22px rgba(34,197,94,.18);
}
.live-location-mini{
  background:rgba(34,197,94,.14) !important;
  border:1px solid rgba(34,197,94,.38) !important;
  color:#86efac !important;
  box-shadow:0 0 18px rgba(34,197,94,.22);
}
.live-location-mini::before{
  content:"";
  width:8px;
  height:8px;
  border-radius:50%;
  background:#22c55e;
  box-shadow:0 0 12px #22c55e;
  animation:liveLocationPulse 1.35s infinite ease-out;
}
.live-location-ribbon{
  position:absolute;
  left:12px;
  right:12px;
  top:12px;
  z-index:7;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:7px;
  max-width:max-content;
  padding:8px 11px;
  border-radius:999px;
  background:rgba(0,0,0,.72);
  border:1px solid rgba(34,197,94,.42);
  color:#86efac;
  font-size:10px;
  font-weight:950;
  letter-spacing:.2px;
  box-shadow:0 0 22px rgba(34,197,94,.28);
  backdrop-filter:blur(10px);
  pointer-events:none;
}
.live-location-ribbon span{
  width:8px;
  height:8px;
  border-radius:50%;
  background:#22c55e;
  box-shadow:0 0 12px #22c55e;
  animation:liveLocationPulse 1.35s infinite ease-out;
}
@keyframes liveLocationPulse{
  0%{transform:scale(1);opacity:1}
  70%{transform:scale(1.9);opacity:.2}
  100%{transform:scale(1);opacity:1}
}

.view-profile-btn{
  grid-column:1/-1;
  min-height:36px;
  border-radius:16px;
  display:flex;
  align-items:center;
  justify-content:center;
  gap:6px;
  font-size:10px;
  font-weight:900;
  background:linear-gradient(145deg,#ffd54a,#ff9f1c);
  color:#000;
  box-shadow:inset 0 1px 1px rgba(255,255,255,.25),0 8px 22px rgba(255,180,0,.18);
}



.verified-badge{
  position:absolute;
  top:14px;
  left:42px;
  background:#0ea5e9;
  color:#fff;
  padding:6px 12px;
  border-radius:999px;
  font-size:10px;
  font-weight:900;
  z-index:6;
  box-shadow:0 0 20px rgba(14,165,233,.35);
  border:1px solid rgba(255,255,255,.28);
}

.verified-inline{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  margin-left:6px;
  width:17px;
  height:17px;
  border-radius:50%;
  background:#0ea5e9;
  color:#fff;
  font-size:11px;
  font-weight:950;
  vertical-align:middle;
  box-shadow:0 0 14px rgba(14,165,233,.35);
}

.trust-pill{
  display:inline-flex;
  align-items:center;
  gap:4px;
  background:rgba(14,165,233,.14);
  border:1px solid rgba(14,165,233,.32);
  color:#7dd3fc;
  border-radius:999px;
  padding:5px 8px;
  font-weight:900;
}

.featured-badge{
  position:absolute;
  top:14px;
  right:14px;
  background:rgba(0,0,0,.72);
  color:#ffd54a;
  padding:8px 16px;
  border-radius:999px;
  font-size:11px;
  font-weight:900;
  z-index:5;
}


.trend-rank-badge{
  position:absolute;
  top:44px;
  left:14px;
  z-index:6;
  padding:8px 12px;
  border-radius:999px;
  font-size:11px;
  font-weight:900;
  letter-spacing:.2px;
  color:#000;
  box-shadow:0 0 22px rgba(255,190,70,.34);
  backdrop-filter:blur(10px);
}

.trend-rank-1{
  background:linear-gradient(135deg,#fff4a8,#ffd54a,#ff9f1c);
}

.trend-rank-2{
  background:linear-gradient(135deg,#f8fafc,#cbd5e1,#94a3b8);
}

.trend-rank-3{
  background:linear-gradient(135deg,#f7c58a,#cd7f32,#8a4b16);
  color:white;
}

.online-dot{
  position:absolute;
  top:14px;
  left:14px;
  width:18px;
  height:18px;
  border-radius:50%;
  background:#31ff71;
  border:3px solid white;
  z-index:5;
}

.action-row{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:8px;
}

.call-btn,
.wa-btn{
  min-height:34px;
  border-radius:16px;
  display:flex;
  align-items:center;
  justify-content:center;
  gap:6px;
  font-size:9px;
  font-weight:800;
}

.call-btn{
  background:linear-gradient(145deg,#08114f,#050717);
  color:white;
  box-shadow:inset 0 1px 1px rgba(255,255,255,.08),0 6px 18px rgba(0,0,0,.35);
}

.wa-btn{
  background:linear-gradient(145deg,#0b5f2d,#06361b);
  color:white;
  box-shadow:inset 0 1px 1px rgba(255,255,255,.08),0 6px 18px rgba(0,0,0,.35);
}

.wa-btn img{
  width:14px;
  height:14px;
}

.disabled-contact{
  grid-column:1/-1;
  min-height:34px;
  border-radius:16px;
  background:#171717;
  color:#777;
  border:none;
  font-size:9px;
  font-weight:900;
}

.map-wrap{padding:0 18px 28px}

.map-card{
  overflow:hidden;
  border-radius:28px;
  border:1px solid rgba(255,213,74,.08);
  background:linear-gradient(180deg,#020a56,#010633);
}

.map-header{
  padding:22px;
}

.map-header h3{
  color:#ffd54a;
  font-size:26px;
  margin-bottom:10px;
}

.map-header p{
  color:#d8d8d8;
  font-size:15px;
  line-height:1.6;
}

.map-card iframe{
  width:100%;
  height:320px;
  border:none;
  display:block;
}

.disclaimer{padding:0 18px 80px}

.disclaimer-box{
  background:linear-gradient(180deg,#020a56,#010633);
  border-radius:30px;
  padding:28px;
  border:1px solid rgba(255,213,74,.08);
}

.disclaimer-box h3{
  color:#ffd54a;
  font-size:26px;
  margin-bottom:18px;
}

.disclaimer-box p{
  color:#d8d8d8;
  line-height:1.8;
  font-size:15px;
}

.sweet-ai{
  position:fixed;
  right:18px;
  bottom:82px;
  width:44px;
  height:44px;
  border-radius:50%;
  overflow:hidden;
  z-index:999;
  cursor:pointer;
  border:3px solid #7dffcf;
  background:linear-gradient(145deg,#071a17,#120022);
  box-shadow:0 0 22px rgba(125,255,207,.45),0 0 42px rgba(160,84,255,.28);
  animation:sweetFloat 3s infinite ease-in-out;
}

.sweet-ai img{
  width:100%;
  height:100%;
  object-fit:cover;
}

@keyframes sweetFloat{
  0%{transform:translateY(0)}
  50%{transform:translateY(-7px)}
  100%{transform:translateY(0)}
}

.sweet-panel{
  position:fixed;
  right:18px;
  bottom:138px;
  width:min(360px,92vw);
  background:linear-gradient(180deg,#071a17,#120022);
  border:1px solid rgba(125,255,207,.22);
  border-radius:26px;
  overflow:hidden;
  z-index:1400;
  display:none;
  box-shadow:0 0 40px rgba(125,255,207,.18),0 0 60px rgba(160,84,255,.12);
}

.sweet-panel.active{display:block}

.sweet-header{
  display:flex;
  justify-content:space-between;
  align-items:center;
  padding:16px 18px;
  background:linear-gradient(90deg,#05110f,#1b0033);
}

.sweet-header h3{
  color:#7dffcf;
  font-size:20px;
  font-weight:900;
}

.sweet-header button{
  background:none;
  border:none;
  color:#b388ff;
  font-size:24px;
  cursor:pointer;
}

.sweet-body{padding:16px}

.sweet-body input{
  width:100%;
  padding:14px;
  border-radius:16px;
  border:1px solid rgba(125,255,207,.14);
  background:#081412;
  color:white;
  outline:none;
}

.sweet-chips{
  display:flex;
  gap:8px;
  overflow-x:auto;
  margin:12px 0;
  scrollbar-width:none;
}

.sweet-chips::-webkit-scrollbar{display:none}

.sweet-chips button{
  min-width:max-content;
  border:none;
  border-radius:999px;
  padding:10px 12px;
  background:linear-gradient(145deg,#0d2a24,#1b0033);
  color:#7dffcf;
  font-size:12px;
  font-weight:900;
  border:1px solid rgba(125,255,207,.12);
  cursor:pointer;
}

.sweet-send{
  width:100%;
  border:none;
  border-radius:16px;
  padding:14px;
  background:linear-gradient(145deg,#7dffcf,#a054ff);
  color:#000;
  font-weight:900;
  cursor:pointer;
}

.sweet-results{
  margin-top:14px;
  color:#d7f7ef;
  font-size:14px;
  line-height:1.5;
}

.sweet-card{
  margin:10px 0;
  padding:10px;
  border-radius:14px;
  background:#0d2a24;
  border:1px solid rgba(125,255,207,.12);
}

.sweet-card strong{color:#7dffcf}

.bottom-nav{
  position:fixed;
  left:0;
  right:0;
  bottom:0;
  height:64px;
  background:rgba(0,0,0,.96);
  display:flex;
  align-items:center;
  justify-content:space-around;
  z-index:999;
  border-top:1px solid rgba(255,213,74,.08);
}

.bottom-nav button{
  border:none;
  background:none;
  color:#ffd54a;
  font-size:20px;
  cursor:pointer;
}

.loading,
.empty{
  grid-column:1/-1;
  padding:50px;
  color:#ffd54a;
  font-weight:900;
  text-align:center;
}

.load-more-wrap{
  grid-column:1/-1;
  display:flex;
  justify-content:center;
  padding:10px 0 30px;
}

.load-more-btn{
  border:none;
  border-radius:999px;
  padding:15px 26px;
  background:linear-gradient(145deg,#ffd54a,#ff9f1c);
  color:#000;
  font-size:14px;
  font-weight:950;
  cursor:pointer;
  box-shadow:0 12px 26px rgba(255,180,0,.18);
}

.mobile-map-load{
  width:100%;
  min-height:180px;
  display:flex;
  align-items:center;
  justify-content:center;
  flex-direction:column;
  gap:12px;
  background:linear-gradient(180deg,#020617,#010633);
  color:#fff;
  padding:24px;
  text-align:center;
}

.mobile-map-load button{
  border:none;
  border-radius:999px;
  padding:13px 22px;
  background:linear-gradient(145deg,#ffd54a,#ff9f1c);
  color:#000;
  font-weight:950;
  cursor:pointer;
}

@media(min-width:1100px){
  .hero,
  .filters,
  .stats-wrap,
  .signature-wrap,
  .sweet-gallery-wrap,
  .shorts-section,
  .profiles,
  .map-wrap,
  .disclaimer{
    padding-left:90px;
    padding-right:90px;
  }

  .brand-logo{
    width:70px;
    height:70px;
    min-width:70px;
    border-radius:20px;
  }

  .brand-text span{
    font-size:38px;
  }

  .menu-btn{
    width:64px;
    height:64px;
    min-width:64px;
  }
}

@media(max-width:1100px){
  .profiles{grid-template-columns:repeat(3,minmax(220px,1fr))}
}

@media(max-width:900px){
  .profiles{grid-template-columns:1fr}
}


/* =========================
SWEET GALLERY SCROLL 🍬
Continuous Supabase profile gallery
========================= */
.sweet-gallery-wrap{
  padding:0 18px 26px;
}

.sweet-gallery-box{
  background:linear-gradient(135deg,#07145f,#02083d,#140022);
  border-radius:30px;
  border:1px solid rgba(255,213,74,.18);
  overflow:hidden;
  box-shadow:0 0 40px rgba(255,213,74,.10),0 25px 90px rgba(0,0,0,.45);
}

.sweet-gallery-header{
  padding:22px;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:14px;
  flex-wrap:wrap;
}

.sweet-gallery-header h2{
  color:#ffd54a;
  font-size:28px;
  font-weight:900;
  line-height:1.05;
}

.sweet-gallery-header span{
  color:#e6d7ff;
  font-size:13px;
  font-weight:800;
}

.sweet-gallery-scroll{
  position:relative;
  overflow:hidden;
  padding:0 22px 22px;
}

.sweet-gallery-scroll::before,
.sweet-gallery-scroll::after{
  content:"";
  position:absolute;
  top:0;
  bottom:22px;
  width:70px;
  z-index:4;
  pointer-events:none;
}

.sweet-gallery-scroll::before{
  left:0;
  background:linear-gradient(to right,#07145f,rgba(7,20,95,0));
}

.sweet-gallery-scroll::after{
  right:0;
  background:linear-gradient(to left,#140022,rgba(20,0,34,0));
}

.sweet-gallery-track{
  display:flex;
  gap:16px;
  width:max-content;
  will-change:transform;
  animation:sweetGallerySlide 240s linear infinite;
}

.sweet-gallery-scroll:hover .sweet-gallery-track{
  animation-play-state:paused;
}

@keyframes sweetGallerySlide{
  0%{
    transform:translate3d(0,0,0);
  }
  100%{
    transform:translate3d(-50%,0,0);
  }
}

.sweet-gallery-card{
  position:relative;
  min-width:260px;
  width:260px;
  border-radius:24px;
  overflow:hidden;
  background:#020617;
  border:1px solid rgba(255,255,255,.08);
  flex-shrink:0;
  box-shadow:0 16px 38px rgba(0,0,0,.35);
}

.sweet-gallery-card img{
  width:100%;
  height:340px;
  object-fit:cover;
  display:block;
  background:#020617;
  image-rendering:auto;
  backface-visibility:hidden;
  transform:translateZ(0);
  filter:contrast(1.03) saturate(1.04);
}

.sweet-gallery-info{
  padding:14px;
  background:linear-gradient(180deg,#020a56,#010633);
}

.sweet-gallery-name{
  color:#fff;
  font-size:15px;
  font-weight:950;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}

.sweet-gallery-location{
  color:#cfcfcf;
  font-size:12px;
  margin-top:6px;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}

.sweet-gallery-pill{
  position:absolute;
  left:12px;
  top:12px;
  z-index:3;
  border-radius:999px;
  padding:7px 10px;
  font-size:10px;
  font-weight:950;
  color:#000;
  background:linear-gradient(145deg,#ffd54a,#ff9f1c);
  box-shadow:0 0 20px rgba(255,213,74,.28);
}

.sweet-gallery-loading,
.sweet-gallery-empty{
  min-width:260px;
  color:#ffd54a;
  font-weight:950;
  padding:22px;
}

@media(min-width:1100px){
  .sweet-gallery-wrap{
    padding-left:90px;
    padding-right:90px;
  }
}

@media(max-width:650px){
  .sweet-gallery-wrap{
    padding:0 14px 22px;
  }

  .sweet-gallery-header{
    padding:18px;
  }

  .sweet-gallery-header h2{
    font-size:24px;
  }

  .sweet-gallery-scroll{
    padding:0 18px 18px;
  }

  .sweet-gallery-scroll::before,
  .sweet-gallery-scroll::after{
    bottom:18px;
    width:36px;
  }

  .sweet-gallery-track{
    gap:14px;
    animation-duration:240s;
  }

  .sweet-gallery-card{
    min-width:220px;
    width:220px;
    border-radius:22px;
  }

  .sweet-gallery-card img{
    height:300px;
  }
}

@media(prefers-reduced-motion:reduce){
  .sweet-gallery-track{
    animation:none;
    overflow-x:auto;
  }

  .sweet-gallery-scroll{
    overflow-x:auto;
  }
}



/* =========================
SEO CRAWL BOOST PATCH
Adds top internal links so Google discovers and crawls profile URLs faster.
========================= */
.top-location-links,
.latest-profiles-seo{
  padding:0 18px 24px;
}
.latest-profiles-grid{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:10px;
  margin-top:14px;
  width:100%;
}
.latest-profile-link{
  display:flex;
  align-items:center;
  gap:10px;
  min-width:0;
  width:100%;
  min-height:54px;
  padding:10px 12px;
  border-radius:18px;
  background:linear-gradient(145deg,#1d243f,#08114f);
  border:1px solid rgba(255,213,74,.14);
  color:#fff;
  font-size:12px;
  font-weight:900;
  line-height:1.2;
  overflow:hidden;
}
.latest-profile-link img{
  width:42px;
  height:42px;
  min-width:42px;
  border-radius:12px;
  object-fit:cover;
  background:#020617;
}
.latest-profile-link > div{
  min-width:0;
  max-width:100%;
  overflow:hidden;
}
.latest-profile-link strong{
  display:block;
  max-width:100%;
  color:#ffd54a;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.latest-profile-link span{
  display:block;
  max-width:100%;
  color:#d8d8d8;
  font-size:10px;
  margin-top:3px;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.latest-view-all-link{
  background:linear-gradient(145deg,#ffd54a,#ff9f1c) !important;
  color:#000 !important;
  justify-content:center;
  text-align:center;
  box-shadow:0 12px 24px rgba(255,180,0,.18);
}
.latest-view-all-link strong{
  color:#000 !important;
}
.latest-view-all-link span{
  color:#271800 !important;
}
.seo-mini-note{
  color:#bfc3d9;
  font-size:12px;
  line-height:1.6;
  margin-top:12px;
}
@media(min-width:1100px){
  .top-location-links,
  .latest-profiles-seo{
    padding-left:90px;
    padding-right:90px;
  }
}
@media(max-width:900px){
  .latest-profiles-grid{grid-template-columns:repeat(2,minmax(0,1fr));}
}
@media(max-width:650px){
  .top-location-links,
  .latest-profiles-seo{padding-left:14px;padding-right:14px;}
  .latest-profiles-grid{grid-template-columns:1fr;}
}


/* =========================
LATEST PROFILES LIMIT PATCH
Homepage shows 8 latest profiles plus one View All button.
========================= */
.latest-view-all-link{
  background:linear-gradient(145deg,#ffd54a,#ff9f1c) !important;
  color:#000 !important;
  justify-content:center !important;
  text-align:center !important;
  border-color:rgba(255,213,74,.42) !important;
  box-shadow:0 10px 24px rgba(255,180,0,.16);
}
.latest-view-all-link strong{
  color:#000 !important;
}
.latest-view-all-link span{
  color:#171717 !important;
}


/* =========================
AGE GATE
========================= */
.age-gate{
  position:fixed;
  inset:0;
  z-index:99999;
  background:rgba(0,0,0,.88);
  backdrop-filter:blur(18px);
  display:none;
  align-items:center;
  justify-content:center;
  padding:20px;
}

.age-gate.active{display:flex}

.age-card{
  width:min(560px,94vw);
  background:radial-gradient(circle at top,#101b69 0%,#050817 55%,#000 100%);
  border:1px solid rgba(255,213,74,.18);
  border-radius:34px;
  padding:30px;
  position:relative;
  text-align:center;
  box-shadow:0 0 35px rgba(255,180,0,.20),0 0 80px rgba(255,0,128,.12),0 30px 100px rgba(0,0,0,.8);
}

.age-close{
  position:absolute;
  top:18px;
  right:18px;
  width:42px;
  height:42px;
  border-radius:50%;
  border:none;
  background:rgba(255,255,255,.08);
  color:#ffd54a;
  font-size:30px;
  cursor:pointer;
}

.age-logo{
  width:110px;
  height:110px;
  border-radius:28px;
  object-fit:cover;
  margin-bottom:18px;
  box-shadow:0 0 28px rgba(255,140,0,.45),0 0 60px rgba(255,80,0,.25);
}

.age-card h2{
  color:#ffd54a;
  font-size:34px;
  font-weight:900;
  line-height:1;
  margin-bottom:10px;
}

.age-sub{
  color:#d7d7d7;
  font-size:15px;
  margin-bottom:22px;
}

.age-label{
  display:block;
  color:white;
  font-weight:900;
  margin-bottom:10px;
  text-align:left;
}

.age-input{
  width:100%;
  height:56px;
  background:#0b1235;
  color:white;
  border:1px solid rgba(255,255,255,.18);
  border-radius:18px;
  padding:0 16px;
  font-size:16px;
  outline:none;
  margin-bottom:18px;
}

.age-warning{
  background:rgba(255,213,74,.10);
  border:1px solid rgba(255,213,74,.18);
  color:#f4f4f4;
  border-radius:20px;
  padding:16px;
  font-size:14px;
  line-height:1.6;
  margin-bottom:18px;
}

.age-warning strong{color:#ffd54a}

.age-check{
  display:flex;
  gap:12px;
  align-items:flex-start;
  text-align:left;
  color:#ddd;
  font-size:14px;
  line-height:1.5;
  margin-bottom:22px;
}

.age-check input{
  margin-top:4px;
  transform:scale(1.25);
}

.age-actions{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:12px;
}

.enter-btn,
.leave-btn{
  min-height:54px;
  border:none;
  border-radius:18px;
  font-weight:900;
  cursor:pointer;
  font-size:14px;
}

.enter-btn{
  background:linear-gradient(145deg,#ffd54a,#ff9f1c);
  color:#000;
}

.leave-btn{
  background:linear-gradient(145deg,#111827,#050505);
  color:white;
  border:1px solid rgba(255,255,255,.12);
}

.cookie-note{
  color:#9ca3af;
  font-size:12px;
  line-height:1.5;
  margin-top:18px;
}


@media(max-width:650px){
  .signature-card{
    min-width:100%;
    width:100%;
    height:auto;
    aspect-ratio:16/9;
  }
}

@media(max-width:600px){
  .age-card{padding:24px;border-radius:28px}
  .age-card h2{font-size:28px}
  .age-actions{grid-template-columns:1fr}
  .age-logo{width:92px;height:92px}
}


/* =========================
ADMIN HELP CENTER
========================= */
.admin-help-section{
  padding:0 18px 28px;
}

.admin-help-box{
  background:linear-gradient(135deg,#07145f,#02083d,#140022);
  border:1px solid rgba(255,213,74,.12);
  border-radius:30px;
  padding:28px;
  text-align:center;
  box-shadow:0 20px 70px rgba(0,0,0,.42);
}

.admin-help-box h3{
  color:#ffd54a;
  font-size:30px;
  font-weight:900;
  margin-bottom:12px;
}

.admin-help-box p{
  color:#d8d8d8;
  font-size:14px;
  line-height:1.8;
  max-width:800px;
  margin:auto auto 20px;
}

.admin-help-buttons{
  display:flex;
  justify-content:center;
  gap:12px;
  flex-wrap:wrap;
}

.admin-help-buttons a{
  min-height:50px;
  padding:14px 22px;
  border-radius:18px;
  display:flex;
  align-items:center;
  justify-content:center;
  font-weight:900;
}

.admin-call-btn{
  background:linear-gradient(145deg,#ffd54a,#ff9f1c);
  color:#000;
}

.admin-whatsapp-btn{
  background:#25D366;
  color:white;
}

.admin-email-btn{
  background:#06b6d4;
  color:#000;
}

@media(min-width:1100px){
  .admin-help-section{
    padding-left:90px;
    padding-right:90px;
  }
}


/* =========================
MOBILE UX CLEANUP PATCH
========================= */
.boost-badge{
  position:absolute;
  top:52px;
  right:14px;
  background:linear-gradient(145deg,#ec4899,#a855f7);
  color:#fff;
  padding:7px 12px;
  border-radius:999px;
  font-size:10px;
  font-weight:950;
  z-index:7;
  box-shadow:0 0 20px rgba(236,72,153,.34);
}

.pinned-badge{
  position:absolute;
  top:52px;
  left:14px;
  background:linear-gradient(145deg,#ffd54a,#ff9f1c);
  color:#000;
  padding:7px 12px;
  border-radius:999px;
  font-size:10px;
  font-weight:950;
  z-index:7;
  box-shadow:0 0 20px rgba(255,213,74,.34);
}

@media(max-width:650px){
  body{padding-bottom:110px}
  .topbar{padding:10px 14px}
  .brand-logo{width:58px;height:58px;min-width:58px;border-radius:17px}
  .brand-text span{font-size:34px;letter-spacing:-1.5px}
  .menu-btn{width:58px;height:58px;min-width:58px;border-radius:18px}
  .menu-btn span{font-size:30px}
  .hero{padding:14px 14px 10px}
  .hero-box{padding:26px 20px;border-radius:28px}
  .hero-box h2{font-size:64px}
  .hero-box p{font-size:18px;line-height:1.55}
  .filters{padding:10px 14px}
  .profiles{padding:10px 14px 34px}
  .card-name{font-size:20px}
  .card-image{aspect-ratio:4/5;object-fit:cover}
  .seo-locations,.join-pricing-wrap,.signature-wrap,.sweet-gallery-wrap,.shorts-section,.map-wrap,.admin-help-section,.disclaimer,.stats-wrap{padding-left:14px;padding-right:14px}
  .seo-locations{padding-top:8px}
  .seo-keyword-intro h1{font-size:36px}
  .seo-keyword-intro p,.seo-locations-box p{font-size:15px;line-height:1.75}
  .bottom-nav{height:64px}
  .bottom-nav button{font-size:21px}
  .sweet-ai{right:18px;bottom:78px;width:44px;height:44px}
}



/* FINAL CLEANUP: keep all profile photos clear. Old absolute badges are hidden;
   the visible badges now live in .card-badge-rail under the image. */
.card > .featured-badge,
.card > .verified-badge,
.card > .boost-badge,
.card > .pinned-badge,
.card > .trend-rank-badge,
.card > .online-dot{
  display:none !important;
}

/* =========================
CLEAN CARD BADGE RAIL
Keeps image clear: no badges cover faces/photos
========================= */
.card-badge-rail{
  display:flex;
  align-items:center;
  gap:7px;
  flex-wrap:wrap;
  padding:10px 12px 0;
  background:linear-gradient(180deg,#020a56,#010633);
}
.card-chip{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:4px;
  min-height:28px;
  padding:7px 10px;
  border-radius:999px;
  font-size:10px;
  font-weight:950;
  line-height:1;
  white-space:nowrap;
}
.card-chip.verified{background:#0ea5e9;color:#fff}
.card-chip.trending{background:rgba(0,0,0,.72);color:#ffd54a;border:1px solid rgba(255,213,74,.20)}
.card-chip.rank{background:linear-gradient(145deg,#ffd54a,#ff9f1c);color:#000}
.card-chip.boost{background:linear-gradient(145deg,#ec4899,#a855f7);color:#fff}
.card-chip.quality{background:linear-gradient(145deg,#7dd3fc,#2563eb);color:#fff}
.card-chip.pinned{background:linear-gradient(145deg,#22c55e,#06b6d4);color:#00111f}
.card-chip.online-mini{width:16px;min-height:16px;height:16px;padding:0;background:#31ff71;border:3px solid #fff;box-shadow:0 0 12px rgba(49,255,113,.45)}
.card .online-dot,
.card .featured-badge,
.card .verified-badge,
.card .boost-badge,
.card .pinned-badge,
.card .trend-rank-badge{
  display:none !important;
}

/* =========================
MOBILE CRASH-SAFE PATCH
Keeps the same section order as desktop, but loads lighter on phones.
========================= */
@media(max-width:700px){
  html{scroll-behavior:auto}
  .hero,.signature-wrap,.sweet-gallery-wrap,.shorts-section,.stats-wrap,.filters,.profiles,.join-pricing-wrap,.seo-locations,.map-wrap,.admin-help-section,.disclaimer{order:initial}
  .card,.hero-box,.signature-box,.join-pricing-box,.seo-locations-box,.map-card,.admin-help-box,.disclaimer-box{box-shadow:none}
  .sweet-ai{animation:none}
  .short-card video{background:#020617}
}


/* =========================
FINAL PREMIUM UI PATCH - 2026
Fixes: oversized header, large hamburger, crowded badges, bottom-nav overlap, clearer cards.
========================= */
.topbar{
  padding:10px 18px !important;
  min-height:88px !important;
}
.brand{gap:14px !important;}
.brand-logo{
  width:68px !important;
  height:68px !important;
  min-width:68px !important;
  border-radius:19px !important;
}
.brand-text span{
  font-size:clamp(1.65rem,3.6vw,2.8rem) !important;
  line-height:.9 !important;
  letter-spacing:-1.5px !important;
}
.menu-btn{
  width:58px !important;
  height:58px !important;
  min-width:58px !important;
  border-radius:18px !important;
}
.menu-btn span{font-size:30px !important;}
body{padding-bottom:155px !important;}
.profiles{padding-bottom:130px !important;}
.card{border-radius:24px !important;}
.card-image{aspect-ratio:4/4.35 !important;}
.card-badge-rail{
  padding:10px 14px 2px !important;
  gap:7px !important;
  min-height:46px !important;
}
.card-chip{
  min-height:27px !important;
  padding:7px 10px !important;
  font-size:10px !important;
  letter-spacing:.1px !important;
}
.card-chip.plan{background:rgba(0,0,0,.74);color:#ffd54a;border:1px solid rgba(255,213,74,.22)}
.card-chip.new{background:linear-gradient(145deg,#ffd54a,#ff9f1c);color:#000}
.card-body{padding:16px 18px 20px !important;}
.card-name{font-size:19px !important;line-height:1.1 !important;margin-bottom:8px !important;}
.online{font-size:13px !important;margin-bottom:10px !important;}
.location,.phone,.bio,.engagement{font-size:11px !important;}
.action-row{gap:9px !important;}
.call-btn,.wa-btn,.disabled-contact{min-height:40px !important;font-size:10px !important;border-radius:15px !important;}

.live-location-btn{
  grid-column:1/-1;
  min-height:34px;
  border-radius:16px;
  display:flex;
  align-items:center;
  justify-content:center;
  gap:6px;
  font-size:10px;
  font-weight:950;
  background:linear-gradient(145deg,#22c55e,#16a34a);
  color:#fff;
  box-shadow:0 8px 22px rgba(34,197,94,.18);
}
.live-location-mini{
  background:rgba(34,197,94,.14) !important;
  border:1px solid rgba(34,197,94,.38) !important;
  color:#86efac !important;
  box-shadow:0 0 18px rgba(34,197,94,.22);
}
.live-location-mini::before{
  content:"";
  width:8px;
  height:8px;
  border-radius:50%;
  background:#22c55e;
  box-shadow:0 0 12px #22c55e;
  animation:liveLocationPulse 1.35s infinite ease-out;
}
.live-location-ribbon{
  position:absolute;
  left:12px;
  right:12px;
  top:12px;
  z-index:7;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:7px;
  max-width:max-content;
  padding:8px 11px;
  border-radius:999px;
  background:rgba(0,0,0,.72);
  border:1px solid rgba(34,197,94,.42);
  color:#86efac;
  font-size:10px;
  font-weight:950;
  letter-spacing:.2px;
  box-shadow:0 0 22px rgba(34,197,94,.28);
  backdrop-filter:blur(10px);
  pointer-events:none;
}
.live-location-ribbon span{
  width:8px;
  height:8px;
  border-radius:50%;
  background:#22c55e;
  box-shadow:0 0 12px #22c55e;
  animation:liveLocationPulse 1.35s infinite ease-out;
}
@keyframes liveLocationPulse{
  0%{transform:scale(1);opacity:1}
  70%{transform:scale(1.9);opacity:.2}
  100%{transform:scale(1);opacity:1}
}

.view-profile-btn{min-height:40px !important;font-size:10px !important;border-radius:15px !important;}
.bottom-nav{
  height:74px !important;
  background:rgba(0,0,0,.94) !important;
  backdrop-filter:blur(18px) !important;
}
.bottom-nav button{font-size:22px !important;}
.sweet-ai{bottom:90px !important;width:44px !important;height:44px !important;}
.sweet-panel{bottom:150px !important;}

@media(min-width:1100px){
  .profiles{grid-template-columns:repeat(4,minmax(220px,1fr)) !important;gap:24px !important;}
  .topbar{padding-left:24px !important;padding-right:24px !important;}
}
@media(max-width:900px){
  .profiles{grid-template-columns:1fr !important;}
}
@media(max-width:650px){
  body{padding-bottom:150px !important;}
  .topbar{min-height:76px !important;padding:9px 14px !important;}
  .brand-logo{width:56px !important;height:56px !important;min-width:56px !important;border-radius:16px !important;}
  .brand-text span{font-size:32px !important;}
  .menu-btn{width:52px !important;height:52px !important;min-width:52px !important;border-radius:16px !important;}
  .menu-btn span{font-size:27px !important;}
  .profiles{padding-bottom:120px !important;}
  .card-image{aspect-ratio:4/5 !important;}
  .card-body{padding:15px 17px 20px !important;}
  .card-name{font-size:20px !important;}
  .bottom-nav{height:72px !important;}
  .sweet-ai{bottom:86px !important;}
}


/* =========================
SHORTS AUTOPLAY FIX PATCH
Makes homepage shorts load and start muted playback instead of staying black.
========================= */
.short-card{
  background:linear-gradient(180deg,#05091f,#01030d) !important;
}
.short-card::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:0;
  background:linear-gradient(110deg,rgba(255,255,255,.03),rgba(255,213,74,.08),rgba(255,255,255,.03));
  animation:shortLoadGlow 1.8s infinite linear;
}
.short-card video{
  position:relative;
  z-index:1;
  display:block !important;
  opacity:1 !important;
}
.short-overlay{z-index:2}
.short-card.video-error::after{
  content:"Video unavailable";
  position:absolute;
  inset:auto 12px 74px 12px;
  z-index:3;
  text-align:center;
  color:#ffd54a;
  font-size:12px;
  font-weight:950;
}
@keyframes shortLoadGlow{
  0%{transform:translateX(-40%)}
  100%{transform:translateX(40%)}
}


/* =========================
MOBILE STABILITY PATCH
Stops phone Chrome from crashing by avoiding heavy continuous animation and autoplay video loading.
========================= */
@media(max-width:700px){
  .sweet-gallery-track{
    animation:none !important;
    transform:none !important;
  }
  .sweet-gallery-scroll{
    overflow-x:auto !important;
    -webkit-overflow-scrolling:touch;
  }
  .short-card::before{
    animation:none !important;
  }
}


/* =========================
FINAL MOBILE SPEED PATCH
Keeps the current Nairobi Sweets design, but makes phones breathe.
========================= */
@media(max-width:700px){
  *{
    -webkit-tap-highlight-color:transparent;
  }

  body{
    background:#050611 !important;
  }

  .hero-box,
  .signature-box,
  .sweet-gallery-box,
  .join-pricing-box,
  .seo-locations-box,
  .map-card,
  .admin-help-box,
  .disclaimer-box,
  .card,
  .short-card,
  .stat-mini{
    box-shadow:none !important;
  }

  .hero-box{
    padding:22px 18px !important;
  }

  .hero-box h2{
    font-size:56px !important;
  }

  .signature-row,
  .shorts-row,
  .filters,
  .sweet-gallery-scroll{
    contain:layout paint;
  }

  .signature-card img,
  .sweet-gallery-card img,
  .card-image{
    content-visibility:auto;
  }

  .shorts-section{
    min-height:0;
  }

  .short-card{
    min-width:150px !important;
    width:150px !important;
    height:260px !important;
    border-radius:22px !important;
  }

  .short-card video{
    object-fit:cover;
  }

  .sweet-gallery-card{
    min-width:180px !important;
    width:180px !important;
  }

  .sweet-gallery-card img{
    height:240px !important;
  }

  .join-price-card p{
    min-height:auto !important;
  }

  .seo-keyword-intro{
    display:none;
  }
}

.profile-skeleton-card{
  min-height:420px;
  border-radius:28px;
  background:linear-gradient(110deg,rgba(255,255,255,.035),rgba(255,213,74,.10),rgba(255,255,255,.035));
  background-size:220% 100%;
  border:1px solid rgba(255,213,74,.08);
  animation:profileSkeletonGlow 1.5s linear infinite;
}

@keyframes profileSkeletonGlow{
  0%{background-position:0 0}
  100%{background-position:-220% 0}
}

@media(max-width:700px){
  .profile-skeleton-card{
    min-height:390px;
    animation:none;
  }
}


/* PATCH: keep latest profile text inside the cards */
.seo-locations-box{
  overflow:hidden;
}
@media(max-width:650px){
  .latest-profile-link{
    font-size:11px;
    padding:10px;
  }
  .latest-profile-link span{
    font-size:9px;
  }
}



/* =========================================================
   NAIROBI SWEETS V3 PREMIUM PATCH
   Safe visual + mobile + PWA polish layer
   ========================================================= */
:root{
  --ns-gold:#ffd84b;
  --ns-amber:#ff9f1c;
  --ns-ink:#020617;
  --ns-glass:rgba(7,12,44,.72);
  --ns-glass-strong:rgba(3,8,38,.86);
  --ns-line:rgba(255,216,75,.18);
  --ns-soft:rgba(255,255,255,.08);
}
html{background:#000814;scroll-padding-top:120px;}
body{
  min-height:100svh;
  background:
    radial-gradient(circle at 50% -12%,rgba(255,216,75,.14),transparent 28%),
    radial-gradient(circle at 0% 8%,rgba(255,45,117,.12),transparent 32%),
    linear-gradient(180deg,#050733 0%,#000814 48%,#000 100%) !important;
  padding-bottom:calc(118px + env(safe-area-inset-bottom)) !important;
}
body::before{
  content:"";
  position:fixed;
  inset:0;
  pointer-events:none;
  z-index:-1;
  background-image:
    linear-gradient(rgba(255,255,255,.025) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.02) 1px,transparent 1px);
  background-size:42px 42px;
  mask-image:linear-gradient(to bottom,rgba(0,0,0,.75),transparent 78%);
}
.topbar{
  position:sticky !important;
  top:0;
  padding-top:calc(12px + env(safe-area-inset-top)) !important;
  background:rgba(0,0,0,.78) !important;
  backdrop-filter:blur(22px) saturate(1.25) !important;
  -webkit-backdrop-filter:blur(22px) saturate(1.25) !important;
  box-shadow:0 14px 36px rgba(0,0,0,.28), inset 0 -1px 0 rgba(255,216,75,.08);
}
.brand-logo{
  animation:nsLogoBreathe 5.4s ease-in-out infinite;
  box-shadow:0 0 24px rgba(255,216,75,.28),0 0 58px rgba(255,77,141,.16) !important;
}
@keyframes nsLogoBreathe{0%,100%{transform:scale(1)}50%{transform:scale(1.035)}}
.hero-box,.seo-locations-box,.join-pricing-box,.stat-mini,.signature-box,.map-card,.disclaimer-box,.card,.sweet-panel,.join-price-card{
  background:linear-gradient(145deg,rgba(10,18,64,.76),rgba(3,8,38,.88)) !important;
  border:1px solid var(--ns-line) !important;
  backdrop-filter:blur(20px) saturate(1.18) !important;
  -webkit-backdrop-filter:blur(20px) saturate(1.18) !important;
  box-shadow:0 22px 70px rgba(0,0,0,.48), inset 0 1px 0 rgba(255,255,255,.06) !important;
}
.card{
  transform:translateZ(0);
  transition:transform .22s ease, box-shadow .22s ease, border-color .22s ease;
}
.card:active{transform:scale(.985)}
@media(hover:hover){
  .card:hover{transform:translateY(-5px);border-color:rgba(255,216,75,.34) !important;box-shadow:0 28px 82px rgba(0,0,0,.56),0 0 34px rgba(255,216,75,.12) !important;}
}
.card-image,.signature-card img,.short-card video{background:#020617;}
.card-image[loading="lazy"]{content-visibility:auto;}
.search-box{
  background:rgba(2,9,38,.82) !important;
  border-color:rgba(255,216,75,.16) !important;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 10px 30px rgba(0,0,0,.2);
}
.search-box:focus{border-color:rgba(255,216,75,.55) !important;box-shadow:0 0 0 4px rgba(255,216,75,.10)}
.install-app-btn,.hero-join-btn,.view-profile-btn,.join-price-card a,.join-main-link{
  box-shadow:0 14px 34px rgba(255,159,28,.18), inset 0 1px 1px rgba(255,255,255,.35) !important;
}
.bottom-nav{
  height:calc(72px + env(safe-area-inset-bottom)) !important;
  padding:8px 10px calc(8px + env(safe-area-inset-bottom)) !important;
  background:rgba(0,0,0,.86) !important;
  backdrop-filter:blur(22px) saturate(1.22) !important;
  -webkit-backdrop-filter:blur(22px) saturate(1.22) !important;
  display:flex !important;
  align-items:center !important;
  justify-content:space-around !important;
  gap:8px !important;
}
.bottom-nav a,.bottom-nav button{
  width:46px !important;
  height:46px !important;
  min-width:46px !important;
  border-radius:50% !important;
  display:flex !important;
  align-items:center !important;
  justify-content:center !important;
  background:rgba(255,216,75,.08) !important;
  border:1px solid rgba(255,216,75,.12) !important;
  color:var(--ns-gold) !important;
  font-size:22px !important;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.04) !important;
}
.bottom-nav a.active,.bottom-nav button.active{background:linear-gradient(145deg,var(--ns-gold),var(--ns-amber)) !important;color:#000 !important;}
.sweet-ai{
  bottom:calc(86px + env(safe-area-inset-bottom)) !important;
  animation:nsFloat 3.6s ease-in-out infinite, nsRing 2.8s linear infinite !important;
}
@keyframes nsFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-7px)}}
@keyframes nsRing{0%,100%{box-shadow:0 0 22px rgba(125,255,207,.45),0 0 42px rgba(160,84,255,.24)}50%{box-shadow:0 0 30px rgba(255,216,75,.42),0 0 58px rgba(255,45,117,.24)}}
.sweet-panel{bottom:calc(142px + env(safe-area-inset-bottom)) !important;}
.verified-badge,.featured-badge,.trend-rank-badge,.ranking-score,.trust-pill,.live-location-ribbon,.live-location-mini{
  box-shadow:0 10px 24px rgba(0,0,0,.32),0 0 18px rgba(255,216,75,.10) !important;
}
.ns-install-modal{
  position:fixed;inset:0;z-index:5000;display:none;align-items:flex-end;justify-content:center;background:rgba(0,0,0,.62);padding:18px;padding-bottom:calc(18px + env(safe-area-inset-bottom));
}
.ns-install-modal.show{display:flex;}
.ns-install-card{width:min(440px,94vw);border-radius:28px;padding:22px;background:linear-gradient(145deg,rgba(7,16,70,.94),rgba(0,0,0,.96));border:1px solid rgba(255,216,75,.24);box-shadow:0 24px 90px rgba(0,0,0,.65);color:#fff;}
.ns-install-card h3{color:var(--ns-gold);font-size:24px;line-height:1.05;margin:0 0 10px;font-weight:950;}
.ns-install-card p{color:#e5e7eb;line-height:1.55;margin:0 0 14px;font-size:14px;}
.ns-install-steps{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08);border-radius:18px;padding:14px;margin:12px 0;color:#fff;font-weight:850;font-size:14px;line-height:1.6;}
.ns-install-actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:14px;}
.ns-install-actions button{border:0;border-radius:16px;min-height:48px;font-weight:950;cursor:pointer;}
.ns-install-primary{background:linear-gradient(145deg,var(--ns-gold),var(--ns-amber));color:#000;}
.ns-install-secondary{background:rgba(255,255,255,.08);color:#fff;border:1px solid rgba(255,255,255,.12)!important;}
.ns-skeleton{position:relative;overflow:hidden;background:#07105a!important;}
.ns-skeleton::after{content:"";position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,rgba(255,255,255,.16),transparent);animation:nsShimmer 1.6s infinite;}
@keyframes nsShimmer{100%{transform:translateX(100%)}}
@media(max-width:760px){
  .topbar{gap:10px !important;padding-left:12px !important;padding-right:12px !important;}
  .brand{gap:10px !important;}
  .brand-logo{width:58px !important;height:58px !important;min-width:58px !important;border-radius:18px !important;}
  .brand-text span{font-size:clamp(1.45rem,8vw,2.2rem) !important;letter-spacing:-1px !important;}
  .menu-btn{width:52px !important;height:52px !important;min-width:52px !important;border-radius:18px !important;}
  .menu-btn span{font-size:28px !important;}
  .hero{padding:14px 12px 10px !important;}
  .hero-box{border-radius:26px !important;padding:24px 16px !important;}
  .hero-box h2{font-size:clamp(38px,13vw,62px) !important;}
  .profiles{grid-template-columns:repeat(2,minmax(0,1fr)) !important;gap:12px !important;padding-left:12px !important;padding-right:12px !important;}
  .card{border-radius:22px !important;}
  .card-body{padding:12px !important;}
  .action-row{gap:7px !important;}
  .call-btn,.wa-btn,.view-profile-btn,.live-location-btn{min-height:38px !important;border-radius:14px !important;font-size:9px !important;}
  .verified-badge{left:38px !important;top:10px !important;padding:5px 9px !important;font-size:9px !important;}
  .featured-badge{top:10px !important;right:10px !important;padding:6px 10px !important;font-size:9px !important;}
  .trend-rank-badge{top:38px !important;left:10px !important;padding:6px 9px !important;font-size:9px !important;}
}
@media(max-width:390px){.profiles{grid-template-columns:1fr !important}.card-image{aspect-ratio:4/4.6 !important}}
@media(prefers-reduced-motion:reduce){*{animation-duration:.001ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-duration:.001ms!important}}

</style>
<link rel="stylesheet" href="/assets/css/v5-phase3.css">
</head>

<body>

<!-- =========================
AGE GATE
========================= -->
<div class="age-gate" id="ageGate">
  <div class="age-card">
    <button class="age-close" onclick="leaveSite()">×</button>

    <img src="/assets/logo/logo-badge.png" class="age-logo" alt="Nairobi Sweets">

    <h2>Welcome to Nairobi Sweets</h2>
    <p class="age-sub">Luxury discovery platform for adults only.</p>

    <label class="age-label">🌍 Select your country</label>
    <select id="countrySelect" class="age-input">
      <option value="">Choose country</option>
      <option>Kenya</option>
      <option>Uganda</option>
      <option>Tanzania</option>
      <option>Rwanda</option>
      <option>South Africa</option>
      <option>Nigeria</option>
      <option>Ghana</option>
      <option>United Arab Emirates</option>
      <option>United Kingdom</option>
      <option>United States</option>
    </select>

    <div class="age-warning">
      <strong>WARNING:</strong> This website may contain adult-oriented material.
      Continue only if you are legally allowed to view this type of content in your location.
    </div>

    <label class="age-check">
      <input type="checkbox" id="ageConfirm">
      <span>I confirm that I am 18 years or older and accept responsibility for my own actions.</span>
    </label>

    <div class="age-actions">
      <button onclick="enterSite()" class="enter-btn">Enter Nairobi Sweets</button>
      <button onclick="leaveSite()" class="leave-btn">Leave Site</button>
    </div>

    <p class="cookie-note">
      By entering, you agree to our cookie use, privacy notice, and platform disclaimer.
    </p>
  </div>
</div>


<header class="topbar">
  <a href="/" class="brand">
    <img
      src="/assets/logo/logo-badge.png"
      onerror="this.src='/assets/logo/logo-badge.png'"
      alt="Nairobi Sweets"
      class="brand-logo"
    >

    <div class="brand-text">
      <span>Nairobi</span>
      <span>Sweets</span>
    </div>
  </a>

  <div class="menu-btn" onclick="toggleMenu()">
    <span>☰</span>
  </div>
</header>

<div class="mobile-menu" id="mobileMenu">
  <div class="menu-close" onclick="toggleMenu()">✕</div>

  <div class="menu-links">
    <a href="/">🏠 Home</a>
    <a href='/shorts'>🔥 Nairobi Shorts</a>
    <a href='/reel'>🎬 Nairobi Reels</a>
    <a href='/join'>💎 Join Nairobi Sweets</a>
    <a href='/login'>👤 Member Login</a>
  </div>
</div>

<section class="hero">
  <div class="hero-box">
    <h2>Profiles</h2>
    <p>Verified profiles, WhatsApp access, VIP listings, reels and luxury discovery.</p>

    <input
      type="text"
      class="search-box"
      id="searchInput"
      placeholder="Search by name, bio, location..."
    >

    <div class="hero-cta-row">
      <a class='hero-join-btn' href='/join'>💎 Join / View Pricing</a>
      <a class='hero-login-btn' href='/login'>👤 Member Login</a>
    </div>

    <button id="installAppBtn" class="install-app-btn" style="display:none;">
      📲 Install Nairobi Sweets App
    </button>
  </div>
</section>

<section class="signature-wrap">
  <div class="signature-box">
    <div class="signature-header">
      <h2>💆 Spa & Massage Profiles</h2>
      <span>Spa Only • Premium Top Placement</span>
    </div>

    <div class="signature-row" id="signatureProfiles"></div>
  </div>
</section>

<section class="sweet-gallery-wrap" id="sweet-gallery-scroll" aria-label="Sweet Gallery Scroll">
  <div class="sweet-gallery-box">
    <div class="sweet-gallery-header">
      <h2>🍬 Sweet Gallery Scroll</h2>
      <span>Featured Nairobi Sweets Profiles</span>
    </div>

    <div class="sweet-gallery-scroll" id="sweetGalleryScroll">
      <div class="sweet-gallery-loading">Loading sweet gallery...</div>
    </div>
  </div>
</section>

<section class="shorts-section">
  <div class="shorts-header">
    <h2>🔥 Nairobi Shorts</h2>
    <a href='/reel'>Open Reels →</a>
  </div>

  <div class="shorts-row" id="shortsRow"></div>
</section>

<section class="stats-wrap" aria-label="Live Nairobi Sweets stats">
  <div class="stats-box">
    <div class="stat-mini">
      <div class="stats-label">Total Profiles</div>
      <div class="stats-number" id="profileCount">0</div>
    </div>

    <div class="stat-mini">
      <div class="stats-label">Verified</div>
      <div class="stats-number" id="verifiedCount">0</div>
    </div>

    <div class="stat-mini">
      <div class="stats-label">VIP / VIP+</div>
      <div class="stats-number" id="vipCount">0</div>
    </div>

    <div class="stat-mini">
      <div class="stats-label">Signature</div>
      <div class="stats-number" id="signatureCount">0</div>
    </div>

    <div class="stat-mini live-stat-mini">
      <div class="stats-label">Live Location</div>
      <div class="stats-number" id="liveLocationCount">0</div>
    </div>
  </div>
</section>

<section class="top-location-links" aria-label="Popular Nairobi Sweets location links">
  <div class="seo-locations-box">
    <h2>📍 Popular Nairobi Locations</h2>
    <p>Quick links to active Nairobi Sweets location pages. These links help visitors and Google discover profiles faster.</p>
    <div class="seo-location-links">
      <a class='primary-location' href='/seo/locations/kilimani'>Kilimani Profiles</a>
      <a href='/seo/locations/westlands'>Westlands Profiles</a>
      <a href='/seo/locations/kasarani'>Kasarani Profiles</a>
      <a href='/seo/locations/roysambu'>Roysambu Profiles</a>
      <a href='/seo/locations/ruiru'>Ruiru Profiles</a>
      <a href='/seo/locations/kiambu'>Kiambu Profiles</a>
      <a href='/seo/locations/ruaka'>Ruaka Profiles</a>
      <a href='/seo/locations/kahawa-sukari'>Kahawa Sukari Profiles</a>
    </div>
  </div>
</section>

<section class="latest-profiles-seo" aria-label="Latest Nairobi Sweets profile links">
  <div class="seo-locations-box">
    <h2>🆕 Latest Nairobi Sweets Profiles</h2>
    <p>Fresh profile links from the homepage give Google a stronger path to crawl newly approved Nairobi Sweets pages.</p>
    <div class="latest-profiles-grid" id="latestProfilesLinks">
      <a class='latest-profile-link' href='/profile'>Loading latest profiles...</a>
    </div>
    <div class="seo-mini-note">Updated from approved live profiles. If a profile expires, its page will now load a real 404 instead of a Soft 404.</div>
  </div>
</section>


<div class="filters">
  <button class="active" data-filter="home">HOME</button>
  <button data-filter="vip">VIP</button>
  <button data-filter="online">ONLINE</button>
  <button data-filter="whatsapp">WHATSAPP</button>
  <button data-filter="live-location">📍 LIVE LOCATION</button>
  <button data-filter="nairobi">NAIROBI</button>
  <button data-filter="kilimani">KILIMANI</button>
  <button data-filter="westlands">WESTLANDS</button>
  <button data-filter="ruiru">RUIRU</button>
  <button data-filter="kasarani">KASARANI</button>
</div>

<section class="profiles" id="profiles">
  <div class="loading">Loading profiles...</div>
</section>

<section class="join-pricing-wrap" id="join">
  <div class="join-pricing-box">
    <div class="join-pricing-header">
      <div>
        <h2>💎 Join Nairobi Sweets</h2>
        <p>
          Choose your visibility level before creating your profile. Start with Featured,
          upgrade to VIP or VIP+, or take premium placement with Signature.
        </p>
      </div>
    </div>

    <div class="join-pricing-grid">
      <article class="join-price-card">
        <h3>⭐ Featured</h3>
        <strong>From KSh 300</strong>
        <p>Entry visibility with listing placement, contact buttons and dashboard access.</p>
        <a href='/public-signup-payment-page?plan=featured'>Choose Featured</a>
      </article>

      <article class="join-price-card">
        <h3>🔥 VIP</h3>
        <strong>From KSh 800</strong>
        <p>Higher exposure, better discovery ranking and VIP badge placement.</p>
        <a href='/public-signup-payment-page?plan=vip'>Choose VIP</a>
      </article>

      <article class="join-price-card">
        <h3>💎 VIP+</h3>
        <strong>From KSh 1,000</strong>
        <p>Premium boost, stronger homepage visibility and priority location placement.</p>
        <a href='/public-signup-payment-page?plan=vip-plus'>Choose VIP+</a>
      </article>

      <article class="join-price-card">
        <h3>👑 Signature</h3>
        <strong>From KSh 1,500</strong>
        <p>Top-tier premium placement with maximum ranking priority and luxury visibility.</p>
        <a href='/public-signup-payment-page?plan=signature'>Choose Signature</a>
      </article>
    </div>

    <a class='join-main-link' href='/join'>
      View Full Membership Plans →
    </a>
  </div>
</section>

<section class="seo-locations" aria-label="Nairobi escorts directory by location and category">
  <div class="seo-locations-box">
    <h2>Browse Verified Escorts Nairobi By Location</h2>
    <p>
      Nairobi Sweets is a Nairobi escorts directory helping visitors discover verified escorts Nairobi,
      VIP escorts Nairobi and Signature escorts Nairobi across Roysambu, Kasarani, Ruiru, Kiambu,
      Westlands, Kilimani and Ruaka.
    </p>

    <div class="seo-keyword-intro">
      <h1>Nairobi Escorts Directory</h1>
      <p>
        Find Roysambu escorts, Kasarani escorts, Ruiru escorts, Kiambu escorts, Westlands escorts,
        Kilimani escorts and Ruaka escorts from one trusted Nairobi directory. Browse VIP escorts Nairobi,
        verified escorts Nairobi and Signature escorts Nairobi with location-based discovery.
      </p>
    </div>

    <div class="seo-location-links">
      <a class='primary-location' href='/seo/locations/roysambu'>Roysambu Escorts</a>
      <a href='/seo/locations/kasarani'>Kasarani Escorts</a>
      <a href='/seo/locations/ruiru'>Ruiru Escorts</a>
      <a href='/seo/locations/kiambu'>Kiambu Escorts</a>
      <a href='/seo/locations/westlands'>Westlands Escorts</a>
      <a href='/seo/locations/kilimani'>Kilimani Escorts</a>
      <a href='/seo/locations/ruaka'>Ruaka Escorts</a>
      <a href="/seo/">Nairobi Escorts Directory</a>
      <a href='/seo/categories/verified'>Verified Escorts Nairobi</a>
      <a href='/seo/categories/vip'>VIP Escorts Nairobi</a>
      <a href='/seo/categories/signature'>Signature Escorts Nairobi</a>
    </div>
  </div>
</section>

<section class="map-wrap">
  <div class="map-card">
    <div class="map-header">
      <h3>Nairobi Coverage Map</h3>
      <p>Explore active areas across Nairobi and nearby towns.</p>
    </div>

    <div class="mobile-map-load" id="mapLoader">
      <strong>🗺️ Nairobi Coverage Map</strong>
      <span>Tap to load the map. This keeps phones fast and prevents Chrome crashes.</span>
      <button onclick="loadCoverageMap()">Open Map</button>
    </div>
  </div>
</section>


<section class="admin-help-section">
  <div class="admin-help-box">

    <h3>📞 Need Help?</h3>

    <p>
      Contact Nairobi Sweets Admin for profile approvals, payments, renewals, VIP upgrades,
      Signature upgrades, and technical support.
    </p>

    <div class="admin-help-buttons">
      <a id="adminCallBtn" href="tel:+254143616363" class="admin-call-btn">📞 Call Admin</a>
      <a id="adminWhatsappBtn" href="https://wa.me/254143616363" target="_blank" rel="noopener" class="admin-whatsapp-btn">💬 WhatsApp Admin</a>
      <a id="adminEmailBtn" href="mailto:nairobisweets05@gmail.com" class="admin-email-btn">📧 Email Admin</a>
    </div>

  </div>
</section>

<section class="disclaimer">
  <div class="disclaimer-box">
    <h3>Disclaimer</h3>
    <p>
      Nairobi Sweets is an advertising and discovery platform only.
      All profiles are independently managed. Users must act responsibly
      and comply with all applicable laws and regulations.
    </p>
  </div>
</section>

<div class="sweet-ai" onclick="openSweet()">
  <img src="/assets/logo/logo-badge.png" alt="Sweet AI">
</div>

<div class="sweet-panel" id="sweetPanel">
  <div class="sweet-header">
    <h3>Sweet AI ✨</h3>
    <button onclick="closeSweet()">✕</button>
  </div>

  <div class="sweet-body">
    <input id="sweetInput" placeholder="VIP in Kilimani, online now...">

    <div class="sweet-chips">
      <button onclick="quickAsk('VIP in Kilimani')">VIP Kilimani</button>
      <button onclick="quickAsk('Online now')">Online Now</button>
      <button onclick="quickAsk('WhatsApp Westlands')">WhatsApp Westlands</button>
      <button onclick="quickAsk('Most liked')">Most Liked</button>
    </div>

    <button class="sweet-send" onclick="askSweet()">Ask Sweet</button>
    <div id="sweetResults" class="sweet-results">Hi, I’m Sweet 💋</div>
  </div>
</div>

<nav class="bottom-nav">
  <button onclick="window.location.href='/'">🏠</button>
  <button onclick="window.location.href='/shorts.html'">🔥</button>
  <button onclick="window.location.href='/reel.html'">🎬</button>
  <button onclick="openSweet()">✨</button>
  <button onclick="toggleMenu()">☰</button>
</nav>

<script>
/* =========================
SIGNATURE AUTO SLIDER
========================= */
let signatureAutoSlideTimer = null;

function startSignatureAutoSlide(){
  if(typeof isMobilePhone === "function" && isMobilePhone()) return;
  const track = document.getElementById("signatureProfiles");
  if(!track) return;

  clearInterval(signatureAutoSlideTimer);

  signatureAutoSlideTimer = setInterval(()=>{
    const card = track.querySelector(".signature-card");
    if(!card) return;

    const computed = window.getComputedStyle(track);
    const gap = parseFloat(computed.columnGap || computed.gap || 18) || 18;
    const step = card.offsetWidth + gap;

    const atEnd = track.scrollLeft + track.clientWidth >= track.scrollWidth - 30;

    if(atEnd){
      track.scrollTo({ left:0, behavior:"smooth" });
    }else{
      track.scrollBy({ left:step, behavior:"smooth" });
    }
  }, 3500);
}

function pauseSignatureAutoSlide(){
  clearInterval(signatureAutoSlideTimer);
}

function resumeSignatureAutoSlide(){
  setTimeout(startSignatureAutoSlide, 800);
}

document.addEventListener("visibilitychange",()=>{
  if(document.hidden){
    pauseSignatureAutoSlide();
  }else{
    resumeSignatureAutoSlide();
  }
});





const SUPABASE_URL = "https://dkjlvyynvgtijccitvvd.supabase.co";
const SUPABASE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImRramx2eXludmd0aWpjY2l0dnZkIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzU1NDA4MzIsImV4cCI6MjA5MTExNjgzMn0.6wlZCQPJ2En4egpQUo5LAyQhee2hkCQ_tHGxfxbv1EQ";
const SITE_URL = "https://nairobi-sweets.com";

const sb = supabase.createClient(SUPABASE_URL, SUPABASE_KEY);

const profilesEl = document.getElementById("profiles");
const shortsRow = document.getElementById("shortsRow");
const searchInput = document.getElementById("searchInput");
const profileCount = document.getElementById("profileCount");

let ALL_PROFILES = [];
let ACTIVE_FILTER = "home";
let CURRENT_PROFILE_RESULTS = [];
let PROFILE_VISIBLE_LIMIT = getInitialProfileLimit();


/* =========================
PROFILE LOADING SAFETY PATCH
Clears old cached profile data and old service worker caches after uploads.
========================= */
try{
  [
    "nairobi_sweets_fast_profiles_v4",
    "nairobi_sweets_fast_profiles_time_v4",
    "nairobi_sweets_fast_profiles_v5",
    "nairobi_sweets_fast_profiles_time_v5"
  ].forEach(key => localStorage.removeItem(key));
}catch(error){}

const PROFILE_CACHE_KEY = "nairobi_sweets_fast_profiles_v6";
const PROFILE_CACHE_TIME_KEY = "nairobi_sweets_fast_profiles_time_v6";
const PROFILE_CACHE_MAX_AGE = 1000 * 60 * 3;
let HOME_MEDIA_RENDER_TIMER = null;
let LAST_MEDIA_SOURCE = [];
let FIRST_PROFILE_PAINT_DONE = false;

function isMobilePhone(){
  return window.innerWidth <= 700;
}

function getInitialProfileLimit(){
  return isMobilePhone() ? 8 : 24;
}

function resetProfileLimit(){
  PROFILE_VISIBLE_LIMIT = getInitialProfileLimit();
}

function loadMoreProfiles(){
  PROFILE_VISIBLE_LIMIT += isMobilePhone() ? 8 : 16;
  renderProfiles(CURRENT_PROFILE_RESULTS.length ? CURRENT_PROFILE_RESULTS : []);
}

function profileSkeletons(count = 4){
  const skeletonCount = isMobilePhone() ? Math.min(count, 3) : Math.min(count, 8);
  return Array.from({length:skeletonCount}).map(()=>`<div class="profile-skeleton-card"></div>`).join("");
}

function readProfilesCache(){
  try{
    const cachedAt = Number(localStorage.getItem(PROFILE_CACHE_TIME_KEY) || 0);
    const raw = localStorage.getItem(PROFILE_CACHE_KEY);
    if(!raw) return null;
    if(Date.now() - cachedAt > PROFILE_CACHE_MAX_AGE) return null;
    const parsed = JSON.parse(raw);
    return Array.isArray(parsed) ? parsed : null;
  }catch(error){
    return null;
  }
}

function writeProfilesCache(list){
  try{
    if(!Array.isArray(list)) return;
    localStorage.setItem(PROFILE_CACHE_KEY, JSON.stringify(list));
    localStorage.setItem(PROFILE_CACHE_TIME_KEY, String(Date.now()));
  }catch(error){}
}

function scheduleHomeMediaRender(list, delay = null){
  LAST_MEDIA_SOURCE = Array.isArray(list) ? list : [];
  clearTimeout(HOME_MEDIA_RENDER_TIMER);

  const run = () => {
    const renderNow = () => {
      renderSweetGallery(LAST_MEDIA_SOURCE);
      renderShorts(LAST_MEDIA_SOURCE);
    };

    if("requestIdleCallback" in window){
      requestIdleCallback(renderNow,{timeout:isMobilePhone() ? 2200 : 1300});
    }else{
      setTimeout(renderNow,isMobilePhone() ? 1200 : 450);
    }
  };

  HOME_MEDIA_RENDER_TIMER = setTimeout(run, delay ?? (isMobilePhone() ? 900 : 220));
}

function loadCoverageMap(){
  const holder = document.getElementById("mapLoader");
  if(!holder || holder.dataset.loaded === "yes") return;
  holder.dataset.loaded = "yes";
  holder.outerHTML = `
    <iframe
      src="https://maps.google.com/maps?q=Nairobi&t=&z=11&ie=UTF8&iwloc=&output=embed"
      loading="lazy"
      allowfullscreen>
    </iframe>
  `;
}

function toggleMenu(){
  document.getElementById("mobileMenu").classList.toggle("active");
}

function openSweet(){
  document.getElementById("sweetPanel").classList.add("active");
}

function closeSweet(){
  document.getElementById("sweetPanel").classList.remove("active");
}

function quickAsk(text){
  document.getElementById("sweetInput").value = text;
  askSweet();
}

function safePhone(phone){
  let p = String(phone || "").replace(/\D/g,"");
  if(!p) return "";
  if(p.startsWith("0")) p = "254" + p.slice(1);
  if(p.startsWith("7") || p.startsWith("1")) p = "254" + p;
  return p;
}

function cleanImageUrl(url){
  url = String(url || "").trim();
  if(!url || url.toLowerCase() === "null" || url.toLowerCase() === "undefined"){
    return "/assets/logo/logo-badge.png";
  }

  try{
    const imageUrl = new URL(url, window.location.origin);

    // Remove tiny thumbnail parameters that make profile cards blurry.
    [
      "w",
      "width",
      "h",
      "height",
      "resize",
      "quality",
      "q",
      "thumbnail",
      "thumb"
    ].forEach(param => imageUrl.searchParams.delete(param));

    return imageUrl.href;
  }catch(error){
    return url;
  }
}

function normaliseImageArray(value){
  if(!value) return [];
  if(Array.isArray(value)){
    return value
      .flatMap(item => normaliseImageArray(item))
      .filter(Boolean);
  }

  if(typeof value === "object"){
    return [
      value.url,
      value.publicUrl,
      value.public_url,
      value.src,
      value.path,
      value.image_url,
      value.photo_url
    ].filter(Boolean);
  }

  const text = String(value || "").trim();
  if(!text || text === "null" || text === "undefined") return [];

  try{
    const parsed = JSON.parse(text);
    if(parsed && parsed !== text){
      return normaliseImageArray(parsed);
    }
  }catch(error){}

  return text
    .split(/[,\n|]+/)
    .map(item => item.trim())
    .filter(Boolean);
}

function firstUsableImageUrl(profile){
  const candidates = [
    profile.photo_url,
    profile.image_url,
    profile.main_image,
    profile.main_photo,
    profile.profile_photo,
    profile.avatar_url,
    profile.cover_url,
    profile.photo,
    profile.image,
    profile.picture,
    ...normaliseImageArray(profile.gallery_images),
    ...normaliseImageArray(profile.gallery),
    ...normaliseImageArray(profile.images),
    ...normaliseImageArray(profile.photos),
    ...normaliseImageArray(profile.image_urls),
    ...normaliseImageArray(profile.photo_urls)
  ].filter(Boolean);

  const cleanCandidates = candidates
    .map(url => cleanImageUrl(url))
    .filter(url => url && !String(url).includes("undefined") && !String(url).includes("null"));

  return cleanCandidates.find(url => !String(url).includes("/assets/logo/logo-badge.png")) || cleanCandidates[0] || "/assets/logo/logo-badge.png";
}

function getImage(profile){
  return firstUsableImageUrl(profile || {});
}

function getImageSrcSet(profile){
  const image = getImage(profile);

  // Keep one clean source. This avoids browser picking old tiny thumbnail URLs.
  return `${image} 1x`;
}

function getSignatureImage(profile){
  return profile.signature_banner_url || getImage(profile);
}

function getVideo(profile){
  return (
    profile.short_video ||
    profile.short_video_url ||
    profile.short_url ||
    profile.reel ||
    profile.reel_url ||
    profile.video_url ||
    profile.video ||
    ""
  );
}

function hasVideo(profile){
  const video = String(getVideo(profile) || "").trim();
  return Boolean(video) && video.toLowerCase() !== "null" && video.toLowerCase() !== "undefined";
}

function isVideo(url){
  const clean = String(url || "").split("?")[0].split("#")[0];
  return /\.(mp4|webm|mov|m4v)$/i.test(clean);
}

function getName(profile){
  return profile.stage_name || profile.name || profile.full_name || "Verified";
}

function getLocation(profile){
  return profile.location || profile.town || profile.area || "Nairobi";
}

function getPlan(profile){
  return String(profile.plan || profile.plan_name || profile.package || profile.tier || "").toLowerCase();
}

function getBio(profile){
  return profile.bio || profile.description || profile.about || "Luxury Nairobi profile.";
}

function getBadge(profile){
  if((Number(profile.trending_score || 0)) >= 1000) return "🔥 TRENDING";
  if(profile.verified) return "✔ VERIFIED";

  const plan = getPlan(profile);
  if(plan.includes("signature")) return "👑 SIGNATURE";
  if(plan.includes("vvip")) return "👑 VVIP";
  if(plan.includes("vip")) return "✨ VIP";
  if(plan.includes("featured")) return "🔥 FEATURED";

  return "✨ Featured";
}


function truthyFlag(value){
  if(value === true) return true;
  const text = String(value || "").trim().toLowerCase();
  return ["true","yes","1","on","active"].includes(text);
}

function isSignatureProfile(profile){
  const planText = [
    profile.plan,
    profile.plan_name,
    profile.package,
    profile.tier,
    profile.category,
    profile.profile_type,
    profile.membership,
    profile.badge
  ].map(v => String(v || "").toLowerCase()).join(" ");

  return Boolean(
    truthyFlag(profile.is_signature) ||
    truthyFlag(profile.signature) ||
    truthyFlag(profile.signature_profile) ||
    truthyFlag(profile.homepage_featured) ||
    truthyFlag(profile.is_vvip) ||
    planText.includes("signature") ||
    planText.includes("vvip")
  );
}

function seoSlug(value = ""){
  return String(value || "")
    .toLowerCase()
    .trim()
    .replace(/&/g," and ")
    .replace(/[^a-z0-9]+/g,"-")
    .replace(/^-+|-+$/g,"");
}

function escapeHTML(value = ""){
  return String(value ?? "")
    .replaceAll("&","&amp;")
    .replaceAll("<","&lt;")
    .replaceAll(">","&gt;")
    .replaceAll('"',"&quot;")
    .replaceAll("'","&#039;");
}

function jsString(value = ""){
  return JSON.stringify(String(value ?? ""));
}

function jsValue(value = ""){
  return String(value ?? "").replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\n/g," ");
}

function getProfileUrl(profile){
  const existingSlug = String(profile.slug || profile.profile_slug || profile.seo_slug || profile.username || "").trim();
  const cleanedExistingSlug = seoSlug(existingSlug);

  if(cleanedExistingSlug){
    return `/profile.html?slug=${encodeURIComponent(cleanedExistingSlug)}`;
  }

  const sitemapStyleSlug = seoSlug(`${getName(profile)}-${getLocation(profile)}-${profile.id || ""}`);

  if(sitemapStyleSlug){
    return `/profile.html?slug=${encodeURIComponent(sitemapStyleSlug)}`;
  }

  return `/profile.html?id=${encodeURIComponent(profile.id)}`;
}

function clampScore(value,max){
  const n = Number(value || 0);
  if(!Number.isFinite(n) || n <= 0) return 0;
  return Math.min(100,(n / max) * 100);
}

function derivedImageQuality(profile){
  let score = Number(profile.image_quality_score || 0);

  const img = getImage(profile);
  const video = getVideo(profile);
  const plan = getPlan(profile);

  if(img && !img.includes("logo-badge")) score += 25;
  if(profile.gallery && Array.isArray(profile.gallery) && profile.gallery.length >= 3) score += 15;
  if(profile.gallery && Array.isArray(profile.gallery) && profile.gallery.length >= 5) score += 10;
  if(video) score += 20;
  if(profile.verified) score += 15;
  if(plan.includes("vip")) score += 10;
  if(plan.includes("signature") || plan.includes("vvip")) score += 20;

  return Math.min(100,Math.max(0,score));
}

function finalProfileScore(profile){
  const imageQualityScore = derivedImageQuality(profile);
  const likesScore = clampScore(profile.favorites || profile.likes_count || profile.likes,500);
  const viewsScore = clampScore(profile.views_count || profile.views,10000);
  const boostScore = clampScore(profile.boost_score || profile.boost,1000);
  const verificationScore = profile.verified ? 100 : 0;

  return (
    imageQualityScore * 0.40 +
    likesScore * 0.20 +
    viewsScore * 0.15 +
    boostScore * 0.15 +
    verificationScore * 0.10
  );
}

function rankingScore(profile){
  return Math.round(finalProfileScore(profile));
}

function sortByMarketplaceRank(list){
  return [...list].sort((a,b)=>{
    const pinnedA = a.pinned_top ? 1 : 0;
    const pinnedB = b.pinned_top ? 1 : 0;
    if(pinnedA !== pinnedB) return pinnedB - pinnedA;

    const heroA = a.homepage_featured ? 1 : 0;
    const heroB = b.homepage_featured ? 1 : 0;
    if(heroA !== heroB) return heroB - heroA;

    const scoreA = finalProfileScore(a);
    const scoreB = finalProfileScore(b);
    if(scoreA !== scoreB) return scoreB - scoreA;

    const sigA = isSignatureProfile(a) ? 1 : 0;
    const sigB = isSignatureProfile(b) ? 1 : 0;
    if(sigA !== sigB) return sigB - sigA;

    const trendA = Number(a.trending_score || 0);
    const trendB = Number(b.trending_score || 0);
    if(trendA !== trendB) return trendB - trendA;

    const newestA = new Date(a.last_active || a.created_at || 0).getTime() || 0;
    const newestB = new Date(b.last_active || b.created_at || 0).getTime() || 0;
    return newestB - newestA;
  });
}

/* =========================
SMART HOMEPAGE ROTATION
Keeps paid/ranked profiles strong, but changes the visible top cards on refresh.
========================= */
function randomizeArray(list){
  const array = [...list];

  for(let i = array.length - 1; i > 0; i--){
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }

  return array;
}

function isNewProfile(profile, days = 7){
  const created = new Date(profile.created_at || profile.updated_at || 0).getTime();
  if(!created) return false;

  const ageMs = Date.now() - created;
  return ageMs >= 0 && ageMs <= days * 24 * 60 * 60 * 1000;
}

function smartProfileRotation(list, topLimit = 28){
  const ranked = sortByMarketplaceRank(list);

  if(ranked.length <= 2){
    return ranked;
  }

  const pinned = ranked.filter(p => p.pinned_top);
  const notPinned = ranked.filter(p => !p.pinned_top);

  /* NEW PROFILES FIRST:
     Fresh approved profiles get a visible homepage boost for 7 days.
     This makes new profiles appear on index immediately after approval instead of being buried by old VIP/trending profiles. */
  const newest = notPinned
    .filter(p => isNewProfile(p, 7))
    .sort((a,b)=>{
      const dateA = new Date(a.created_at || a.updated_at || 0).getTime() || 0;
      const dateB = new Date(b.created_at || b.updated_at || 0).getTime() || 0;
      return dateB - dateA;
    })
    .slice(0, 12);

  const newestIds = new Set(newest.map(p => String(p.id)));
  const remainingPool = notPinned.filter(p => !newestIds.has(String(p.id)));

  const signature = remainingPool.filter(isSignatureProfile);
  const vip = remainingPool.filter(p => getPlan(p).includes("vip") && !isSignatureProfile(p));
  const featured = remainingPool.filter(p => {
    const plan = getPlan(p);
    return !isSignatureProfile(p) && !plan.includes("vip");
  });

  const topPool = [
    ...signature.slice(0, Math.ceil(topLimit * 0.30)),
    ...vip.slice(0, Math.ceil(topLimit * 0.35)),
    ...featured.slice(0, Math.ceil(topLimit * 0.20))
  ];

  const topPoolIds = new Set(topPool.map(p => String(p.id)));
  const remaining = ranked.filter(p =>
    !topPoolIds.has(String(p.id)) &&
    !newestIds.has(String(p.id)) &&
    !p.pinned_top
  );

  // Pinned profiles stay first, new profiles get immediate visibility, then rotating VIP/Signature pool.
  return [
    ...randomizeArray(pinned),
    ...newest,
    ...randomizeArray(topPool),
    ...remaining
  ];
}

function smartSignatureRotation(list){
  const signatures = list
    .filter(isSignatureProfile)
    .sort((a,b)=>(Number(a.signature_position || 999) - Number(b.signature_position || 999)));

  const pinnedSignatures = signatures.filter(p => p.pinned_top || Number(p.signature_position || 999) <= 3);
  const normalSignatures = signatures.filter(p => !pinnedSignatures.some(x => String(x.id) === String(p.id)));

  return [
    ...randomizeArray(pinnedSignatures),
    ...randomizeArray(normalSignatures)
  ];
}

function markPosterImage(img){
  try{
    if(img.naturalWidth && img.naturalHeight && (img.naturalWidth / img.naturalHeight) > 1.2){
      img.classList.add("poster-image");
    }
  }catch(error){}
}

function getLikes(profile){
  return Number(profile.favorites || profile.likes_count || profile.likes || 0);
}

function getViews(profile){
  return Number(profile.views || profile.views_count || 0);
}

function compact(text,max=115){
  text = String(text || "");
  return text.length > max ? text.slice(0,max).trim() + "..." : text;
}

function whatsappMessage(profile){
  return encodeURIComponent(
`🔥 Nairobi Sweets

Hi ${getName(profile)},

I found your profile on Nairobi Sweets.

🌍 ${SITE_URL}

💎 Verified Profiles
🔥 Nairobi Shorts
🎬 Nairobi Reels`
  );
}


function getContactValueFromUrl(url){
  const text = String(url || "");
  if(text.startsWith("tel:")) return text.replace(/^tel:/i, "");
  if(text.includes("wa.me/")){
    try{
      const cleanUrl = text.split("?")[0];
      return cleanUrl.split("wa.me/")[1] || "";
    }catch(error){
      return "";
    }
  }
  return text;
}

async function trackEvent(eventType, profileId, profileName = "", contactValue = ""){
  const now = new Date().toISOString();

  /*
    CONTACT TRACKING PATCH
    Supabase can store profile IDs as bigint, uuid, or text depending on your project.
    To avoid uuid/bigint errors, we always save the tracked profile_id as TEXT.
    The Vault joins using s.profile_id::text = p.id::text.
  */
  const safeProfileId = String(profileId || "").trim() || null;
  const safeProfileName = String(profileName || "").trim();
  const pageUrl = window.location.href;

  const contactEvents = [
    "whatsapp_clicks",
    "call_clicks",
    "live_location_clicks",
    "profile_opens"
  ];

  let saved = false;

  if(contactEvents.includes(eventType)){
    const contactPayload = {
      profile_id: safeProfileId,
      profile_name: safeProfileName,
      event_type: eventType,
      contact_value: String(contactValue || ""),
      page_url: pageUrl,
      user_agent: navigator.userAgent || "",
      created_at: now
    };

    try{
      const { error } = await sb.from("profile_contact_events").insert(contactPayload);
      if(error){
        console.warn("profile_contact_events insert failed:", error.message || error);
      }else{
        saved = true;
      }
    }catch(err){
      console.warn("profile_contact_events error:", err);
    }
  }

  /*
    Optional legacy analytics tables. These are intentionally best-effort only.
    If any table does not exist, the real contact tracking above still works.
  */
  try{
    await sb.from("analytics_events").insert({
      profile_id: safeProfileId,
      profile_name: safeProfileName,
      event_name: eventType,
      source_page: window.location.pathname,
      page_url: pageUrl,
      user_agent: navigator.userAgent || "",
      created_at: now
    });
  }catch(err){}

  try{
    await sb.from("profile_events").insert({
      profile_id: safeProfileId,
      profile_name: safeProfileName,
      event_type: eventType,
      source_page: window.location.pathname,
      page_url: pageUrl,
      user_agent: navigator.userAgent || "",
      created_at: now
    });
  }catch(err){}

  return saved;
}

async function handleTrackedLink(event,eventType,profileId,url,newTab=false,profileName="",contactValue=""){
  event.preventDefault();
  event.stopPropagation();
  const value = contactValue || getContactValueFromUrl(url);
  await trackEvent(eventType,profileId,profileName,value);
  if(newTab){
    window.open(url,"_blank","noopener");
  }else{
    window.location.href = url;
  }
  return false;
}

async function openProfileCard(profileId){
  const profile = ALL_PROFILES.find(p => String(p.id) === String(profileId)) || {};
  const profileName = getName(profile);

  await trackEvent("profile_opens", profileId, profileName);

  window.location.href = getProfileUrl(profile);
}

function profileSearchText(profile){
  return `
    ${getName(profile)}
    ${getLocation(profile)}
    ${getBio(profile)}
    ${getPlan(profile)}
    ${profile.phone || ""}
    ${profile.whatsapp || ""}
  `.toLowerCase();
}


function isSpaOrMassageProfile(profile){
  /*
    STRICT TOP PLACEMENT RULE:
    The premium top carousel must show ONLY spa / massage BUSINESS profiles.
    Do NOT use bio, services, location, or plan here because normal profiles can mention
    massage in their services and then sneak into the top banner. Tiny gatekeeper goblin defeated.
  */
  const nameText = `
    ${profile.stage_name || ""}
    ${profile.name || ""}
    ${profile.full_name || ""}
    ${profile.business_name || ""}
    ${profile.slug || ""}
  `.toLowerCase();

  const categoryText = `
    ${profile.category || ""}
    ${profile.profile_type || ""}
    ${profile.type || ""}
  `.toLowerCase();

  const nameLooksSpa = /\b(spa|massage|massages|masseuse|wellness|beauty\s*spa)\b/i.test(nameText);
  const categoryLooksSpa = /\b(spa|massage|massage_spa|spa_massage)\b/i.test(categoryText);

  return Boolean(nameLooksSpa || categoryLooksSpa);
}

function renderSignatureProfiles(list){
  const container = document.getElementById("signatureProfiles");
  if(!container) return;

  const spaOnlyTopProfiles = (Array.isArray(list) ? list : [])
    .filter(profile => isSignatureProfile(profile) && isSpaOrMassageProfile(profile));

  const signatures = smartSignatureRotation(spaOnlyTopProfiles).slice(0, isMobilePhone() ? 3 : 8);

  if(!signatures.length){
    container.innerHTML = `
      <div style="padding:20px;color:#ffd54a;font-weight:900;">
        No Spa & Massage Profiles Yet
      </div>
    `;
    return;
  }

  container.innerHTML = signatures.map(profile=>`
    <div
      class="signature-card"
      onclick="openProfileCard('${profile.id}')"
      title="Open ${getName(profile)}"
    >
      <img
        src="${cleanImageUrl(getSignatureImage(profile))}"
        alt="${getName(profile)}"
        loading="lazy"
        decoding="async"
        referrerpolicy="no-referrer"
        onerror="this.src='/assets/logo/logo-badge.png'"
      >
    </div>
  `).join("");

  if(!isMobilePhone()) setTimeout(startSignatureAutoSlide, 500);
}


function renderSweetGallery(list){
  const gallery = document.getElementById("sweetGalleryScroll");
  const gallerySection = document.querySelector(".sweet-gallery-wrap");
  if(!gallery) return;

  const source = Array.isArray(list) ? list : [];
  const galleryProfiles = smartProfileRotation(
    source.filter(profile => {
      const image = getImage(profile);
      return image && !String(image).includes("logo-badge.png");
    }),
    30
  ).slice(0, isMobilePhone() ? 6 : 24);

  if(!galleryProfiles.length){
    if(gallerySection) gallerySection.style.display = "none";
    gallery.innerHTML = `<div class="sweet-gallery-empty">No Sweet Gallery photos yet.</div>`;
    return;
  }

  if(gallerySection) gallerySection.style.display = "block";

  const galleryCards = galleryProfiles.map((profile,index)=>`
    <a
      href="${getProfileUrl(profile)}"
      class="sweet-gallery-card"
      onclick="event.stopPropagation(); trackEvent('profile_opens','${profile.id}','${getName(profile)}')"
      title="Open ${getName(profile)}"
    >
      ${index < 4 ? `<div class="sweet-gallery-pill">🍬 Featured</div>` : ``}
      <img
        src="${getImage(profile)}"
        alt="${getName(profile)}"
        loading="lazy"
        decoding="async"
        referrerpolicy="no-referrer"
        onerror="this.src='/assets/logo/logo-badge.png'"
      >

      <div class="sweet-gallery-info">
        <div class="sweet-gallery-name">${getName(profile)}</div>
        <div class="sweet-gallery-location">📍 ${getLocation(profile)}</div>
      </div>
    </a>
  `).join("");

  gallery.innerHTML = `
    <div class="sweet-gallery-track" aria-label="Continuous Sweet Gallery Scroll">
      ${galleryCards}
      ${isMobilePhone() ? "" : galleryCards}
    </div>
  `;
}

let shortsAutoScrollFrame = null;
let shortsAutoScrollPaused = false;

function stopShortsAutoScroll(){
  if(shortsAutoScrollFrame){
    cancelAnimationFrame(shortsAutoScrollFrame);
    shortsAutoScrollFrame = null;
  }
}

function startShortsAutoScroll(){
  const row = document.getElementById("shortsRow");
  if(!row) return;

  stopShortsAutoScroll();
  row.classList.add("auto-moving");

  const speed = window.innerWidth < 650 ? 0.45 : 0.65;

  function moveShorts(){
    if(!shortsAutoScrollPaused && row.scrollWidth > row.clientWidth){
      row.scrollLeft += speed;

      const halfWidth = row.scrollWidth / 2;
      if(row.scrollLeft >= halfWidth){
        row.scrollLeft = 0;
      }
    }

    shortsAutoScrollFrame = requestAnimationFrame(moveShorts);
  }

  moveShorts();
}

function bindShortsPauseEvents(){
  const row = document.getElementById("shortsRow");
  if(!row || row.dataset.pauseReady === "yes") return;

  row.dataset.pauseReady = "yes";

  row.addEventListener("mouseenter",()=>{
    shortsAutoScrollPaused = true;
  });

  row.addEventListener("mouseleave",()=>{
    shortsAutoScrollPaused = false;
  });

  row.addEventListener("touchstart",()=>{
    shortsAutoScrollPaused = true;
  },{passive:true});

  row.addEventListener("touchend",()=>{
    setTimeout(()=>{ shortsAutoScrollPaused = false; },1200);
  },{passive:true});
}

function renderShorts(list){
  const shortsSection = document.querySelector(".shorts-section");

  // Randomize homepage video shorts on every refresh.
  // This keeps Nairobi Shorts fresh while still showing video-only profiles.
  const videoShortsPool = list
    .filter(hasVideo)
    .filter(profile => isVideo(getVideo(profile)) || String(getVideo(profile)).startsWith("http"));

  const shorts = randomizeArray(videoShortsPool).slice(0, isMobilePhone() ? 2 : 8);

  if(!shorts.length){
    if(shortsSection) shortsSection.style.display = "none";
    shortsRow.innerHTML = "";
    stopShortsAutoScroll();
    return;
  }

  if(shortsSection) shortsSection.style.display = "block";

  // Duplicate the list for endless left-moving scroll, but shuffle each half
  // so the first visible short changes from refresh to refresh.
  const movingShorts = (!isMobilePhone() && shorts.length > 1)
    ? [...randomizeArray(shorts), ...randomizeArray(shorts)]
    : shorts;

  shortsRow.innerHTML = movingShorts.map(profile=>{
    const media = getVideo(profile);

    return `
      <div class="short-card" onclick="window.location.href='/reel.html'">
        <video
          muted
          ${isMobilePhone() ? "controls" : "autoplay loop"}
          playsinline
          webkit-playsinline
          preload="${isMobilePhone() ? "none" : "metadata"}"
          poster="/assets/logo/logo-badge.png"
          controlsList="nodownload"
          disablePictureInPicture
          oncontextmenu="return false"
          ${isMobilePhone() ? "" : "onloadedmetadata=\"this.play().catch(()=>{})\" oncanplay=\"this.play().catch(()=>{})\""}
          onerror="this.closest('.short-card').classList.add('video-error')"
        >
          <source src="${media}" type="video/mp4">
        </video>

        <div class="short-overlay">
          <div class="short-name">${getName(profile)}</div>
          <div class="short-location">📍 ${getLocation(profile)}</div>
        </div>
      </div>
    `;
  }).join("");

  bindShortsPauseEvents();
  playHomepageShorts();
  setTimeout(playHomepageShorts,700);
  if(!isMobilePhone()) setTimeout(startShortsAutoScroll,500);
}

function playHomepageShorts(){
  if(isMobilePhone()) return;
  const videos = document.querySelectorAll("#shortsRow video");

  videos.forEach(video=>{
    try{
      video.muted = true;
      video.defaultMuted = true;
      video.playsInline = true;
      video.setAttribute("muted","");
      video.setAttribute("playsinline","");
      video.setAttribute("webkit-playsinline","");

      const playPromise = video.play();
      if(playPromise && typeof playPromise.catch === "function"){
        playPromise.catch(()=>{});
      }
    }catch(error){}
  });
}


function trendRankBadge(index){
  if(index === 0){
    return `<div class="trend-rank-badge trend-rank-1">🥇 #1 TRENDING</div>`;
  }

  if(index === 1){
    return `<div class="trend-rank-badge trend-rank-2">🥈 #2 TRENDING</div>`;
  }

  if(index === 2){
    return `<div class="trend-rank-badge trend-rank-3">🥉 #3 TRENDING</div>`;
  }

  return "";
}


function isLiveLocationActive(profile){
  if(!profile || !profile.live_location_enabled) return false;
  if(profile.live_location_expires_at && new Date(profile.live_location_expires_at).getTime() < Date.now()) return false;
  return Boolean(profile.live_location_url || (profile.live_lat && profile.live_lng));
}

function getLiveLocationUrl(profile){
  if(!isLiveLocationActive(profile)) return "";
  if(profile.live_location_url) return profile.live_location_url;
  return `https://www.google.com/maps?q=${profile.live_lat},${profile.live_lng}`;
}

function renderProfiles(data, statsData = data){
  CURRENT_PROFILE_RESULTS = Array.isArray(data) ? data : [];
  const STATS_PROFILE_RESULTS = Array.isArray(statsData) ? statsData : CURRENT_PROFILE_RESULTS;
  if(profileCount) profileCount.textContent = STATS_PROFILE_RESULTS.length.toLocaleString();

  const verifiedCountEl = document.getElementById("verifiedCount");
  const vipCountEl = document.getElementById("vipCount");
  const signatureCountEl = document.getElementById("signatureCount");
  const liveLocationCountEl = document.getElementById("liveLocationCount");

  if(liveLocationCountEl){
    liveLocationCountEl.textContent = STATS_PROFILE_RESULTS.filter(isLiveLocationActive).length.toLocaleString();
  }

  if(verifiedCountEl){
    verifiedCountEl.textContent = STATS_PROFILE_RESULTS.filter(p => p.verified || p.is_verified).length.toLocaleString();
  }

  if(vipCountEl){
    vipCountEl.textContent = STATS_PROFILE_RESULTS.filter(p => getPlan(p).includes("vip") || p.is_vip || p.vip).length.toLocaleString();
  }

  if(signatureCountEl){
    signatureCountEl.textContent = STATS_PROFILE_RESULTS.filter(isSignatureProfile).length.toLocaleString();
  }

  if(!CURRENT_PROFILE_RESULTS.length){
    profilesEl.innerHTML = `<div class="empty">No profiles found.</div>`;
    return;
  }

  const visibleProfiles = CURRENT_PROFILE_RESULTS.slice(0, PROFILE_VISIBLE_LIMIT);

  profilesEl.innerHTML = visibleProfiles.map((profile,index)=>{
    const phone = safePhone(profile.phone || profile.whatsapp);
    const profileId = String(profile.id || "");
    const profileName = getName(profile);
    const profileUrl = getProfileUrl(profile);
    const liveUrl = getLiveLocationUrl(profile);
    const waUrl = phone ? `https://wa.me/${phone}?text=${whatsappMessage(profile)}` : "";
    const rankLabel = index === 0 ? "🏆 #1" : index === 1 ? "🏆 #2" : "🏆 #3";

    return `
      <article class="card" onclick="openProfileCard(${jsString(profileId)})">
        ${isLiveLocationActive(profile) ? `<div class="live-location-ribbon"><span></span> LIVE LOCATION ON</div>` : ``}
        <img
          src="${escapeHTML(getImage(profile))}"
          srcset="${escapeHTML(getImageSrcSet(profile))}"
          sizes="(min-width:1100px) 25vw, (min-width:901px) 33vw, 100vw"
          class="card-image"
          loading="${index < (isMobilePhone() ? 1 : 4) ? 'eager' : 'lazy'}"
          decoding="async"
          fetchpriority="${index < (isMobilePhone() ? 1 : 4) ? 'high' : 'auto'}"
          referrerpolicy="no-referrer"
          alt="${escapeHTML(profileName)}"
          onload="markPosterImage(this)"
          onerror="this.src='/assets/logo/logo-badge.png'"
        >

        <div class="card-badge-rail">
          <span class="card-chip online-mini" title="Online Now"></span>
          ${isNewProfile(profile, 7) ? `<span class="card-chip new">🆕 NEW</span>` : ""}
          ${profile.pinned_top ? `<span class="card-chip pinned">👑 PINNED</span>` : index < 3 ? `<span class="card-chip rank">${rankLabel}</span>` : ``}
          ${profile.verified ? `<span class="card-chip verified">✔ VERIFIED</span>` : ``}
          ${isLiveLocationActive(profile) ? `<span class="card-chip live-location-mini">📍 LIVE LOCATION</span>` : ``}
          <span class="card-chip plan">${escapeHTML(getBadge(profile))}</span>
        </div>

        <div class="card-body">
          <div class="card-name">
            ${escapeHTML(profileName)}
            ${profile.verified ? `<span class="verified-inline">✓</span>` : ``}
          </div>
          <div class="online">Online Now</div>
          <div class="location">📍 ${escapeHTML(getLocation(profile))}</div>
          <div class="phone">📞 ${escapeHTML(phone || "Hidden")}</div>
          <div class="bio">${escapeHTML(compact(getBio(profile)))}</div>

          <div class="engagement">
            <span class="ranking-score">🏆 ${rankingScore(profile).toLocaleString()} Quality Rank</span>
            ${profile.verified ? `<span class="trust-pill">✔ Verified</span>` : ``}
            <span>❤️ ${getLikes(profile)}</span>
            <span>👁 ${getViews(profile)}</span>
            <span>💬 ${Number(profile.whatsapp_clicks || 0)}</span>
            <span>☎ ${Number(profile.call_clicks || 0)}</span>
          </div>

          <div class="action-row">
            ${
              phone
              ? `
                <a
                  class="call-btn"
                  href="tel:${escapeHTML(phone)}"
                  onclick="return handleTrackedLink(event,'call_clicks',${jsString(profileId)},'tel:${escapeHTML(phone)}',false,${jsString(profileName)},${jsString(phone)})"
                >☎ CALL</a>

                <a
                  class="wa-btn"
                  href="${escapeHTML(waUrl)}"
                  target="_blank"
                  rel="noopener"
                  onclick="return handleTrackedLink(event,'whatsapp_clicks',${jsString(profileId)},${jsString(waUrl)},true,${jsString(profileName)},${jsString(phone)})"
                >
                  <img src="https://upload.wikimedia.org/wikipedia/commons/6/6b/WhatsApp.svg" alt="">
                  WHATSAPP
                </a>
              `
              : `<button class="disabled-contact" onclick="event.stopPropagation()">CONTACT HIDDEN</button>`
            }

            ${
              isLiveLocationActive(profile)
              ? `<a
                  class="live-location-btn"
                  href="${escapeHTML(liveUrl)}"
                  target="_blank"
                  rel="noopener"
                  onclick="return handleTrackedLink(event,'live_location_clicks',${jsString(profileId)},${jsString(liveUrl)},true,${jsString(profileName)},${jsString(liveUrl)})"
                >
                  📍 LIVE LOCATION
                </a>`
              : ``
            }

            <a
              class="view-profile-btn"
              href="${escapeHTML(profileUrl)}"
              onclick="return handleTrackedLink(event,'profile_opens',${jsString(profileId)},${jsString(profileUrl)},false,${jsString(profileName)},${jsString(profileUrl)})"
            >
              👤 VIEW PROFILE
            </a>
          </div>
        </div>
      </article>
    `;
  }).join("");

  if(CURRENT_PROFILE_RESULTS.length > visibleProfiles.length){
    profilesEl.innerHTML += `
      <div class="load-more-wrap">
        <button class="load-more-btn" onclick="loadMoreProfiles()">Load More Profiles</button>
      </div>
    `;
  }
}

function applyFilters(resetLimit = false){
  if(resetLimit) resetProfileLimit();
  let list = [...ALL_PROFILES];
  const q = searchInput.value.toLowerCase().trim();

  if(ACTIVE_FILTER !== "home"){
    list = list.filter(p=>{
      if(ACTIVE_FILTER === "vip") return getPlan(p).includes("vip");
      if(ACTIVE_FILTER === "online") return true;
      if(ACTIVE_FILTER === "whatsapp") return Boolean(p.phone || p.whatsapp);
      if(ACTIVE_FILTER === "live-location") return isLiveLocationActive(p);
      return profileSearchText(p).includes(ACTIVE_FILTER);
    });
  }

  if(q){
    list = list.filter(p=>profileSearchText(p).includes(q));
  }

  list = smartProfileRotation(list, 28);

  const signatureProfiles = list.filter(isSignatureProfile);
  const normalProfiles = list.filter(p => !isSignatureProfile(p));
  const mainProfiles = normalProfiles.length ? normalProfiles : list;

  renderSignatureProfiles(signatureProfiles);
  renderProfiles(mainProfiles, list);

  // Gallery and Shorts are heavier than cards. Render them after the grid,
  // and debounce them during typing/filter changes so mobile does not choke.
  scheduleHomeMediaRender(list, resetLimit ? 650 : 1100);
}

document.querySelectorAll(".filters button").forEach(button=>{
  button.addEventListener("click",()=>{
    document.querySelectorAll(".filters button").forEach(btn=>btn.classList.remove("active"));
    button.classList.add("active");
    ACTIVE_FILTER = button.dataset.filter || "home";
    applyFilters(true);
  });
});

let SEARCH_DEBOUNCE_TIMER = null;
searchInput.addEventListener("input",()=>{
  clearTimeout(SEARCH_DEBOUNCE_TIMER);
  SEARCH_DEBOUNCE_TIMER = setTimeout(()=>applyFilters(true),180);
});

async function askSweet(){
  const input = document.getElementById("sweetInput");
  const results = document.getElementById("sweetResults");
  const message = input.value.trim();

  if(!message){
    results.innerHTML = "Sweet needs a clue 💋";
    return;
  }

  results.innerHTML = "Sweet is searching... ✨";

  const q = message.toLowerCase();

  let local = ALL_PROFILES.filter(p=>{
    if(q.includes("vip")) return getPlan(p).includes("vip");
    if(q.includes("whatsapp")) return Boolean(p.phone || p.whatsapp);
    if(q.includes("online")) return true;
    if(q.includes("liked")) return getLikes(p) > 0;
    return profileSearchText(p).includes(q);
  }).slice(0,4);

  if(local.length){
    results.innerHTML = local.map(p=>`
      <div class="sweet-card" onclick="window.location.href='/reel.html'">
        <strong>${getName(p)}</strong><br>
        📍 ${getLocation(p)}<br>
        📞 ${safePhone(p.phone || p.whatsapp) || "Hidden"}<br>
        💎 ${getBadge(p)}
      </div>
    `).join("");
    return;
  }

  try{
    const response = await fetch("/.netlify/functions/sweet-chat",{
      method:"POST",
      headers:{"Content-Type":"application/json"},
      body:JSON.stringify({message})
    });

    const data = await response.json();
    results.innerHTML = data.reply || data.answer || "Sweet found something 💋";
  }catch(error){
    results.innerHTML = "No exact match yet 💔 Try VIP, Kilimani, Westlands, or Online.";
  }
}

async function fetchApprovedProfiles(){
  const limit = isMobilePhone() ? 80 : 260;

  async function restQuery(label, table, params){
    try{
      const query = new URLSearchParams(params || {});
      const url = `${SUPABASE_URL}/rest/v1/${table}?${query.toString()}`;

      const response = await fetch(url, {
        method: "GET",
        cache: "no-store",
        headers: {
          apikey: SUPABASE_KEY,
          Authorization: `Bearer ${SUPABASE_KEY}`,
          Accept: "application/json",
          "Cache-Control": "no-cache"
        }
      });

      if(!response.ok){
        const msg = await response.text().catch(()=>"");
        console.warn(`Profile REST fallback failed (${label}):`, response.status, msg);
        return null;
      }

      const data = await response.json();
      return Array.isArray(data) ? data : [];
    }catch(error){
      console.warn(`Profile REST fallback failed (${label}):`, error && (error.message || error.name) ? `${error.name || "Error"}: ${error.message || error}` : error);
      return null;
    }
  }

  async function supabaseQuery(label, builder){
    try{
      const { data, error } = await builder();
      if(error){
        console.warn(`Profile Supabase query failed (${label}):`, error.message || error);
        return null;
      }
      return Array.isArray(data) ? data : [];
    }catch(error){
      console.warn(`Profile Supabase query failed (${label}):`, error && (error.message || error.name) ? `${error.name || "Error"}: ${error.message || error}` : error);
      return null;
    }
  }

  // REST first: it avoids the AbortError loop some browsers/PWA caches trigger with supabase-js.
  let rows = await restQuery("profiles approved REST", "profiles", {
    select: "*",
    approved: "eq.true",
    order: "created_at.desc",
    limit: String(limit)
  });

  if(!rows){
    rows = await restQuery("active profiles view REST", "active_profiles_view", {
      select: "*",
      order: "created_at.desc",
      limit: String(limit)
    });
  }

  if(!rows){
    rows = await restQuery("profiles basic REST", "profiles", {
      select: "*",
      order: "created_at.desc",
      limit: String(limit)
    });
  }

  // Last fallback: supabase-js. This keeps compatibility if REST policies differ.
  if(!rows && window.sb){
    rows = await supabaseQuery("profiles approved JS", () =>
      sb.from("profiles")
        .select("*")
        .eq("approved", true)
        .order("created_at", { ascending:false })
        .limit(limit)
    );
  }

  if(!rows && window.sb){
    rows = await supabaseQuery("active profiles view JS", () =>
      sb.from("active_profiles_view")
        .select("*")
        .order("created_at", { ascending:false })
        .limit(limit)
    );
  }

  if(!rows && window.sb){
    rows = await supabaseQuery("profiles basic JS", () =>
      sb.from("profiles")
        .select("*")
        .order("created_at", { ascending:false })
        .limit(limit)
    );
  }

  if(!rows){
    throw new Error("Unable to load profiles. Check Supabase public SELECT policy for profiles.");
  }

  return rows
    .filter(p => p && p.id)
    .filter(p => p.approved !== false)
    .filter(p => p.is_expired !== true)
    .sort((a,b)=>{
      const pinned = Number(Boolean(b.pinned_top)) - Number(Boolean(a.pinned_top));
      if(pinned) return pinned;
      const boost = Number(b.boost_score || 0) - Number(a.boost_score || 0);
      if(boost) return boost;
      return new Date(b.created_at || b.updated_at || 0) - new Date(a.created_at || a.updated_at || 0);
    });
}
function renderLatestProfileSeoLinks(list){
  const latestBox = document.getElementById("latestProfilesLinks");
  if(!latestBox) return;

  const latest = [...(list || [])]
    .filter(p => p && p.id)
    .sort((a,b) => new Date(b.created_at || b.updated_at || 0) - new Date(a.created_at || a.updated_at || 0))
    .slice(0,8);

  if(!latest.length){
    latestBox.innerHTML = `<a class="latest-profile-link" href="/join.html">No latest profiles yet. Join Nairobi Sweets.</a>`;
    return;
  }

  latestBox.innerHTML = latest.map(profile => `
    <a class="latest-profile-link" href="${getProfileUrl(profile)}">
      <img src="${escapeHTML(getImage(profile))}" alt="${escapeHTML(getName(profile))}" loading="lazy" decoding="async" onerror="this.src='/assets/logo/logo-badge.png'">
      <div>
        <strong>${escapeHTML(getName(profile))}</strong>
        <span>📍 ${escapeHTML(getLocation(profile))} · ${escapeHTML(getBadge(profile).replace(/[✔🔥👑✨]/g,'').trim() || 'Featured')}</span>
      </div>
    </a>
  `).join("") + `
    <a class="latest-profile-link latest-view-all-link" href="/latest-profiles.html">
      <div>
        <strong>View All Latest Profiles →</strong>
        <span>Open the full latest profiles page</span>
      </div>
    </a>
  `;
}

function paintProfilesFromList(list){
  ALL_PROFILES = sortByMarketplaceRank(list || []);
  FIRST_PROFILE_PAINT_DONE = true;
  renderLatestProfileSeoLinks(ALL_PROFILES);
  applyFilters(true);
}

async function loadProfiles(){
  if(!profilesEl) return;
  profilesEl.innerHTML = profileSkeletons(isMobilePhone() ? 3 : 8);

  const cachedProfiles = readProfilesCache();

  if(cachedProfiles && cachedProfiles.length){
    paintProfilesFromList(cachedProfiles);

    // Quiet refresh keeps newly approved profiles appearing without making
    // mobile users wait on a blank homepage.
    fetchApprovedProfiles()
      .then(freshProfiles=>{
        writeProfilesCache(freshProfiles);
        paintProfilesFromList(freshProfiles);
      })
      .catch(error=>{
        console.warn("Quiet profile refresh failed:", error.message || error);
      });

    return;
  }

  try{
    const freshProfiles = await fetchApprovedProfiles();
    writeProfilesCache(freshProfiles);
    paintProfilesFromList(freshProfiles);
  }catch(error){
    console.error("Profile load failed:", error);
    const backupProfiles = readProfilesCache();
    if(backupProfiles && backupProfiles.length){
      paintProfilesFromList(backupProfiles);
      return;
    }
    profilesEl.innerHTML = `<div class="empty" style="color:#ff5b5b;">Supabase error: ${escapeHTML(error.message || error.name || "Profiles could not load")}. Refresh once after clearing site cache.</div>`;
  }
}


/* =========================
AGE GATE
========================= */
function showAgeGate(){
  const verified = localStorage.getItem("nairobi_sweets_age_verified");
  const verifiedAt = Number(localStorage.getItem("nairobi_sweets_age_verified_at") || 0);
  const oneDay = 24 * 60 * 60 * 1000;

  if(verified === "true" && Date.now() - verifiedAt < oneDay){
    return;
  }

  const gate = document.getElementById("ageGate");
  if(!gate) return;

  gate.classList.add("active");
  document.body.style.overflow = "hidden";
}

function enterSite(){
  const country = document.getElementById("countrySelect").value;
  const confirm = document.getElementById("ageConfirm").checked;

  if(!country){
    alert("Please select your country first.");
    return;
  }

  if(!confirm){
    alert("Please confirm that you are 18 years or older.");
    return;
  }

  localStorage.setItem("nairobi_sweets_country", country);
  localStorage.setItem("nairobi_sweets_age_verified", "true");
  localStorage.setItem("nairobi_sweets_age_verified_at", String(Date.now()));

  document.getElementById("ageGate").classList.remove("active");
  document.body.style.overflow = "";
}

function leaveSite(){
  window.location.href = "https://www.google.com";
}

document.addEventListener("DOMContentLoaded", showAgeGate);



/* =========================
ANDROID + IOS PWA HELPERS
========================= */
function isIOSDevice(){
  return /iphone|ipad|ipod/i.test(navigator.userAgent) || (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
}

function isStandalonePWA(){
  return window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true;
}

function updateInstallButtonForPlatform(){
  const installBtn = document.getElementById("installAppBtn");
  if(!installBtn) return;

  if(isStandalonePWA()){
    installBtn.style.display = "none";
    return;
  }

  if(isIOSDevice()){
    installBtn.style.display = "block";
    installBtn.textContent = "📲 Add to iPhone Home Screen";
  }
}

document.addEventListener("DOMContentLoaded", updateInstallButtonForPlatform);

/* =========================
PWA INSTALL BUTTON
========================= */
let deferredInstallPrompt = null;

window.addEventListener("beforeinstallprompt", (event) => {
  event.preventDefault();
  deferredInstallPrompt = event;

  const installBtn = document.getElementById("installAppBtn");
  if(installBtn){
    installBtn.style.display = "block";
  }
});

const installAppBtn = document.getElementById("installAppBtn");

if(installAppBtn){
  installAppBtn.addEventListener("click", async () => {
    if(!deferredInstallPrompt){
      alert(isIOSDevice() ? "On iPhone/iPad: tap Safari Share button, then tap Add to Home Screen." : "Use your browser menu and tap Install App or Add to Home Screen.");
      return;
    }

    deferredInstallPrompt.prompt();

    const choice = await deferredInstallPrompt.userChoice;
    console.log("Nairobi Sweets install choice:", choice.outcome);

    deferredInstallPrompt = null;
    installAppBtn.style.display = "none";
  });
}

window.addEventListener("appinstalled", () => {
  console.log("Nairobi Sweets installed");

  const installBtn = document.getElementById("installAppBtn");
  if(installBtn){
    installBtn.style.display = "none";
  }
});

/* =========================
PWA SERVICE WORKER
========================= */
if("serviceWorker" in navigator){
  window.addEventListener("load", () => {
    navigator.serviceWorker
      .register("/sw.js", { scope: "/" })
      .then(reg => { console.log("Nairobi Sweets PWA ready"); reg.update && reg.update(); })
      .catch(err => console.error("PWA error:", err));
  });
}


/* =========================
ADMIN CONTACT LOADER
========================= */
async function loadAdminContact(){
  try{
    const { data } = await sb
      .from("site_settings")
      .select("admin_name,admin_phone,admin_whatsapp,admin_email")
      .limit(1)
      .single();

    if(!data) return;

    const phone = data.admin_phone || "+254143616363";
    const whatsapp = data.admin_whatsapp || phone || "+254143616363";
    const email = data.admin_email || "nairobisweets05@gmail.com";

    const cleanWhatsapp = String(whatsapp).replace(/\D/g,"");

    const callBtn = document.getElementById("adminCallBtn");
    const whatsappBtn = document.getElementById("adminWhatsappBtn");
    const emailBtn = document.getElementById("adminEmailBtn");

    if(callBtn) callBtn.href = `tel:${phone}`;
    if(whatsappBtn) whatsappBtn.href = `https://wa.me/${cleanWhatsapp}`;
    if(emailBtn) emailBtn.href = `mailto:${email}`;

  }catch(error){
    console.log("Admin contact load failed:", error.message || error);
  }
}

loadAdminContact();
loadProfiles();
</script>



<script>
/* =========================================================
   NAIROBI SWEETS V3 PREMIUM PATCH JS
   Install modal + safe lazy media + smooth mobile helpers
   ========================================================= */
(function(){
  const d = document;
  const w = window;

  function isIOS(){
    return /iphone|ipad|ipod/i.test(navigator.userAgent) || (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
  }
  function isStandalone(){
    return w.matchMedia("(display-mode: standalone)").matches || w.navigator.standalone === true;
  }

  function ensureInstallModal(){
    let modal = d.getElementById("nsInstallModal");
    if(modal) return modal;
    modal = d.createElement("div");
    modal.id = "nsInstallModal";
    modal.className = "ns-install-modal";
    modal.innerHTML = `
      <div class="ns-install-card" role="dialog" aria-modal="true" aria-labelledby="nsInstallTitle">
        <h3 id="nsInstallTitle">📲 Install Nairobi Sweets</h3>
        <p>Get faster loading, full-screen browsing and one-tap access from your home screen.</p>
        <div class="ns-install-steps" id="nsInstallSteps">Tap Install App to continue.</div>
        <div class="ns-install-actions">
          <button type="button" class="ns-install-secondary" id="nsInstallClose">Got It</button>
          <button type="button" class="ns-install-primary" id="nsInstallGo">Install App</button>
        </div>
      </div>`;
    d.body.appendChild(modal);
    modal.querySelector("#nsInstallClose").addEventListener("click",()=>modal.classList.remove("show"));
    modal.addEventListener("click", e => { if(e.target === modal) modal.classList.remove("show"); });
    return modal;
  }

  function showInstallHelp(){
    const modal = ensureInstallModal();
    const steps = modal.querySelector("#nsInstallSteps");
    const go = modal.querySelector("#nsInstallGo");
    if(isIOS()){
      steps.innerHTML = "1. Open in Safari<br>2. Tap the Share button<br>3. Choose <b>Add to Home Screen</b><br>4. Tap Add";
      go.textContent = "Got It";
      go.onclick = () => modal.classList.remove("show");
    }else if(w.__nsDeferredInstallPrompt){
      steps.innerHTML = "Tap the button below and confirm installation in your browser.";
      go.textContent = "Install App";
      go.onclick = async () => {
        const promptEvent = w.__nsDeferredInstallPrompt;
        if(!promptEvent) return;
        promptEvent.prompt();
        await promptEvent.userChoice.catch(()=>null);
        w.__nsDeferredInstallPrompt = null;
        modal.classList.remove("show");
        const installBtn = d.getElementById("installAppBtn");
        if(installBtn) installBtn.style.display = "none";
      };
    }else{
      steps.innerHTML = "Use your browser menu and choose <b>Install app</b> or <b>Add to Home screen</b>.";
      go.textContent = "Got It";
      go.onclick = () => modal.classList.remove("show");
    }
    modal.classList.add("show");
  }

  w.addEventListener("beforeinstallprompt", event => {
    event.preventDefault();
    w.__nsDeferredInstallPrompt = event;
    const installBtn = d.getElementById("installAppBtn");
    if(installBtn) installBtn.style.display = "block";
  });

  d.addEventListener("DOMContentLoaded", () => {
    const installBtn = d.getElementById("installAppBtn");
    if(installBtn){
      if(!isStandalone() && isIOS()){
        installBtn.style.display = "block";
        installBtn.textContent = "📲 Add to iPhone Home Screen";
      }
      installBtn.addEventListener("click", e => {
        e.preventDefault();
        e.stopImmediatePropagation();
        showInstallHelp();
      }, true);
    }

    d.querySelectorAll("img").forEach((img, index) => {
      if(index > 1 && !img.hasAttribute("loading")) img.loading = "lazy";
      if(!img.hasAttribute("decoding")) img.decoding = "async";
      img.addEventListener("error", () => {
        if(!img.dataset.nsFallback){
          img.dataset.nsFallback = "1";
          img.src = "/assets/logo/logo-badge.png";
        }
      }, { once:true });
    });

    d.querySelectorAll("video").forEach(video => {
      video.preload = video.closest(".short-card,.signature-card") ? "metadata" : "none";
      video.playsInline = true;
      video.setAttribute("playsinline","");
      video.addEventListener("waiting", () => video.classList.add("ns-skeleton"));
      video.addEventListener("canplay", () => video.classList.remove("ns-skeleton"));
      video.addEventListener("loadeddata", () => video.classList.remove("ns-skeleton"));
    });

    const nav = d.querySelector(".bottom-nav");
    if(nav){
      const current = location.pathname.replace(/\/$/,"") || "/";
      nav.querySelectorAll("a").forEach(a => {
        const href = new URL(a.getAttribute("href"), location.origin).pathname.replace(/\/$/,"") || "/";
        if(href === current) a.classList.add("active");
      });
    }
  });
})();
</script>

<script src="/assets/js/v5-phase3.js" defer></script>
</body>
</html>
