<?php
require_once '../config/database.php';
require_once '../includes/functions.php';
$pageTitle = 'Digital Store';
include 'side.php';
$conn = getConnection();

// ── Admin color injection (matches side.php exactly) ──────────────────────
// $adminPrimary / $adminSecondary / $pRgb / $sRgb already set in side.php
// Re-use them directly here — no redeclaration needed

$uCountry = $userData['country'] ?? 'Kenya';
$cStmt = $conn->prepare("SELECT currency_symbol,exchange_rate FROM countries WHERE name=? AND status='active'");
$cStmt->bind_param("s",$uCountry); $cStmt->execute();
$cRow  = $cStmt->get_result()->fetch_assoc();
$cSym  = $cRow['currency_symbol'] ?? 'KSh';
$cRate = floatval($cRow['exchange_rate'] ?? 1);
$usdRate = ($cRate > 0) ? $cRate : 1;

$userPhone = $userData['phone'] ?? '';
$cat    = isset($_GET['cat'])  ? $conn->real_escape_string(trim($_GET['cat']))  : 'all';
$search = isset($_GET['s'])    ? $conn->real_escape_string(trim($_GET['s']))    : '';
$sort   = isset($_GET['sort']) ? $conn->real_escape_string(trim($_GET['sort'])) : 'newest';
$page   = isset($_GET['page']) ? max(1,intval($_GET['page'])) : 1;
$pp = 12; $off = ($page-1)*$pp;

$validCats = ['ebook','source_code','template','software','course','other'];
$where = "p.status='active'";
if ($cat !== 'all' && in_array($cat,$validCats)) $where .= " AND p.category='$cat'";
if ($search) $where .= " AND (p.title LIKE '%$search%' OR p.description LIKE '%$search%')";
$orderBy = match($sort) {
    'price_asc'  => 'p.price ASC',
    'price_desc' => 'p.price DESC',
    'popular'    => 'p.sales_count DESC',
    default      => 'p.created_at DESC'
};

$pQuery = $conn->query("SELECT p.*,(SELECT id FROM product_purchases WHERE user_id=$userId AND product_id=p.id AND status='completed' LIMIT 1) AS purchased_id FROM digital_products p WHERE $where ORDER BY p.featured DESC,$orderBy LIMIT $off,$pp");
$products = [];
if ($pQuery) while ($r = $pQuery->fetch_assoc()) $products[] = $r;

$totalCount = intval($conn->query("SELECT COUNT(*) AS c FROM digital_products p WHERE $where")->fetch_assoc()['c'] ?? 0);
$totalPages = max(1, ceil($totalCount/$pp));

$cats = ['all'=>0,'ebook'=>0,'source_code'=>0,'template'=>0,'software'=>0,'course'=>0,'other'=>0];
$cq = $conn->query("SELECT category,COUNT(*) AS c FROM digital_products WHERE status='active' GROUP BY category");
if ($cq) while ($r = $cq->fetch_assoc()) if (isset($cats[$r['category']])) $cats[$r['category']] = intval($r['c']);
$cats['all'] = array_sum(array_slice($cats,1));

$myPurchases  = intval($conn->query("SELECT COUNT(*) AS c FROM product_purchases WHERE user_id=$userId AND status='completed'")->fetch_assoc()['c'] ?? 0);
$totalProducts= intval($conn->query("SELECT COUNT(*) AS c FROM digital_products WHERE status='active'")->fetch_assoc()['c'] ?? 0);
$totalSellers = intval($conn->query("SELECT COUNT(DISTINCT created_by) AS c FROM digital_products WHERE status='active'")->fetch_assoc()['c'] ?? 0);

$stkNotif = $_SESSION['store_notif'] ?? null; unset($_SESSION['store_notif']);

$catMeta = [
    'ebook'       => ['label'=>'eBooks',      'icon'=>'fa-book-open',      'color'=>'var(--P)'],
    'source_code' => ['label'=>'Source Code', 'icon'=>'fa-code',           'color'=>'#0ea5e9'],
    'template'    => ['label'=>'Templates',   'icon'=>'fa-layer-group',    'color'=>'var(--WN)'],
    'software'    => ['label'=>'Software',    'icon'=>'fa-cube',           'color'=>'var(--OK)'],
    'course'      => ['label'=>'Courses',     'icon'=>'fa-graduation-cap', 'color'=>'#ec4899'],
    'other'       => ['label'=>'Other',       'icon'=>'fa-box-open',       'color'=>'#06b6d4'],
];

// Phone normalisation
$savedNorm = ''; $savedValid = false; $savedDisplay = '';
if ($userPhone) {
    $d = preg_replace('/\D/','',$userPhone);
    if      (preg_match('/^0(7|1)\d{8}$/',   $d)) $savedNorm = '254'.substr($d,1);
    elseif  (preg_match('/^(7|1)\d{8}$/',    $d)) $savedNorm = '254'.$d;
    elseif  (preg_match('/^254(7|1)\d{8}$/', $d)) $savedNorm = $d;
}
$savedValid = (bool)preg_match('/^254(7|1)\d{8}$/', $savedNorm);
if ($savedValid) {
    $loc = '0'.substr($savedNorm,3);
    $savedDisplay = substr($loc,0,4).' '.substr($loc,4,3).' '.substr($loc,7,3);
}
?>
<style>
/* ═══════════════════════════════════════════════════════════════
   EARNOVIX — Digital Store
   Uses CSS vars from side.php — no redeclaration of :root tokens
═══════════════════════════════════════════════════════════════ */

.pg { padding:0; overflow-x:hidden; width:100%; max-width:100%; }

/* ── Flash notification (matches dashboard pattern) ── */
.sfl {
    display:flex; align-items:center; gap:8px;
    padding:9px 13px; border-radius:10px; font-size:12px; font-weight:600;
    margin:10px 13px 0; border-left:3px solid;
    animation:fadeUp .3s ease both;
}
.sfl.success { background:var(--OK-bg); border-color:var(--OK); color:var(--OK); }
.sfl.error   { background:var(--DN-bg); border-color:var(--DN); color:var(--DN); }
.sfl.info    { background:var(--P-bg);  border-color:var(--P);  color:var(--P);  }

/* ── HERO ── */
.shero {
    position:relative; overflow:hidden;
    padding:22px 16px 26px;
    background:var(--bg2);
    border-bottom:1px solid var(--bdr);
}
[data-theme="dark"] .shero {
    background: linear-gradient(150deg, #07060f 0%, #0e0c1a 45%, #141228 100%);
}
.shero-mesh {
    position:absolute; inset:0; pointer-events:none;
    background:
        radial-gradient(ellipse 55% 55% at 15% 25%, rgba(var(--Pr),.18) 0%, transparent 65%),
        radial-gradient(ellipse 45% 55% at 85% 75%, rgba(var(--Pr),.10) 0%, transparent 65%);
}
[data-theme="light"] .shero-mesh { opacity:.6; }
.shero-glow {
    position:absolute; bottom:0; left:0; right:0; height:1px;
    background:linear-gradient(90deg, transparent, rgba(var(--Pr),.5) 50%, transparent);
}
.shero-inner { position:relative; z-index:2; }
.shero-top {
    display:flex; align-items:flex-start; justify-content:space-between;
    gap:12px; margin-bottom:16px;
}
.shero-eyebrow {
    font-size:9px; font-weight:800; letter-spacing:2px; text-transform:uppercase;
    color:var(--P); opacity:.7; display:flex; align-items:center; gap:5px; margin-bottom:6px;
}
.shero-title {
    font-size:21px; font-weight:900; letter-spacing:-.5px; line-height:1.15;
    color:var(--txt);
}
[data-theme="dark"] .shero-title { color:#fff; }
.shero-sub { font-size:11px; color:var(--txt2); margin-top:5px; line-height:1.55; }
.shero-right {
    display:flex; flex-direction:column; gap:7px; align-items:flex-end; flex-shrink:0;
}

/* Hero button — matches .hico hover style */
.shero-btn {
    display:inline-flex; align-items:center; gap:6px;
    background:var(--P-bg); border:1px solid rgba(var(--Pr),.25);
    color:var(--P); padding:8px 13px; border-radius:10px;
    font-size:11.5px; font-weight:700; text-decoration:none;
    white-space:nowrap; transition:.18s;
}
.shero-btn:hover { background:rgba(var(--Pr),.18); transform:translateY(-1px); }
[data-theme="dark"] .shero-btn {
    background:rgba(255,255,255,.07); border-color:rgba(255,255,255,.15); color:#fff;
}
[data-theme="dark"] .shero-btn:hover { background:rgba(255,255,255,.14); }

.shero-badge {
    font-size:10px; color:var(--txt2);
    background:var(--bg3); padding:3px 10px;
    border-radius:20px; border:1px solid var(--bdr);
}

/* Hero stats — matches .nstat from dashboard */
.shero-stats {
    display:grid; grid-template-columns:repeat(4,1fr); gap:8px;
}
.shs {
    background:var(--bg3); border:1px solid var(--bdr);
    border-radius:12px; padding:10px 8px; text-align:center;
    transition:background .2s,border-color .2s;
}
.shs:hover { border-color:rgba(var(--Pr),.25); }
.shs-n { font-size:18px; font-weight:900; color:var(--txt); letter-spacing:-.5px; line-height:1; }
.shs-l { font-size:9px; color:var(--txt2); text-transform:uppercase; letter-spacing:.7px; font-weight:600; margin-top:3px; }

/* Currency toggle — identical to dashboard .cur-row */
.cur-toggle {
    display:flex; align-items:center;
    background:var(--bg3); border:1px solid var(--bdr);
    border-radius:20px; padding:3px; gap:2px;
}
.cur-opt {
    padding:3px 11px; border-radius:16px; font-size:10.5px; font-weight:700;
    cursor:pointer; transition:all .22s; color:var(--txt2);
    border:none; background:none; font-family:inherit;
}
.cur-opt.active { background:var(--P); color:#fff; box-shadow:0 2px 10px rgba(var(--Pr),.4); }
[data-theme="light"] .cur-opt.active { color:#fff; }

/* ── STORE BODY ── */
.store-body { padding:13px 13px 0; }
@media(max-width:480px) { .store-body { padding:10px 10px 0; } }

/* Search bar */
.sbar { display:flex; gap:7px; margin-bottom:11px; flex-wrap:wrap; }
.sbar form { display:contents; }
.sinp-wrap { flex:1; position:relative; min-width:130px; }
.sinp-ico { position:absolute; left:11px; top:50%; transform:translateY(-50%); color:var(--txt3); font-size:12px; pointer-events:none; }
.sinp {
    width:100%; height:40px; padding:0 11px 0 33px;
    background:var(--card); border:1px solid var(--bdr);
    border-radius:11px; color:var(--txt); font-size:13px;
    outline:none; font-family:inherit; transition:.15s;
}
.sinp:focus { border-color:rgba(var(--Pr),.5); box-shadow:0 0 0 3px rgba(var(--Pr),.08); background:var(--P-bg); }
.sinp::placeholder { color:var(--txt3); }

.ssbtn {
    height:40px; width:40px; flex-shrink:0;
    background:var(--P); color:#fff; border:none; border-radius:11px;
    cursor:pointer; display:flex; align-items:center; justify-content:center;
    font-size:13px; transition:.15s;
    box-shadow:0 4px 12px rgba(var(--Pr),.3);
}
.ssbtn:hover { filter:brightness(1.1); transform:translateY(-1px); }
[data-theme="light"] .ssbtn { color:#fff; }

.ssort {
    height:40px; padding:0 11px; flex-shrink:0;
    background:var(--card); border:1px solid var(--bdr);
    border-radius:11px; color:var(--txt); font-size:12px;
    outline:none; cursor:pointer; font-family:inherit;
    transition:border-color .15s;
}
.ssort:focus { border-color:rgba(var(--Pr),.4); }
[data-theme="light"] .ssort option { background:#fff; color:#111; }
[data-theme="dark"]  .ssort option { background:#141228; color:#fff; }

/* Category tabs — matches .chip from dashboard */
.ctabs { display:flex; gap:6px; margin-bottom:11px; overflow-x:auto; padding-bottom:3px; scrollbar-width:none; }
.ctabs::-webkit-scrollbar { display:none; }
.ctab {
    display:flex; align-items:center; gap:5px;
    padding:6px 13px; border-radius:20px;
    font-size:11px; font-weight:700; text-decoration:none;
    border:1px solid var(--bdr); color:var(--txt2);
    background:var(--card); white-space:nowrap; flex-shrink:0;
    transition:all .18s;
}
.ctab:hover { border-color:rgba(var(--Pr),.35); color:var(--P); transform:translateY(-1px); }
.ctab.on { background:var(--P); color:#fff; border-color:transparent; box-shadow:0 4px 14px rgba(var(--Pr),.35); }
[data-theme="light"] .ctab.on { color:#fff; }
.ctab-cnt {
    font-size:9px; padding:1px 5px; border-radius:7px; font-weight:800;
}
.ctab.on  .ctab-cnt { background:rgba(255,255,255,.25); color:#fff; }
.ctab:not(.on) .ctab-cnt { background:var(--bg3); color:var(--txt3); }

/* Results bar */
.rbar { display:flex; align-items:center; justify-content:space-between; margin-bottom:9px; gap:6px; flex-wrap:wrap; }
.rbar-count { font-size:11.5px; color:var(--txt2); font-weight:600; }
.rbar-count b { color:var(--txt); }
.rbar-clear {
    font-size:11px; color:var(--txt3); text-decoration:none;
    font-weight:700; display:flex; align-items:center; gap:4px; transition:.12s;
}
.rbar-clear:hover { color:var(--P); }

/* ── PRODUCT GRID ── */
.pgrid { display:grid; grid-template-columns:repeat(2,1fr); gap:10px; margin-bottom:12px; }
@media(min-width:560px) { .pgrid { grid-template-columns:repeat(3,1fr); } }
@media(min-width:900px) { .pgrid { grid-template-columns:repeat(4,1fr); } }

/* Product card — matches .hstat / .wcard structure */
.pcard {
    background:var(--card); border:1px solid var(--bdr);
    border-radius:14px; overflow:hidden; cursor:pointer;
    transition:transform .22s cubic-bezier(.34,1.4,.64,1), box-shadow .22s, border-color .22s;
}
.pcard:hover {
    transform:translateY(-5px) scale(1.01);
    box-shadow:var(--shadow); border-color:rgba(var(--Pr),.3);
}
.pcard.owned { border-color:rgba(34,197,94,.35); }
.pcard.owned:hover { box-shadow:0 12px 28px rgba(34,197,94,.12); }

.pcover { height:115px; position:relative; overflow:hidden; }
.pcover-img { width:100%; height:100%; object-fit:cover; transition:transform .4s; }
.pcard:hover .pcover-img { transform:scale(1.08); }
.pcover-grad {
    width:100%; height:100%;
    display:flex; align-items:center; justify-content:center;
    font-size:36px; color:rgba(255,255,255,.85);
}
.pcover-shadow {
    position:absolute; inset:0;
    background:linear-gradient(180deg,transparent 40%,rgba(0,0,0,.4));
    opacity:0; transition:opacity .25s;
}
.pcard:hover .pcover-shadow { opacity:1; }

/* Badges on cover */
.pcover-feat {
    position:absolute; top:8px; left:8px;
    background:var(--WN); color:#fff;
    font-size:9px; font-weight:800; padding:3px 8px; border-radius:8px;
    display:flex; align-items:center; gap:3px;
}
.pcover-own {
    position:absolute; top:8px; right:8px;
    background:rgba(34,197,94,.85); backdrop-filter:blur(4px); color:#fff;
    font-size:9px; font-weight:800; padding:3px 8px; border-radius:8px;
    display:flex; align-items:center; gap:3px;
}

/* Card body — matches .wcard / .hstat body */
.pcbody { padding:11px 10px; }
.pcat-pill {
    display:inline-flex; align-items:center; gap:3px;
    font-size:9px; font-weight:800; padding:2px 8px;
    border-radius:20px; color:#fff; margin-bottom:5px;
}
.ptitle {
    font-size:12.5px; font-weight:700; color:var(--txt); line-height:1.35;
    margin-bottom:7px; display:-webkit-box; -webkit-line-clamp:2;
    -webkit-box-orient:vertical; overflow:hidden; min-height:34px;
}
.pprice-row { display:flex; align-items:flex-end; justify-content:space-between; gap:4px; margin-bottom:7px; }
.pprice { font-size:15px; font-weight:900; color:var(--txt); letter-spacing:-.3px; }
.pprice-orig { font-size:10.5px; color:var(--txt3); text-decoration:line-through; margin-top:1px; }

/* Matches .badge-up / .badge-dn from dashboard */
.pdisc-badge {
    font-size:9px; font-weight:800; padding:2px 7px; border-radius:6px;
    background:var(--WN-bg); color:var(--WN); white-space:nowrap;
}
.pcomm-badge {
    font-size:9.5px; font-weight:700; padding:2px 7px; border-radius:6px;
    background:var(--OK-bg); color:var(--OK); white-space:nowrap;
}

.pmeta-row { display:flex; gap:8px; margin-bottom:9px; }
.pm { display:flex; align-items:center; gap:3px; font-size:10px; color:var(--txt3); }
.pm i { font-size:8.5px; }

/* Buy button — matches .copy-btn from dashboard */
.pbuy-btn {
    width:100%; height:34px; border:none; border-radius:9px;
    font-size:11.5px; font-weight:700; cursor:pointer;
    display:flex; align-items:center; justify-content:center; gap:5px;
    font-family:inherit; transition:.18s;
}
.pbuy-btn.buy {
    background:var(--P); color:#fff;
    box-shadow:0 3px 12px rgba(var(--Pr),.3);
}
.pbuy-btn.buy:hover { filter:brightness(1.1); transform:translateY(-1px); }
[data-theme="light"] .pbuy-btn.buy { color:#fff; }
.pbuy-btn.owned-btn { background:var(--OK-bg); color:var(--OK); }
.pbuy-btn.owned-btn:hover { background:rgba(34,197,94,.2); }

/* Pagination — matches .pagbtn */
.pag { display:flex; justify-content:center; gap:5px; margin-bottom:12px; }
.pagbtn {
    width:33px; height:33px; border-radius:9px;
    display:flex; align-items:center; justify-content:center;
    background:var(--card); border:1px solid var(--bdr);
    color:var(--txt2); font-size:12px; text-decoration:none;
    transition:.12s; font-weight:600;
}
.pagbtn.on { background:var(--P); color:#fff; border-color:transparent; box-shadow:0 3px 10px rgba(var(--Pr),.35); }
[data-theme="light"] .pagbtn.on { color:#fff; }
.pagbtn:hover:not(.on) { border-color:rgba(var(--Pr),.3); color:var(--P); }

/* Empty state */
.empty {
    text-align:center; padding:36px 16px;
    background:var(--card); border:1px solid var(--bdr); border-radius:14px;
}
.empty-ico { font-size:36px; color:var(--txt3); margin-bottom:9px; }
.empty-t { font-size:14px; font-weight:700; color:var(--txt); margin-bottom:3px; }
.empty-s { font-size:12px; color:var(--txt2); }

/* ── MODAL — bottom sheet / centered ── */
.mov {
    position:fixed; inset:0;
    background:rgba(0,0,0,.6); backdrop-filter:blur(8px);
    z-index:2000; display:none;
    align-items:flex-end; justify-content:center;
}
.mov.open { display:flex; }
@media(min-width:500px) { .mov { align-items:center; padding:16px; } }

.mbox {
    width:100%; max-width:430px;
    background:var(--card); border:1px solid var(--bdr);
    border-radius:20px 20px 0 0; overflow:hidden; overflow-y:auto;
    max-height:96vh;
    box-shadow:0 -16px 60px rgba(0,0,0,.35);
    animation:slideUp .32s cubic-bezier(.32,1.25,.6,1);
    transition:background .25s, border-color .25s;
}
[data-theme="dark"] .mbox { border-color:rgba(var(--Pr),.14); }
@media(min-width:500px) {
    .mbox { border-radius:18px; max-height:90vh; animation:popIn .28s cubic-bezier(.32,1.25,.6,1); }
}
@keyframes slideUp { from{transform:translateY(60px);opacity:0} to{transform:translateY(0);opacity:1} }
@keyframes popIn   { from{transform:scale(.88);opacity:0} to{transform:scale(1);opacity:1} }

.mhandle {
    width:38px; height:4px; background:var(--bdr);
    border-radius:3px; margin:10px auto 0;
}
@media(min-width:500px) { .mhandle { display:none; } }

/* Modal cover */
.mcov { width:100%; height:110px; position:relative; overflow:hidden; flex-shrink:0; }
.mcov-img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.mcov-grad { width:100%; height:100%; display:flex; align-items:center; justify-content:center; font-size:40px; color:rgba(255,255,255,.9); }
.mcov-overlay { position:absolute; inset:0; background:linear-gradient(180deg,transparent 30%,rgba(0,0,0,.5)); }
.mcov-close {
    position:absolute; top:10px; right:10px;
    width:30px; height:30px; border-radius:50%;
    background:rgba(0,0,0,.4); backdrop-filter:blur(4px);
    border:none; color:#fff; cursor:pointer;
    display:flex; align-items:center; justify-content:center;
    font-size:12px; z-index:2; transition:.15s;
}
.mcov-close:hover { background:rgba(0,0,0,.65); }
.mcov-cat {
    position:absolute; bottom:9px; left:13px; z-index:2;
    display:inline-flex; align-items:center; gap:4px;
    font-size:9px; font-weight:800; color:#fff;
    background:rgba(0,0,0,.35); backdrop-filter:blur(4px);
    padding:3px 9px; border-radius:20px; text-transform:uppercase; letter-spacing:.4px;
}

/* Modal body */
.mbdy { padding:15px 16px 20px; }
.mtitle { font-size:16px; font-weight:800; color:var(--txt); line-height:1.3; margin-bottom:12px; }

/* Price row — matches .hstat structure */
.mpricerow {
    display:flex; align-items:center; justify-content:space-between;
    background:var(--bg3); border:1px solid var(--bdr);
    border-radius:12px; padding:11px 14px; margin-bottom:12px; gap:8px;
    transition:background .25s;
}
.mpricerow-l { display:flex; flex-direction:column; }
.mplbl { font-size:9px; font-weight:800; color:var(--txt2); text-transform:uppercase; letter-spacing:.5px; margin-bottom:2px; }
.mpval { font-size:22px; font-weight:900; color:var(--txt); letter-spacing:-.5px; }
.mporig { font-size:11px; color:var(--txt3); text-decoration:line-through; }
.mcomm-pill {
    display:flex; align-items:center; gap:4px;
    font-size:10.5px; font-weight:700;
    color:var(--OK); background:var(--OK-bg);
    padding:6px 12px; border-radius:20px; flex-shrink:0;
}

/* Phone input section */
.mpesa-phone-wrap { margin-bottom:12px; }
.mpesa-phone-label { display:flex; align-items:center; margin-bottom:8px; }
.mpesa-phone-label-txt {
    font-size:10px; font-weight:800; color:var(--txt2);
    text-transform:uppercase; letter-spacing:.6px;
    display:flex; align-items:center; gap:5px;
}
.mpesa-phone-label-txt i { color:var(--P); font-size:12px; }

/* Saved phone chip */
.ph-saved {
    display:flex; align-items:center; gap:10px;
    background:var(--OK-bg); border:1px solid rgba(34,197,94,.3);
    border-radius:12px; padding:11px 13px;
}
.ph-saved-icon {
    width:36px; height:36px; border-radius:10px; flex-shrink:0;
    background:var(--OK); display:flex; align-items:center; justify-content:center;
    box-shadow:0 3px 10px rgba(34,197,94,.3);
}
.ph-saved-icon i { color:#fff; font-size:16px; }
.ph-saved-body { flex:1; min-width:0; }
.ph-saved-top  { font-size:9.5px; font-weight:700; color:var(--OK); text-transform:uppercase; letter-spacing:.4px; margin-bottom:2px; }
.ph-saved-num  { font-size:17px; font-weight:900; color:var(--txt); letter-spacing:.5px; line-height:1; }
.ph-saved-sub  { font-size:10.5px; color:var(--txt2); margin-top:2px; }

/* Change button — matches .hico */
.ph-change-btn {
    flex-shrink:0; display:inline-flex; align-items:center; gap:5px;
    padding:7px 12px; border-radius:9px; cursor:pointer;
    font-size:11.5px; font-weight:700;
    border:1px solid rgba(var(--Pr),.25); color:var(--P);
    background:var(--P-bg); transition:.15s; font-family:inherit;
}
.ph-change-btn:hover { background:rgba(var(--Pr),.18); }

/* Phone input box */
.ph-input-box {
    background:var(--bg3); border:1px solid var(--bdr);
    border-radius:12px; overflow:hidden; transition:.2s;
}
.ph-input-box:focus-within { border-color:rgba(var(--Pr),.5); box-shadow:0 0 0 3px rgba(var(--Pr),.08); }
.ph-input-box.ok  { border-color:rgba(34,197,94,.5); box-shadow:0 0 0 3px rgba(34,197,94,.07); }
.ph-input-box.err { border-color:rgba(239,68,68,.45); box-shadow:0 0 0 3px rgba(239,68,68,.06); }

.ph-input-row { display:flex; align-items:center; height:50px; }
.ph-prefix {
    display:flex; align-items:center; gap:6px;
    padding:0 12px; height:100%; flex-shrink:0;
    border-right:1px solid var(--bdr); background:var(--card);
}
.ph-flag { font-size:18px; line-height:1; }
.ph-code { font-size:13px; font-weight:800; color:var(--txt2); }
.ph-inp {
    flex:1; height:100%; border:none; background:transparent;
    color:var(--txt); font-size:17px; font-weight:700;
    outline:none; padding:0 12px; min-width:0; letter-spacing:.5px;
}
.ph-inp::placeholder { color:var(--txt3); font-weight:400; font-size:14px; letter-spacing:0; }
.ph-status-ico { padding:0 13px; font-size:18px; flex-shrink:0; transition:opacity .2s; opacity:0; }
.ph-input-box.ok  .ph-status-ico,
.ph-input-box.err .ph-status-ico { opacity:1; }

.ph-status-bar {
    display:flex; align-items:center; gap:8px;
    padding:8px 13px; font-size:11.5px; font-weight:600;
    border-top:1px solid var(--bdr); transition:.2s;
    color:var(--txt2);
}
.ph-input-box.ok  .ph-status-bar { background:var(--OK-bg); border-color:rgba(34,197,94,.18); color:var(--OK); }
.ph-input-box.err .ph-status-bar { background:var(--DN-bg); border-color:rgba(239,68,68,.15); color:var(--DN); }

.ph-use-saved-link {
    display:none; align-items:center; gap:5px;
    padding:8px 13px; font-size:11.5px; font-weight:700;
    color:var(--P); cursor:pointer; border-top:1px solid var(--bdr);
    background:var(--P-bg); transition:.15s;
}
.ph-use-saved-link:hover { background:rgba(var(--Pr),.18); }
.ph-use-saved-link.show { display:flex; }

/* Info strip — matches .notif-bar from dashboard */
.mpesa-info {
    display:flex; align-items:center; gap:8px;
    background:var(--OK-bg); border:1px solid rgba(34,197,94,.2);
    border-left:3px solid var(--OK);
    border-radius:0 9px 9px 0; padding:9px 12px; margin-bottom:12px;
    font-size:11.5px; color:var(--txt2); font-weight:600; line-height:1.5;
}
.mpesa-info i { color:var(--OK); font-size:13px; flex-shrink:0; }

/* Preview list */
.mpreview { margin-bottom:12px; }
.mpreview-t {
    font-size:9px; font-weight:800; color:var(--txt2);
    text-transform:uppercase; letter-spacing:1px; margin-bottom:7px;
    display:flex; align-items:center; gap:5px;
}
.mpreview-item {
    display:flex; align-items:flex-start; gap:7px;
    font-size:11.5px; color:var(--txt2); padding:3px 0; line-height:1.45;
}
.mpreview-item i { color:var(--OK); margin-top:2px; flex-shrink:0; font-size:10px; }

/* Pay button */
.mpay-btn {
    width:100%; height:48px;
    background:var(--OK); color:#fff; border:none; border-radius:12px;
    font-size:14px; font-weight:800; cursor:pointer; font-family:inherit;
    display:flex; align-items:center; justify-content:center; gap:7px;
    transition:.18s; box-shadow:0 5px 18px rgba(34,197,94,.35);
}
.mpay-btn:hover:not(:disabled) { filter:brightness(1.08); transform:translateY(-1px); box-shadow:0 8px 24px rgba(34,197,94,.45); }
.mpay-btn:disabled {
    background:var(--bg3); color:var(--txt3);
    box-shadow:none; cursor:not-allowed; transform:none;
}

/* ── TOAST (matches dashboard .db-toast) ── */
.db-toast {
    position:fixed; top:-80px; left:50%; transform:translateX(-50%);
    min-width:260px; max-width:calc(100vw - 32px);
    background:var(--card2); border:1px solid rgba(var(--Pr),.3);
    border-left:3px solid var(--P); border-radius:10px;
    padding:10px 36px 10px 12px; z-index:9999;
    display:flex; align-items:center; gap:9px;
    transition:top .4s cubic-bezier(.34,1.56,.64,1);
    box-shadow:0 8px 32px rgba(0,0,0,.3);
}
.db-toast.show { top:calc(var(--hh) + 10px); }
.t-dot {
    width:20px; height:20px; border-radius:50%; background:var(--P);
    display:flex; align-items:center; justify-content:center;
    font-size:10px; font-weight:800; color:#fff; flex-shrink:0;
}
[data-theme="light"] .t-dot { color:#fff; }
.t-txt { font-size:12px; font-weight:600; color:var(--txt); flex:1; }
.t-cls { position:absolute; right:9px; top:50%; transform:translateY(-50%); background:none; border:none; font-size:17px; color:var(--txt3); cursor:pointer; }

/* ── Animations (matches dashboard) ── */
@keyframes fadeUp { from{opacity:0;transform:translateY(14px)} to{opacity:1;transform:translateY(0)} }
.pcard:nth-child(1)   { animation:fadeUp .3s ease .04s both }
.pcard:nth-child(2)   { animation:fadeUp .3s ease .08s both }
.pcard:nth-child(3)   { animation:fadeUp .3s ease .12s both }
.pcard:nth-child(4)   { animation:fadeUp .3s ease .16s both }
.pcard:nth-child(5)   { animation:fadeUp .3s ease .20s both }
.pcard:nth-child(6)   { animation:fadeUp .3s ease .24s both }
.pcard:nth-child(7)   { animation:fadeUp .3s ease .28s both }
.pcard:nth-child(8)   { animation:fadeUp .3s ease .32s both }
.pcard:nth-child(n+9) { animation:fadeUp .3s ease .35s both }
</style>

<div class="pg">

<?php if ($stkNotif): ?>
<div class="sfl <?= htmlspecialchars($stkNotif['type']) ?>">
    <i class="fa-solid fa-<?= $stkNotif['type']==='success'?'circle-check':'circle-info' ?>"></i>
    <?= htmlspecialchars($stkNotif['msg']) ?>
</div>
<?php endif; ?>

<?php if (empty($userPhone)): ?>
<div class="sfl error">
    <i class="fa-solid fa-triangle-exclamation"></i>
    No phone number on your account.
    <a href="profile.php" style="color:inherit;font-weight:800;margin-left:5px;text-decoration:underline">Add in Profile →</a>
</div>
<?php endif; ?>

<!-- ── HERO ── -->
<div class="shero">
    <div class="shero-mesh"></div>
    <div class="shero-glow"></div>
    <div class="shero-inner">
        <div class="shero-top">
            <div>
                <div class="shero-eyebrow"><i class="fa-solid fa-store"></i> Digital Store</div>
                <div class="shero-title">Buy once,<br>access instantly.</div>
                <div class="shero-sub">Premium products. Earn commissions every time someone buys through your link.</div>
            </div>
            <div class="shero-right">
                <div class="cur-toggle">
                    <button class="cur-opt active" id="btnKES" onclick="setCur('kes')"><?= htmlspecialchars($cSym) ?></button>
                    <button class="cur-opt" id="btnUSD" onclick="setCur('usd')">USD $</button>
                </div>
                <a href="my_purchases.php" class="shero-btn"><i class="fa-solid fa-bag-shopping"></i> My Library</a>
                <?php if ($myPurchases > 0): ?>
                <div class="shero-badge"><?= $myPurchases ?> owned</div>
                <?php endif; ?>
            </div>
        </div>
        <div class="shero-stats">
            <div class="shs"><div class="shs-n"><?= number_format($totalProducts) ?></div><div class="shs-l">Products</div></div>
            <div class="shs"><div class="shs-n"><?= number_format($myPurchases) ?></div><div class="shs-l">Owned</div></div>
            <div class="shs"><div class="shs-n"><?= count($catMeta) ?></div><div class="shs-l">Categories</div></div>
            <div class="shs"><div class="shs-n"><?= number_format($totalSellers) ?></div><div class="shs-l">Sellers</div></div>
        </div>
    </div>
</div>

<!-- ── STORE BODY ── -->
<div class="store-body">

<!-- Search -->
<div class="sbar"><form method="GET">
    <input type="hidden" name="cat" value="<?= htmlspecialchars($cat) ?>">
    <div class="sinp-wrap">
        <i class="fa-solid fa-magnifying-glass sinp-ico"></i>
        <input type="text" name="s" class="sinp" placeholder="Search products…" value="<?= htmlspecialchars(stripslashes($search)) ?>">
    </div>
    <select name="sort" class="ssort" onchange="this.form.submit()">
        <option value="newest"     <?= $sort==='newest'    ?'selected':'' ?>>Newest</option>
        <option value="popular"    <?= $sort==='popular'   ?'selected':'' ?>>Popular</option>
        <option value="price_asc"  <?= $sort==='price_asc' ?'selected':'' ?>>Price ↑</option>
        <option value="price_desc" <?= $sort==='price_desc'?'selected':'' ?>>Price ↓</option>
    </select>
    <button type="submit" class="ssbtn"><i class="fa-solid fa-magnifying-glass"></i></button>
</form></div>

<!-- Category tabs -->
<div class="ctabs">
    <a href="?cat=all&sort=<?= $sort ?>&s=<?= urlencode(stripslashes($search)) ?>" class="ctab <?= $cat==='all'?'on':'' ?>">
        <i class="fa-solid fa-grid-2"></i>All<span class="ctab-cnt"><?= $cats['all'] ?></span>
    </a>
    <?php foreach ($catMeta as $ck => $cv): ?>
    <a href="?cat=<?= $ck ?>&sort=<?= $sort ?>&s=<?= urlencode(stripslashes($search)) ?>" class="ctab <?= $cat===$ck?'on':'' ?>">
        <i class="fa-solid <?= $cv['icon'] ?>"></i><?= $cv['label'] ?><span class="ctab-cnt"><?= $cats[$ck] ?></span>
    </a>
    <?php endforeach; ?>
</div>

<!-- Results bar -->
<div class="rbar">
    <div class="rbar-count">
        <b><?= number_format(count($products)) ?></b> of <b><?= number_format($totalCount) ?></b>
        <?= $cat!=='all' ? ' in <b>'.htmlspecialchars($catMeta[$cat]['label']??$cat).'</b>' : ' products' ?>
    </div>
    <?php if ($search): ?>
    <a href="?cat=<?= $cat ?>&sort=<?= $sort ?>" class="rbar-clear"><i class="fa-solid fa-xmark"></i> Clear</a>
    <?php endif; ?>
</div>

<?php if (empty($products)): ?>
<div class="empty">
    <div class="empty-ico"><i class="fa-solid fa-store"></i></div>
    <div class="empty-t">No products found</div>
    <div class="empty-s">Try a different category or search term.</div>
</div>
<?php else: ?>

<!-- Product grid -->
<div class="pgrid">
<?php foreach ($products as $p):
    $cm    = $catMeta[$p['category']] ?? $catMeta['other'];
    $owned = !empty($p['purchased_id']);
    $pRaw  = floatval($p['price']);
    $oRaw  = floatval($p['original_price'] ?? 0);
    $pDisp = round($pRaw);
    $oDisp = $oRaw > 0 ? round($oRaw) : 0;
    $disc  = ($oDisp > $pDisp && $oDisp > 0) ? round((1 - $pDisp/$oDisp)*100) : 0;
    $hasCov = !empty($p['cover_image']) && file_exists('../'.$p['cover_image']);
    $da = sprintf(
        'data-id="%d" data-title="%s" data-praw="%.4f" data-oraw="%.4f" data-icon="%s" data-color="%s" data-owned="%d" data-comm="%s" data-cover="%s" data-cat="%s" data-preview="%s"',
        $p['id'], htmlspecialchars(addslashes($p['title']),ENT_QUOTES),
        $pRaw, $oRaw,
        htmlspecialchars($cm['icon'],ENT_QUOTES),
        htmlspecialchars($cm['color'],ENT_QUOTES),
        $owned ? 1 : 0, $p['commission_percent'],
        htmlspecialchars($hasCov ? '../'.$p['cover_image'] : '',ENT_QUOTES),
        htmlspecialchars($cm['label'],ENT_QUOTES),
        htmlspecialchars(addslashes($p['preview_text'] ?? ''),ENT_QUOTES)
    );
?>
<div class="pcard <?= $owned?'owned':'' ?>" <?= $da ?> onclick="handleCardClick(this)">
    <div class="pcover">
        <?php if ($hasCov): ?>
        <img src="../<?= htmlspecialchars($p['cover_image']) ?>" class="pcover-img" loading="lazy" alt="">
        <?php else: ?>
        <div class="pcover-grad" style="background:linear-gradient(135deg, <?= $cm['color'] ?>, rgba(var(--Pr),.6))">
            <i class="fa-solid <?= $cm['icon'] ?>"></i>
        </div>
        <?php endif; ?>
        <div class="pcover-shadow"></div>
        <?php if ($p['featured']): ?>
        <div class="pcover-feat"><i class="fa-solid fa-fire"></i> Hot</div>
        <?php endif; ?>
        <?php if ($owned): ?>
        <div class="pcover-own"><i class="fa-solid fa-check"></i> Owned</div>
        <?php endif; ?>
    </div>
    <div class="pcbody">
        <div class="pcat-pill" style="background:<?= $cm['color'] ?>">
            <i class="fa-solid <?= $cm['icon'] ?>" style="font-size:8px"></i><?= $cm['label'] ?>
        </div>
        <div class="ptitle"><?= htmlspecialchars($p['title']) ?></div>
        <div class="pprice-row">
            <div>
                <div class="pprice mv" data-kes="<?= $pDisp ?>"><?= $cSym.' '.number_format($pDisp) ?></div>
                <?php if ($disc > 0): ?>
                <div class="pprice-orig mv-orig" data-kes="<?= $oDisp ?>"><?= $cSym.' '.number_format($oDisp) ?></div>
                <?php endif; ?>
            </div>
            <?php if ($disc > 0): ?>
            <div class="pdisc-badge">-<?= $disc ?>%</div>
            <?php else: ?>
            <div class="pcomm-badge"><i class="fa-solid fa-coins" style="font-size:8px;margin-right:2px"></i><?= $p['commission_percent'] ?>%</div>
            <?php endif; ?>
        </div>
        <div class="pmeta-row">
            <span class="pm"><i class="fa-solid fa-download"></i><?= number_format($p['sales_count']) ?> sold</span>
            <span class="pm"><i class="fa-solid fa-file"></i><?= strtoupper($p['category']==='source_code'?'CODE':($p['category']??'FILE')) ?></span>
        </div>
        <?php if ($owned): ?>
        <button class="pbuy-btn owned-btn" onclick="event.stopPropagation();location.href='my_purchases.php'">
            <i class="fa-solid fa-download"></i> Download
        </button>
        <?php else: ?>
        <button class="pbuy-btn buy"><i class="fa-solid fa-bolt"></i> Access Now</button>
        <?php endif; ?>
    </div>
</div>
<?php endforeach; ?>
</div>

<!-- Pagination -->
<?php if ($totalPages > 1):
    $qb = '?cat='.urlencode($cat).'&sort='.urlencode($sort).'&s='.urlencode(stripslashes($search)).'&page='; ?>
<div class="pag">
    <?php if ($page > 1): ?>
    <a href="<?= $qb.($page-1) ?>" class="pagbtn"><i class="fa-solid fa-chevron-left" style="font-size:10px"></i></a>
    <?php endif; ?>
    <?php for ($i=max(1,$page-2); $i<=min($totalPages,$page+2); $i++): ?>
    <a href="<?= $qb.$i ?>" class="pagbtn <?= $i==$page?'on':'' ?>"><?= $i ?></a>
    <?php endfor; ?>
    <?php if ($page < $totalPages): ?>
    <a href="<?= $qb.($page+1) ?>" class="pagbtn"><i class="fa-solid fa-chevron-right" style="font-size:10px"></i></a>
    <?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?>

</div><!-- /store-body -->
</div><!-- /pg -->

<!-- ── BUY MODAL ── -->
<div class="mov" id="buyModal" onclick="if(event.target===this)closeModal()">
<div class="mbox" id="mBoxEl">
    <div class="mhandle"></div>
    <div class="mcov">
        <div class="mcov-grad" id="mCovGrad" style="background:var(--P)">
            <i class="fa-solid fa-cube" id="mCovIcon"></i>
        </div>
        <img id="mCovImg" src="" alt="" class="mcov-img" style="display:none">
        <div class="mcov-overlay"></div>
        <div class="mcov-cat">
            <i class="fa-solid fa-cube" id="mCovCatIcon"></i>
            <span id="mCovCatLbl">Product</span>
        </div>
        <button class="mcov-close" onclick="closeModal()"><i class="fa-solid fa-xmark"></i></button>
    </div>
    <div class="mbdy">
        <div class="mtitle" id="mTitle">—</div>
        <div class="mpricerow">
            <div class="mpricerow-l">
                <div class="mplbl">Price</div>
                <div class="mpval mv" id="mPriceVal" data-kes="0">—</div>
                <div class="mporig mv-orig" id="mOrigVal" data-kes="0" style="display:none"></div>
            </div>
            <div class="mcomm-pill"><i class="fa-solid fa-coins"></i><span id="mCommVal">—</span></div>
        </div>

        <!-- Phone section -->
        <div class="mpesa-phone-wrap">
            <div class="mpesa-phone-label">
                <div class="mpesa-phone-label-txt">
                    <i class="fa-solid fa-sim-card"></i>M-Pesa Payment Number
                </div>
            </div>
            <div id="phSavedChip" style="display:<?= $savedValid?'flex':'none' ?>">
                <div class="ph-saved">
                    <div class="ph-saved-icon"><i class="fa-solid fa-sim-card"></i></div>
                    <div class="ph-saved-body">
                        <div class="ph-saved-top">&#10003; M-Pesa number saved</div>
                        <div class="ph-saved-num"><?= htmlspecialchars($savedDisplay) ?></div>
                        <div class="ph-saved-sub">STK push goes to this number</div>
                    </div>
                    <div class="ph-change-btn" onclick="switchToInput()"><i class="fa-solid fa-pen"></i> Change</div>
                </div>
            </div>
            <div id="phInputWrap" style="display:<?= $savedValid?'none':'block' ?>">
                <div class="ph-input-box" id="phInputBox">
                    <div class="ph-input-row">
                        <div class="ph-prefix">
                            <span class="ph-flag">🇰🇪</span>
                            <span class="ph-code">+254</span>
                        </div>
                        <input type="tel" id="phInp" class="ph-inp"
                            placeholder="7XX XXX XXX"
                            inputmode="numeric" maxlength="12" autocomplete="tel"
                            oninput="livePhone(this.value)"
                            onkeydown="if(event.key==='Enter')this.blur()">
                        <span class="ph-status-ico" id="phStatusIco"></span>
                    </div>
                    <div class="ph-status-bar" id="phStatusBar">
                        <i class="fa-solid fa-circle-info" id="phStatusIcoSm"></i>
                        <span id="phStatusTxt">Enter your Safaricom number (07XX or 01XX)</span>
                    </div>
                    <?php if ($savedValid): ?>
                    <div class="ph-use-saved-link" id="phUseSavedLink" onclick="switchToSaved()">
                        <i class="fa-solid fa-rotate-left"></i>Use saved (<?= htmlspecialchars($savedDisplay) ?>)
                    </div>
                    <?php endif; ?>
                </div>
            </div>
        </div>

        <div class="mpesa-info">
            <i class="fa-solid fa-mobile-screen-button"></i>
            <span>An M-Pesa STK push will pop up on your phone. Enter your PIN to complete.</span>
        </div>

        <div class="mpreview" id="mPreviewBlock" style="display:none">
            <div class="mpreview-t"><i class="fa-solid fa-list-check"></i> What's included</div>
            <div id="mPreviewItems"></div>
        </div>

        <button class="mpay-btn" id="mPayBtn" onclick="confirmPurchase()" disabled>
            <i class="fa-solid fa-lock"></i> Pay &amp; Get Instant Access
        </button>
    </div>
</div>
</div>

<!-- Toast -->
<div class="db-toast" id="db-toast">
    <div class="t-dot" id="t-dot">&#10003;</div>
    <span class="t-txt" id="t-txt"></span>
    <button class="t-cls" onclick="hideToast()">&#215;</button>
</div>

<input type="hidden" id="curPid" value="">

<script>
/* ── PHP → JS constants (same pattern as dashboard.php) ── */
var CS          = '<?= addslashes($cSym) ?>';
var USD_RATE    = <?= (float)$usdRate ?>;
var ADMIN_P     = '<?= addslashes($adminPrimary) ?>';
var ADMIN_OK    = '<?= addslashes($adminSuccess) ?>';
var ADMIN_WN    = '<?= addslashes($adminWarning) ?>';
var ADMIN_DN    = '<?= addslashes($adminDanger) ?>';
var SAVED_NORM  = '<?= addslashes($savedNorm) ?>';
var SAVED_VALID = <?= $savedValid ? 'true' : 'false' ?>;
var SAVED_DISP  = '<?= addslashes($savedDisplay) ?>';

var curMode    = 'kes';
var validPhone = SAVED_VALID ? SAVED_NORM : '';
var usingSaved = SAVED_VALID;
var mPriceRaw = 0, mOrigRaw = 0, mComm = 0;
var toastTimer = null;

/* ── Currency (identical logic to dashboard.js) ── */
function fmtMoney(local, mode) {
    if (mode === 'usd') {
        var usd = USD_RATE > 0 ? local / USD_RATE : local;
        return '$ ' + usd.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    }
    return CS + ' ' + Math.round(local).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}

function refreshAll(mode) {
    document.querySelectorAll('.mv').forEach(function(el){
        var v = parseFloat(el.getAttribute('data-kes') || 0);
        el.textContent = fmtMoney(v, mode);
    });
    document.querySelectorAll('.mv-orig').forEach(function(el){
        var v = parseFloat(el.getAttribute('data-kes') || 0);
        if (v > 0) el.textContent = fmtMoney(v, mode);
    });
    if (mPriceRaw > 0) {
        var pEl = document.getElementById('mPriceVal');
        if (pEl) pEl.textContent = fmtMoney(mPriceRaw, mode);
        var oEl = document.getElementById('mOrigVal');
        if (oEl && mOrigRaw > mPriceRaw) oEl.textContent = fmtMoney(mOrigRaw, mode);
        document.getElementById('mCommVal').textContent =
            mComm + '% — earn ' + fmtMoney(mPriceRaw * mComm / 100, mode);
    }
}

window.setCur = function(mode) {
    curMode = mode;
    document.getElementById('btnKES').classList.toggle('active', mode === 'kes');
    document.getElementById('btnUSD').classList.toggle('active', mode === 'usd');
    refreshAll(mode);
};

/* ── Card / Modal ── */
function handleCardClick(el) {
    if (parseInt(el.dataset.owned)) { location.href = 'my_purchases.php'; return; }
    openModal(el);
}

function openModal(el) {
    mPriceRaw = parseFloat(el.dataset.praw || 0);
    mOrigRaw  = parseFloat(el.dataset.oraw || 0);
    mComm     = parseFloat(el.dataset.comm || 0);

    document.getElementById('curPid').value = el.dataset.id;
    document.getElementById('mTitle').textContent = el.dataset.title;

    var img = document.getElementById('mCovImg');
    var grd = document.getElementById('mCovGrad');
    if (el.dataset.cover) {
        img.src = el.dataset.cover; img.style.display = 'block'; grd.style.display = 'none';
    } else {
        img.style.display = 'none'; grd.style.display = 'flex';
        grd.style.background = el.dataset.color || 'var(--P)';
        document.getElementById('mCovIcon').className = 'fa-solid ' + el.dataset.icon;
    }
    document.getElementById('mCovCatIcon').className = 'fa-solid ' + el.dataset.icon;
    document.getElementById('mCovCatLbl').textContent = el.dataset.cat;

    var pEl = document.getElementById('mPriceVal');
    pEl.setAttribute('data-kes', mPriceRaw);
    pEl.textContent = fmtMoney(mPriceRaw, curMode);

    var oEl = document.getElementById('mOrigVal');
    if (mOrigRaw > mPriceRaw && mOrigRaw > 0) {
        oEl.setAttribute('data-kes', mOrigRaw);
        oEl.textContent = fmtMoney(mOrigRaw, curMode);
        oEl.style.display = 'block';
    } else { oEl.style.display = 'none'; }

    document.getElementById('mCommVal').textContent =
        mComm + '% — earn ' + fmtMoney(mPriceRaw * mComm / 100, curMode);

    var pb = document.getElementById('mPreviewBlock');
    var preview = el.dataset.preview || '';
    if (preview.trim()) {
        document.getElementById('mPreviewItems').innerHTML = preview.trim().split('\n')
            .filter(function(l){ return l.trim(); }).slice(0, 6)
            .map(function(l){ return '<div class="mpreview-item"><i class="fa-solid fa-circle-check"></i>' + l.replace(/^[•\-\*]\s*/,'') + '</div>'; })
            .join('');
        pb.style.display = 'block';
    } else { pb.style.display = 'none'; }

    resetPhone();
    document.getElementById('buyModal').classList.add('open');
    document.body.style.overflow = 'hidden';
    setTimeout(function(){ document.getElementById('mBoxEl').scrollTop = 0; }, 30);
}

function closeModal() {
    document.getElementById('buyModal').classList.remove('open');
    document.body.style.overflow = '';
    mPriceRaw = 0;
}
document.addEventListener('keydown', function(e){ if (e.key === 'Escape') closeModal(); });

/* ── Phone ── */
function resetPhone() {
    if (SAVED_VALID) { showChip(); }
    else {
        document.getElementById('phInputWrap').style.display = 'block';
        document.getElementById('phInp').value = '';
        setInputState('neutral','Enter your Safaricom number (07XX or 01XX)');
        document.getElementById('mPayBtn').disabled = true;
        validPhone = ''; usingSaved = false;
    }
}
function showChip() {
    document.getElementById('phSavedChip').style.display = 'flex';
    document.getElementById('phInputWrap').style.display = 'none';
    validPhone = SAVED_NORM; usingSaved = true;
    document.getElementById('mPayBtn').disabled = false;
}
function switchToInput() {
    document.getElementById('phSavedChip').style.display = 'none';
    document.getElementById('phInputWrap').style.display = 'block';
    var l = document.getElementById('phUseSavedLink');
    if (l) l.classList.add('show');
    document.getElementById('phInp').value = '';
    setInputState('neutral','Enter a different Safaricom number');
    document.getElementById('mPayBtn').disabled = true;
    validPhone = ''; usingSaved = false;
    setTimeout(function(){ document.getElementById('phInp').focus(); }, 80);
}
function switchToSaved() { showChip(); }

function livePhone(raw) {
    var d = raw.replace(/\D/g,''), norm = '';
    if      (/^0(7|1)\d{8}$/.test(d))   norm = '254' + d.slice(1);
    else if (/^(7|1)\d{8}$/.test(d))    norm = '254' + d;
    else if (/^254(7|1)\d{8}$/.test(d)) norm = d;
    var ok = /^254(7|1)\d{8}$/.test(norm);
    if (!raw.trim()) {
        setInputState('neutral','Enter your Safaricom number (07XX or 01XX)');
        document.getElementById('mPayBtn').disabled = true; validPhone = '';
    } else if (ok) {
        var loc = '0' + norm.slice(3);
        setInputState('ok','✓ '+loc.slice(0,4)+' '+loc.slice(4,7)+' '+loc.slice(7)+' — valid');
        document.getElementById('mPayBtn').disabled = false; validPhone = norm; usingSaved = false;
    } else if (d.length >= 5) {
        setInputState('err','Use format 07XX XXX XXX or 01XX XXX XXX');
        document.getElementById('mPayBtn').disabled = true; validPhone = '';
    } else {
        setInputState('neutral','Keep typing…');
        document.getElementById('mPayBtn').disabled = true; validPhone = '';
    }
}

function setInputState(s, msg) {
    var box  = document.getElementById('phInputBox');
    var bar  = document.getElementById('phStatusBar');
    var ico  = document.getElementById('phStatusIcoSm');
    var sico = document.getElementById('phStatusIco');
    box.classList.remove('ok','err');
    if (s === 'ok')  { box.classList.add('ok');  sico.textContent = '✅'; if (ico) ico.className = 'fa-solid fa-circle-check'; }
    else if (s === 'err') { box.classList.add('err'); sico.textContent = '❌'; if (ico) ico.className = 'fa-solid fa-circle-xmark'; }
    else { sico.textContent = ''; if (ico) ico.className = 'fa-solid fa-circle-info'; }
    document.getElementById('phStatusTxt').textContent = msg;
}

/* ── Purchase ── */
function confirmPurchase() {
    var pid = document.getElementById('curPid').value;
    if (!pid || !validPhone) return;
    var btn = document.getElementById('mPayBtn');
    btn.disabled = true;
    btn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Sending STK push…';
    fetch('process_product_purchase.php', {
        method:'POST',
        headers:{'Content-Type':'application/x-www-form-urlencoded'},
        body:'product_id='+encodeURIComponent(pid)+'&phone='+encodeURIComponent(validPhone)
    })
    .then(function(r){ return r.json(); })
    .then(function(d){
        closeModal();
        if (d.success) {
            showToast('STK push sent! Check your phone.','info');
            setTimeout(function(){ location.href = 'my_purchases.php?pending=1'; }, 2800);
        } else {
            showToast(d.message || 'Payment failed. Try again.','error');
            btn.disabled = false;
            btn.innerHTML = '<i class="fa-solid fa-lock"></i> Pay &amp; Get Instant Access';
        }
    })
    .catch(function(){
        showToast('Network error. Try again.','error');
        btn.disabled = false;
        btn.innerHTML = '<i class="fa-solid fa-lock"></i> Pay &amp; Get Instant Access';
    });
}

/* ── Toast (matches dashboard toast exactly) ── */
function showToast(msg, type) {
    var t   = document.getElementById('db-toast');
    var dot = document.getElementById('t-dot');
    var txt = document.getElementById('t-txt');
    clearTimeout(toastTimer);
    t.className = 'db-toast show';
    var color = type === 'error' ? ADMIN_DN : (type === 'success' ? ADMIN_OK : ADMIN_P);
    t.style.borderLeftColor = color;
    dot.style.background    = color;
    dot.innerHTML = type === 'error' ? '&#10007;' : '&#10003;';
    txt.textContent = msg;
    toastTimer = setTimeout(hideToast, 4500);
}
function hideToast() { document.getElementById('db-toast').classList.remove('show'); }
window.hideToast = hideToast;
</script>

<?php include 'footer.php'; ?>