{"id":3240,"date":"2025-07-11T01:00:32","date_gmt":"2025-07-11T01:00:32","guid":{"rendered":"https:\/\/godsgalaxygame.com\/GGG\/?page_id=3240"},"modified":"2026-09-09T14:44:54","modified_gmt":"2026-09-09T14:44:54","slug":"owners-club","status":"publish","type":"page","link":"https:\/\/godsgalaxygame.com\/GGG\/owners-club\/","title":{"rendered":"Owners Club"},"content":{"rendered":"\r\n<!-- ===== OWNERS CLUB \u2014 STARFIELD BACKGROUND (behind cube + map) ===== -->\r\n<canvas id=\"ocStarfield\" aria-hidden=\"true\"><\/canvas>\r\n\r\n<style>\r\n  \/* Fullscreen background behind everything *\/\r\n  #ocStarfield{\r\n    position: fixed;\r\n    inset: 0;\r\n    width: 100%;\r\n    height: 100%;\r\n    display: block;\r\n    z-index: 0;\r\n    pointer-events: none;\r\n  }\r\n\r\n  \/* Keep Owners Club UI above the starfield *\/\r\n  #ownerCubeContainer{ position: relative; z-index: 5; }\r\n\r\n  \/* Optional: keep page dark *\/\r\n  body{ background:#000; }\r\n<\/style>\r\n\r\n<script>\r\n(function(){\r\n  const c = document.getElementById('ocStarfield');\r\n  if(!c) return;\r\n  const ctx = c.getContext('2d');\r\n\r\n  let W=0, H=0, dpr=1, stars=[], meteors=[];\r\n  let rafId=null, running=true;\r\n\r\n  function resize(){\r\n    dpr = Math.max(1, Math.min(2, window.devicePixelRatio||1));\r\n    W = c.width  = Math.floor(innerWidth  * dpr);\r\n    H = c.height = Math.floor(innerHeight * dpr);\r\n    c.style.width  = innerWidth  + 'px';\r\n    c.style.height = innerHeight + 'px';\r\n    buildStars();\r\n  }\r\n\r\n  function buildStars(){\r\n    const count = Math.floor((W*H) \/ (14000*dpr));\r\n    stars = Array.from({length: count}, () => ({\r\n      x: Math.random()*W,\r\n      y: Math.random()*H,\r\n      r: (Math.random()*1.2+0.4)*dpr,\r\n      a: Math.random()*1\r\n    }));\r\n  }\r\n\r\n  function spawnMeteor(){\r\n    const startX = Math.random()<0.5 ? -50*dpr : W+50*dpr;\r\n    const dir = startX<0 ? 1 : -1;\r\n    const startY = Math.random()*H*0.6 + H*0.1;\r\n    meteors.push({ x:startX, y:startY, vx: dir*(3.2*dpr), vy: 1.2*dpr, life: 0, max: 1600 });\r\n  }\r\n\r\n  let last=0, accum=0;\r\n  function tick(ts){\r\n    if(!running) return;\r\n\r\n    const dt = Math.min(33, ts-last || 16); \r\n    last=ts; \r\n    accum+=dt;\r\n\r\n    if (accum>900+Math.random()*900) { spawnMeteor(); accum=0; }\r\n\r\n    ctx.setTransform(1,0,0,1,0,0);\r\n    ctx.clearRect(0,0,W,H);\r\n\r\n    \/\/ Subtle cyan nebula glow (premium)\r\n    const g = ctx.createRadialGradient(\r\n      W\/2, H*0.15, 0,\r\n      W\/2, H*0.4,  Math.hypot(W,H)\/1.4\r\n    );\r\n    g.addColorStop(0,'rgba(0,220,255,0.10)');\r\n    g.addColorStop(1,'rgba(0,0,0,0)');\r\n    ctx.fillStyle=g; \r\n    ctx.fillRect(0,0,W,H);\r\n\r\n    \/\/ Twinkle stars\r\n    for(const s of stars){\r\n      s.a += (Math.random()*0.06-0.03);\r\n      const a = 0.35+0.35*Math.sin(s.a);\r\n      ctx.fillStyle = `rgba(200,245,255,${a})`;\r\n      ctx.beginPath();\r\n      ctx.arc(s.x,s.y,s.r,0,Math.PI*2);\r\n      ctx.fill();\r\n    }\r\n\r\n    \/\/ Meteors\r\n    for (let i=meteors.length-1;i>=0;i--){\r\n      const m = meteors[i];\r\n      m.x += m.vx; \r\n      m.y += m.vy; \r\n      m.life += dt;\r\n\r\n      const trailX = m.x - m.vx*6;\r\n      const trailY = m.y - m.vy*6;\r\n\r\n      const grad = ctx.createLinearGradient(m.x,m.y, trailX,trailY);\r\n      grad.addColorStop(0,'rgba(0,255,255,0.9)');\r\n      grad.addColorStop(1,'rgba(0,255,255,0)');\r\n\r\n      ctx.strokeStyle = grad;\r\n      ctx.lineWidth = 2*dpr;\r\n      ctx.lineCap='round';\r\n\r\n      ctx.beginPath();\r\n      ctx.moveTo(m.x,m.y);\r\n      ctx.lineTo(trailX, trailY);\r\n      ctx.stroke();\r\n\r\n      if (m.x<-200*dpr || m.x>W+200*dpr || m.y>H+200*dpr || m.life>m.max){\r\n        meteors.splice(i,1);\r\n      }\r\n    }\r\n\r\n    rafId = requestAnimationFrame(tick);\r\n  }\r\n\r\n  \/\/ Optional controller (if you ever want to pause\/play)\r\n  window.ocStarfieldControl = {\r\n    pause(){ running=false; if(rafId) cancelAnimationFrame(rafId); },\r\n    play(){ if(running) return; running=true; last=0; accum=0; rafId=requestAnimationFrame(tick); }\r\n  };\r\n\r\n  addEventListener('resize', resize, {passive:true});\r\n  resize();\r\n  rafId = requestAnimationFrame(tick);\r\n})();\r\n<\/script>\r\n<!-- ===== end OWNERS CLUB starfield ===== -->\r\n\r\n\r\n\r\n<!-- BLOQUE 2 - Owners Club Cube V19 Completo + Mapa Circular + API -->\r\n<style>\r\n  @media (max-width: 768px) {\r\n    #glowMapContainer {\r\n      margin-top: -50px !important;\r\n    }\r\n  }\r\n<\/style>\r\n<div id=\"ownerCubeContainer\" style=\"opacity:1; pointer-events: auto; transition: opacity 0.6s ease;\">\r\n  <!-- ESCENA CUBO -->\r\n  <div class=\"cube-scene\" style=\"width:180px; height:180px; perspective:1000px; position:fixed; bottom:20px; left:20px; z-index:1000;\">\r\n    <div class=\"cube\" id=\"ownerCube\" style=\"width:100%; height:100%; position:relative; transform-style:preserve-3d; transform:rotateX(0deg) rotateY(0deg); transition:transform 0.3s ease;\">\r\n   <!-- FRONT -->\r\n      <div class=\"face front\" style=\"width:180px; height:180px; background:transparent; border:2px solid white; box-shadow:0 0 20px white; position:absolute; transform:rotateY(0deg) translateZ(90px); display:flex; flex-direction:column; justify-content:center; align-items:center; font-family:Orbitron;\">\r\n        <div style=\"font-size:42px; color:white; text-shadow:0 0 15px white;\">\ud83d\udc51<\/div>\r\n        <div style=\"font-size:16px; color:white; font-weight:bold; text-shadow:0 0 10px white; margin-top:6px;\">Owners Club<\/div>\r\n      <\/div>\r\n\r\n      <!-- Cara Trasera del Cubo: Transportation -->\r\n<!-- Back Face - Transportation Cube - Nuevo Dise\u00f1o con Botones Circulares -->\r\n<div class=\"face back\" style=\"width:180px; height:180px; background:#000; border:2px solid white; box-shadow:0 0 15px white; position:absolute; transform:rotateY(180deg) translateZ(90px); font-family:Orbitron,sans-serif;\">\r\n\r\n  <!-- Sol central -->\r\n  <img decoding=\"async\" src=\"http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/06\/1000065346-scaled.jpg\"\r\n       style=\"width:70px; height:70px; border-radius:50%; position:absolute; top:50%; left:50%; transform:translate(-50%, -50%); box-shadow:0 0 20px white;\" \/>\r\n\r\n  <!-- Reserve -->\r\n  <a href=\"https:\/\/godsgalaxygame.com\/GGG\/fractional-ownership\/?fractional=1\" target=\"_blank\"\r\n     style=\"position:absolute; top:8px; left:8px; width:44px; height:44px; border-radius:50%; background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/06\/Screenshot_20240108-225452_Chrome-scaled.jpg'); background-size:cover; box-shadow:0 0 12px cyan;\"\r\n     title=\"Reserve\"><\/a>\r\n\r\n  <!-- Bliss Coin -->\r\n  <div onclick=\"openBlissCoinPopup()\"\r\n       style=\"position:absolute; top:8px; right:8px; width:44px; height:44px; border-radius:50%; background:#222; font-size:40px; display:flex; justify-content:center; align-items:center; color:white; box-shadow:0 0 10px cyan; cursor:pointer;\"\r\n       title=\"Pay with Bliss Coin\">\ud83d\udcb3<\/div>\r\n\r\n  <!-- Coupon Button (Bottom-Left Corner) -->\r\n<a href=\"https:\/\/godsgalaxygame.com\/GGG\/discounts-gift\/\"\r\n   target=\"_blank\"\r\n   style=\"position: absolute;\r\n          bottom: 8px;\r\n          left: 8px;\r\n          width: 44px;\r\n          height: 44px;\r\n          border-radius: 50%;\r\n          background-image: url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/06\/Screenshot_20240108-225546_Chrome.jpg');\r\n          background-size: cover;\r\n          box-shadow: 0 0 12px cyan;\r\n          cursor: pointer;\"\r\n   title=\"Get Coupons\">\r\n<\/a>\r\n\r\n  <!-- Become a Host -->\r\n  <a href=\"https:\/\/luxus2.godaddysites.com\/\" target=\"_blank\"\r\n     style=\"position:absolute; bottom:8px; right:8px; width:44px; height:44px; border-radius:50%; background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/06\/Screenshot_20240108-224514_Chrome-scaled.jpg'); background-size:cover; box-shadow:0 0 12px cyan;\"\r\n     title=\"Become a Host\"><\/a>\r\n<\/div>\r\n\r\n\r\n\r\n      <!-- RIGHT (Use) -->\r\n      <div class=\"face right\" style=\"width:180px; height:180px; background:#000; border:2px solid beige; box-shadow:0 0 15px beige; position:absolute; transform:rotateY(90deg) translateZ(90px); font-family:Orbitron;\">\r\n        <button onclick=\"showHostButtons('use-week')\" style=\"position:absolute; top:8px; left:27px; width:126px; height:17px; border:1px solid beige; color:white; background:transparent;\">Week<\/button>\r\n        <button onclick=\"showHostButtons('use-short')\" style=\"position:absolute; bottom:8px; left:27px; width:126px; height:17px; border:1px solid beige; color:white; background:transparent;\">Short Stay<\/button>\r\n        <button onclick=\"showHostButtons('use-onlinez')\" style=\"position:absolute; top:27px; left:8px; height:126px; width:17px; border:1px solid beige; color:white; writing-mode:vertical-rl; background:transparent;\">Online<\/button>\r\n        <button onclick=\"showHostButtons('use-penthouse')\" style=\"position:absolute; top:27px; right:8px; height:126px; width:17px; border:1px solid beige; color:white; writing-mode:vertical-lr; background:transparent;\">Penthouse<\/button>\r\n        <div style=\"position:absolute; top:50%; left:50%; transform:translate(-50%, -50%); text-align:center;\">\r\n          <div style=\"color:beige; font-size:16px; font-weight:bold;\">Use<\/div>\r\n          <img decoding=\"async\" src=\"http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/06\/Screenshot_20250612_075245_Gallery.jpg\" style=\"width:65px; height:65px; border-radius:50%; box-shadow:0 0 12px beige;\">\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- LEFT (Exchange) -->\r\n      <div class=\"face left\" style=\"width:180px; height:180px; background:#000; border:2px solid #00ccff; box-shadow:0 0 15px #00ccff; position:absolute; transform:rotateY(-90deg) translateZ(90px); font-family:Orbitron;\">\r\n        <button onclick=\"showHostButtons('exchangez-internally')\" style=\"position:absolute; top:8px; left:27px; width:126px; height:17px; border:1px solid #00ccff; color:white; background:transparent;\">Internally<\/button>\r\n        <button onclick=\"showHostButtons('exchangez-comm')\" style=\"position:absolute; bottom:8px; left:27px; width:126px; height:17px; border:1px solid #00ccff; color:white; background:transparent;\">Community<\/button>\r\n        <button onclick=\"showHostButtons('exchangez-year')\" style=\"position:absolute; top:27px; left:8px; height:126px; width:17px; border:1px solid #00ccff; color:white; writing-mode:vertical-rl; background:transparent;\">Year<\/button>\r\n        <button onclick=\"showHostButtons('exchangez-ownership')\" style=\"position:absolute; top:27px; right:8px; height:126px; width:17px; border:1px solid #00ccff; color:white; writing-mode:vertical-lr; background:transparent;\">Ownership<\/button>\r\n        <div style=\"position:absolute; top:50%; left:50%; transform:translate(-50%, -50%); text-align:center;\">\r\n          <div style=\"color:#00ccff; font-size:16px; font-weight:bold;\">Exchange<\/div>\r\n          <img decoding=\"async\" src=\"http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/06\/Screenshot_20250612_075344_Gallery.jpg\" style=\"width:65px; height:65px; border-radius:50%; box-shadow:0 0 12px #00ccff;\">\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- TOP (Trade) -->\r\n      <div class=\"face top\" style=\"width:180px; height:180px; background:#000; border:2px solid green; box-shadow:0 0 15px #33ff33; position:absolute; transform:rotateX(90deg) translateZ(90px); font-family:Orbitron;\">\r\n        <button onclick=\"showHostButtons('trade-rooms')\" style=\"position:absolute; top:8px; left:27px; width:126px; height:17px; border:1px solid green; color:white; background:transparent;\">Rooms<\/button>\r\n        <button onclick=\"showHostButtons('trade-dayzz')\" style=\"position:absolute; bottom:8px; left:27px; width:126px; height:17px; border:1px solid green; color:white; background:transparent;\">Day<\/button>\r\n        <button onclick=\"showHostButtons('trade-wknd')\" style=\"position:absolute; top:27px; left:8px; height:126px; width:17px; border:1px solid green; color:white; writing-mode:vertical-rl; background:transparent;\">Weekend<\/button>\r\n        <button onclick=\"showHostButtons('trade-wk')\" style=\"position:absolute; top:27px; right:8px; height:126px; width:17px; border:1px solid green; color:white; writing-mode:vertical-lr; background:transparent;\">Week<\/button>\r\n        <div style=\"position:absolute; top:50%; left:50%; transform:translate(-50%, -50%); text-align:center;\">\r\n          <div style=\"color:#33ff33; font-size:16px; font-weight:bold;\">Trade<\/div>\r\n          <img decoding=\"async\" src=\"http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/06\/Screenshot_20250612_075305_Gallery.jpg\" style=\"width:65px; height:65px; border-radius:50%; box-shadow:0 0 12px #33ff33;\">\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- BOTTOM (Buy) -->\r\n      <div class=\"face bottom\" style=\"width:180px; height:180px; background:#000; border:2px solid red; box-shadow:0 0 15px red; position:absolute; transform:rotateX(-90deg) translateZ(90px); font-family:Orbitron;\">\r\n        <button onclick=\"showHostButtons('buyzz-wkz')\" style=\"position:absolute; top:8px; left:27px; width:126px; height:17px; border:1px solid red; color:white; background:transparent;\">Weeks<\/button>\r\n        <button onclick=\"showHostButtons('buyzz-bc')\" style=\"position:absolute; bottom:8px; left:27px; width:126px; height:17px; border:1px solid red; color:white; background:transparent;\">Bliss Coin<\/button>\r\n        <button onclick=\"showHostButtons('buyzz-trc')\" style=\"position:absolute; top:27px; left:8px; height:126px; width:17px; border:1px solid red; color:white; writing-mode:vertical-rl; background:transparent;\">Travel Club<\/button>\r\n        <button onclick=\"showHostButtons('buyzz-cc')\" style=\"position:absolute; top:27px; right:8px; height:126px; width:17px; border:1px solid red; color:white; writing-mode:vertical-lr; background:transparent;\">City Card<\/button>\r\n        <div style=\"position:absolute; top:50%; left:50%; transform:translate(-50%, -50%); text-align:center;\">\r\n          <div style=\"color:red; font-size:16px; font-weight:bold;\">Buy<\/div>\r\n          <img decoding=\"async\" src=\"http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/06\/Screenshot_20250612_075325_Gallery.jpg\" style=\"width:65px; height:65px; border-radius:50%; box-shadow:0 0 12px red;\">\r\n        <\/div>\r\n      <\/div>\r\n\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- MAPA CIRCULAR -->\r\n  <div id=\"glowMapContainer\" style=\"opacity:1; pointer-events:auto; transition: opacity 0.6s ease; margin: 0 auto; margin-top: -90px; margin-bottom: 40px; width: 320px; height: 320px; border-radius: 50%; overflow: hidden; border: 6px solid rgba(0,255,255,0.6); box-shadow: 0 0 25px cyan; position: relative; z-index: 900;\">\r\n    <div id=\"googleMap\" style=\"width:100%; height:100%;\"><\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- Google Maps API (clave v\u00e1lida y correcta) -->\r\n<script src=\"https:\/\/maps.googleapis.com\/maps\/api\/js?key=AIzaSyDLPhx98z9AgoqXS6VeoESE9NV6URuOhiE&#038;callback=initMap\" async defer><\/script>\r\n\r\n<script>\r\n  function activateownerCube() {\r\n    \/\/ Oculta el grid de opciones\r\n    const rrGrid = document.getElementById(\"rrGrid\");\r\n    if (rrGrid) {\r\n      rrGrid.style.display = \"none\";\r\n    }\r\n\r\n    \/\/ Muestra el contenedor del cubo Owners Club\r\n    const container = document.getElementById(\"ownerContainer\");\r\n    if (container) {\r\n      container.style.opacity = \"1\";\r\n      container.style.pointerEvents = \"auto\";\r\n    }\r\n\r\n    \/\/ Muestra el mapa\r\n    const map = document.getElementById(\"glowMapContainer\");\r\n    if (map) {\r\n      map.style.opacity = \"1\";\r\n      map.style.pointerEvents = \"auto\";\r\n    }\r\n\r\n    \/\/ Reinicia el mapa si es necesario\r\n    if (typeof initMap === \"function\") {\r\n      initMap();\r\n    }\r\n  }\r\n<\/script>\r\n<script>\r\n  function initMap() {\r\n    const location = { lat: 6.25184, lng: -75.56359 }; \/\/ Puedes cambiar esto a tu zona de inter\u00e9s\r\n\r\n    const map = new google.maps.Map(document.getElementById(\"googleMap\"), {\r\n      zoom: 14,\r\n      center: location,\r\n      mapTypeId: google.maps.MapTypeId.HYBRID, \/\/ Aqu\u00ed activas el modo hybrid\r\n    });\r\n\r\n    new google.maps.Marker({\r\n      position: location,\r\n      map: map,\r\n      title: \"Ubicaci\u00f3n Principal\",\r\n    });\r\n  }\r\n<\/script>\r\n\r\n<!-- POP-UP para Bliss Coin -->\r\n<div id=\"blissCoinPopup\" style=\"display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.9); z-index:9999; justify-content:center; align-items:center; font-family:Orbitron;\">\r\n  <div style=\"background:#111; padding:30px 20px; border:2px solid cyan; border-radius:20px; color:white; width:300px; text-align:center; box-shadow:0 0 20px cyan;\">\r\n    <h3 style=\"font-size:18px;\">\ud83d\udcb3 Pay with Bliss Coin<\/h3>\r\n    <p style=\"font-size:14px;\">Enter your digital wallet #:<\/p>\r\n    <input type=\"text\" placeholder=\"Your Wallet #\" style=\"width:90%; padding:8px; border-radius:10px; border:1px solid white; background:#000; color:white; margin-top:8px;\" \/>\r\n    <p style=\"margin-top:14px;\">Send payment to:<\/p>\r\n    <div style=\"margin:8px auto; padding:6px; background:#222; border:1px solid cyan; border-radius:8px;\">\r\n      <code style=\"font-size:13px;\">HOST-WALLET-ADDRESS-123<\/code>\r\n    <\/div>\r\n    <button onclick=\"closeBlissCoinPopup()\" style=\"margin-top:12px; padding:6px 16px; border-radius:10px; background:cyan; border:none; color:#000; font-weight:bold; cursor:pointer;\">\r\n      Close\r\n    <\/button>\r\n  <\/div>\r\n<\/div>\r\n\r\n<script>\r\n  function openBlissCoinPopup() {\r\n    document.getElementById('blissCoinPopup').style.display = 'flex';\r\n  }\r\n  function closeBlissCoinPopup() {\r\n    document.getElementById('blissCoinPopup').style.display = 'none';\r\n  }\r\n<\/script>\r\n\r\n\r\n\r\n<!-- =========================================================\r\nGGG BLOCK 3 \u2014 OWNERS CLUB\r\nFull floating controls + auth + favorites + rose + city card\r\n========================================================= -->\r\n\r\n<style>\r\n  #floatingButtons {\r\n    position: fixed;\r\n    top: 14px;\r\n    right: 14px;\r\n    display: flex;\r\n    flex-direction: row;\r\n    gap: 10px;\r\n    z-index: 3000;\r\n  }\r\n\r\n  #favoritesBtn, #signinBtn {\r\n    font-size: 15px;\r\n    padding: 6px 10px;\r\n    border-radius: 8px;\r\n    border: 2px solid white;\r\n    color: white;\r\n    background: rgba(0, 0, 0, 0.6);\r\n    cursor: pointer;\r\n    box-shadow: 0 0 8px cyan;\r\n    font-family: Orbitron, system-ui, sans-serif;\r\n  }\r\n\r\n  #favoritesBtn:hover::after {\r\n    content: ' Double click a Host to add or remove \ud83d\udc98';\r\n    font-size: 10px;\r\n    margin-left: 8px;\r\n    color: cyan;\r\n  }\r\n\r\n  #signinBtn:hover::after {\r\n    content: ' Sign in to save your Favorites';\r\n    font-size: 10px;\r\n    margin-left: 8px;\r\n    color: cyan;\r\n  }\r\n\r\n  #cityCardBtn {\r\n    width: 39px;\r\n    height: 39px;\r\n    border-radius: 50%;\r\n    border: 2px solid #ffffffaa;\r\n    background: rgba(0,0,0,0.65);\r\n    color: #fff;\r\n    font-size: 11px;\r\n    font-family: 'Orbitron', system-ui, sans-serif;\r\n    letter-spacing: 1px;\r\n    cursor: pointer;\r\n    box-shadow: 0 0 10px cyan;\r\n    display: flex;\r\n    justify-content: center;\r\n    align-items: center;\r\n    transition: 0.25s ease;\r\n    overflow: hidden;\r\n  }\r\n\r\n  #cityCardBtn:hover {\r\n    box-shadow: 0 0 16px cyan;\r\n    transform: translateY(-1px);\r\n  }\r\n\r\n  #pyramidBtn {\r\n    width: 38px;\r\n    height: 38px;\r\n    background-color: black;\r\n    border: 2px solid white;\r\n    border-radius: 50%;\r\n    box-shadow: 0 0 10px cyan;\r\n    display: flex;\r\n    justify-content: center;\r\n    align-items: center;\r\n    font-size: 20px;\r\n    cursor: pointer;\r\n    margin-top: 2px;\r\n  }\r\n\r\n  #pyramidBtn:hover {\r\n    transform: scale(1.2);\r\n  }\r\n\r\n  #roseBtn {\r\n    width: 38px;\r\n    height: 38px;\r\n    background-color: black;\r\n    background-image: url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/07\/ChatGPT-Image-Jul-7-2025-05_11_38-PM.png');\r\n    background-size: cover;\r\n    background-position: center;\r\n    border: 2px solid white;\r\n    border-radius: 50%;\r\n    box-shadow: 0 0 10px white;\r\n    cursor: pointer;\r\n    margin-top: 2px;\r\n  }\r\n\r\n  #roseBtn:hover {\r\n    transform: scale(1.2);\r\n  }\r\n\r\n  \/* FAVORITES PANEL *\/\r\n  #favoritesPanel {\r\n    position: fixed;\r\n    top: 64px;\r\n    right: 14px;\r\n    width: min(92vw, 340px);\r\n    max-height: 68vh;\r\n    overflow-y: auto;\r\n    display: none;\r\n    z-index: 3200;\r\n    border-radius: 18px;\r\n    padding: 12px;\r\n    background: linear-gradient(180deg, rgba(8,12,24,.96), rgba(4,7,18,.98));\r\n    border: 1px solid rgba(255,255,255,.12);\r\n    box-shadow:\r\n      0 0 20px rgba(0,255,255,.18),\r\n      0 0 60px rgba(0,0,0,.45);\r\n    color: #fff;\r\n    font-family: Orbitron, system-ui, sans-serif;\r\n  }\r\n\r\n  #favoritesPanel.show {\r\n    display: block;\r\n  }\r\n\r\n  .favorites-header {\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: space-between;\r\n    gap: 10px;\r\n    margin-bottom: 10px;\r\n  }\r\n\r\n  .favorites-title {\r\n    font-size: 12px;\r\n    letter-spacing: .14em;\r\n    text-transform: uppercase;\r\n    color: rgba(255,255,255,.85);\r\n  }\r\n\r\n  .favorites-close {\r\n    border: 1px solid rgba(255,255,255,.16);\r\n    background: rgba(255,255,255,.06);\r\n    color: #fff;\r\n    border-radius: 999px;\r\n    padding: 6px 10px;\r\n    cursor: pointer;\r\n    font-size: 11px;\r\n    text-transform: uppercase;\r\n    font-family: inherit;\r\n  }\r\n\r\n  .favorites-actions {\r\n    display: flex;\r\n    gap: 8px;\r\n    margin-bottom: 12px;\r\n    flex-wrap: wrap;\r\n  }\r\n\r\n  .favorites-action-btn {\r\n    border: 1px solid rgba(0,255,255,.35);\r\n    background: rgba(0,255,255,.08);\r\n    color: #fff;\r\n    border-radius: 999px;\r\n    padding: 8px 10px;\r\n    cursor: pointer;\r\n    font-size: 11px;\r\n    text-transform: uppercase;\r\n    font-family: inherit;\r\n  }\r\n\r\n  .favorites-empty {\r\n    font-size: 12px;\r\n    color: rgba(255,255,255,.72);\r\n    line-height: 1.6;\r\n  }\r\n\r\n  .favorite-card {\r\n    display: grid;\r\n    grid-template-columns: 58px 1fr;\r\n    gap: 10px;\r\n    align-items: center;\r\n    padding: 10px;\r\n    border-radius: 14px;\r\n    margin-bottom: 10px;\r\n    background: rgba(255,255,255,.04);\r\n    border: 1px solid rgba(255,255,255,.08);\r\n  }\r\n\r\n  .favorite-thumb {\r\n    width: 58px;\r\n    height: 58px;\r\n    border-radius: 50%;\r\n    background-size: cover;\r\n    background-position: center;\r\n    border: 2px solid rgba(255,255,255,.8);\r\n    box-shadow: 0 0 12px cyan;\r\n  }\r\n\r\n  .favorite-info {\r\n    min-width: 0;\r\n  }\r\n\r\n  .favorite-name {\r\n    font-size: 11px;\r\n    line-height: 1.35;\r\n    word-break: break-word;\r\n    color: #fff;\r\n  }\r\n\r\n  .favorite-meta {\r\n    margin-top: 4px;\r\n    font-size: 10px;\r\n    color: rgba(255,255,255,.64);\r\n    text-transform: uppercase;\r\n    letter-spacing: .08em;\r\n  }\r\n\r\n  .favorite-row {\r\n    display: flex;\r\n    gap: 8px;\r\n    margin-top: 8px;\r\n    flex-wrap: wrap;\r\n  }\r\n\r\n  .favorite-btn {\r\n    border: 1px solid rgba(255,255,255,.14);\r\n    background: rgba(255,255,255,.06);\r\n    color: #fff;\r\n    border-radius: 999px;\r\n    padding: 6px 9px;\r\n    cursor: pointer;\r\n    font-size: 10px;\r\n    font-family: inherit;\r\n    text-transform: uppercase;\r\n  }\r\n<\/style>\r\n\r\n<div id=\"floatingButtons\">\r\n  <button id=\"cityCardBtn\" class=\"ggg-icon-btn\" title=\"City Card\">\r\n    <img decoding=\"async\" src=\"http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240911_204007_Gallery.jpg\" style=\"width:170%; height:100%; border-radius:50%;\">\r\n  <\/button>\r\n\r\n  <button\r\n    id=\"pyramidBtn\"\r\n    title=\"Back to MedaYork Pyramid\"\r\n    onclick=\"window.location.href='https:\/\/godsgalaxygame.com\/GGG\/medayork-pyramid-2\/';\">\r\n    \ud83e\uddca\r\n  <\/button>\r\n\r\n  <button id=\"roseBtn\" title=\"Rose of the Universe\"><\/button>\r\n\r\n  <button id=\"favoritesBtn\">\ud83d\udc96<\/button>\r\n  <button id=\"signinBtn\">Sign In \/ Sign Up<\/button>\r\n<\/div>\r\n\r\n<div id=\"favoritesPanel\">\r\n  <div class=\"favorites-header\">\r\n    <div class=\"favorites-title\">My Favorites<\/div>\r\n    <button class=\"favorites-close\" type=\"button\" onclick=\"gggCloseFavoritesPanel()\">Close<\/button>\r\n  <\/div>\r\n\r\n  <div class=\"favorites-actions\">\r\n    <button class=\"favorites-action-btn\" type=\"button\" onclick=\"gggShowCurrentPageFavorites()\">Show on Page<\/button>\r\n    <button class=\"favorites-action-btn\" type=\"button\" onclick=\"gggClearFavoritesWithConfirm()\">Clear All<\/button>\r\n  <\/div>\r\n\r\n  <div id=\"favoritesPanelContent\" class=\"favorites-empty\">No favorites saved yet.<\/div>\r\n<\/div>\r\n\r\n<script>\r\n  \/* ========================================================\r\n     PAGE SETTINGS\r\n  ======================================================== *\/\r\n  const PAGE_KEY = \"ownersclub\";\r\n  const CUBE_ID = \"ownerCube\";\r\n  const AJAX_URL = \"\/GGG\/wp-admin\/admin-ajax.php\";\r\n  const ACCOUNT_URL = \"https:\/\/godsgalaxygame.com\/account\/\";\r\n  const LOGIN_URL = \"https:\/\/godsgalaxygame.com\/login\/\";\r\n  const PYRAMID_URL = \"https:\/\/godsgalaxygame.com\/GGG\/medayork-pyramid-2\/\";\r\n  const CITY_CARD_URL = \"https:\/\/godsgalaxygame.com\/GGG\/aries\/?citycard=1\";\r\n\r\n  \/* ========================================================\r\n     CUBE MOVEMENT\r\n  ======================================================== *\/\r\n  let isDragging = false, startX, startY, rotateX = 0, rotateY = 0;\r\n\r\n  const cube = document.getElementById(CUBE_ID);\r\n  const cubeContainer = document.querySelector('.cube-scene');\r\n\r\n  function updateRotation(x, y) {\r\n    if (!cube) return;\r\n    cube.style.transform = `rotateX(${x}deg) rotateY(${y}deg)`;\r\n  }\r\n\r\n  function onMouseDown(e) {\r\n    isDragging = true;\r\n    startX = e.clientX;\r\n    startY = e.clientY;\r\n  }\r\n\r\n  function onMouseMove(e) {\r\n    if (!isDragging) return;\r\n    const deltaX = e.clientX - startX;\r\n    const deltaY = e.clientY - startY;\r\n    rotateY += deltaX * 0.5;\r\n    rotateX -= deltaY * 0.5;\r\n    updateRotation(rotateX, rotateY);\r\n    startX = e.clientX;\r\n    startY = e.clientY;\r\n  }\r\n\r\n  function onMouseUp() {\r\n    isDragging = false;\r\n  }\r\n\r\n  function onTouchStart(e) {\r\n    isDragging = true;\r\n    startX = e.touches[0].clientX;\r\n    startY = e.touches[0].clientY;\r\n  }\r\n\r\n  function onTouchMove(e) {\r\n    if (!isDragging) return;\r\n    const deltaX = e.touches[0].clientX - startX;\r\n    const deltaY = e.touches[0].clientY - startY;\r\n    rotateY += deltaX * 0.5;\r\n    rotateX -= deltaY * 0.5;\r\n    updateRotation(rotateX, rotateY);\r\n    startX = e.touches[0].clientX;\r\n    startY = e.touches[0].clientY;\r\n  }\r\n\r\n  function onTouchEnd() {\r\n    isDragging = false;\r\n  }\r\n\r\n  if (cubeContainer && cube) {\r\n    cubeContainer.addEventListener('mousedown', onMouseDown);\r\n    window.addEventListener('mousemove', onMouseMove);\r\n    window.addEventListener('mouseup', onMouseUp);\r\n    cubeContainer.addEventListener('touchstart', onTouchStart, { passive: true });\r\n    window.addEventListener('touchmove', onTouchMove, { passive: true });\r\n    window.addEventListener('touchend', onTouchEnd);\r\n  }\r\n\r\n  \/* ========================================================\r\n     USER STATUS\r\n  ======================================================== *\/\r\n  let gggUserStatus = {\r\n    logged_in: false,\r\n    user_id: 0,\r\n    display_name: \"\",\r\n    email: \"\",\r\n    account_url: ACCOUNT_URL,\r\n    login_url: LOGIN_URL\r\n  };\r\n\r\n  function gggUpdateSignInButton() {\r\n    const btn = document.getElementById(\"signinBtn\");\r\n    if (!btn) return;\r\n\r\n    if (gggUserStatus.logged_in) {\r\n      btn.textContent = \"My Account\";\r\n      btn.onclick = function () {\r\n        window.location.href = gggUserStatus.account_url || ACCOUNT_URL;\r\n      };\r\n    } else {\r\n      btn.textContent = \"Sign In \/ Sign Up\";\r\n      btn.onclick = function () {\r\n        window.location.href = gggUserStatus.login_url || LOGIN_URL;\r\n      };\r\n    }\r\n  }\r\n\r\n  function gggLoadUserStatus() {\r\n    const formData = new FormData();\r\n    formData.append(\"action\", \"ggg_get_current_user_status\");\r\n\r\n    return fetch(AJAX_URL, {\r\n      method: \"POST\",\r\n      credentials: \"same-origin\",\r\n      body: formData\r\n    })\r\n    .then(r => r.json())\r\n    .then(data => {\r\n      if (data && data.success && data.data) {\r\n        gggUserStatus = data.data;\r\n      }\r\n      gggUpdateSignInButton();\r\n    })\r\n    .catch(() => {\r\n      gggUpdateSignInButton();\r\n    });\r\n  }\r\n\r\n  \/* ========================================================\r\n     FAVORITES\r\n  ======================================================== *\/\r\n  let favorites = [];\r\n\r\n  function gggUpdateFavoritesButton() {\r\n    const btn = document.getElementById(\"favoritesBtn\");\r\n    if (!btn) return;\r\n    btn.textContent = favorites.length > 0 ? \"\ud83d\udc98\" : \"\ud83d\udc96\";\r\n  }\r\n\r\n  function gggLoadFavorites() {\r\n    const formData = new FormData();\r\n    formData.append(\"action\", \"ggg_get_favorites\");\r\n\r\n    return fetch(AJAX_URL, {\r\n      method: \"POST\",\r\n      credentials: \"same-origin\",\r\n      body: formData\r\n    })\r\n    .then(r => r.json())\r\n    .then(data => {\r\n      if (data && data.success && data.data) {\r\n        favorites = Array.isArray(data.data.favorites) ? data.data.favorites : [];\r\n      } else {\r\n        favorites = [];\r\n      }\r\n      gggUpdateFavoritesButton();\r\n      gggRenderFavoritesPanel();\r\n    })\r\n    .catch(() => {\r\n      favorites = [];\r\n      gggUpdateFavoritesButton();\r\n      gggRenderFavoritesPanel();\r\n    });\r\n  }\r\n\r\n  function gggRenderFavoritesPanel() {\r\n    const panelContent = document.getElementById(\"favoritesPanelContent\");\r\n    if (!panelContent) return;\r\n\r\n    if (!favorites.length) {\r\n      panelContent.innerHTML = `<div class=\"favorites-empty\">No favorites saved yet.<\/div>`;\r\n      return;\r\n    }\r\n\r\n    panelContent.innerHTML = favorites.map(fav => {\r\n      const title = fav.id ? String(fav.id).replace(\/-\/g, ' ') : 'Favorite';\r\n      const pageLabel = fav.pageKey ? String(fav.pageKey).toUpperCase() : 'PAGE';\r\n\r\n      return `\r\n        <div class=\"favorite-card\">\r\n          <div class=\"favorite-thumb\" style=\"background-image:url('${fav.imgUrl || ''}')\"><\/div>\r\n          <div class=\"favorite-info\">\r\n            <div class=\"favorite-name\">${title}<\/div>\r\n            <div class=\"favorite-meta\">${pageLabel}<\/div>\r\n            <div class=\"favorite-row\">\r\n              ${fav.pageKey === PAGE_KEY ? `<button class=\"favorite-btn\" type=\"button\" onclick=\"gggFocusFavoriteOnPage('${fav.id}')\">Show<\/button>` : ``}\r\n              ${(fav.lat && fav.lng) ? `<button class=\"favorite-btn\" type=\"button\" onclick=\"focusOnHost(${parseFloat(fav.lat)}, ${parseFloat(fav.lng)})\">Map<\/button>` : ``}\r\n              <button class=\"favorite-btn\" type=\"button\" onclick=\"gggRemoveFavoriteById('${fav.id}')\">Remove<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      `;\r\n    }).join('');\r\n  }\r\n\r\n  function gggOpenFavoritesPanel() {\r\n    const panel = document.getElementById(\"favoritesPanel\");\r\n    if (!panel) return;\r\n    panel.classList.add(\"show\");\r\n  }\r\n\r\n  function gggCloseFavoritesPanel() {\r\n    const panel = document.getElementById(\"favoritesPanel\");\r\n    if (!panel) return;\r\n    panel.classList.remove(\"show\");\r\n  }\r\n\r\n  function gggShowCurrentPageFavorites() {\r\n    const currentPageFavorites = favorites.filter(f => f.pageKey === PAGE_KEY);\r\n    if (!currentPageFavorites.length) return;\r\n\r\n    document.querySelectorAll('.host-circle').forEach(btn => btn.style.display = 'none');\r\n\r\n    currentPageFavorites.forEach(fav => {\r\n      const matches = document.querySelectorAll(`.${fav.id}`);\r\n      matches.forEach(el => el.style.display = 'inline-block');\r\n    });\r\n\r\n    gggCloseFavoritesPanel();\r\n  }\r\n\r\n  function gggFocusFavoriteOnPage(id) {\r\n    document.querySelectorAll('.host-circle').forEach(btn => btn.style.display = 'none');\r\n    const matches = document.querySelectorAll(`.${id}`);\r\n    matches.forEach(el => el.style.display = 'inline-block');\r\n    gggCloseFavoritesPanel();\r\n  }\r\n\r\n  function toggleFavorite(id, imgUrl, mapLat, mapLng) {\r\n    if (!gggUserStatus.logged_in) {\r\n      alert(\"Please sign in first to save favorites.\");\r\n      window.location.href = gggUserStatus.login_url || LOGIN_URL;\r\n      return;\r\n    }\r\n\r\n    const alreadySaved = favorites.some(f => f.id === id);\r\n\r\n    if (alreadySaved) {\r\n      return gggRemoveFavoriteById(id);\r\n    }\r\n\r\n    const formData = new FormData();\r\n    formData.append(\"action\", \"ggg_add_favorite\");\r\n    formData.append(\"id\", id);\r\n    formData.append(\"imgUrl\", imgUrl || \"\");\r\n    formData.append(\"mapLat\", mapLat || \"\");\r\n    formData.append(\"mapLng\", mapLng || \"\");\r\n    formData.append(\"pageKey\", PAGE_KEY);\r\n\r\n    fetch(AJAX_URL, {\r\n      method: \"POST\",\r\n      credentials: \"same-origin\",\r\n      body: formData\r\n    })\r\n    .then(r => r.json())\r\n    .then(data => {\r\n      if (data && data.success && data.data) {\r\n        favorites = Array.isArray(data.data.favorites) ? data.data.favorites : [];\r\n        gggUpdateFavoritesButton();\r\n        gggRenderFavoritesPanel();\r\n        console.log(\"Favorite added:\", id);\r\n      }\r\n    });\r\n  }\r\n\r\n  function gggRemoveFavoriteById(id) {\r\n    if (!gggUserStatus.logged_in) return;\r\n\r\n    const formData = new FormData();\r\n    formData.append(\"action\", \"ggg_remove_favorite\");\r\n    formData.append(\"id\", id);\r\n\r\n    fetch(AJAX_URL, {\r\n      method: \"POST\",\r\n      credentials: \"same-origin\",\r\n      body: formData\r\n    })\r\n    .then(r => r.json())\r\n    .then(data => {\r\n      if (data && data.success && data.data) {\r\n        favorites = Array.isArray(data.data.favorites) ? data.data.favorites : [];\r\n        gggUpdateFavoritesButton();\r\n        gggRenderFavoritesPanel();\r\n        console.log(\"Favorite removed:\", id);\r\n      }\r\n    });\r\n  }\r\n\r\n  function clearFavorites() {\r\n    if (!gggUserStatus.logged_in) return;\r\n\r\n    const formData = new FormData();\r\n    formData.append(\"action\", \"ggg_clear_favorites\");\r\n\r\n    fetch(AJAX_URL, {\r\n      method: \"POST\",\r\n      credentials: \"same-origin\",\r\n      body: formData\r\n    })\r\n    .then(r => r.json())\r\n    .then(data => {\r\n      if (data && data.success && data.data) {\r\n        favorites = Array.isArray(data.data.favorites) ? data.data.favorites : [];\r\n        gggUpdateFavoritesButton();\r\n        gggRenderFavoritesPanel();\r\n      }\r\n    });\r\n  }\r\n\r\n  function gggClearFavoritesWithConfirm() {\r\n    if (!favorites.length) return;\r\n    const ok = confirm(\"Clear all saved favorites?\");\r\n    if (!ok) return;\r\n    clearFavorites();\r\n  }\r\n\r\n  \/* ========================================================\r\n     MAP FOCUS\r\n  ======================================================== *\/\r\n  function focusOnHost(lat, lng) {\r\n    if (window.ggMap) {\r\n      window.ggMap.setCenter({ lat, lng });\r\n      window.ggMap.setZoom(15);\r\n      new google.maps.Marker({ position: { lat, lng }, map: window.ggMap });\r\n    }\r\n  }\r\n\r\n  \/* ========================================================\r\n     EXTRA BUTTONS\r\n  ======================================================== *\/\r\n  document.getElementById(\"favoritesBtn\").addEventListener(\"click\", () => {\r\n    gggOpenFavoritesPanel();\r\n  });\r\n\r\n  document.getElementById(\"cityCardBtn\").addEventListener(\"click\", () => {\r\n    window.location.href = CITY_CARD_URL;\r\n  });\r\n\r\n  document.getElementById(\"roseBtn\").addEventListener(\"click\", () => {\r\n    alert(\"Rose of the Universe portfolio area coming next.\");\r\n  });\r\n\r\n  \/* ========================================================\r\n     INIT\r\n  ======================================================== *\/\r\n  document.addEventListener(\"DOMContentLoaded\", function () {\r\n  const parameters = new URLSearchParams(window.location.search);\r\n\r\n  \/*\r\n   * The Level 8 Control Panel does not need the customer\r\n   * account and Favorites requests running underneath it.\r\n   *\/\r\n  if (parameters.get(\"level8panel\") === \"1\") {\r\n    return;\r\n  }\r\n\r\n  Promise.all([\r\n    gggLoadUserStatus(),\r\n    gggLoadFavorites()\r\n  ]).then(() => {\r\n    gggUpdateSignInButton();\r\n    gggUpdateFavoritesButton();\r\n    gggRenderFavoritesPanel();\r\n  });\r\n});\r\n<\/script>\r\n\r\n\r\n\r\n<!-- HOST CIRCLES \u2014 CSS (Accommodations) -->\r\n<style>\r\n  #hostButtons{\r\n    display:none;                 \/* hidden until a sub-option is clicked *\/\r\n    position:absolute;\r\n    top:50%; left:50%;\r\n    transform:translate(-50%,-50%);\r\n    width:100%; max-width:500px; height:500px;\r\n    pointer-events:none;          \/* turned ON in JS when shown *\/\r\n    z-index:3000;\r\n  }\r\n\r\n  \/* buttons *\/\r\n  #hostButtons .host-circle{\r\n    width:80px; height:80px; border-radius:50%;\r\n    border:2px solid #fff; box-shadow:0 0 14px #fff;\r\n    background-size:cover; background-position:center;\r\n    position:absolute; pointer-events:auto; cursor:pointer;\r\n    transition:transform .3s, box-shadow .3s;\r\n  }\r\n  #hostButtons .host-circle:hover{ transform:scale(1.15); box-shadow:0 0 20px cyan; }\r\n\r\n  \/* desktop placement (around the circle) *\/\r\n  #hostButtons .one    { top:4%;    left:10%; }\r\n  #hostButtons .five   { top:4%;    right:10%; }\r\n  #hostButtons .seven  { bottom:8%; left:10%; }\r\n  #hostButtons .month  { bottom:8%; right:10%; }\r\n\r\n  \/* color accents per family (match cube face glows) *\/\r\n  #hostButtons .highrise { border-color:beige;   box-shadow:0 0 14px beige; }\r\n  #hostButtons .historic { border-color:#00ccff; box-shadow:0 0 14px #00ccff; }\r\n  #hostButtons .ecostay  { border-color:#33ff33; box-shadow:0 0 14px #33ff33; }\r\n  #hostButtons .mansions { border-color:red;     box-shadow:0 0 14px red; }\r\n\r\n  \/* phone: turn into one row under the map *\/\r\n  @media (max-width:768px){\r\n    #hostButtons{\r\n      position:relative; top:auto; left:auto; transform:none;\r\n      height:auto; margin-top:-35px;\r\n      display:none;               \/* still hidden by default *\/\r\n      flex-wrap:nowrap; justify-content:center; gap:10px;\r\n    }\r\n    #hostButtons .host-circle{ position:relative; width:75px; height:75px; margin:0 6px; }\r\n  }\r\n\r\n<\/style>\r\n\r\n<!-- HOST CIRCLES \u2014 HTML (Accommodations: High-Rise\r\n \/ Historic \/ Eco-Stay \/ Mansions) -->\r\n<div id=\"hostButtons\">\r\n  <!-- HIGH-RISE (beige) -->\r\n  <button class=\"host-circle use use-week one\"\r\n    data-lat=\"6.241568778606768\" data-lng=\"-75.22695655776336\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240821_175227_Instagram.jpg');\"\r\n    title=\"High-Rise \u2022 1\u20133 Days\"><\/button>\r\n\r\n  <button class=\"host-circle use use-short five\"\r\n    data-lat=\"6.241568778606768\" data-lng=\"-75.22695655776336\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"High-Rise \u2022 4\u20136 Days\"><\/button>\r\n\r\n  <button class=\"host-circle use use-onlinez seven\"\r\n    data-lat=\"6.24267\" data-lng=\"-75.22668\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"High-Rise \u2022 7 Days\"><\/button>\r\n\r\n  <button class=\"host-circle use use-penthouse month\"\r\n    data-lat=\"6.24267\" data-lng=\"-75.22668\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"High-Rise \u2022 1 Month\"><\/button>\r\n\r\n  <!-- HISTORIC (cyan) -->\r\n  <button class=\"host-circle exchangez exchangez-internally one\"\r\n    data-lat=\"6.23796\" data-lng=\"-75.21421\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"Historic \u2022 1\u20133 Days\"><\/button>\r\n\r\n  <button class=\"host-circle exchangez exchangez-comm five\"\r\n    data-lat=\"6.23796\" data-lng=\"-75.21421\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"Historic \u2022 4\u20136 Days\"><\/button>\r\n\r\n  <button class=\"host-circle exchangez exchangez-year seven\"\r\n    data-lat=\"6.24006\" data-lng=\"-75.18750\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"Historic \u2022 7 Days\"><\/button>\r\n\r\n  <button class=\"host-circle exchangez exchangez-ownership month\"\r\n    data-lat=\"6.22670\" data-lng=\"-75.18056\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"Historic \u2022 1 Month\"><\/button>\r\n\r\n  <!-- ECO-STAY (green) -->\r\n  <button class=\"host-circle trade trade-rooms one\"\r\n    data-lat=\"6.241568778606768\" data-lng=\"-75.22695655776336\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"Eco-Stay \u2022 1\u20133 Days\"><\/button>\r\n\r\n  <button class=\"host-circle trade trade-dayzz five\"\r\n    data-lat=\"6.241568778606768\" data-lng=\"-75.22695655776336\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"Eco-Stay \u2022 4\u20136 Days\"><\/button>\r\n\r\n  <button class=\"host-circle trade trade-wknd seven\"\r\n    data-lat=\"6.22879\" data-lng=\"-75.21184\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"Eco-Stay \u2022 7 Days\"><\/button>\r\n\r\n  <button class=\"host-circle trade trade-wk month\"\r\n    data-lat=\"6.22879\" data-lng=\"-75.21184\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"Eco-Stay \u2022 1 Month\"><\/button>\r\n\r\n  <!-- MANSIONS (red) -->\r\n  <button class=\"host-circle buyzz buyzz-wkz one\"\r\n    data-lat=\"6.24203\" data-lng=\"-75.22696\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"Mansions \u2022 1\u20133 Days\"><\/button>\r\n\r\n  <button class=\"host-circle buyzz buyzz-bc five\"\r\n    data-lat=\"6.24203\" data-lng=\"-75.22696\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061057_PowerPoint-1.jpg');\"\r\n    title=\"Mansions \u2022 4\u20136 Days\"><\/button>\r\n\r\n  <button class=\"host-circle buyzz buyzz-trc seven\"\r\n    data-lat=\"6.24203\" data-lng=\"-75.22696\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240706_061611_PowerPoint.jpg');\"\r\n    title=\"Mansions \u2022 7 Days\"><\/button>\r\n\r\n  <button class=\"host-circle buyzz buyzz-cc month\"\r\n    data-lat=\"6.24203\" data-lng=\"-75.22696\"\r\n    style=\"background-image:url('http:\/\/godsgalaxygame.com\/GGG\/wp-content\/uploads\/2025\/12\/Screenshot_20240821_175227_Instagram.jpg');\"\r\n    title=\"Mansions \u2022 1 Month\"><\/button>\r\n<\/div>\r\n\r\n<!-- HOST CIRCLES \u2014 JS (Accommodations) -->\r\n<script>\r\n  \/* Show only the requested key, e.g., 'highrise-one' *\/\r\n  function showHostButtons(suboption){\r\n  loadLevel8Hosts(suboption);\r\n}\r\n\r\n  \/\/ dbl-tap \/ dbl-click to favorite (uses your existing toggleFavorite)\r\n  document.addEventListener('DOMContentLoaded', () => {\r\n    document.querySelectorAll('#hostButtons .host-circle').forEach(btn => {\r\n      btn.addEventListener('dblclick', (e) => {\r\n        e.preventDefault();\r\n\r\n        \/\/ \u2705 Get the specific key like \"heli-around\" \/ \"yacht-goto\"\r\n        const id = [...btn.classList].find(c =>\r\n          c.includes('-') &&\r\n          !['host-circle','around','goto','emergency','adventure'].includes(c)\r\n        );\r\n\r\n        if (!id) {\r\n          console.warn(\"No favorite id found for button:\", btn.className);\r\n          return;\r\n        }\r\n\r\n        \/\/ background-image: url(\"...\") or url('...')\r\n        const bg = btn.style.backgroundImage || '';\r\n        const img = bg.startsWith('url(')\r\n          ? bg.slice(4, -1).replace(\/^[\"']|[\"']$\/g, '')\r\n          : '';\r\n\r\n        const lat = parseFloat(btn.dataset.lat);\r\n        const lng = parseFloat(btn.dataset.lng);\r\n\r\n        if (typeof toggleFavorite === 'function') {\r\n          toggleFavorite(id, img, lat, lng);\r\n        } else {\r\n          console.warn(\"toggleFavorite() is not defined yet.\");\r\n        }\r\n      });\r\n    });\r\n  });\r\n\r\n\r\n\r\n  \/* Center the map when any host circle is clicked *\/\r\n  document.addEventListener('click', function (e) {\r\n    const btn = e.target.closest('#hostButtons .host-circle');\r\n    if (!btn) return;\r\n\r\n    const lat = parseFloat(btn.dataset.lat);\r\n    const lng = parseFloat(btn.dataset.lng);\r\n    if (!Number.isFinite(lat) || !Number.isFinite(lng)) return;\r\n\r\n    if (typeof window.focusOnHost === 'function') {\r\n      focusOnHost(lat, lng);\r\n      return;\r\n    }\r\n\r\n    if (window.ggMap && window.google) {\r\n      const pos = new google.maps.LatLng(lat, lng);\r\n      ggMap.setCenter(pos);\r\n      ggMap.setZoom(15);\r\n      new google.maps.Marker({ position: pos, map: ggMap });\r\n    }\r\n  });\r\n<\/script>\r\n<script>\r\nasync function loadLevel8Hosts(suboption){\r\n\r\n  const fd = new FormData();\r\n  fd.append(\"action\", \"ggg_l8_get_inventory\");\r\n\r\n  const res = await fetch(\"\/GGG\/wp-admin\/admin-ajax.php\", {\r\n    method: \"POST\",\r\n    credentials: \"same-origin\",\r\n    body: fd\r\n  });\r\n\r\n  const data = await res.json();\r\n  if(!data.success) return;\r\n\r\n  const items = data.data.items || [];\r\n\r\n  const filtered = items.filter(item =>\r\n    item.suboptionKey === suboption &&\r\n    item.status === \"active\"\r\n  );\r\n\r\n  const wrap = document.getElementById(\"hostButtons\");\r\n  if(!wrap) return;\r\n\r\n  wrap.innerHTML = \"\";\r\n\r\n  if(!filtered.length){\r\n    wrap.style.display = \"none\";\r\n    return;\r\n  }\r\n\r\n  const positions = [\"one\",\"five\",\"seven\",\"month\"];\r\n\r\n  filtered.forEach((item, index) => {\r\n    const btn = document.createElement(\"button\");\r\n    btn.className = \"host-circle \" + positions[index % 4];\r\n    btn.style.backgroundImage = `url('${item.imageUrl || \"\"}')`;\r\n    btn.dataset.lat = item.lat || \"\";\r\n    btn.dataset.lng = item.lng || \"\";\r\n    btn.title = item.name || \"Level 8 Item\";\r\n\r\n    btn.addEventListener(\"dblclick\", function(e){\r\n      e.preventDefault();\r\n      if(typeof toggleFavorite === \"function\"){\r\n        toggleFavorite(item.id, item.imageUrl, item.lat, item.lng);\r\n      }\r\n    });\r\n\r\n    wrap.appendChild(btn);\r\n  });\r\n\r\n  wrap.style.display = \"flex\";\r\n  wrap.style.pointerEvents = \"auto\";\r\n}\r\n<\/script>\r\n\r\n\r\n\r\n<style>\r\n\r\nhtml:has(#l8cp.is-open),body:has(#l8cp.is-open){overflow:hidden!important}\r\n#l8cp{display:none;position:fixed;inset:0;z-index:2147483647;width:100vw;height:100vh;height:100dvh;overflow:hidden;color:#f4fbff;background:radial-gradient(circle at 5% 0,rgba(0,229,255,.18),transparent 28%),radial-gradient(circle at 100% 10%,rgba(144,76,255,.18),transparent 30%),#030712;font-family:Inter,Arial,sans-serif}\r\n#l8cp.is-open{display:grid;grid-template-rows:auto auto 1fr}#l8cp *{box-sizing:border-box}\r\n.l8cp-head{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:17px 22px;border-bottom:1px solid #19364b;background:rgba(3,7,18,.9)}\r\n.l8cp-title{font-size:clamp(20px,2.1vw,34px);font-weight:950;letter-spacing:-.04em}.l8cp-title span{color:#70ecff}.l8cp-note{color:#8da8ba;font-size:12px;margin-top:3px}\r\n.l8cp-btn,.l8cp-chip,.l8cp-system{border:1px solid #234d64;color:#eaffff;background:#0a1725;cursor:pointer;font-weight:850}.l8cp-btn{padding:11px 16px;border-radius:12px}.l8cp-btn:hover,.l8cp-chip:hover,.l8cp-system:hover{border-color:#65eaff;box-shadow:0 0 18px rgba(55,220,255,.14)}.l8cp-btn.primary{color:#03131a;background:linear-gradient(135deg,#7df2ff,#36a9ff);border:0}.l8cp-btn.danger{color:#ffb8c4;border-color:#713145}.l8cp-btn:disabled{opacity:.5;cursor:wait}\r\n.l8cp-systems{display:grid;grid-template-columns:repeat(3,minmax(180px,1fr));gap:12px;padding:11px 22px;border-bottom:1px solid #19364b}.l8cp-selectbox label{display:block;margin-bottom:5px;color:#88a4b7;font-size:10px;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.l8cp-selectbox select{width:100%;padding:11px;border:1px solid #25516a;border-radius:12px;color:#fff;background:#071522;font-weight:850}.l8cp-selectbox select option{color:#07101f;background:#fff}\r\n.l8cp-main{min-height:0;display:grid;grid-template-columns:250px minmax(360px,.9fr) minmax(420px,1.25fr);gap:12px;padding:12px}.l8cp-panel{min-height:0;overflow:auto;border:1px solid #19364b;border-radius:20px;background:rgba(9,18,31,.82);padding:16px}.l8cp-panel h2{font-size:16px;margin:0 0 12px}.l8cp-side{display:flex;flex-direction:column;gap:8px}.l8cp-chip{width:100%;padding:12px;border-radius:12px;text-align:left}.l8cp-chip.active{color:#83f2ff;border-color:#69e8ff;background:#102b3c}.l8cp-chip small{display:block;color:#829daf;margin-top:4px;font-weight:600}\r\n.l8cp-path{min-height:38px;padding:8px 11px;margin-bottom:12px;border:1px solid #1b4055;border-radius:11px;color:#82eaff;background:#071523;font-size:12px}.l8cp-options{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px}.l8cp-options .l8cp-chip{width:auto;min-width:104px}.l8cp-form{display:grid;grid-template-columns:1fr 1fr;gap:10px}.l8cp-field.full{grid-column:1\/-1}.l8cp-field label{display:block;margin:0 0 5px;color:#87a3b5;font-size:10px;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.l8cp-field input,.l8cp-field textarea{width:100%;border:1px solid #20455b;border-radius:11px;padding:11px;color:#fff;background:#050d18;outline:none}.l8cp-field input:focus,.l8cp-field textarea:focus{border-color:#5be5ff;box-shadow:0 0 0 3px rgba(91,229,255,.08)}.l8cp-field textarea{min-height:72px;resize:vertical}.l8cp-toggle{display:flex;gap:8px;align-items:center;padding-top:20px}.l8cp-toggle input{accent-color:#5eeaff}.l8cp-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:13px}.l8cp-search{width:100%;padding:11px;border:1px solid #20455b;border-radius:12px;color:#fff;background:#050d18;margin-bottom:10px}\r\n.l8cp-list{display:grid;gap:9px}.l8cp-empty,.l8cp-error{padding:20px;border:1px dashed #28506a;border-radius:15px;color:#8da8ba}.l8cp-error{color:#ffb4c2;border-color:#773044}.l8cp-item{display:grid;grid-template-columns:64px 1fr auto;gap:11px;align-items:center;padding:10px;border:1px solid #173b50;border-radius:15px;background:#07121f}.l8cp-thumb{width:64px;height:64px;border-radius:13px;background:#0d1a28 center\/cover no-repeat;border:1px solid #25546d}.l8cp-name{font-weight:900;color:#eaffff}.l8cp-meta{margin-top:4px;color:#7f9daf;font-size:11px;line-height:1.4}.l8cp-badge{display:inline-block;margin-top:6px;padding:4px 8px;border:1px solid #2b6178;border-radius:999px;color:#75eaff;font-size:9px;font-weight:900;text-transform:uppercase}.l8cp-item-actions{display:flex;gap:6px}.l8cp-item-actions .l8cp-btn{padding:8px 10px;font-size:10px}.l8cp-live{padding:10px 12px;border-radius:11px;background:#09241f;color:#74f5ca;border:1px solid #17614f;font-size:11px;margin-bottom:10px}.l8cp-toast{position:fixed;right:18px;bottom:18px;z-index:2147483647;max-width:360px;padding:13px 16px;border-radius:13px;background:#09251f;border:1px solid #1a765f;color:#baffea;box-shadow:0 15px 50px #000;display:none}.l8cp-toast.bad{background:#35101a;border-color:#8b2f49;color:#ffc2ce}\r\n@media(max-width:1050px){.l8cp-main{grid-template-columns:210px minmax(330px,1fr)}.l8cp-list-panel{grid-column:1\/-1;max-height:38vh}.l8cp-systems{grid-template-columns:repeat(3,minmax(160px,1fr))}}\r\n@media(max-width:700px){#l8cp.is-open{overflow:auto;display:block}.l8cp-head{position:sticky;top:0;z-index:3;padding:12px}.l8cp-note{display:none}.l8cp-systems{padding:9px 12px;grid-template-columns:1fr}.l8cp-main{display:block;padding:9px}.l8cp-panel{margin-bottom:9px;overflow:visible}.l8cp-side{display:grid;grid-template-columns:1fr 1fr}.l8cp-form{grid-template-columns:1fr}.l8cp-field.full{grid-column:auto}.l8cp-item{grid-template-columns:52px 1fr}.l8cp-thumb{width:52px;height:52px}.l8cp-item-actions{grid-column:1\/-1}.l8cp-list-panel{max-height:none}}\r\n\r\n\/* =========================================================\r\n   LEVEL 8 \u2014 CUSTOMER WORKFLOW INTERFACE\r\n========================================================= *\/\r\n\r\n.l8cp-request {\r\n  width: 100%;\r\n  display: grid;\r\n  grid-template-columns: minmax(0, 1fr) auto;\r\n  align-items: start;\r\n  gap: 12px;\r\n  padding: 14px;\r\n  border: 1px solid #1d4359;\r\n  border-radius: 16px;\r\n  color: #eefcff;\r\n  background: linear-gradient(\r\n    145deg,\r\n    rgba(10, 25, 40, 0.96),\r\n    rgba(5, 13, 24, 0.96)\r\n  );\r\n  cursor: pointer;\r\n  text-align: left;\r\n  transition:\r\n    border-color 0.2s ease,\r\n    box-shadow 0.2s ease,\r\n    transform 0.2s ease;\r\n}\r\n\r\n.l8cp-request:hover {\r\n  border-color: #69e8ff;\r\n  box-shadow: 0 0 22px rgba(75, 224, 255, 0.13);\r\n  transform: translateY(-1px);\r\n}\r\n\r\n.l8cp-request.active {\r\n  border-color: #69e8ff;\r\n  background: linear-gradient(\r\n    145deg,\r\n    rgba(12, 45, 61, 0.98),\r\n    rgba(6, 18, 31, 0.98)\r\n  );\r\n  box-shadow:\r\n    0 0 0 1px rgba(105, 232, 255, 0.25),\r\n    0 0 24px rgba(75, 224, 255, 0.16);\r\n}\r\n\r\n.l8cp-request strong {\r\n  display: block;\r\n  color: #ffffff;\r\n  font-size: 14px;\r\n  line-height: 1.35;\r\n}\r\n\r\n.l8cp-request small {\r\n  display: block;\r\n  margin-top: 5px;\r\n  color: #88a6b9;\r\n  font-size: 11px;\r\n  line-height: 1.45;\r\n  overflow-wrap: anywhere;\r\n}\r\n\r\n.l8cp-requestStatus {\r\n  align-self: start;\r\n  padding: 5px 8px;\r\n  border: 1px solid #2c617b;\r\n  border-radius: 999px;\r\n  color: #7cecff;\r\n  background: rgba(35, 100, 126, 0.12);\r\n  font-size: 9px;\r\n  font-weight: 950;\r\n  text-transform: uppercase;\r\n  white-space: nowrap;\r\n}\r\n\r\n.l8cp-requestInfo {\r\n  display: grid;\r\n  grid-template-columns: repeat(2, minmax(0, 1fr));\r\n  gap: 9px;\r\n  margin-bottom: 14px;\r\n}\r\n\r\n.l8cp-infoBox {\r\n  min-width: 0;\r\n  padding: 11px;\r\n  border: 1px solid #183b50;\r\n  border-radius: 12px;\r\n  background: #06111e;\r\n}\r\n\r\n.l8cp-infoBox span {\r\n  display: block;\r\n  color: #7899ad;\r\n  font-size: 9px;\r\n  font-weight: 900;\r\n  letter-spacing: 0.1em;\r\n  text-transform: uppercase;\r\n}\r\n\r\n.l8cp-infoBox strong {\r\n  display: block;\r\n  margin-top: 5px;\r\n  color: #effcff;\r\n  font-size: 12px;\r\n  line-height: 1.4;\r\n  overflow-wrap: anywhere;\r\n}\r\n\r\n.l8cp-workflowHelp {\r\n  padding: 12px;\r\n  margin-bottom: 13px;\r\n  border-left: 3px solid #65eaff;\r\n  border-radius: 10px;\r\n  color: #9eb8c8;\r\n  background: rgba(74, 224, 255, 0.055);\r\n  font-size: 11px;\r\n  line-height: 1.55;\r\n}\r\n\r\n.l8cp-workflowHelp strong {\r\n  color: #ffffff;\r\n}\r\n\r\n.l8cp-refresh {\r\n  width: 100%;\r\n  margin-bottom: 9px;\r\n}\r\n\r\n.l8cp-sectionLabel {\r\n  margin: 16px 0 9px;\r\n  color: #72e9ff;\r\n  font-size: 10px;\r\n  font-weight: 950;\r\n  letter-spacing: 0.14em;\r\n  text-transform: uppercase;\r\n}\r\n\r\n.l8cp-readonly {\r\n  padding: 11px;\r\n  border: 1px solid #1d4055;\r\n  border-radius: 11px;\r\n  color: #a9c0ce;\r\n  background: #050d18;\r\n  line-height: 1.55;\r\n  white-space: pre-wrap;\r\n  overflow-wrap: anywhere;\r\n}\r\n\r\n.l8cp-requestItems {\r\n  display: grid;\r\n  gap: 7px;\r\n  margin-bottom: 13px;\r\n}\r\n\r\n.l8cp-requestItem {\r\n  display: grid;\r\n  grid-template-columns: 45px minmax(0, 1fr);\r\n  align-items: center;\r\n  gap: 9px;\r\n  padding: 8px;\r\n  border: 1px solid #17384b;\r\n  border-radius: 12px;\r\n  background: #071320;\r\n}\r\n\r\n.l8cp-requestItem img {\r\n  width: 45px;\r\n  height: 45px;\r\n  border-radius: 9px;\r\n  object-fit: cover;\r\n}\r\n\r\n.l8cp-requestItem strong {\r\n  display: block;\r\n  color: #ecfbff;\r\n  font-size: 11px;\r\n  overflow-wrap: anywhere;\r\n}\r\n\r\n.l8cp-requestItem small {\r\n  display: block;\r\n  margin-top: 3px;\r\n  color: #7f9daf;\r\n  font-size: 9px;\r\n  line-height: 1.4;\r\n}\r\n\r\n.l8cp-statusActions {\r\n  display: flex;\r\n  flex-wrap: wrap;\r\n  gap: 8px;\r\n  margin-top: 14px;\r\n}\r\n\r\n.l8cp-statusActions .l8cp-btn {\r\n  padding: 9px 11px;\r\n  font-size: 10px;\r\n}\r\n\r\n@media (max-width: 700px) {\r\n  .l8cp-request {\r\n    grid-template-columns: 1fr;\r\n  }\r\n\r\n  .l8cp-requestStatus {\r\n    justify-self: start;\r\n  }\r\n\r\n  .l8cp-requestInfo {\r\n    grid-template-columns: 1fr;\r\n  }\r\n\r\n  .l8cp-statusActions {\r\n    display: grid;\r\n    grid-template-columns: 1fr 1fr;\r\n  }\r\n\r\n  .l8cp-statusActions .l8cp-btn {\r\n    width: 100%;\r\n  }\r\n}\r\n\r\n\/* =========================================================\r\n   LEVEL 8 CONTROL PANEL \u2014 TRUE FULL-SCREEN DESKTOP FIX\r\n========================================================= *\/\r\n\r\nhtml.ggg-l8-panel-open,\r\nbody.ggg-l8-panel-open {\r\n  width: 100% !important;\r\n  height: 100% !important;\r\n  min-height: 100% !important;\r\n  margin: 0 !important;\r\n  padding: 0 !important;\r\n  overflow: hidden !important;\r\n}\r\n\r\nbody.ggg-l8-panel-open #l8cp {\r\n  display: grid !important;\r\n  position: fixed !important;\r\n  inset: 0 !important;\r\n  top: 0 !important;\r\n  right: 0 !important;\r\n  bottom: 0 !important;\r\n  left: 0 !important;\r\n\r\n  width: 100vw !important;\r\n  max-width: none !important;\r\n\r\n  height: 100vh !important;\r\n  height: 100dvh !important;\r\n  min-height: 100vh !important;\r\n\r\n  margin: 0 !important;\r\n  padding: 0 !important;\r\n\r\n  overflow: hidden !important;\r\n  transform: none !important;\r\n  z-index: 2147483647 !important;\r\n\r\n  grid-template-rows: auto auto minmax(0, 1fr) !important;\r\n}\r\n\r\nbody.ggg-l8-panel-open #l8cp .l8cp-main {\r\n  width: 100% !important;\r\n  max-width: none !important;\r\n  min-width: 0 !important;\r\n  min-height: 0 !important;\r\n  height: 100% !important;\r\n  overflow: hidden !important;\r\n\r\n  grid-template-columns:\r\n    minmax(220px, 16vw)\r\n    minmax(420px, 34vw)\r\n    minmax(480px, 1fr) !important;\r\n}\r\n\r\nbody.ggg-l8-panel-open #l8cp .l8cp-panel {\r\n  width: 100% !important;\r\n  max-width: none !important;\r\n  min-width: 0 !important;\r\n  min-height: 0 !important;\r\n  overflow-y: auto !important;\r\n  overflow-x: hidden !important;\r\n}\r\n\r\nbody.ggg-l8-panel-open #l8cp .l8cp-head,\r\nbody.ggg-l8-panel-open #l8cp .l8cp-systems {\r\n  width: 100% !important;\r\n  max-width: none !important;\r\n}\r\n\r\n@media (max-width: 1050px) {\r\n  body.ggg-l8-panel-open #l8cp .l8cp-main {\r\n    grid-template-columns:\r\n      minmax(200px, 26vw)\r\n      minmax(360px, 1fr) !important;\r\n    overflow-y: auto !important;\r\n  }\r\n\r\n  body.ggg-l8-panel-open #l8cp .l8cp-list-panel {\r\n    grid-column: 1 \/ -1 !important;\r\n    max-height: none !important;\r\n  }\r\n}\r\n\r\n@media (max-width: 700px) {\r\n  body.ggg-l8-panel-open #l8cp {\r\n    display: block !important;\r\n    overflow-y: auto !important;\r\n    overflow-x: hidden !important;\r\n  }\r\n\r\n  body.ggg-l8-panel-open #l8cp .l8cp-main {\r\n    display: block !important;\r\n    height: auto !important;\r\n    overflow: visible !important;\r\n  }\r\n\r\n  body.ggg-l8-panel-open #l8cp .l8cp-panel {\r\n    height: auto !important;\r\n    overflow: visible !important;\r\n  }\r\n}\r\n\r\n\/* THE CIRCLE \u2014 OWNER RENTALS *\/\r\n\r\n.l8cp-ownerSummary {\r\n  display: grid;\r\n  grid-template-columns: repeat(3, minmax(0, 1fr));\r\n  gap: 9px;\r\n  margin: 12px 0;\r\n}\r\n\r\n.l8cp-ownerMetric {\r\n  padding: 11px;\r\n  border: 1px solid #1c4960;\r\n  border-radius: 13px;\r\n  background: linear-gradient(\r\n    145deg,\r\n    rgba(7, 25, 39, 0.96),\r\n    rgba(4, 12, 22, 0.96)\r\n  );\r\n}\r\n\r\n.l8cp-ownerMetric span {\r\n  display: block;\r\n  color: #789caf;\r\n  font-size: 9px;\r\n  font-weight: 900;\r\n  letter-spacing: 0.1em;\r\n  text-transform: uppercase;\r\n}\r\n\r\n.l8cp-ownerMetric strong {\r\n  display: block;\r\n  margin-top: 5px;\r\n  color: #79efff;\r\n  font-size: 16px;\r\n}\r\n\r\n.l8cp-field select {\r\n  width: 100%;\r\n  padding: 11px;\r\n  border: 1px solid #20455b;\r\n  border-radius: 11px;\r\n  color: #fff;\r\n  background: #050d18;\r\n  outline: none;\r\n}\r\n\r\n.l8cp-field select:focus {\r\n  border-color: #5be5ff;\r\n  box-shadow: 0 0 0 3px rgba(91, 229, 255, 0.08);\r\n}\r\n\r\n.l8cp-ownerRecord {\r\n  width: 100%;\r\n  display: grid;\r\n  grid-template-columns: minmax(0, 1fr) auto;\r\n  gap: 10px;\r\n  padding: 13px;\r\n  border: 1px solid #173b50;\r\n  border-radius: 15px;\r\n  color: #eaffff;\r\n  background: #07121f;\r\n  text-align: left;\r\n  cursor: pointer;\r\n}\r\n\r\n.l8cp-ownerRecord:hover,\r\n.l8cp-ownerRecord.active {\r\n  border-color: #65eaff;\r\n  box-shadow: 0 0 20px rgba(55, 220, 255, 0.13);\r\n}\r\n\r\n.l8cp-ownerRecord strong {\r\n  display: block;\r\n  font-size: 13px;\r\n}\r\n\r\n.l8cp-ownerRecord small {\r\n  display: block;\r\n  margin-top: 5px;\r\n  color: #7f9daf;\r\n  font-size: 10px;\r\n  line-height: 1.45;\r\n}\r\n\r\n.l8cp-ownerStatus {\r\n  align-self: start;\r\n  padding: 5px 8px;\r\n  border: 1px solid #2b6178;\r\n  border-radius: 999px;\r\n  color: #75eaff;\r\n  font-size: 9px;\r\n  font-weight: 900;\r\n  text-transform: uppercase;\r\n  white-space: nowrap;\r\n}\r\n\r\n.l8cp-ownerNotice {\r\n  margin-top: 13px;\r\n  padding: 11px 12px;\r\n  border-left: 3px solid #65eaff;\r\n  border-radius: 10px;\r\n  color: #9db7c7;\r\n  background: rgba(74, 224, 255, 0.055);\r\n  font-size: 10px;\r\n  line-height: 1.5;\r\n}\r\n\r\n@media (max-width: 700px) {\r\n  .l8cp-ownerSummary {\r\n    grid-template-columns: repeat(2, minmax(0, 1fr));\r\n  }\r\n\r\n  .l8cp-ownerRecord {\r\n    grid-template-columns: 1fr;\r\n  }\r\n\r\n  .l8cp-ownerStatus {\r\n    justify-self: start;\r\n  }\r\n}\r\n\r\n<\/style>\r\n\r\n<div id=\"l8cp\" aria-hidden=\"true\">\r\n  <header class=\"l8cp-head\"><div><div class=\"l8cp-title\"><span>LEVEL 8<\/span> OPERATIONS<\/div><div class=\"l8cp-note\">Reservations \u00b7 Rent Before Owning \u00b7 The Circle \u00b7 Owner Rentals \u00b7 City Card \u00b7 Exchange \u00b7 Trade\r\n<\/div>\r\n<\/div>\r\n\r\n<button\r\n  class=\"l8cp-btn\"\r\n  id=\"l8cpExit\"\r\n  type=\"button\"\r\n>\r\n  Exit Panel\r\n<\/button>\r\n<\/header>\r\n\r\n<nav class=\"l8cp-systems\">\r\n    <div class=\"l8cp-selectbox\"><label>System<\/label><select id=\"l8cpSystemSelect\"><\/select><\/div>\r\n    <div class=\"l8cp-selectbox\"><label>Area<\/label><select id=\"l8cpGroupSelect\"><\/select><\/div>\r\n    <div class=\"l8cp-selectbox\"><label>Option<\/label><select id=\"l8cpOptionSelect\"><\/select><\/div>\r\n  <\/nav>\r\n  <main class=\"l8cp-main\">\r\n    <section class=\"l8cp-panel\"><h2 id=\"l8cpSideTitle\">Choose an area<\/h2><div class=\"l8cp-side\" id=\"l8cpGroups\"><\/div><\/section>\r\n    <section class=\"l8cp-panel\" id=\"l8cpEditorPanel\">\r\n      <h2 id=\"l8cpEditorTitle\">Add Level 8 Offer<\/h2><div class=\"l8cp-path\" id=\"l8cpPath\"><\/div><div class=\"l8cp-options\" id=\"l8cpOptions\"><\/div><div class=\"l8cp-form\" id=\"l8cpDynamic\"><\/div>\r\n      <div class=\"l8cp-form\">\r\n        <input type=\"hidden\" id=\"l8cpId\"><div class=\"l8cp-field full\"><label>Offer \/ Host Name<\/label><input id=\"l8cpName\" placeholder=\"Name shown to members\"><\/div>\r\n        <div class=\"l8cp-field\"><label>Price<\/label><input id=\"l8cpPrice\" placeholder=\"$0.00\"><\/div><div class=\"l8cp-field\"><label>Bliss Coin Credits<\/label><input id=\"l8cpCoins\" placeholder=\"Example: 250 BC\"><\/div>\r\n        <div class=\"l8cp-field\"><label>Location \/ Host<\/label><input id=\"l8cpLocation\" placeholder=\"Medelli\u00adn \/ Guatape \/ Host\"><\/div><div class=\"l8cp-field\"><label>Availability<\/label><input id=\"l8cpAvailability\" placeholder=\"Dates, days, weeks or hours\"><\/div>\r\n        <div class=\"l8cp-field full\"><label>Main Image URL<\/label><input id=\"l8cpImage\" placeholder=\"https:\/\/...\"><\/div><div class=\"l8cp-field full\"><label>Gallery URLs &#8211; one per line<\/label><textarea id=\"l8cpGallery\"><\/textarea><\/div>\r\n        <div class=\"l8cp-field\"><label>Website URL<\/label><input id=\"l8cpWebsite\" placeholder=\"https:\/\/...\"><\/div><div class=\"l8cp-field\"><label>Reserve \/ Checkout URL<\/label><input id=\"l8cpReserve\" placeholder=\"https:\/\/...\"><\/div>\r\n        <div class=\"l8cp-field\"><label>Map URL<\/label><input id=\"l8cpMap\" placeholder=\"https:\/\/maps.google.com\/...\"><\/div><div class=\"l8cp-field\"><label>Coordinates<\/label><input id=\"l8cpCoords\" placeholder=\"6.24, -75.22\"><\/div>\r\n        <div class=\"l8cp-field full\"><label>Description<\/label><textarea id=\"l8cpDescription\"><\/textarea><\/div><div class=\"l8cp-field full\"><label>Highlights \u00e2\u20ac\u201d one per line<\/label><textarea id=\"l8cpHighlights\"><\/textarea><\/div>\r\n        <label class=\"l8cp-toggle\"><input type=\"checkbox\" id=\"l8cpActive\" checked> Active<\/label><label class=\"l8cp-toggle\"><input type=\"checkbox\" id=\"l8cpFeatured\"> Featured<\/label>\r\n      <\/div>\r\n      <div class=\"l8cp-actions\"><button class=\"l8cp-btn primary\" id=\"l8cpSaveItem\">Save Item<\/button><button class=\"l8cp-btn\" id=\"l8cpClear\">Clear<\/button><\/div>\r\n    <\/section>\r\n    <section class=\"l8cp-panel l8cp-list-panel\"><h2 id=\"l8cpListTitle\">Current Inventory<\/h2><div id=\"l8cpLive\"><\/div><input class=\"l8cp-search\" id=\"l8cpSearch\" placeholder=\"Search this area\"><div class=\"l8cp-list\" id=\"l8cpList\"><\/div><\/section>\r\n  <\/main>\r\n<\/div><div class=\"l8cp-toast\" id=\"l8cpToast\"><\/div>\r\n\r\n<script>\r\n(function(){\r\n\"use strict\";\r\nconst AJAX =\r\n  window.GGGL8ControlPanelConfig?.ajaxUrl ||\r\n  window.GGGL8ReservationsConfig?.ajaxUrl ||\r\n  \"\/GGG\/wp-admin\/admin-ajax.php\";\r\nconst SYSTEMS={\r\n reservations:{label:\"Reservations\",hint:\"Direct Level 8 offers\",mode:\"inventory\",section:\"Reservations\",groups:{\"First Time Visitor\":[\"Live Medellin\",\"Getting Around\",\"Before You Arrive\",\"My Smart Recommendations\"],Accommodations:[\"High-Rise\",\"Historic\",\"Eco-Stay\",\"Mansions\"],Transportation:[\"Heli\",\"Yacht\",\"Car\",\"Driver\"],Sustainability:[\"Recycling\",\"Rivers & Canals\",\"Sustainable Agriculture\",\"Energy & Conservation\"],Legacy:[\"Imagine\",\"Exchange\",\"Record\",\"Franchise\"],Discover:[\"Adventure\",\"Ancestral\",\"Cultural\",\"Historic\"],Entertainment:[\"Concerts\",\"Fashion\",\"Comedy\",\"Sports\"],\"Medical Tourism\":[\"Vision Care\",\"Dental Care\",\"Aesthetic Care\",\"Regenerative Medicine\"],Survival:[\"Networking\",\"Dating\",\"Shared Dining\",\"Partnership\"],Gastronomic:[\"Culinary Skills\",\"Culinary Experiences\",\"Food Discovery\",\"Food Innovation\"],Conference:[\"Creative Learning\",\"Books and Writing\",\"Digital Innovation\",\"Reinvention\"],Give:[\"Support Children\",\"Strengthen Families\",\"Honor Older Adults\",\"Community Support\"],Cosmic:[\"Celestial Travel\",\"Universal Love\",\"Healing Journey\",\"Higher Self\"],Entrepreneur:[\"Inspiration\",\"Growth Mindset\",\"Creation\",\"Launch\"],Insight:[\"Mindful Movement\",\"Silent Reflection\",\"Nature Connection\",\"Meditation and Energy\"]}},\r\n imported:{label:\"Bliss Travel Hosts\",hint:\"Imported from Limitless\",mode:\"remote\",action:\"ggg_tc_get_inventory\"},\r\n rent: {\r\n  label: \"Rent Before Owning\",\r\n  hint: \"Experience rewards, property intervals and prepaid experience time\",\r\n  mode: \"inventory\",\r\n  section: \"Rent Before Owning\",\r\n\r\n  groups: {\r\n    \"Experience Rewards\": [\r\n      \"Antioquia Experience\",\r\n      \"Dining Experience\",\r\n      \"Boat Experience\",\r\n      \"Air Experience\",\r\n      \"Entertainment Experience\"\r\n    ],\r\n\r\n    \"Property Intervals\": [\r\n      \"1 Day\",\r\n      \"3 Days\",\r\n      \"5 Days\",\r\n      \"7 Days\"\r\n    ],\r\n\r\n    \"City Card Products\": [\r\n      \"Accommodation Days\",\r\n      \"Air Hours\",\r\n      \"Water Hours\",\r\n      \"Driver Hours\",\r\n      \"Chef Hours\",\r\n      \"Dining Credits\",\r\n      \"Bliss Coin Credits\"\r\n    ]\r\n  }\r\n},\r\n circle: {\r\n  label: \"Build Your Circle\",\r\n  hint: \"Products purchased through Bliss Comercializador and issued to the Luxus City Card\",\r\n  mode: \"inventory\",\r\n  section: \"The Circle\",\r\n\r\n  groups: {\r\n    \"Bliss Coin\": [\r\n      \"100 BC\",\r\n      \"500 BC\",\r\n      \"1,000 BC\"\r\n    ],\r\n\r\n    \"Air\": [\r\n      \"Helicopter Time\",\r\n      \"Private Air Time\",\r\n      \"Airport Transfer Time\"\r\n    ],\r\n\r\n    \"Aqua\": [\r\n      \"Boat Time\",\r\n      \"Pontoon Time\",\r\n      \"Yacht Time\"\r\n    ],\r\n\r\n    \"Gastro\": [\r\n      \"Private Chef Hours\",\r\n      \"In-Stay Chef Packages\"\r\n    ],\r\n\r\n    \"Land\": [\r\n      \"Eco-Hotels\",\r\n      \"Private Estates\",\r\n      \"Cottages & Cabins\"\r\n    ],\r\n\r\n    \"GGG Access\": [\r\n      \"Level Access\",\r\n      \"Level 8 Access\"\r\n    ]\r\n  }\r\n},\r\n\r\npreviewRequests: {\r\n  label: \"Preview Reward Requests\",\r\n  hint: \"Bliss OPC deposits, presentations, attendance and coupons\",\r\n  mode: \"workflow\",\r\n  path: \"rewards\",\r\n  groups: {\r\n    \"All Requests\": [],\r\n    \"Pending Deposit\": [],\r\n    \"Deposit Paid\": [],\r\n    \"Presentation Scheduled\": [],\r\n    \"Attendance Confirmed\": [],\r\n    \"Coupon Issued\": [],\r\n    \"Deposit Refunded\": [],\r\n    \"No Show\": [],\r\n    \"Cancelled\": []\r\n  }\r\n},\r\n\r\nintervalRequests: {\r\n  label: \"Property Interval Requests\",\r\n  hint: \"Bliss Administration date approval and payment authorization\",\r\n  mode: \"workflow\",\r\n  path: \"intervals\",\r\n  groups: {\r\n    \"All Requests\": [],\r\n    \"Availability Requested\": [],\r\n    \"Under Review\": [],\r\n    \"Alternative Dates Offered\": [],\r\n    \"Dates Confirmed\": [],\r\n    \"Half Paid\": [],\r\n    \"Balance Due\": [],\r\n    \"Paid In Full\": [],\r\n    \"Agreement Sent\": [],\r\n    \"Completed\": [],\r\n    \"Declined\": [],\r\n    \"Cancelled\": []\r\n  }\r\n},\r\n\r\ncityOrders: {\r\n  label: \"City Card Orders\",\r\n  hint: \"Bliss VOA payments and wallet activation\",\r\n  mode: \"workflow\",\r\n  path: \"citycard\",\r\n  groups: {\r\n    \"All Requests\": [],\r\n    \"Awaiting Payment\": [],\r\n    \"Half Paid\": [],\r\n    \"Balance Due\": [],\r\n    \"Paid In Full\": [],\r\n    \"Wallet Pending\": [],\r\n    \"Wallet Activated\": [],\r\n    \"Completed\": [],\r\n    \"Cancelled\": []\r\n  }\r\n},\r\n\r\n tradeOperations:{\r\n  label:\"Trade Constellation\",\r\n  hint:\"Owner offers, counteroffers, holds and Property Time verification\",\r\n  mode:\"trade_admin\",\r\n  groups:{\r\n    \"All Trades\":[],\r\n    \"Open Marketplace\":[],\r\n    \"Property Verification\":[],\r\n    \"Completed\":[],\r\n    \"Closed\":[]\r\n  }\r\n},\r\n\r\nlive:{\r\n  label:\"Legacy Exchange + Trade\",\r\n  hint:\"Legacy member activity\",\r\n  mode:\"activity\",\r\n  groups:{\r\n    \"Exchange Pins\":[],\r\n    \"Trade Posts\":[]\r\n  }\r\n}\r\n};\r\nconst LEVELS={\"First Time Visitor\":2,Accommodations:2,Transportation:2,Sustainability:2,Legacy:2,Discover:3,Entertainment:3,\"Medical Tourism\":3,Survival:4,Gastronomic:4,Conference:4,Give:4,Cosmic:4,Entrepreneur:4,Insight:4};\r\nconst DYNAMIC={\r\n reservations:[['leaf','Specific suboption','text','Exact final filter shown to customers'],['level','Required level','number','2, 3 or 4'],['providerType','Provider type','text','Hotel, driver, clinic, experience...'],['source','Inventory source','text','Direct Level 8'],['contactEmail','Provider contact email','email',''],['terms','Provider \/ reservation terms','textarea','Cancellation, availability and restrictions']],\r\n imported:[],\r\n rentIntervals: [\r\n  [\"ownerId\", \"Owner ID\", \"text\", \"Owner or account identifier\"],\r\n  [\"listingId\", \"Property Listing ID\", \"text\", \"Property inventory identifier\"],\r\n  [\"includedUnits\", \"Included property \/ units\", \"text\", \"Example: all five domes\"],\r\n  [\"intervalDays\", \"Interval length\", \"number\", \"1, 3, 5 or 7\"],\r\n  [\"validity\", \"Validity period\", \"text\", \"\"],\r\n  [\"rentalRights\", \"Unused-unit rights\", \"textarea\", \"Explain whether unused units may be rented\"],\r\n  [\"halfPriceId\", \"Stripe 50% Price ID\", \"text\", \"price_...\"],\r\n  [\"fullPriceId\", \"Stripe Full-Payment Price ID\", \"text\", \"price_...\"],\r\n  [\"terms\", \"Purchase conditions\", \"textarea\", \"\"]\r\n],\r\n\r\nrentCity: [\r\n  [\"balanceType\", \"Wallet balance type\", \"text\", \"Air hours, water hours, accommodation days...\"],\r\n  [\"quantity\", \"Included quantity\", \"number\", \"\"],\r\n  [\"unit\", \"Balance unit\", \"text\", \"Hours, days or credits\"],\r\n  [\"validity\", \"Validity \/ expiration\", \"text\", \"\"],\r\n  [\"halfPriceId\", \"Stripe 50% Price ID\", \"text\", \"price_...\"],\r\n  [\"fullPriceId\", \"Stripe Full-Payment Price ID\", \"text\", \"price_...\"],\r\n  [\"redemption\", \"Redemption conditions\", \"textarea\", \"\"]\r\n],\r\n rentCoins:[['creditAmount','Credit amount','number',''],['conversionValue','Conversion value','text',''],['validity','Validity \/ expiration','text',''],['terms','Credit terms','textarea','']],\r\n rentAvatar:[['accessDuration','Access duration','text',''],['privileges','Included privileges','textarea',''],['restrictions','Restrictions','textarea','']],\r\n circleCoins: [\r\n  [\"creditAmount\", \"Bliss Coin amount\", \"number\", \"Example: 500\"],\r\n  [\"usdValue\", \"USD value\", \"text\", \"Example: $500.00\"],\r\n  [\"stripePriceId\", \"Stripe Price ID\", \"text\", \"price_...\"],\r\n  [\"validity\", \"Validity\", \"text\", \"Expiration or no expiration\"],\r\n  [\"purchaseTerms\", \"Purchase conditions\", \"textarea\", \"\"]\r\n],\r\n\r\ncircleAir: [\r\n  [\"serviceType\", \"Air service\", \"text\", \"Helicopter, private air or transfer\"],\r\n  [\"quantity\", \"Included time\", \"number\", \"\"],\r\n  [\"unit\", \"Time unit\", \"text\", \"Minutes or hours\"],\r\n  [\"provider\", \"Fulfilling provider\", \"text\", \"\"],\r\n  [\"stripePriceId\", \"Stripe Price ID\", \"text\", \"price_...\"],\r\n  [\"redemption\", \"Booking and redemption conditions\", \"textarea\", \"\"]\r\n],\r\n\r\ncircleAqua: [\r\n  [\"serviceType\", \"Aqua service\", \"text\", \"Boat, pontoon or yacht\"],\r\n  [\"quantity\", \"Included time\", \"number\", \"\"],\r\n  [\"unit\", \"Time unit\", \"text\", \"Minutes or hours\"],\r\n  [\"provider\", \"Fulfilling provider\", \"text\", \"\"],\r\n  [\"stripePriceId\", \"Stripe Price ID\", \"text\", \"price_...\"],\r\n  [\"redemption\", \"Booking and redemption conditions\", \"textarea\", \"\"]\r\n],\r\n\r\ncircleGastro: [\r\n  [\"serviceType\", \"Chef service\", \"text\", \"Private Chef Hours or In-Stay Chef Package\"],\r\n  [\"quantity\", \"Included chef time\", \"number\", \"\"],\r\n  [\"unit\", \"Time unit\", \"text\", \"Hours or service\"],\r\n  [\"provider\", \"Fulfilling chef or provider\", \"text\", \"\"],\r\n  [\"stripePriceId\", \"Stripe Price ID\", \"text\", \"price_...\"],\r\n  [\"redemption\", \"Booking and redemption conditions\", \"textarea\", \"\"]\r\n],\r\n\r\ncircleLand: [\r\n  [\"propertyId\", \"Property ID\", \"text\", \"Property or inventory identifier\"],\r\n  [\"timeType\", \"Purchase type\", \"text\", \"Day or Week\"],\r\n  [\"quantity\", \"Number of days or weeks\", \"number\", \"\"],\r\n  [\"includedProperty\", \"Included property\", \"text\", \"Entire property being purchased\"],\r\n  [\"provider\", \"Property administrator\", \"text\", \"\"],\r\n  [\"stripePriceId\", \"Stripe Price ID\", \"text\", \"price_...\"],\r\n  [\"availabilityRules\", \"Availability conditions\", \"textarea\", \"\"],\r\n  [\"purchaseTerms\", \"Purchase conditions\", \"textarea\", \"\"]\r\n],\r\n\r\ncircleAccess: [\r\n  [\"levelNumber\", \"GGG level\", \"number\", \"1 through 8\"],\r\n  [\"accessDuration\", \"Access duration\", \"text\", \"\"],\r\n  [\"stripePriceId\", \"Stripe Price ID\", \"text\", \"price_...\"],\r\n  [\"includedAccess\", \"Included access\", \"textarea\", \"\"],\r\n  [\"purchaseTerms\", \"Purchase conditions\", \"textarea\", \"\"]\r\n],\r\n\r\nrentRewards: [\r\n  [\"presentationRequired\", \"Presentation required\", \"text\", \"Yes\"],\r\n  [\"presentationModes\", \"Presentation options\", \"text\", \"Online or Bliss Club in person\"],\r\n  [\"attendanceDeposit\", \"Attendance deposit\", \"text\", \"$9.99 USD\"],\r\n  [\"depositPriceId\", \"Stripe Deposit Price ID\", \"text\", \"price_...\"],\r\n  [\"rewardExpiration\", \"Reward expiration\", \"text\", \"Example: 12 months\"],\r\n  [\"rewardConditions\", \"Reward conditions\", \"textarea\", \"Presentation attendance and redemption conditions\"]\r\n],\r\n\r\nlive: []\r\n};\r\nconst $ = id => document.getElementById(id);\r\n\r\nconst state = {\r\n  system: \"reservations\",\r\n  group: \"Accommodations\",\r\n  option: \"High-Rise\",\r\n  items: [],\r\n  remote: [],\r\n  requests: [],\r\n  request: null,\r\n  editing: null,\r\n  busy: false\r\n};\r\nconst esc=s=>String(s??\"\").replace(\/[&<>\"']\/g,c=>({\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#039;\"}[c]));\r\nfunction toast(msg,bad){const e=$(\"l8cpToast\");e.textContent=msg;e.className=\"l8cp-toast\"+(bad?\" bad\":\"\");e.style.display=\"block\";clearTimeout(toast.t);toast.t=setTimeout(()=>e.style.display=\"none\",4200)}\r\nasync function post(action, data = {}) {\r\n  const fd = new FormData();\r\n\r\n  fd.append(\"action\", action);\r\n\r\n  const nonce =\r\n    window.GGGL8ControlPanelConfig?.nonce || \"\";\r\n\r\n  if (nonce) {\r\n    fd.append(\"nonce\", nonce);\r\n  }\r\n\r\n  Object.entries(data).forEach(([key, value]) => {\r\n    fd.append(key, value);\r\n  });\r\n\r\n  const response = await fetch(AJAX, {\r\n    method: \"POST\",\r\n    credentials: \"same-origin\",\r\n    body: fd\r\n  });\r\n\r\n  const result = await response.json();\r\n\r\n  if (!response.ok || result?.success !== true) {\r\n    throw new Error(\r\n      result?.data?.message ||\r\n      result?.data ||\r\n      action + \" was rejected by WordPress\"\r\n    );\r\n  }\r\n\r\n  return result.data || {};\r\n}\r\nfunction slug(s){return String(s||\"\").toLowerCase().trim().replace(\/[^a-z0-9]+\/g,\"-\").replace(\/^-|-$\/g,\"\")}\r\nfunction openPanel() {\r\n  const parameters = new URLSearchParams(\r\n    window.location.search\r\n  );\r\n\r\n  if (parameters.get(\"level8panel\") !== \"1\") {\r\n    return;\r\n  }\r\n\r\n  const panel = document.getElementById(\"l8cp\");\r\n  const toast = document.getElementById(\"l8cpToast\");\r\n\r\n  if (!panel) {\r\n    console.error(\r\n      \"Level 8 Control Panel: #l8cp was not found.\"\r\n    );\r\n\r\n    return;\r\n  }\r\n\r\n  \/*\r\n   * WordPress can place the HTML block inside a container\r\n   * that restricts position:fixed, width and height.\r\n   *\r\n   * Moving the panel directly into body removes that\r\n   * restriction.\r\n   *\/\r\n  if (panel.parentElement !== document.body) {\r\n    document.body.appendChild(panel);\r\n  }\r\n\r\n  if (\r\n    toast &&\r\n    toast.parentElement !== document.body\r\n  ) {\r\n    document.body.appendChild(toast);\r\n  }\r\n\r\n  document.documentElement.classList.add(\r\n    \"ggg-l8-panel-open\"\r\n  );\r\n\r\n  document.body.classList.add(\r\n    \"ggg-l8-panel-open\"\r\n  );\r\n\r\n  panel.classList.add(\"is-open\");\r\n\r\n  panel.setAttribute(\r\n    \"aria-hidden\",\r\n    \"false\"\r\n  );\r\n\r\n  chooseSystem(\"reservations\");\r\n}\r\n\r\nconst INVENTORY_EDITOR_HTML =\r\n  $(\"l8cpEditorPanel\").innerHTML;\r\n\r\nconst WORKFLOW_STATUS = {\r\n  \"All Requests\": \"\",\r\n\r\n  \"Pending Deposit\": \"pending_deposit\",\r\n  \"Deposit Paid\": \"deposit_paid\",\r\n  \"Presentation Scheduled\": \"presentation_scheduled\",\r\n  \"Attendance Confirmed\": \"attendance_confirmed\",\r\n  \"Coupon Issued\": \"coupon_issued\",\r\n  \"Deposit Refunded\": \"deposit_refunded\",\r\n  \"No Show\": \"no_show\",\r\n\r\n  \"Availability Requested\": \"availability_requested\",\r\n  \"Under Review\": \"under_review\",\r\n  \"Alternative Dates Offered\": \"alternative_dates_offered\",\r\n  \"Dates Confirmed\": \"dates_confirmed\",\r\n  \"Half Paid\": \"half_paid\",\r\n  \"Balance Due\": \"balance_due\",\r\n  \"Paid In Full\": \"paid_in_full\",\r\n  \"Agreement Sent\": \"agreement_sent\",\r\n\r\n  \"Awaiting Payment\": \"awaiting_payment\",\r\n  \"Wallet Pending\": \"wallet_pending\",\r\n  \"Wallet Activated\": \"wallet_activated\",\r\n\r\n  \"Completed\": \"completed\",\r\n  \"Declined\": \"declined\",\r\n  \"Cancelled\": \"cancelled\"\r\n};\r\n\r\nfunction renderSystems() {\r\n  const select = $(\"l8cpSystemSelect\");\r\n\r\n  select.innerHTML = Object.entries(SYSTEMS)\r\n    .map(([key, configuration]) => `\r\n      <option\r\n        value=\"${esc(key)}\"\r\n        ${key === state.system ? \"selected\" : \"\"}\r\n      >\r\n        ${esc(configuration.label)}\r\n      <\/option>\r\n    `)\r\n    .join(\"\");\r\n\r\n  renderSelects();\r\n}\r\n\r\nfunction renderSelects() {\r\n  const configuration = SYSTEMS[state.system];\r\n  const groups = Object.keys(configuration.groups || {});\r\n\r\n  $(\"l8cpGroupSelect\").innerHTML = groups.length\r\n    ? groups.map(group => `\r\n        <option\r\n          value=\"${esc(group)}\"\r\n          ${group === state.group ? \"selected\" : \"\"}\r\n        >\r\n          ${esc(group)}\r\n        <\/option>\r\n      `).join(\"\")\r\n    : `<option value=\"\">Live records<\/option>`;\r\n\r\n  const options =\r\n    configuration.groups?.[state.group] || [];\r\n\r\n  const optionSelect = $(\"l8cpOptionSelect\");\r\n\r\n  optionSelect.disabled =\r\n    configuration.mode === \"workflow\" ||\r\n    !options.length;\r\n\r\n  optionSelect.innerHTML = options.length\r\n    ? options.map(option => `\r\n        <option\r\n          value=\"${esc(option)}\"\r\n          ${option === state.option ? \"selected\" : \"\"}\r\n        >\r\n          ${esc(option)}\r\n        <\/option>\r\n      `).join(\"\")\r\n    : `<option value=\"\">All<\/option>`;\r\n}\r\n\r\nfunction chooseSystem(key) {\r\n  state.system = key;\r\n  state.editing = null;\r\n  state.request = null;\r\n\r\n  const configuration = SYSTEMS[key];\r\n\r\n  state.group =\r\n    Object.keys(configuration.groups || {})[0] || \"\";\r\n\r\n  state.option =\r\n    configuration.groups?.[state.group]?.[0] || \"\";\r\n\r\n  renderSystems();\r\n  renderGroups();\r\n  renderEditor();\r\n\r\n  if (configuration.mode === \"inventory\") {\r\n    renderList();\r\n    return;\r\n  }\r\n\r\n  if (configuration.mode === \"workflow\") {\r\n    loadWorkflow();\r\n    return;\r\n  }\r\n\r\n  loadSpecial();\r\n}\r\n\r\nfunction renderGroups() {\r\n  const configuration = SYSTEMS[state.system];\r\n\r\n  $(\"l8cpSideTitle\").textContent =\r\n    configuration.label;\r\n\r\n  if (configuration.mode === \"workflow\") {\r\n    $(\"l8cpGroups\").innerHTML = `\r\n      <button\r\n        class=\"l8cp-btn\"\r\n        type=\"button\"\r\n        data-refresh-requests\r\n      >\r\n        Refresh Requests\r\n      <\/button>\r\n\r\n      <div class=\"l8cp-empty\">\r\n        <strong>${esc(configuration.label)}<\/strong>\r\n        <br>\r\n        ${esc(configuration.hint)}\r\n        <br><br>\r\n        Select a request status above, then select a\r\n        customer request from the right.\r\n      <\/div>\r\n    `;\r\n  } else {\r\n    $(\"l8cpGroups\").innerHTML = `\r\n      <div class=\"l8cp-empty\">\r\n        <strong>${esc(configuration.label)}<\/strong>\r\n        <br>\r\n        ${esc(configuration.hint)}\r\n        <br><br>\r\n        The editor changes to match the selected\r\n        system, area and option.\r\n      <\/div>\r\n    `;\r\n  }\r\n\r\n  renderSelects();\r\n}\r\n\r\nfunction chooseGroup(group) {\r\n  state.group = group;\r\n  state.option =\r\n    SYSTEMS[state.system].groups?.[group]?.[0] || \"\";\r\n\r\n  state.editing = null;\r\n  state.request = null;\r\n\r\n  renderGroups();\r\n  renderEditor();\r\n\r\n  const mode = SYSTEMS[state.system].mode;\r\n\r\n  if (mode === \"workflow\") {\r\n    loadWorkflow();\r\n    return;\r\n  }\r\n\r\n  if (mode === \"activity\") {\r\n    loadSpecial();\r\n    return;\r\n  }\r\n\r\n  renderList();\r\n}\r\nfunction schemaKey() {\r\n  if (state.system === \"rent\") {\r\n    if (state.group === \"Experience Rewards\") {\r\n      return \"rentRewards\";\r\n    }\r\n\r\n    if (state.group === \"Property Intervals\") {\r\n      return \"rentIntervals\";\r\n    }\r\n\r\n    if (state.group === \"City Card Products\") {\r\n      return \"rentCity\";\r\n    }\r\n  }\r\n\r\n  if (state.system === \"circle\") {\r\n    const circleSchemas = {\r\n      \"Bliss Coin\": \"circleCoins\",\r\n      \"Air\": \"circleAir\",\r\n      \"Aqua\": \"circleAqua\",\r\n      \"Gastro\": \"circleGastro\",\r\n      \"Land\": \"circleLand\",\r\n      \"GGG Access\": \"circleAccess\"\r\n    };\r\n\r\n    return circleSchemas[state.group] || \"circleCoins\";\r\n  }\r\n\r\n  return state.system;\r\n}\r\nfunction renderDynamic(){const old={};document.querySelectorAll('#l8cpDynamic [data-extra]').forEach(e=>old[e.dataset.extra]=e.value);const schema=DYNAMIC[schemaKey()]||[];$(\"l8cpDynamic\").innerHTML=schema.map(([key,label,type,placeholder])=>`<div class=\"l8cp-field ${type==='textarea'?'full':''}\"><label>${esc(label)}<\/label>${type==='textarea'?`<textarea data-extra=\"${key}\" placeholder=\"${esc(placeholder)}\"><\/textarea>`:`<input data-extra=\"${key}\" type=\"${type}\" placeholder=\"${esc(placeholder)}\">`}<\/div>`).join('');document.querySelectorAll('#l8cpDynamic [data-extra]').forEach(e=>{if(old[e.dataset.extra]!=null)e.value=old[e.dataset.extra]});if(state.system==='reservations'){const level=document.querySelector('[data-extra=\"level\"]');if(level&&!level.value)level.value=LEVELS[state.group]||2}}\r\nfunction restoreInventoryEditor() {\r\n  const panel = $(\"l8cpEditorPanel\");\r\n\r\n  if (panel.dataset.mode !== \"inventory\") {\r\n    panel.innerHTML = INVENTORY_EDITOR_HTML;\r\n    panel.dataset.mode = \"inventory\";\r\n  }\r\n}\r\n\r\nfunction renderEditor() {\r\n  const configuration = SYSTEMS[state.system];\r\n  const panel = $(\"l8cpEditorPanel\");\r\n\r\n  if (configuration.mode === \"workflow\") {\r\n    panel.style.display = \"block\";\r\n    panel.dataset.mode = \"workflow\";\r\n    renderWorkflowEditor();\r\n    return;\r\n  }\r\n\r\n  if (configuration.mode !== \"inventory\") {\r\n    panel.style.display = \"none\";\r\n    return;\r\n  }\r\n\r\n  panel.style.display = \"block\";\r\n  restoreInventoryEditor();\r\n\r\n  $(\"l8cpPath\").textContent = [\r\n    configuration.label,\r\n    state.group,\r\n    state.option\r\n  ].filter(Boolean).join(\" > \");\r\n\r\n  $(\"l8cpOptions\").innerHTML = \"\";\r\n\r\n  renderDynamic();\r\n\r\n  $(\"l8cpEditorTitle\").textContent =\r\n    state.editing\r\n      ? \"Edit Level 8 Item\"\r\n      : \"Add Level 8 Item\";\r\n\r\n  $(\"l8cpListTitle\").textContent =\r\n    configuration.label + \" Inventory\";\r\n\r\n  $(\"l8cpLive\").innerHTML = \"\";\r\n}\r\n\r\nfunction chooseOption(option) {\r\n  state.option = option;\r\n  renderEditor();\r\n\r\n  if (SYSTEMS[state.system].mode === \"inventory\") {\r\n    renderList();\r\n  }\r\n}\r\n\r\nfunction values() {\r\n  const coordinates = $(\"l8cpCoords\")\r\n    .value\r\n    .split(\",\")\r\n    .map(value => value.trim());\r\n\r\n  const lat = coordinates[0] || \"\";\r\n  const lng = coordinates[1] || \"\";\r\n  const extras = {};\r\n\r\n  document\r\n    .querySelectorAll(\"#l8cpDynamic [data-extra]\")\r\n    .forEach(element => {\r\n      extras[element.dataset.extra] =\r\n        element.value.trim();\r\n    });\r\n\r\n  const configuration = SYSTEMS[state.system];\r\n\r\n  const base = state.editing\r\n    ? {...state.editing}\r\n    : {};\r\n\r\n  return {\r\n    ...base,\r\n    ...extras,\r\n    adminFields: extras,\r\n\r\n    id:\r\n      $(\"l8cpId\").value ||\r\n      \"l8_\" +\r\n        Date.now() +\r\n        \"_\" +\r\n        Math.random().toString(36).slice(2, 7),\r\n\r\n    name: $(\"l8cpName\").value.trim(),\r\n    section: configuration.section,\r\n    group: state.group,\r\n    category: state.group,\r\n    option: state.option,\r\n\r\n    suboption:\r\n      extras.leaf || state.option,\r\n\r\n    suboptionKey:\r\n      slug(extras.leaf || state.option),\r\n\r\n    imageUrl: $(\"l8cpImage\").value.trim(),\r\n    galleryUrls: $(\"l8cpGallery\").value.trim(),\r\n    price: $(\"l8cpPrice\").value.trim(),\r\n    blissCoinValue: $(\"l8cpCoins\").value.trim(),\r\n    location: $(\"l8cpLocation\").value.trim(),\r\n    availability: $(\"l8cpAvailability\").value.trim(),\r\n    websiteUrl: $(\"l8cpWebsite\").value.trim(),\r\n    reserveUrl: $(\"l8cpReserve\").value.trim(),\r\n    mapUrl: $(\"l8cpMap\").value.trim(),\r\n    lat,\r\n    lng,\r\n    description: $(\"l8cpDescription\").value.trim(),\r\n    highlights: $(\"l8cpHighlights\").value.trim(),\r\n\r\n    status:\r\n      $(\"l8cpActive\").checked\r\n        ? \"active\"\r\n        : \"hidden\",\r\n\r\n    featured:\r\n      $(\"l8cpFeatured\").checked ? 1 : 0\r\n  };\r\n}\r\n\r\nfunction fill(item = {}) {\r\n  state.editing = item.id ? item : null;\r\n\r\n  $(\"l8cpId\").value = item.id || \"\";\r\n  $(\"l8cpName\").value = item.name || \"\";\r\n  $(\"l8cpPrice\").value = item.price || \"\";\r\n  $(\"l8cpCoins\").value = item.blissCoinValue || \"\";\r\n  $(\"l8cpLocation\").value = item.location || \"\";\r\n  $(\"l8cpAvailability\").value = item.availability || \"\";\r\n  $(\"l8cpImage\").value = item.imageUrl || \"\";\r\n\r\n  $(\"l8cpGallery\").value =\r\n    Array.isArray(item.galleryUrls)\r\n      ? item.galleryUrls.join(\"\\n\")\r\n      : item.galleryUrls || \"\";\r\n\r\n  $(\"l8cpWebsite\").value = item.websiteUrl || \"\";\r\n  $(\"l8cpReserve\").value = item.reserveUrl || \"\";\r\n  $(\"l8cpMap\").value = item.mapUrl || \"\";\r\n\r\n  $(\"l8cpCoords\").value = [\r\n    item.lat,\r\n    item.lng\r\n  ].filter(Boolean).join(\", \");\r\n\r\n  $(\"l8cpDescription\").value =\r\n    item.description || \"\";\r\n\r\n  $(\"l8cpHighlights\").value =\r\n    Array.isArray(item.highlights)\r\n      ? item.highlights.join(\"\\n\")\r\n      : item.highlights || \"\";\r\n\r\n  $(\"l8cpActive\").checked =\r\n    (item.status || \"active\") !== \"hidden\";\r\n\r\n  $(\"l8cpFeatured\").checked =\r\n    Boolean(Number(item.featured || 0));\r\n\r\n  renderEditor();\r\n\r\n  document\r\n    .querySelectorAll(\"#l8cpDynamic [data-extra]\")\r\n    .forEach(element => {\r\n      element.value =\r\n        item[element.dataset.extra] ??\r\n        item.adminFields?.[element.dataset.extra] ??\r\n        \"\";\r\n    });\r\n}\r\n\r\nasync function saveAll(message) {\r\n  await post(\"ggg_l8_save_inventory\", {\r\n    items: JSON.stringify(state.items)\r\n  });\r\n\r\n  toast(message || \"Level 8 item saved.\");\r\n}\r\n\r\nasync function saveItem() {\r\n  const item = values();\r\n\r\n  if (!item.name) {\r\n    toast(\"Add the offer or host name first.\", true);\r\n    return;\r\n  }\r\n\r\n  const index = state.items.findIndex(\r\n    existing =>\r\n      String(existing.id) === String(item.id)\r\n  );\r\n\r\n  if (index >= 0) {\r\n    state.items[index] = item;\r\n  } else {\r\n    state.items.push(item);\r\n  }\r\n\r\n  setBusy(true);\r\n\r\n  try {\r\n    await saveAll();\r\n    fill({});\r\n    renderList();\r\n  } catch (error) {\r\n    toast(error.message, true);\r\n  } finally {\r\n    setBusy(false);\r\n  }\r\n}\r\n\r\nasync function removeItem(id) {\r\n  if (!confirm(\"Delete this Level 8 item?\")) {\r\n    return;\r\n  }\r\n\r\n  const previousItems = state.items.slice();\r\n\r\n  state.items = state.items.filter(\r\n    item => String(item.id) !== String(id)\r\n  );\r\n\r\n  renderList();\r\n\r\n  try {\r\n    await saveAll(\"Item deleted.\");\r\n  } catch (error) {\r\n    state.items = previousItems;\r\n    renderList();\r\n    toast(error.message, true);\r\n  }\r\n}\r\n\r\nfunction setBusy(isBusy) {\r\n  state.busy = isBusy;\r\n\r\n  const inventorySaveButton =\r\n    $(\"l8cpSaveItem\");\r\n\r\n  if (inventorySaveButton) {\r\n    inventorySaveButton.disabled = isBusy;\r\n\r\n    inventorySaveButton.textContent =\r\n      isBusy ? \"Saving...\" : \"Save Item\";\r\n  }\r\n\r\n  document\r\n    .querySelectorAll(\r\n      \"[data-workflow-status], [data-save-request]\"\r\n    )\r\n    .forEach(button => {\r\n      button.disabled = isBusy;\r\n    });\r\n}\r\n\r\nfunction belongs(item, configuration) {\r\n  const section =\r\n    String(item.section || \"\").toLowerCase();\r\n\r\n  const target =\r\n    String(configuration.section || \"\").toLowerCase();\r\n\r\n  if (section === target) {\r\n    return true;\r\n  }\r\n\r\n  if (configuration.section === \"Reservations\") {\r\n    return [\r\n      \"reservations\",\r\n      \"invitation\"\r\n    ].includes(section);\r\n  }\r\n\r\n  if (\r\n    configuration.section ===\r\n    \"Rent Before Owning\"\r\n  ) {\r\n    return [\r\n      \"rent before owning\",\r\n      \"rent before buying\",\r\n      \"preview\",\r\n      \"the preview\",\r\n      \"packages \/ opc\"\r\n    ].includes(section);\r\n  }\r\n\r\n  if (configuration.section === \"The Circle\") {\r\n    return [\r\n      \"the circle\",\r\n      \"owners club\"\r\n    ].includes(section);\r\n  }\r\n\r\n  return false;\r\n}\r\n\r\nfunction renderList() {\r\n  const configuration = SYSTEMS[state.system];\r\n\r\n  if (configuration.mode !== \"inventory\") {\r\n    return;\r\n  }\r\n\r\n  const search =\r\n    $(\"l8cpSearch\").value.toLowerCase();\r\n\r\n  const rows = state.items\r\n    .filter(item => belongs(item, configuration))\r\n    .filter(item => {\r\n      if (!state.group) {\r\n        return true;\r\n      }\r\n\r\n      return String(\r\n        item.group || item.category || \"\"\r\n      ).toLowerCase() === state.group.toLowerCase();\r\n    })\r\n    .filter(item => {\r\n      if (!state.option) {\r\n        return true;\r\n      }\r\n\r\n      return String(\r\n        item.option ||\r\n        item.suboption ||\r\n        item.suboptionKey ||\r\n        \"\"\r\n      )\r\n        .toLowerCase()\r\n        .replace(\/-\/g, \" \") ===\r\n        state.option.toLowerCase();\r\n    })\r\n    .filter(item => {\r\n      return (\r\n        !search ||\r\n        JSON.stringify(item)\r\n          .toLowerCase()\r\n          .includes(search)\r\n      );\r\n    });\r\n\r\n  $(\"l8cpList\").innerHTML = rows.length\r\n    ? rows.map(item => card(item)).join(\"\")\r\n    : `\r\n      <div class=\"l8cp-empty\">\r\n        No items saved for\r\n        <strong>\r\n          ${esc(state.option || state.group)}\r\n        <\/strong>.\r\n        Add the first one here.\r\n      <\/div>\r\n    `;\r\n}\r\n\r\nfunction card(item, readonly = false) {\r\n  const id = esc(\r\n    item.id ||\r\n    item.profileKey ||\r\n    item.name ||\r\n    \"\"\r\n  );\r\n\r\n  const picture =\r\n    item.imageUrl ||\r\n    item.image ||\r\n    item.avatar ||\r\n    \"\";\r\n\r\n  return `\r\n    <article class=\"l8cp-item\">\r\n      <div\r\n        class=\"l8cp-thumb\"\r\n        style=\"background-image:url('${esc(picture)}')\"\r\n      ><\/div>\r\n\r\n      <div>\r\n        <div class=\"l8cp-name\">\r\n          ${esc(\r\n            item.name ||\r\n            item.title ||\r\n            item.businessName ||\r\n            \"Unnamed\"\r\n          )}\r\n        <\/div>\r\n\r\n        <div class=\"l8cp-meta\">\r\n          ${esc(item.section || item.category || \"\")}\r\n          \u00b7\r\n          ${esc(\r\n            item.group ||\r\n            item.suboption ||\r\n            item.suboptionKey ||\r\n            \"\"\r\n          )}\r\n          <br>\r\n          ${esc(item.location || item.price || \"\")}\r\n        <\/div>\r\n\r\n        <span class=\"l8cp-badge\">\r\n          ${esc(item.status || \"active\")}\r\n        <\/span>\r\n      <\/div>\r\n\r\n      ${\r\n        readonly\r\n          ? \"\"\r\n          : `\r\n            <div class=\"l8cp-item-actions\">\r\n              <button\r\n                class=\"l8cp-btn\"\r\n                type=\"button\"\r\n                data-edit=\"${id}\"\r\n              >\r\n                Edit\r\n              <\/button>\r\n\r\n              <button\r\n                class=\"l8cp-btn danger\"\r\n                type=\"button\"\r\n                data-delete=\"${id}\"\r\n              >\r\n                Delete\r\n              <\/button>\r\n            <\/div>\r\n          `\r\n      }\r\n    <\/article>\r\n  `;\r\n}\r\n\r\nasync function loadInventory() {\r\n  try {\r\n    const data =\r\n      await post(\"ggg_l8_get_inventory\");\r\n\r\n    state.items =\r\n      Array.isArray(data.items)\r\n        ? data.items\r\n        : Array.isArray(data.inventory)\r\n          ? data.inventory\r\n          : [];\r\n\r\n    renderList();\r\n  } catch (error) {\r\n    $(\"l8cpList\").innerHTML = `\r\n      <div class=\"l8cp-error\">\r\n        ${esc(error.message)}\r\n      <\/div>\r\n    `;\r\n  }\r\n}\r\n\r\nasync function loadSpecial() {\r\n  const configuration = SYSTEMS[state.system];\r\n\r\n  $(\"l8cpSearch\").value = \"\";\r\n\r\n  $(\"l8cpList\").innerHTML = `\r\n    <div class=\"l8cp-empty\">\r\n      Loading live connection...\r\n    <\/div>\r\n  `;\r\n\r\n  if (state.system === \"imported\") {\r\n    try {\r\n      const data =\r\n        await post(configuration.action);\r\n\r\n      const items =\r\n        Array.isArray(data)\r\n          ? data\r\n          : data.items || data.inventory || [];\r\n\r\n      state.remote = items;\r\n\r\n      $(\"l8cpListTitle\").textContent =\r\n        \"Imported Bliss Travel Hosts\";\r\n\r\n      $(\"l8cpLive\").innerHTML = `\r\n        <div class=\"l8cp-live\">\r\n          LIVE READ CONNECTION \u00b7\r\n          ggg_tc_get_inventory\r\n        <\/div>\r\n      `;\r\n\r\n      $(\"l8cpList\").innerHTML = items.length\r\n        ? items.map(item => card(item, true)).join(\"\")\r\n        : `\r\n          <div class=\"l8cp-empty\">\r\n            No imported hosts were returned.\r\n          <\/div>\r\n        `;\r\n    } catch (error) {\r\n      $(\"l8cpList\").innerHTML = `\r\n        <div class=\"l8cp-error\">\r\n          ${esc(error.message)}\r\n        <\/div>\r\n      `;\r\n    }\r\n\r\n    return;\r\n  }\r\n\r\n  const action =\r\n    state.group === \"Exchange Pins\"\r\n      ? \"ggg_l8_get_exchange_pins\"\r\n      : \"ggg_l8_get_trade_posts\";\r\n\r\n  try {\r\n    const data = await post(action);\r\n\r\n    const items =\r\n      Array.isArray(data)\r\n        ? data\r\n        : data.items ||\r\n          data.pins ||\r\n          data.posts ||\r\n          [];\r\n\r\n    $(\"l8cpListTitle\").textContent =\r\n      state.group;\r\n\r\n    $(\"l8cpLive\").innerHTML = `\r\n      <div class=\"l8cp-live\">\r\n        LIVE MEMBER CONNECTION \u00b7 ${esc(action)}\r\n      <\/div>\r\n    `;\r\n\r\n    $(\"l8cpList\").innerHTML = items.length\r\n      ? items.map(item => card(item, true)).join(\"\")\r\n      : `\r\n        <div class=\"l8cp-empty\">\r\n          No live ${esc(\r\n            state.group.toLowerCase()\r\n          )} were returned.\r\n        <\/div>\r\n      `;\r\n  } catch (error) {\r\n    $(\"l8cpList\").innerHTML = `\r\n      <div class=\"l8cp-error\">\r\n        ${esc(error.message)}\r\n      <\/div>\r\n    `;\r\n  }\r\n}\r\n\r\nfunction formatStatus(status) {\r\n  return String(status || \"\")\r\n    .replaceAll(\"_\", \" \");\r\n}\r\n\r\nfunction firstRequestItem(request) {\r\n  return Array.isArray(request.items) &&\r\n    request.items.length\r\n    ? request.items[0]\r\n    : {};\r\n}\r\n\r\nfunction requestTitle(request) {\r\n  const item = firstRequestItem(request);\r\n\r\n  return (\r\n    item.name ||\r\n    `${request.path || \"Customer\"} request`\r\n  );\r\n}\r\n\r\nfunction requestCard(request) {\r\n  const active =\r\n    state.request &&\r\n    state.request.id === request.id;\r\n\r\n  return `\r\n    <button\r\n      class=\"l8cp-request${active ? \" active\" : \"\"}\"\r\n      type=\"button\"\r\n      data-request-id=\"${esc(request.id)}\"\r\n    >\r\n      <span>\r\n        <strong>\r\n          ${esc(requestTitle(request))}\r\n        <\/strong>\r\n\r\n        <small>\r\n          ${esc(request.customer_name || \"Customer\")}\r\n          \u00b7\r\n          ${esc(request.customer_email || \"\")}\r\n          <br>\r\n          ${esc(\r\n            request.requested_arrival ||\r\n            request.preferred_date ||\r\n            \"No date\"\r\n          )}\r\n          \u00b7\r\n          ${esc(request.guests || 1)} guest(s)\r\n        <\/small>\r\n      <\/span>\r\n\r\n      <span class=\"l8cp-requestStatus\">\r\n        ${esc(formatStatus(request.status))}\r\n      <\/span>\r\n    <\/button>\r\n  `;\r\n}\r\n\r\nfunction renderWorkflowList() {\r\n  const search =\r\n    $(\"l8cpSearch\").value.toLowerCase();\r\n\r\n  const rows = state.requests.filter(request => {\r\n    return (\r\n      !search ||\r\n      JSON.stringify(request)\r\n        .toLowerCase()\r\n        .includes(search)\r\n    );\r\n  });\r\n\r\n  $(\"l8cpList\").innerHTML = rows.length\r\n    ? rows.map(requestCard).join(\"\")\r\n    : `\r\n      <div class=\"l8cp-empty\">\r\n        No ${esc(state.group.toLowerCase())}\r\n        were found.\r\n      <\/div>\r\n    `;\r\n}\r\n\r\nasync function loadWorkflow() {\r\n  const configuration = SYSTEMS[state.system];\r\n\r\n  const wantedStatus =\r\n    WORKFLOW_STATUS[state.group] || \"\";\r\n\r\n  $(\"l8cpListTitle\").textContent =\r\n    configuration.label;\r\n\r\n  $(\"l8cpLive\").innerHTML = `\r\n    <div class=\"l8cp-live\">\r\n      SECURE WORKFLOW \u00b7 ${esc(configuration.path)}\r\n    <\/div>\r\n  `;\r\n\r\n  $(\"l8cpList\").innerHTML = `\r\n    <div class=\"l8cp-empty\">\r\n      Loading customer requests...\r\n    <\/div>\r\n  `;\r\n\r\n  $(\"l8cpSearch\").value = \"\";\r\n\r\n  try {\r\n    const data = await post(\r\n      \"ggg_l8_admin_get_path_requests\",\r\n      {\r\n        path: configuration.path,\r\n        status: wantedStatus\r\n      }\r\n    );\r\n\r\n    state.requests =\r\n      Array.isArray(data.requests)\r\n        ? data.requests\r\n        : [];\r\n\r\n    if (state.request) {\r\n      state.request =\r\n        state.requests.find(\r\n          request =>\r\n            request.id === state.request.id\r\n        ) || null;\r\n    }\r\n\r\n    renderWorkflowList();\r\n    renderWorkflowEditor();\r\n  } catch (error) {\r\n    $(\"l8cpList\").innerHTML = `\r\n      <div class=\"l8cp-error\">\r\n        ${esc(error.message)}\r\n      <\/div>\r\n    `;\r\n  }\r\n}\r\n\r\nfunction informationBox(label, value) {\r\n  return `\r\n    <div class=\"l8cp-infoBox\">\r\n      <span>${esc(label)}<\/span>\r\n      <strong>${esc(value || \"\u2014\")}<\/strong>\r\n    <\/div>\r\n  `;\r\n}\r\n\r\nfunction workflowField(\r\n  key,\r\n  label,\r\n  type = \"text\",\r\n  full = false,\r\n  placeholder = \"\"\r\n) {\r\n  const value =\r\n    state.request?.[key] ?? \"\";\r\n\r\n  if (type === \"textarea\") {\r\n    return `\r\n      <div class=\"l8cp-field${full ? \" full\" : \"\"}\">\r\n        <label>${esc(label)}<\/label>\r\n\r\n        <textarea\r\n          data-request-field=\"${esc(key)}\"\r\n          placeholder=\"${esc(placeholder)}\"\r\n        >${esc(value)}<\/textarea>\r\n      <\/div>\r\n    `;\r\n  }\r\n\r\n  return `\r\n    <div class=\"l8cp-field${full ? \" full\" : \"\"}\">\r\n      <label>${esc(label)}<\/label>\r\n\r\n      <input\r\n        data-request-field=\"${esc(key)}\"\r\n        type=\"${esc(type)}\"\r\n        value=\"${esc(value)}\"\r\n        placeholder=\"${esc(placeholder)}\"\r\n      >\r\n    <\/div>\r\n  `;\r\n}\r\n\r\nfunction requestItems(request) {\r\n  return (request.items || [])\r\n    .map(item => `\r\n      <div class=\"l8cp-requestItem\">\r\n        ${\r\n          item.imageUrl\r\n            ? `\r\n              <img decoding=\"async\"\r\n                src=\"${esc(item.imageUrl)}\"\r\n                alt=\"\"\r\n              >\r\n            `\r\n            : `<div><\/div>`\r\n        }\r\n\r\n        <div>\r\n          <strong>\r\n            ${esc(item.name || \"Unnamed item\")}\r\n          <\/strong>\r\n\r\n          <small>\r\n            ${esc(\r\n              item.option ||\r\n              item.suboption ||\r\n              item.group ||\r\n              \"\"\r\n            )}\r\n            \u00b7\r\n            ${esc(item.price || \"\")}\r\n          <\/small>\r\n        <\/div>\r\n      <\/div>\r\n    `)\r\n    .join(\"\");\r\n}\r\n\r\nfunction workflowActions(request) {\r\n  if (request.path === \"rewards\") {\r\n    return [\r\n      [\"presentation_scheduled\", \"Schedule Presentation\"],\r\n      [\"attendance_confirmed\", \"Confirm Attendance\"],\r\n      [\"coupon_issued\", \"Issue Coupon\"],\r\n      [\"deposit_refund_pending\", \"Refund Pending\"],\r\n      [\"deposit_refunded\", \"Deposit Refunded\"],\r\n      [\"no_show\", \"Mark No-Show\"],\r\n      [\"cancelled\", \"Cancel\"]\r\n    ];\r\n  }\r\n\r\n  if (request.path === \"intervals\") {\r\n    return [\r\n      [\"under_review\", \"Start Review\"],\r\n      [\"alternative_dates_offered\", \"Offer Alternative Dates\"],\r\n      [\"dates_confirmed\", \"Approve Dates\"],\r\n      [\"declined\", \"Decline\"],\r\n      [\"agreement_sent\", \"Agreement Sent\"],\r\n      [\"completed\", \"Complete\"],\r\n      [\"cancelled\", \"Cancel\"]\r\n    ];\r\n  }\r\n\r\n  return [\r\n    [\"wallet_pending\", \"Wallet Pending\"],\r\n    [\"wallet_activated\", \"Activate Wallet\"],\r\n    [\"completed\", \"Complete\"],\r\n    [\"cancelled\", \"Cancel\"]\r\n  ];\r\n}\r\n\r\nfunction workflowFields(request) {\r\n  if (request.path === \"rewards\") {\r\n    return (\r\n      workflowField(\r\n        \"presentation_date\",\r\n        \"Presentation Date\",\r\n        \"date\"\r\n      ) +\r\n      workflowField(\r\n        \"refund_status\",\r\n        \"Refund Status\",\r\n        \"text\",\r\n        false,\r\n        \"not_started, pending, refunded...\"\r\n      ) +\r\n      workflowField(\r\n        \"customer_message\",\r\n        \"Customer Message\",\r\n        \"textarea\",\r\n        true\r\n      ) +\r\n      workflowField(\r\n        \"internal_notes\",\r\n        \"Internal Notes\",\r\n        \"textarea\",\r\n        true\r\n      )\r\n    );\r\n  }\r\n\r\n  if (request.path === \"intervals\") {\r\n    return (\r\n      workflowField(\r\n        \"confirmed_arrival\",\r\n        \"Confirmed Arrival\",\r\n        \"date\"\r\n      ) +\r\n      workflowField(\r\n        \"confirmed_departure\",\r\n        \"Confirmed Departure\",\r\n        \"date\"\r\n      ) +\r\n      workflowField(\r\n        \"alternative_arrival\",\r\n        \"Alternative Arrival\",\r\n        \"date\"\r\n      ) +\r\n      workflowField(\r\n        \"alternative_departure\",\r\n        \"Alternative Departure\",\r\n        \"date\"\r\n      ) +\r\n      workflowField(\r\n        \"approved_total\",\r\n        \"Approved Total \u2014 USD\",\r\n        \"number\"\r\n      ) +\r\n      workflowField(\r\n        \"payment_deadline\",\r\n        \"Payment Deadline\",\r\n        \"date\"\r\n      ) +\r\n      workflowField(\r\n        \"customer_message\",\r\n        \"Customer Message\",\r\n        \"textarea\",\r\n        true\r\n      ) +\r\n      workflowField(\r\n        \"internal_notes\",\r\n        \"Internal Notes\",\r\n        \"textarea\",\r\n        true\r\n      )\r\n    );\r\n  }\r\n\r\n  return (\r\n    workflowField(\r\n      \"approved_total\",\r\n      \"Approved Total \u2014 USD\",\r\n      \"number\"\r\n    ) +\r\n    workflowField(\r\n      \"amount_paid\",\r\n      \"Verified Amount Paid \u2014 USD\",\r\n      \"number\"\r\n    ) +\r\n    workflowField(\r\n      \"wallet_status\",\r\n      \"Wallet Status\",\r\n      \"text\",\r\n      false,\r\n      \"not_issued, pending or activated\"\r\n    ) +\r\n    workflowField(\r\n      \"customer_message\",\r\n      \"Customer Message\",\r\n      \"textarea\",\r\n      true\r\n    ) +\r\n    workflowField(\r\n      \"internal_notes\",\r\n      \"Internal Notes\",\r\n      \"textarea\",\r\n      true\r\n    )\r\n  );\r\n}\r\n\r\nfunction renderWorkflowEditor() {\r\n  const panel = $(\"l8cpEditorPanel\");\r\n  const request = state.request;\r\n\r\n  panel.style.display = \"block\";\r\n  panel.dataset.mode = \"workflow\";\r\n\r\n  if (!request) {\r\n    panel.innerHTML = `\r\n      <h2>Customer Workflow<\/h2>\r\n\r\n      <div class=\"l8cp-empty\">\r\n        Select a request from the right to review\r\n        and manage it.\r\n      <\/div>\r\n    `;\r\n\r\n    return;\r\n  }\r\n\r\n  const dates = [\r\n    request.requested_arrival ||\r\n      request.preferred_date,\r\n    request.requested_departure\r\n  ].filter(Boolean).join(\" \u2192 \");\r\n\r\n  panel.innerHTML = `\r\n    <h2>${esc(requestTitle(request))}<\/h2>\r\n\r\n    <div class=\"l8cp-path\">\r\n      ${esc(SYSTEMS[state.system].label)}\r\n      &gt;\r\n      ${esc(formatStatus(request.status))}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-requestInfo\">\r\n      ${informationBox(\"Request ID\", request.id)}\r\n      ${informationBox(\"Customer\", request.customer_name)}\r\n      ${informationBox(\"Email\", request.customer_email)}\r\n      ${informationBox(\"Requested Dates\", dates)}\r\n      ${informationBox(\"Guests\", request.guests)}\r\n      ${informationBox(\"Presentation\", request.presentation_mode)}\r\n\r\n      ${informationBox(\r\n        \"Approved Total\",\r\n        request.approved_total\r\n          ? \"$\" + request.approved_total\r\n          : \"\"\r\n      )}\r\n\r\n      ${informationBox(\r\n        \"Amount Paid\",\r\n        request.amount_paid\r\n          ? \"$\" + request.amount_paid\r\n          : \"\"\r\n      )}\r\n\r\n      ${informationBox(\r\n        \"Balance Due\",\r\n        request.balance_due\r\n          ? \"$\" + request.balance_due\r\n          : \"\"\r\n      )}\r\n\r\n      ${informationBox(\r\n        \"Payment Unlocked\",\r\n        request.payment_unlocked ? \"Yes\" : \"No\"\r\n      )}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-sectionLabel\">\r\n      Selected Inventory\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-requestItems\">\r\n      ${requestItems(request)}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-sectionLabel\">\r\n      Customer Notes\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-readonly\">\r\n      ${esc(request.notes || \"No customer notes.\")}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-sectionLabel\">\r\n      Administration\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-form\">\r\n      ${workflowFields(request)}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-actions\">\r\n      <button\r\n        class=\"l8cp-btn primary\"\r\n        type=\"button\"\r\n        data-save-request\r\n      >\r\n        Save Details\r\n      <\/button>\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-sectionLabel\">\r\n      Workflow Actions\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-statusActions\">\r\n      ${workflowActions(request)\r\n        .map(([status, label]) => `\r\n          <button\r\n            class=\"l8cp-btn ${\r\n              [\r\n                \"declined\",\r\n                \"cancelled\",\r\n                \"no_show\"\r\n              ].includes(status)\r\n                ? \"danger\"\r\n                : \"\"\r\n            }\"\r\n            type=\"button\"\r\n            data-workflow-status=\"${esc(status)}\"\r\n          >\r\n            ${esc(label)}\r\n          <\/button>\r\n        `)\r\n        .join(\"\")}\r\n    <\/div>\r\n  `;\r\n}\r\n\r\nfunction requestPayload(status = \"\") {\r\n  const data = {\r\n    id: state.request.id\r\n  };\r\n\r\n  document\r\n    .querySelectorAll(\"[data-request-field]\")\r\n    .forEach(element => {\r\n      const value = element.value.trim();\r\n      const key = element.dataset.requestField;\r\n\r\n      const fieldsThatMayBeCleared = [\r\n        \"customer_message\",\r\n        \"internal_notes\",\r\n        \"confirmed_arrival\",\r\n        \"confirmed_departure\",\r\n        \"alternative_arrival\",\r\n        \"alternative_departure\",\r\n        \"payment_deadline\",\r\n        \"presentation_date\"\r\n      ];\r\n\r\n      if (\r\n        value !== \"\" ||\r\n        fieldsThatMayBeCleared.includes(key)\r\n      ) {\r\n        data[key] = value;\r\n      }\r\n    });\r\n\r\n  if (status) {\r\n    data.status = status;\r\n  }\r\n\r\n  if (status === \"wallet_activated\") {\r\n    data.wallet_status = \"activated\";\r\n  }\r\n\r\n  return data;\r\n}\r\n\r\nfunction validateWorkflowAction(status, data) {\r\n  if (\r\n    status === \"presentation_scheduled\" &&\r\n    !data.presentation_date\r\n  ) {\r\n    return \"Choose the presentation date first.\";\r\n  }\r\n\r\n  if (\r\n    status === \"alternative_dates_offered\" &&\r\n    (\r\n      !data.alternative_arrival ||\r\n      !data.alternative_departure\r\n    )\r\n  ) {\r\n    return \"Enter both alternative dates first.\";\r\n  }\r\n\r\n  if (\r\n    status === \"dates_confirmed\" &&\r\n    (\r\n      !data.confirmed_arrival ||\r\n      !data.confirmed_departure ||\r\n      !data.approved_total\r\n    )\r\n  ) {\r\n    return \"Enter the confirmed dates and approved total first.\";\r\n  }\r\n\r\n  return \"\";\r\n}\r\n\r\nasync function saveRequest(status = \"\") {\r\n  if (!state.request || state.busy) {\r\n    return;\r\n  }\r\n\r\n  const data = requestPayload(status);\r\n\r\n  const validationMessage =\r\n    validateWorkflowAction(status, data);\r\n\r\n  if (validationMessage) {\r\n    toast(validationMessage, true);\r\n    return;\r\n  }\r\n\r\n  setBusy(true);\r\n\r\n  try {\r\n    const response = await post(\r\n      \"ggg_l8_admin_update_path_request\",\r\n      data\r\n    );\r\n\r\n    state.request =\r\n      response.request || state.request;\r\n\r\n    toast(\r\n      response.message ||\r\n      \"Customer workflow updated.\"\r\n    );\r\n\r\n    await loadWorkflow();\r\n  } catch (error) {\r\n    toast(error.message, true);\r\n  } finally {\r\n    setBusy(false);\r\n  }\r\n}\r\n\r\ndocument.addEventListener(\"click\", event => {\r\n  const refreshButton =\r\n    event.target.closest(\"[data-refresh-requests]\");\r\n\r\n  if (refreshButton) {\r\n    loadWorkflow();\r\n    return;\r\n  }\r\n\r\n  const requestButton =\r\n    event.target.closest(\"[data-request-id]\");\r\n\r\n  if (requestButton) {\r\n    state.request =\r\n      state.requests.find(\r\n        request =>\r\n          request.id ===\r\n          requestButton.dataset.requestId\r\n      ) || null;\r\n\r\n    renderWorkflowList();\r\n    renderWorkflowEditor();\r\n    return;\r\n  }\r\n\r\n  const statusButton =\r\n    event.target.closest(\"[data-workflow-status]\");\r\n\r\n  if (statusButton) {\r\n    saveRequest(\r\n      statusButton.dataset.workflowStatus\r\n    );\r\n    return;\r\n  }\r\n\r\n  if (event.target.closest(\"[data-save-request]\")) {\r\n    saveRequest();\r\n    return;\r\n  }\r\n\r\n  const editButton =\r\n    event.target.closest(\"[data-edit]\");\r\n\r\n  if (editButton) {\r\n    const item = state.items.find(\r\n      currentItem =>\r\n        String(currentItem.id) ===\r\n        editButton.dataset.edit\r\n    );\r\n\r\n    if (item) {\r\n      const system = Object.keys(SYSTEMS).find(key => {\r\n        return (\r\n          SYSTEMS[key].mode === \"inventory\" &&\r\n          belongs(item, SYSTEMS[key])\r\n        );\r\n      });\r\n\r\n      if (system) {\r\n        state.system = system;\r\n      }\r\n\r\n      state.group =\r\n        item.group || item.category || state.group;\r\n\r\n      state.option =\r\n        item.option ||\r\n        item.suboption ||\r\n        String(item.suboptionKey || \"\")\r\n          .replace(\/-\/g, \" \");\r\n\r\n      renderSystems();\r\n      renderGroups();\r\n      fill(item);\r\n    }\r\n\r\n    return;\r\n  }\r\n\r\n  const deleteButton =\r\n    event.target.closest(\"[data-delete]\");\r\n\r\n  if (deleteButton) {\r\n    removeItem(deleteButton.dataset.delete);\r\n    return;\r\n  }\r\n\r\n  if (event.target.closest(\"#l8cpSaveItem\")) {\r\n    saveItem();\r\n    return;\r\n  }\r\n\r\n  if (event.target.closest(\"#l8cpClear\")) {\r\n    fill({});\r\n  }\r\n});\r\n\r\n$(\"l8cpSystemSelect\").addEventListener(\r\n  \"change\",\r\n  event => chooseSystem(event.target.value)\r\n);\r\n\r\n$(\"l8cpGroupSelect\").addEventListener(\r\n  \"change\",\r\n  event => chooseGroup(event.target.value)\r\n);\r\n\r\n$(\"l8cpOptionSelect\").addEventListener(\r\n  \"change\",\r\n  event => chooseOption(event.target.value)\r\n);\r\n\r\n$(\"l8cpSearch\").addEventListener(\r\n  \"input\",\r\n  () => {\r\n    const mode = SYSTEMS[state.system].mode;\r\n\r\n    if (mode === \"inventory\") {\r\n      renderList();\r\n    } else if (mode === \"workflow\") {\r\n      renderWorkflowList();\r\n    }\r\n  }\r\n);\r\n\r\n$(\"l8cpExit\").addEventListener(\r\n  \"click\",\r\n  () => {\r\n    location.href = \"\/GGG\/owners-club\/\";\r\n  }\r\n);\r\n\r\n\/* =========================================================\r\n   MEMBER CITY CARDS \u2014 CONTROL PANEL CONNECTION\r\n========================================================= *\/\r\n\r\nSYSTEMS.memberCards = {\r\n  label: \"Member City Cards\",\r\n  hint: \"Luxus balances, issuance and transaction history\",\r\n  mode: \"citycard\",\r\n  groups: {\r\n    \"Member Account\": []\r\n  }\r\n};\r\n\r\nSYSTEMS.ownerRentals = {\r\n  label: \"The Circle \u2014 Owner Rentals\",\r\n  hint: \"Verified ownership time, rental approvals and 50\/50 accounting\",\r\n  mode: \"ownerRentals\",\r\n\r\n  groups: {\r\n    \"Owner Entitlements\": [],\r\n    \"Rental Listings\": [],\r\n    \"Rental Accounting\": []\r\n  }\r\n};\r\n\r\nstate.memberCard = null;\r\n\r\nasync function cityCardPost(action, data = {}) {\r\n  const configuration =\r\n    window.GGGLuxusCityCardAdmin || {};\r\n\r\n  if (!configuration.nonce) {\r\n    throw new Error(\r\n      \"The Luxus City Card administrator connection did not load.\"\r\n    );\r\n  }\r\n\r\n  const form = new FormData();\r\n\r\n  form.append(\"action\", action);\r\n  form.append(\"nonce\", configuration.nonce);\r\n\r\n  Object.entries(data).forEach(([key, value]) => {\r\n    form.append(key, value);\r\n  });\r\n\r\n  const response = await fetch(\r\n    configuration.ajaxUrl || AJAX,\r\n    {\r\n      method: \"POST\",\r\n      credentials: \"same-origin\",\r\n      body: form\r\n    }\r\n  );\r\n\r\n  const result = await response.json();\r\n\r\n  if (!response.ok || result?.success !== true) {\r\n    throw new Error(\r\n      result?.data?.message ||\r\n      result?.data ||\r\n      \"The City Card request failed.\"\r\n    );\r\n  }\r\n\r\n  return result.data || {};\r\n}\r\n\r\nfunction cityCardMoney(value) {\r\n  const number = Number(value || 0);\r\n\r\n  return Number.isFinite(number)\r\n    ? \"$\" + number.toFixed(2)\r\n    : \"$0.00\";\r\n}\r\n\r\nfunction renderMemberCityCard() {\r\n  const panel = $(\"l8cpEditorPanel\");\r\n  const member = state.memberCard;\r\n\r\n  panel.style.display = \"block\";\r\n  panel.dataset.mode = \"citycard\";\r\n\r\n  panel.innerHTML = `\r\n    <h2>Member City Card<\/h2>\r\n\r\n    <div class=\"l8cp-path\">\r\n      Luxus issuance and balance administration\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-form\">\r\n      <div class=\"l8cp-field full\">\r\n        <label>Member ID, email or username<\/label>\r\n\r\n        <input\r\n          id=\"l8ccMemberLookup\"\r\n          value=\"${esc(\r\n            member?.user?.email ||\r\n            member?.user?.id ||\r\n            \"\"\r\n          )}\"\r\n          placeholder=\"Email, username or WordPress user ID\"\r\n        >\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-actions\">\r\n      <button\r\n        class=\"l8cp-btn primary\"\r\n        type=\"button\"\r\n        data-citycard-find\r\n      >\r\n        Find Member\r\n      <\/button>\r\n    <\/div>\r\n\r\n    ${\r\n      member\r\n        ? `\r\n          <div class=\"l8cp-empty\">\r\n            <strong>\r\n              ${esc(member.user?.name || \"Member\")}\r\n            <\/strong>\r\n\r\n            <br>\r\n\r\n            ${esc(member.user?.email || \"\")}\r\n\r\n            <br>\r\n\r\n            City Card:\r\n            ${member.active ? \"ACTIVE\" : \"NOT ACTIVE\"}\r\n          <\/div>\r\n\r\n          <h2>Issue or Adjust Balance<\/h2>\r\n\r\n          <div class=\"l8cp-form\">\r\n            <div class=\"l8cp-field\">\r\n              <label>Balance<\/label>\r\n\r\n              <select id=\"l8ccBalanceType\">\r\n                <option value=\"bc\">\r\n                  Bliss Coin\r\n                <\/option>\r\n\r\n                <option value=\"air\">\r\n                  Air Hours\r\n                <\/option>\r\n\r\n                <option value=\"aqua\">\r\n                  Aqua Hours\r\n                <\/option>\r\n\r\n                <option value=\"gastro\">\r\n                  Gastro Hours\r\n                <\/option>\r\n\r\n                <option value=\"land_days\">\r\n                  Land Days\r\n                <\/option>\r\n\r\n                <option value=\"land_weeks\">\r\n                  Land Weeks\r\n                <\/option>\r\n              <\/select>\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Action<\/label>\r\n\r\n              <select id=\"l8ccDirection\">\r\n                <option value=\"credit\">\r\n                  Credit \/ Issue\r\n                <\/option>\r\n\r\n                <option value=\"debit\">\r\n                  Debit \/ Remove\r\n                <\/option>\r\n              <\/select>\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Quantity<\/label>\r\n\r\n              <input\r\n                id=\"l8ccQuantity\"\r\n                type=\"number\"\r\n                min=\"0\"\r\n                step=\"0.01\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>USD value<\/label>\r\n\r\n              <input\r\n                id=\"l8ccUsdValue\"\r\n                type=\"number\"\r\n                min=\"0\"\r\n                step=\"0.01\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Control-panel product ID<\/label>\r\n\r\n              <input\r\n                id=\"l8ccProductId\"\r\n                placeholder=\"Optional product ID\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Payment \/ external reference<\/label>\r\n\r\n              <input\r\n                id=\"l8ccReference\"\r\n                placeholder=\"Stripe or administrative reference\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field full\">\r\n              <label>Administrative note<\/label>\r\n\r\n              <textarea\r\n                id=\"l8ccDescription\"\r\n                placeholder=\"Reason for this transaction\"\r\n              ><\/textarea>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"l8cp-actions\">\r\n            <button\r\n              class=\"l8cp-btn primary\"\r\n              type=\"button\"\r\n              data-citycard-apply\r\n            >\r\n              Apply Transaction\r\n            <\/button>\r\n          <\/div>\r\n        `\r\n        : \"\"\r\n    }\r\n  `;\r\n\r\n  renderMemberCityCardDetails();\r\n}\r\n\r\nfunction renderMemberCityCardDetails() {\r\n  const member = state.memberCard;\r\n\r\n  $(\"l8cpListTitle\").textContent = member\r\n    ? \"Balances and Transaction History\"\r\n    : \"Member City Card\";\r\n\r\n  $(\"l8cpLive\").innerHTML = \"\";\r\n  $(\"l8cpSearch\").style.display = \"none\";\r\n\r\n  if (!member) {\r\n    $(\"l8cpList\").innerHTML = `\r\n      <div class=\"l8cp-empty\">\r\n        Find a member to view their Luxus City Card.\r\n      <\/div>\r\n    `;\r\n\r\n    return;\r\n  }\r\n\r\n  const balances = Object.entries(\r\n    member.balances || {}\r\n  )\r\n    .map(([key, balance]) => `\r\n      <div class=\"l8cp-item\">\r\n        <strong>\r\n          ${esc(balance.label || key)}\r\n        <\/strong>\r\n\r\n        <div>\r\n          ${esc(balance.balance || \"0.00\")}\r\n        <\/div>\r\n\r\n        <small>\r\n          ${esc(cityCardMoney(balance.value))}\r\n        <\/small>\r\n      <\/div>\r\n    `)\r\n    .join(\"\");\r\n\r\n  const transactions =\r\n    (member.transactions || []).length\r\n      ? member.transactions\r\n          .map(transaction => `\r\n            <div class=\"l8cp-item\">\r\n              <strong>\r\n                ${esc(\r\n                  transaction.balance_label ||\r\n                  transaction.balance_type\r\n                )}\r\n              <\/strong>\r\n\r\n              <div>\r\n                ${\r\n                  Number(transaction.quantity || 0) >= 0\r\n                    ? \"+\"\r\n                    : \"\"\r\n                }\r\n\r\n                ${esc(transaction.quantity)}\r\n\r\n                \u00b7\r\n\r\n                ${esc(\r\n                  transaction.transaction_type ||\r\n                  \"transaction\"\r\n                )}\r\n              <\/div>\r\n\r\n              <small>\r\n                ${esc(transaction.created_at || \"\")}\r\n\r\n                ${\r\n                  transaction.description\r\n                    ? \" \u00b7 \" +\r\n                      esc(transaction.description)\r\n                    : \"\"\r\n                }\r\n\r\n                ${\r\n                  transaction.external_reference\r\n                    ? \" \u00b7 Ref: \" +\r\n                      esc(transaction.external_reference)\r\n                    : \"\"\r\n                }\r\n              <\/small>\r\n            <\/div>\r\n          `)\r\n          .join(\"\")\r\n      : `\r\n          <div class=\"l8cp-empty\">\r\n            No City Card transactions yet.\r\n          <\/div>\r\n        `;\r\n\r\n  $(\"l8cpList\").innerHTML = `\r\n    <h3>Current Balances<\/h3>\r\n\r\n    ${balances}\r\n\r\n    <h3>Transaction History<\/h3>\r\n\r\n    ${transactions}\r\n  `;\r\n}\r\n\r\nasync function findMemberCityCard() {\r\n  const lookup =\r\n    $(\"l8ccMemberLookup\")?.value.trim() || \"\";\r\n\r\n  if (!lookup) {\r\n    toast(\r\n      \"Enter a member ID, email or username.\",\r\n      true\r\n    );\r\n\r\n    return;\r\n  }\r\n\r\n  try {\r\n    state.memberCard = await cityCardPost(\r\n      \"ggg_luxus_admin_get_member_card\",\r\n      {\r\n        user_lookup: lookup\r\n      }\r\n    );\r\n\r\n    renderMemberCityCard();\r\n\r\n    toast(\"Member City Card loaded.\");\r\n  } catch (error) {\r\n    toast(error.message, true);\r\n  }\r\n}\r\n\r\nasync function applyMemberCityCardTransaction() {\r\n  if (!state.memberCard?.user?.id) {\r\n    toast(\"Find a member first.\", true);\r\n    return;\r\n  }\r\n\r\n  const quantity = Math.abs(\r\n    Number(\r\n      $(\"l8ccQuantity\")?.value || 0\r\n    )\r\n  );\r\n\r\n  const usdValue = Math.abs(\r\n    Number(\r\n      $(\"l8ccUsdValue\")?.value || 0\r\n    )\r\n  );\r\n\r\n  const direction =\r\n    $(\"l8ccDirection\")?.value || \"credit\";\r\n\r\n  const multiplier =\r\n    direction === \"debit\" ? -1 : 1;\r\n\r\n  if (quantity <= 0) {\r\n    toast(\r\n      \"Enter a quantity greater than zero.\",\r\n      true\r\n    );\r\n\r\n    return;\r\n  }\r\n\r\n  try {\r\n    await cityCardPost(\r\n      \"ggg_luxus_admin_apply_transaction\",\r\n      {\r\n        user_id: state.memberCard.user.id,\r\n\r\n        balance_type:\r\n          $(\"l8ccBalanceType\").value,\r\n\r\n        transaction_type:\r\n          direction === \"debit\"\r\n            ? \"admin_debit\"\r\n            : \"admin_credit\",\r\n\r\n        quantity:\r\n          quantity * multiplier,\r\n\r\n        usd_value:\r\n          usdValue * multiplier,\r\n\r\n        product_id:\r\n          $(\"l8ccProductId\").value.trim(),\r\n\r\n        external_reference:\r\n          $(\"l8ccReference\").value.trim(),\r\n\r\n        description:\r\n          $(\"l8ccDescription\").value.trim()\r\n      }\r\n    );\r\n\r\n    state.memberCard = await cityCardPost(\r\n      \"ggg_luxus_admin_get_member_card\",\r\n      {\r\n        user_lookup:\r\n          String(state.memberCard.user.id)\r\n      }\r\n    );\r\n\r\n    renderMemberCityCard();\r\n\r\n    toast(\r\n      \"The Luxus City Card was updated.\"\r\n    );\r\n  } catch (error) {\r\n    toast(error.message, true);\r\n  }\r\n}\r\n\r\nconst originalRenderEditorForCityCards =\r\n  renderEditor;\r\n\r\nrenderEditor = function() {\r\n  if (state.system === \"memberCards\") {\r\n    renderMemberCityCard();\r\n    return;\r\n  }\r\n\r\n  $(\"l8cpSearch\").style.display = \"block\";\r\n\r\n  originalRenderEditorForCityCards();\r\n};\r\n\r\nconst originalChooseSystemForCityCards =\r\n  chooseSystem;\r\n\r\nchooseSystem = function(key) {\r\n  if (key !== \"memberCards\") {\r\n    state.memberCard = null;\r\n\r\n    originalChooseSystemForCityCards(key);\r\n\r\n    return;\r\n  }\r\n\r\n  state.system = key;\r\n  state.group = \"Member Account\";\r\n  state.option = \"\";\r\n  state.editing = null;\r\n  state.request = null;\r\n\r\n  renderSystems();\r\n  renderGroups();\r\n  renderEditor();\r\n};\r\n\r\ndocument.addEventListener(\r\n  \"click\",\r\n  event => {\r\n    if (\r\n      event.target.closest(\r\n        \"[data-citycard-find]\"\r\n      )\r\n    ) {\r\n      findMemberCityCard();\r\n      return;\r\n    }\r\n\r\n    if (\r\n      event.target.closest(\r\n        \"[data-citycard-apply]\"\r\n      )\r\n    ) {\r\n      applyMemberCityCardTransaction();\r\n    }\r\n  }\r\n);\r\n\r\n\/* =========================================================\r\n   THE CIRCLE \u2014 OWNER RENTALS CONTROL PANEL CONNECTION\r\n========================================================= *\/\r\n\r\nstate.ownerRentMember = null;\r\nstate.ownerRentEntitlement = null;\r\nstate.ownerRentListings = [];\r\nstate.ownerRentListing = null;\r\n\r\nconst rentNum = value =>\r\n  Number.isFinite(Number(value))\r\n    ? Number(value)\r\n    : 0;\r\n\r\nconst rentStatus = value =>\r\n  String(value || \"pending\").replaceAll(\"_\", \" \");\r\n\r\nconst rentDates = item =>\r\n  [item?.start_date, item?.end_date]\r\n    .filter(Boolean)\r\n    .join(\" \u2192 \") || \"No dates assigned\";\r\n\r\nconst rentArray = value =>\r\n  Array.isArray(value)\r\n    ? value.join(\", \")\r\n    : value || \"\";\r\n\r\nfunction rentMoney(value, currency = \"USD\") {\r\n  try {\r\n    return new Intl.NumberFormat(\"en-US\", {\r\n      style: \"currency\",\r\n      currency: currency || \"USD\"\r\n    }).format(rentNum(value));\r\n  } catch (error) {\r\n    return \"$\" + rentNum(value).toFixed(2);\r\n  }\r\n}\r\n\r\nfunction rentMetric(label, value) {\r\n  return `\r\n    <div class=\"l8cp-ownerMetric\">\r\n      <span>${esc(label)}<\/span>\r\n      <strong>${esc(value)}<\/strong>\r\n    <\/div>\r\n  `;\r\n}\r\n\r\nfunction rentSummary(summary = {}) {\r\n  return `\r\n    <div class=\"l8cp-ownerSummary\">\r\n      ${rentMetric(\r\n        \"Ownerships\",\r\n        rentNum(summary.ownership_count)\r\n      )}\r\n\r\n      ${rentMetric(\r\n        \"Total Time\",\r\n        rentNum(summary.total_quantity)\r\n      )}\r\n\r\n      ${rentMetric(\r\n        \"Available\",\r\n        rentNum(summary.available_quantity)\r\n      )}\r\n\r\n      ${rentMetric(\r\n        \"Listed\",\r\n        rentNum(summary.listed_quantity)\r\n      )}\r\n\r\n      ${rentMetric(\r\n        \"Reserved\",\r\n        rentNum(summary.reserved_quantity)\r\n      )}\r\n\r\n      ${rentMetric(\r\n        \"Owner Earnings\",\r\n        rentMoney(summary.owner_earnings)\r\n      )}\r\n    <\/div>\r\n  `;\r\n}\r\n\r\nfunction renderEntitlementList() {\r\n  const member = state.ownerRentMember;\r\n  const rows = member?.entitlements || [];\r\n\r\n  $(\"l8cpListTitle\").textContent = member\r\n    ? `${member.user?.name || \"Owner\"} \u2014 Property Time`\r\n    : \"Owner Property Time\";\r\n\r\n  $(\"l8cpLive\").innerHTML = member\r\n    ? `\r\n      <div class=\"l8cp-live\">\r\n        SECURE OWNER RECORD \u00b7\r\n        ${esc(\r\n          member.user?.email ||\r\n          member.user?.id ||\r\n          \"\"\r\n        )}\r\n      <\/div>\r\n    `\r\n    : \"\";\r\n\r\n  $(\"l8cpSearch\").style.display = \"none\";\r\n\r\n  $(\"l8cpList\").innerHTML = rows.length\r\n    ? rows.map(item => `\r\n        <button\r\n          class=\"l8cp-ownerRecord ${\r\n            state.ownerRentEntitlement?.id === item.id\r\n              ? \"active\"\r\n              : \"\"\r\n          }\"\r\n          type=\"button\"\r\n          data-owner-entitlement-id=\"${esc(item.id)}\"\r\n        >\r\n          <span>\r\n            <strong>\r\n              ${esc(item.property_name || \"Property Time\")}\r\n            <\/strong>\r\n\r\n            <small>\r\n              ${esc(rentDates(item))}\r\n              <br>\r\n              Total:\r\n              ${esc(item.total_quantity || 0)}\r\n              ${esc(item.unit_label || \"days\")}\r\n              \u00b7 Available:\r\n              ${esc(item.available_quantity || 0)}\r\n              \u00b7 Listed:\r\n              ${esc(item.listed_quantity || 0)}\r\n              \u00b7 Reserved:\r\n              ${esc(item.reserved_quantity || 0)}\r\n            <\/small>\r\n          <\/span>\r\n\r\n          <span class=\"l8cp-ownerStatus\">\r\n            ${esc(rentStatus(item.status))}\r\n          <\/span>\r\n        <\/button>\r\n      `).join(\"\")\r\n    : `\r\n      <div class=\"l8cp-empty\">\r\n        ${\r\n          member\r\n            ? \"This owner has no verified property time yet.\"\r\n            : \"Find an owner to view verified property time.\"\r\n        }\r\n      <\/div>\r\n    `;\r\n}\r\n\r\nfunction renderEntitlementEditor() {\r\n  const panel = $(\"l8cpEditorPanel\");\r\n  const member = state.ownerRentMember;\r\n  const item = state.ownerRentEntitlement || {};\r\n\r\n  panel.style.display = \"block\";\r\n  panel.dataset.mode = \"ownerRentals\";\r\n\r\n  panel.innerHTML = `\r\n    <h2>Owner Entitlements<\/h2>\r\n\r\n    <div class=\"l8cp-path\">\r\n      The Circle &gt; Verified Property Time\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-form\">\r\n      <div class=\"l8cp-field full\">\r\n        <label>Member ID, email or username<\/label>\r\n\r\n        <input\r\n          id=\"l8orMemberLookup\"\r\n          value=\"${esc(\r\n            member?.user?.email ||\r\n            member?.user?.id ||\r\n            \"\"\r\n          )}\"\r\n          placeholder=\"Email, username or WordPress user ID\"\r\n        >\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-actions\">\r\n      <button\r\n        class=\"l8cp-btn primary\"\r\n        type=\"button\"\r\n        data-owner-find\r\n      >\r\n        Find Owner\r\n      <\/button>\r\n\r\n      ${\r\n        member\r\n          ? `\r\n            <button\r\n              class=\"l8cp-btn\"\r\n              type=\"button\"\r\n              data-owner-new-entitlement\r\n            >\r\n              Add Property Time\r\n            <\/button>\r\n          `\r\n          : \"\"\r\n      }\r\n    <\/div>\r\n\r\n    ${\r\n      member\r\n        ? `\r\n          <div class=\"l8cp-live\">\r\n            ${esc(member.user?.name || \"Member\")}\r\n            \u00b7\r\n            ${esc(member.user?.email || \"\")}\r\n          <\/div>\r\n\r\n          ${rentSummary(member.summary || {})}\r\n\r\n          <div class=\"l8cp-sectionLabel\">\r\n            ${\r\n              item.id\r\n                ? \"Edit Verified Property Time\"\r\n                : \"Issue Verified Property Time\"\r\n            }\r\n          <\/div>\r\n\r\n          <div class=\"l8cp-form\">\r\n            <div class=\"l8cp-field\">\r\n              <label>Property ID<\/label>\r\n\r\n              <input\r\n                id=\"l8orPropertyId\"\r\n                value=\"${esc(item.property_id || \"\")}\"\r\n                placeholder=\"aparthotel-bliss\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Property Name<\/label>\r\n\r\n              <input\r\n                id=\"l8orPropertyName\"\r\n                value=\"${esc(item.property_name || \"\")}\"\r\n                placeholder=\"Aparthotel Bliss\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Ownership Reference<\/label>\r\n\r\n              <input\r\n                id=\"l8orOwnershipReference\"\r\n                value=\"${esc(\r\n                  item.ownership_reference || \"\"\r\n                )}\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Agreement Reference<\/label>\r\n\r\n              <input\r\n                id=\"l8orAgreementReference\"\r\n                value=\"${esc(\r\n                  item.agreement_reference || \"\"\r\n                )}\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Owned Start Date<\/label>\r\n\r\n              <input\r\n                id=\"l8orStartDate\"\r\n                type=\"date\"\r\n                value=\"${esc(item.start_date || \"\")}\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Owned End Date<\/label>\r\n\r\n              <input\r\n                id=\"l8orEndDate\"\r\n                type=\"date\"\r\n                value=\"${esc(item.end_date || \"\")}\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Total Owned Quantity<\/label>\r\n\r\n              <input\r\n                id=\"l8orTotalQuantity\"\r\n                type=\"number\"\r\n                min=\"0\"\r\n                step=\"0.01\"\r\n                value=\"${esc(item.total_quantity ?? \"\")}\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Quantity Unit<\/label>\r\n\r\n              <input\r\n                id=\"l8orUnitLabel\"\r\n                value=\"${esc(item.unit_label || \"days\")}\"\r\n                placeholder=\"days or weeks\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Already Used by Owner<\/label>\r\n\r\n              <input\r\n                id=\"l8orOwnerUsed\"\r\n                type=\"number\"\r\n                min=\"0\"\r\n                step=\"0.01\"\r\n                value=\"${esc(\r\n                  item.owner_used_quantity ?? 0\r\n                )}\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Total Property Units<\/label>\r\n\r\n              <input\r\n                id=\"l8orTotalUnits\"\r\n                type=\"number\"\r\n                min=\"0\"\r\n                step=\"1\"\r\n                value=\"${esc(item.total_units ?? \"\")}\"\r\n                placeholder=\"Example: 5 domes\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field full\">\r\n              <label>\r\n                Included Units \u2014 comma separated\r\n              <\/label>\r\n\r\n              <input\r\n                id=\"l8orUnits\"\r\n                value=\"${esc(rentArray(item.units))}\"\r\n                placeholder=\"Dome 1, Dome 2, Dome 3, Dome 4, Dome 5\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field full\">\r\n              <label>\r\n                Permitted Short-Stay Splits \u2014 comma separated\r\n              <\/label>\r\n\r\n              <input\r\n                id=\"l8orAllowedSplits\"\r\n                value=\"${esc(\r\n                  rentArray(item.allowed_splits)\r\n                )}\"\r\n                placeholder=\"2\/5, 3\/5, full day\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Status<\/label>\r\n\r\n              <select id=\"l8orEntitlementStatus\">\r\n                ${\r\n                  [\r\n                    \"active\",\r\n                    \"pending\",\r\n                    \"suspended\",\r\n                    \"expired\",\r\n                    \"cancelled\"\r\n                  ]\r\n                    .map(status => `\r\n                      <option\r\n                        value=\"${status}\"\r\n                        ${\r\n                          (item.status || \"active\") === status\r\n                            ? \"selected\"\r\n                            : \"\"\r\n                        }\r\n                      >\r\n                        ${esc(rentStatus(status))}\r\n                      <\/option>\r\n                    `)\r\n                    .join(\"\")\r\n                }\r\n              <\/select>\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Recorded Value<\/label>\r\n\r\n              <input\r\n                id=\"l8orValue\"\r\n                value=\"${esc(item.value || \"\")}\"\r\n              >\r\n            <\/div>\r\n\r\n            <label class=\"l8cp-toggle full\">\r\n              <input\r\n                id=\"l8orSplittable\"\r\n                type=\"checkbox\"\r\n                ${item.splittable ? \"checked\" : \"\"}\r\n              >\r\n\r\n              Owner may divide this property time\r\n            <\/label>\r\n\r\n            <div class=\"l8cp-field full\">\r\n              <label>Administrative Notes<\/label>\r\n\r\n              <textarea id=\"l8orNotes\">${esc(\r\n                item.notes || \"\"\r\n              )}<\/textarea>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"l8cp-actions\">\r\n            <button\r\n              class=\"l8cp-btn primary\"\r\n              type=\"button\"\r\n              data-owner-save-entitlement\r\n            >\r\n              ${\r\n                item.id\r\n                  ? \"Update Property Time\"\r\n                  : \"Issue Property Time\"\r\n              }\r\n            <\/button>\r\n\r\n            ${\r\n              item.id\r\n                ? `\r\n                  <button\r\n                    class=\"l8cp-btn\"\r\n                    type=\"button\"\r\n                    data-owner-clear-entitlement\r\n                  >\r\n                    Stop Editing\r\n                  <\/button>\r\n                `\r\n                : \"\"\r\n            }\r\n          <\/div>\r\n\r\n          <div class=\"l8cp-ownerNotice\">\r\n            Property time must match the signed purchase\r\n            or use-right agreement. Split rules do not\r\n            create additional ownership.\r\n          <\/div>\r\n        `\r\n        : `\r\n          <div class=\"l8cp-empty\">\r\n            Find an owner before issuing or changing\r\n            verified property time.\r\n          <\/div>\r\n        `\r\n    }\r\n  `;\r\n\r\n  renderEntitlementList();\r\n}\r\n\r\nasync function findOwnerMember() {\r\n  const lookup =\r\n    $(\"l8orMemberLookup\")?.value.trim() || \"\";\r\n\r\n  if (!lookup) {\r\n    toast(\r\n      \"Enter a member ID, email or username.\",\r\n      true\r\n    );\r\n    return;\r\n  }\r\n\r\n  try {\r\n    state.ownerRentMember = await post(\r\n      \"ggg_l8_admin_find_owner\",\r\n      {\r\n        user_lookup: lookup\r\n      }\r\n    );\r\n\r\n    state.ownerRentEntitlement = null;\r\n\r\n    renderEntitlementEditor();\r\n    toast(\"Owner rental account loaded.\");\r\n  } catch (error) {\r\n    toast(error.message, true);\r\n  }\r\n}\r\n\r\nfunction splitRentInput(id) {\r\n  return ($(id)?.value || \"\")\r\n    .split(\/[\\n,]+\/)\r\n    .map(value => value.trim())\r\n    .filter(Boolean);\r\n}\r\n\r\nasync function saveEntitlement() {\r\n  const userId =\r\n    state.ownerRentMember?.user?.id;\r\n\r\n  if (!userId) {\r\n    toast(\"Find an owner first.\", true);\r\n    return;\r\n  }\r\n\r\n  const entitlement = {\r\n    id:\r\n      state.ownerRentEntitlement?.id || \"\",\r\n\r\n    property_id:\r\n      $(\"l8orPropertyId\")?.value.trim() || \"\",\r\n\r\n    property_name:\r\n      $(\"l8orPropertyName\")?.value.trim() || \"\",\r\n\r\n    ownership_reference:\r\n      $(\"l8orOwnershipReference\")?.value.trim() || \"\",\r\n\r\n    agreement_reference:\r\n      $(\"l8orAgreementReference\")?.value.trim() || \"\",\r\n\r\n    start_date:\r\n      $(\"l8orStartDate\")?.value || \"\",\r\n\r\n    end_date:\r\n      $(\"l8orEndDate\")?.value || \"\",\r\n\r\n    total_quantity:\r\n      rentNum($(\"l8orTotalQuantity\")?.value),\r\n\r\n    unit_label:\r\n      $(\"l8orUnitLabel\")?.value.trim() || \"days\",\r\n\r\n    owner_used_quantity:\r\n      rentNum($(\"l8orOwnerUsed\")?.value),\r\n\r\n    total_units:\r\n      rentNum($(\"l8orTotalUnits\")?.value),\r\n\r\n    units:\r\n      splitRentInput(\"l8orUnits\"),\r\n\r\n    allowed_splits:\r\n      splitRentInput(\"l8orAllowedSplits\"),\r\n\r\n    splittable:\r\n      Boolean($(\"l8orSplittable\")?.checked),\r\n\r\n    status:\r\n      $(\"l8orEntitlementStatus\")?.value || \"active\",\r\n\r\n    value:\r\n      $(\"l8orValue\")?.value.trim() || \"\",\r\n\r\n    notes:\r\n      $(\"l8orNotes\")?.value.trim() || \"\"\r\n  };\r\n\r\n  if (\r\n    !entitlement.property_name ||\r\n    entitlement.total_quantity <= 0\r\n  ) {\r\n    toast(\r\n      \"Enter the property name and owned quantity.\",\r\n      true\r\n    );\r\n    return;\r\n  }\r\n\r\n  try {\r\n    const result = await post(\r\n      \"ggg_l8_admin_save_entitlement\",\r\n      {\r\n        user_id: userId,\r\n        entitlement: JSON.stringify(entitlement)\r\n      }\r\n    );\r\n\r\n    state.ownerRentMember =\r\n      result.member ||\r\n      state.ownerRentMember;\r\n\r\n    state.ownerRentEntitlement = null;\r\n\r\n    renderEntitlementEditor();\r\n\r\n    toast(\r\n      result.message ||\r\n      \"Property time saved.\"\r\n    );\r\n  } catch (error) {\r\n    toast(error.message, true);\r\n  }\r\n}\r\n\r\nfunction renderRentalList() {\r\n  const search =\r\n    $(\"l8cpSearch\").value.toLowerCase();\r\n\r\n  const rows =\r\n    state.ownerRentListings.filter(item =>\r\n      !search ||\r\n      JSON.stringify(item)\r\n        .toLowerCase()\r\n        .includes(search)\r\n    );\r\n\r\n  $(\"l8cpListTitle\").textContent =\r\n    state.group;\r\n\r\n  $(\"l8cpLive\").innerHTML = `\r\n    <div class=\"l8cp-live\">\r\n      SECURE RENTAL RECORDS \u00b7\r\n      ${esc(rows.length)} shown\r\n    <\/div>\r\n  `;\r\n\r\n  $(\"l8cpSearch\").style.display = \"block\";\r\n\r\n  $(\"l8cpSearch\").placeholder =\r\n    \"Search owner, property, date or status\";\r\n\r\n  $(\"l8cpList\").innerHTML = rows.length\r\n    ? rows.map(item => `\r\n        <button\r\n          class=\"l8cp-ownerRecord ${\r\n            state.ownerRentListing?.id === item.id\r\n              ? \"active\"\r\n              : \"\"\r\n          }\"\r\n          type=\"button\"\r\n          data-owner-rental-id=\"${esc(item.id)}\"\r\n        >\r\n          <span>\r\n            <strong>\r\n              ${esc(\r\n                item.property_name ||\r\n                \"Rental Listing\"\r\n              )}\r\n            <\/strong>\r\n\r\n            <small>\r\n              ${esc(item.owner?.name || \"Owner\")}\r\n              \u00b7\r\n              ${esc(item.owner?.email || \"\")}\r\n              <br>\r\n              ${esc(rentDates(item))}\r\n              \u00b7\r\n              ${esc(item.quantity || 0)}\r\n              ${esc(item.unit_label || \"days\")}\r\n              \u00b7\r\n              ${esc(\r\n                rentMoney(\r\n                  item.public_price,\r\n                  item.currency\r\n                )\r\n              )}\r\n            <\/small>\r\n          <\/span>\r\n\r\n          <span class=\"l8cp-ownerStatus\">\r\n            ${esc(rentStatus(item.status))}\r\n          <\/span>\r\n        <\/button>\r\n      `).join(\"\")\r\n    : `\r\n      <div class=\"l8cp-empty\">\r\n        No rental records match this view.\r\n      <\/div>\r\n    `;\r\n}\r\n\r\nfunction renderRentalEditor() {\r\n  const panel = $(\"l8cpEditorPanel\");\r\n  const item = state.ownerRentListing;\r\n\r\n  const accounting =\r\n    state.group === \"Rental Accounting\";\r\n\r\n  panel.style.display = \"block\";\r\n  panel.dataset.mode = \"ownerRentals\";\r\n\r\n  if (!item) {\r\n    panel.innerHTML = `\r\n      <h2>${esc(state.group)}<\/h2>\r\n\r\n      <div class=\"l8cp-path\">\r\n        The Circle &gt; ${esc(state.group)}\r\n      <\/div>\r\n\r\n      <div class=\"l8cp-empty\">\r\n        ${\r\n          accounting\r\n            ? \"Select a rental record to review payment and owner payout accounting.\"\r\n            : \"Select an owner rental submission from the right to review it.\"\r\n        }\r\n      <\/div>\r\n\r\n      <div class=\"l8cp-ownerNotice\">\r\n        Only verified property time issued in Owner\r\n        Entitlements can enter this workflow.\r\n      <\/div>\r\n    `;\r\n\r\n    return;\r\n  }\r\n\r\n  const finance = item.finance || {};\r\n\r\n  const units =\r\n    Array.isArray(item.selected_units)\r\n      ? item.selected_units.join(\", \")\r\n      : item.selected_units ||\r\n        \"None selected\";\r\n\r\n  panel.innerHTML = `\r\n    <h2>\r\n      ${esc(\r\n        item.property_name ||\r\n        \"Rental Listing\"\r\n      )}\r\n    <\/h2>\r\n\r\n    <div class=\"l8cp-path\">\r\n      The Circle &gt;\r\n      ${esc(state.group)}\r\n      &gt;\r\n      ${esc(rentStatus(item.status))}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-requestInfo\">\r\n      ${informationBox(\"Listing ID\", item.id)}\r\n      ${informationBox(\"Owner\", item.owner?.name)}\r\n      ${informationBox(\"Owner Email\", item.owner?.email)}\r\n\r\n      ${informationBox(\r\n        \"Owned Reference\",\r\n        item.ownership_reference\r\n      )}\r\n\r\n      ${informationBox(\r\n        \"Rental Dates\",\r\n        rentDates(item)\r\n      )}\r\n\r\n      ${informationBox(\r\n        \"Quantity\",\r\n        `${item.quantity || 0} ${\r\n          item.unit_label || \"days\"\r\n        }`\r\n      )}\r\n\r\n      ${informationBox(\r\n        \"Selection\",\r\n        rentStatus(item.selection_type)\r\n      )}\r\n\r\n      ${informationBox(\r\n        \"Selected Units\",\r\n        units\r\n      )}\r\n\r\n      ${informationBox(\r\n        \"Public Price\",\r\n        rentMoney(\r\n          item.public_price,\r\n          item.currency\r\n        )\r\n      )}\r\n\r\n      ${informationBox(\r\n        \"Terms Accepted\",\r\n        item.agreement_accepted\r\n          ? \"Yes\"\r\n          : \"No\"\r\n      )}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-sectionLabel\">\r\n      Owner Note\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-readonly\">\r\n      ${esc(item.owner_note || \"No owner note.\")}\r\n    <\/div>\r\n\r\n    ${\r\n      accounting\r\n        ? `\r\n          <div class=\"l8cp-sectionLabel\">\r\n            Rental Accounting\r\n          <\/div>\r\n\r\n          <div class=\"l8cp-form\">\r\n            <div class=\"l8cp-field\">\r\n              <label>Gross Rental Amount<\/label>\r\n\r\n              <input\r\n                id=\"l8orGross\"\r\n                type=\"number\"\r\n                min=\"0\"\r\n                step=\"0.01\"\r\n                value=\"${esc(\r\n                  finance.gross_amount ?? 0\r\n                )}\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Refund Amount<\/label>\r\n\r\n              <input\r\n                id=\"l8orRefund\"\r\n                type=\"number\"\r\n                min=\"0\"\r\n                step=\"0.01\"\r\n                value=\"${esc(\r\n                  finance.refund_amount ?? 0\r\n                )}\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Signed Adjustment<\/label>\r\n\r\n              <input\r\n                id=\"l8orAdjustment\"\r\n                type=\"number\"\r\n                step=\"0.01\"\r\n                value=\"${esc(\r\n                  finance.adjustment_amount ?? 0\r\n                )}\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Payment Reference<\/label>\r\n\r\n              <input\r\n                id=\"l8orPaymentReference\"\r\n                value=\"${esc(\r\n                  finance.payment_reference || \"\"\r\n                )}\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Owner Payout Status<\/label>\r\n\r\n              <select id=\"l8orPayoutStatus\">\r\n                ${\r\n                  [\r\n                    \"not_ready\",\r\n                    \"pending\",\r\n                    \"approved\",\r\n                    \"paid\",\r\n                    \"reversed\"\r\n                  ]\r\n                    .map(status => `\r\n                      <option\r\n                        value=\"${status}\"\r\n                        ${\r\n                          (\r\n                            finance.payout_status ||\r\n                            \"not_ready\"\r\n                          ) === status\r\n                            ? \"selected\"\r\n                            : \"\"\r\n                        }\r\n                      >\r\n                        ${esc(rentStatus(status))}\r\n                      <\/option>\r\n                    `)\r\n                    .join(\"\")\r\n                }\r\n              <\/select>\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Owner Payout Reference<\/label>\r\n\r\n              <input\r\n                id=\"l8orPayoutReference\"\r\n                value=\"${esc(\r\n                  finance.payout_reference || \"\"\r\n                )}\"\r\n              >\r\n            <\/div>\r\n\r\n            <div class=\"l8cp-field\">\r\n              <label>Owner Payout Date<\/label>\r\n\r\n              <input\r\n                id=\"l8orPayoutDate\"\r\n                type=\"date\"\r\n                value=\"${esc(\r\n                  finance.payout_date || \"\"\r\n                )}\"\r\n              >\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"l8cp-ownerSummary\">\r\n            ${rentMetric(\r\n              \"Gross\",\r\n              rentMoney(\r\n                finance.gross_amount,\r\n                item.currency\r\n              )\r\n            )}\r\n\r\n            ${rentMetric(\r\n              \"Administration 50%\",\r\n              rentMoney(\r\n                finance.administration_share,\r\n                item.currency\r\n              )\r\n            )}\r\n\r\n            ${rentMetric(\r\n              \"Owner 50%\",\r\n              rentMoney(\r\n                finance.owner_share,\r\n                item.currency\r\n              )\r\n            )}\r\n          <\/div>\r\n\r\n          <div class=\"l8cp-actions\">\r\n            <button\r\n              class=\"l8cp-btn primary\"\r\n              type=\"button\"\r\n              data-owner-save-finance\r\n            >\r\n              Save Rental Accounting\r\n            <\/button>\r\n          <\/div>\r\n\r\n          <div class=\"l8cp-ownerNotice\">\r\n            The server calculates the 50\/50 division\r\n            from gross minus refunds plus adjustments.\r\n          <\/div>\r\n        `\r\n        : `\r\n          <div class=\"l8cp-sectionLabel\">\r\n            Administration Review\r\n          <\/div>\r\n\r\n          <div class=\"l8cp-field full\">\r\n            <label>Administrative Note<\/label>\r\n\r\n            <textarea id=\"l8orAdminNote\">${esc(\r\n              item.admin_note || \"\"\r\n            )}<\/textarea>\r\n          <\/div>\r\n\r\n          <div class=\"l8cp-statusActions\">\r\n            ${\r\n              [\r\n                [\"changes_requested\", \"Request Changes\"],\r\n                [\"approved\", \"Approve\"],\r\n                [\"active\", \"Publish Rental\"],\r\n                [\"temporary_hold\", \"Temporary Hold\"],\r\n                [\"reserved\", \"Reserved\"],\r\n                [\"completed\", \"Completed\"],\r\n                [\"paused\", \"Pause\"],\r\n                [\"declined\", \"Decline\"],\r\n                [\"cancelled\", \"Cancel\"]\r\n              ]\r\n                .map(([status, label]) => `\r\n                  <button\r\n                    class=\"l8cp-btn ${\r\n                      [\r\n                        \"declined\",\r\n                        \"cancelled\"\r\n                      ].includes(status)\r\n                        ? \"danger\"\r\n                        : \"\"\r\n                    }\"\r\n                    type=\"button\"\r\n                    data-owner-rental-status=\"${status}\"\r\n                  >\r\n                    ${label}\r\n                  <\/button>\r\n                `)\r\n                .join(\"\")\r\n            }\r\n          <\/div>\r\n\r\n          <div class=\"l8cp-ownerNotice\">\r\n            Approval verifies the submitted dates and\r\n            units. Publishing marks the record ready\r\n            for the Bliss Travel rental-inventory\r\n            connection.\r\n          <\/div>\r\n        `\r\n    }\r\n  `;\r\n}\r\n\r\nasync function loadRentalListings(\r\n  keepSelection = true\r\n) {\r\n  const selectedId = keepSelection\r\n    ? state.ownerRentListing?.id\r\n    : \"\";\r\n\r\n  $(\"l8cpList\").innerHTML = `\r\n    <div class=\"l8cp-empty\">\r\n      Loading owner rental records...\r\n    <\/div>\r\n  `;\r\n\r\n  try {\r\n    const data = await post(\r\n      \"ggg_l8_admin_get_rental_listings\",\r\n      {\r\n        status: \"all\"\r\n      }\r\n    );\r\n\r\n    state.ownerRentListings =\r\n      Array.isArray(data.listings)\r\n        ? data.listings\r\n        : [];\r\n\r\n    state.ownerRentListing = selectedId\r\n      ? state.ownerRentListings.find(\r\n          item => item.id === selectedId\r\n        ) || null\r\n      : null;\r\n\r\n    renderRentalList();\r\n    renderRentalEditor();\r\n  } catch (error) {\r\n    $(\"l8cpList\").innerHTML = `\r\n      <div class=\"l8cp-error\">\r\n        ${esc(error.message)}\r\n      <\/div>\r\n    `;\r\n  }\r\n}\r\n\r\nasync function updateRentalStatus(status) {\r\n  if (!state.ownerRentListing) {\r\n    return;\r\n  }\r\n\r\n  try {\r\n    const result = await post(\r\n      \"ggg_l8_admin_update_rental_listing\",\r\n      {\r\n        listing_id:\r\n          state.ownerRentListing.id,\r\n\r\n        status,\r\n\r\n        admin_note:\r\n          $(\"l8orAdminNote\")?.value.trim() || \"\"\r\n      }\r\n    );\r\n\r\n    toast(\r\n      result.message ||\r\n      \"Rental workflow updated.\"\r\n    );\r\n\r\n    await loadRentalListings(true);\r\n  } catch (error) {\r\n    toast(error.message, true);\r\n  }\r\n}\r\n\r\nasync function saveRentalFinance() {\r\n  if (!state.ownerRentListing) {\r\n    return;\r\n  }\r\n\r\n  try {\r\n    const result = await post(\r\n      \"ggg_l8_admin_save_rental_finance\",\r\n      {\r\n        listing_id:\r\n          state.ownerRentListing.id,\r\n\r\n        gross_amount:\r\n          $(\"l8orGross\")?.value || 0,\r\n\r\n        refund_amount:\r\n          $(\"l8orRefund\")?.value || 0,\r\n\r\n        adjustment_amount:\r\n          $(\"l8orAdjustment\")?.value || 0,\r\n\r\n        payment_reference:\r\n          $(\"l8orPaymentReference\")?.value.trim() || \"\",\r\n\r\n        payout_status:\r\n          $(\"l8orPayoutStatus\")?.value || \"not_ready\",\r\n\r\n        payout_reference:\r\n          $(\"l8orPayoutReference\")?.value.trim() || \"\",\r\n\r\n        payout_date:\r\n          $(\"l8orPayoutDate\")?.value || \"\"\r\n      }\r\n    );\r\n\r\n    toast(\r\n      result.message ||\r\n      \"Rental accounting saved.\"\r\n    );\r\n\r\n    await loadRentalListings(true);\r\n  } catch (error) {\r\n    toast(error.message, true);\r\n  }\r\n}\r\n\r\nfunction renderOwnerRentals() {\r\n  if (state.group === \"Owner Entitlements\") {\r\n    renderEntitlementEditor();\r\n    return;\r\n  }\r\n\r\n  renderRentalEditor();\r\n  renderRentalList();\r\n}\r\n\r\nconst renderEditorBeforeOwnerRentals =\r\n  renderEditor;\r\n\r\nrenderEditor = function() {\r\n  if (state.system === \"ownerRentals\") {\r\n    renderOwnerRentals();\r\n    return;\r\n  }\r\n\r\n  renderEditorBeforeOwnerRentals();\r\n};\r\n\r\nconst chooseSystemBeforeOwnerRentals =\r\n  chooseSystem;\r\n\r\nchooseSystem = function(key) {\r\n  if (key !== \"ownerRentals\") {\r\n    state.ownerRentMember = null;\r\n    state.ownerRentEntitlement = null;\r\n    state.ownerRentListing = null;\r\n\r\n    chooseSystemBeforeOwnerRentals(key);\r\n    return;\r\n  }\r\n\r\n  state.system = key;\r\n  state.group = \"Owner Entitlements\";\r\n  state.option = \"\";\r\n  state.editing = null;\r\n  state.request = null;\r\n\r\n  state.ownerRentMember = null;\r\n  state.ownerRentEntitlement = null;\r\n  state.ownerRentListing = null;\r\n\r\n  renderSystems();\r\n  renderGroups();\r\n  renderEditor();\r\n};\r\n\r\nconst chooseGroupBeforeOwnerRentals =\r\n  chooseGroup;\r\n\r\nchooseGroup = function(group) {\r\n  if (state.system !== \"ownerRentals\") {\r\n    chooseGroupBeforeOwnerRentals(group);\r\n    return;\r\n  }\r\n\r\n  state.group = group;\r\n  state.option = \"\";\r\n  state.ownerRentListing = null;\r\n\r\n  renderGroups();\r\n  renderEditor();\r\n\r\n  if (group !== \"Owner Entitlements\") {\r\n    loadRentalListings(false);\r\n  }\r\n};\r\n\r\n$(\"l8cpSearch\").addEventListener(\r\n  \"input\",\r\n  () => {\r\n    if (\r\n      state.system === \"ownerRentals\" &&\r\n      state.group !== \"Owner Entitlements\"\r\n    ) {\r\n      renderRentalList();\r\n    }\r\n  }\r\n);\r\n\r\ndocument.addEventListener(\r\n  \"click\",\r\n  event => {\r\n    if (\r\n      event.target.closest(\"[data-owner-find]\")\r\n    ) {\r\n      findOwnerMember();\r\n      return;\r\n    }\r\n\r\n    if (\r\n      event.target.closest(\r\n        \"[data-owner-new-entitlement], \" +\r\n        \"[data-owner-clear-entitlement]\"\r\n      )\r\n    ) {\r\n      state.ownerRentEntitlement = null;\r\n      renderEntitlementEditor();\r\n      return;\r\n    }\r\n\r\n    if (\r\n      event.target.closest(\r\n        \"[data-owner-save-entitlement]\"\r\n      )\r\n    ) {\r\n      saveEntitlement();\r\n      return;\r\n    }\r\n\r\n    const entitlementButton =\r\n      event.target.closest(\r\n        \"[data-owner-entitlement-id]\"\r\n      );\r\n\r\n    if (entitlementButton) {\r\n      state.ownerRentEntitlement =\r\n        (\r\n          state.ownerRentMember?.entitlements ||\r\n          []\r\n        ).find(\r\n          item =>\r\n            item.id ===\r\n            entitlementButton.dataset\r\n              .ownerEntitlementId\r\n        ) || null;\r\n\r\n      renderEntitlementEditor();\r\n      return;\r\n    }\r\n\r\n    const rentalButton =\r\n      event.target.closest(\r\n        \"[data-owner-rental-id]\"\r\n      );\r\n\r\n    if (rentalButton) {\r\n      state.ownerRentListing =\r\n        state.ownerRentListings.find(\r\n          item =>\r\n            item.id ===\r\n            rentalButton.dataset.ownerRentalId\r\n        ) || null;\r\n\r\n      renderRentalList();\r\n      renderRentalEditor();\r\n      return;\r\n    }\r\n\r\n    const statusButton =\r\n      event.target.closest(\r\n        \"[data-owner-rental-status]\"\r\n      );\r\n\r\n    if (statusButton) {\r\n      updateRentalStatus(\r\n        statusButton.dataset.ownerRentalStatus\r\n      );\r\n      return;\r\n    }\r\n\r\n    if (\r\n      event.target.closest(\r\n        \"[data-owner-save-finance]\"\r\n      )\r\n    ) {\r\n      saveRentalFinance();\r\n    }\r\n  }\r\n);\r\n\r\n\r\n\/* =========================================================\r\n   TRADE CONSTELLATION \u2014 CONTROL PANEL CONNECTION\r\n========================================================= *\/\r\n\r\nstate.tradeAdminRecords = [];\r\nstate.tradeAdminSelected = null;\r\n\r\nconst TRADE_ADMIN_GROUP_STATUS = {\r\n  \"All Trades\": \"all\",\r\n  \"Open Marketplace\": \"open\",\r\n  \"Property Verification\": \"pending_admin\",\r\n  \"Completed\": \"completed\",\r\n  \"Closed\": \"closed\"\r\n};\r\n\r\nfunction tradeAdminAsset(asset) {\r\n  asset = asset || {};\r\n  const amount = Number(asset.amount || 0);\r\n  const cleanAmount = Number.isInteger(amount)\r\n    ? String(amount)\r\n    : amount.toFixed(2);\r\n\r\n  if (asset.type === \"open\") {\r\n    return \"Open to Offers\";\r\n  }\r\n\r\n  const property = asset.property_name\r\n    ? \" \u00b7 \" + asset.property_name\r\n    : \"\";\r\n\r\n  return [\r\n    cleanAmount,\r\n    asset.unit || \"\",\r\n    asset.label || asset.type || \"Asset\"\r\n  ].filter(Boolean).join(\" \") + property;\r\n}\r\n\r\nfunction tradeAdminStatus(status) {\r\n  return String(status || \"unknown\")\r\n    .replaceAll(\"_\", \" \");\r\n}\r\n\r\nfunction tradeAdminAcceptedOffer(trade) {\r\n  return (trade.offers || []).find(\r\n    offer =>\r\n      offer.id === trade.accepted_offer_id ||\r\n      offer.status === \"accepted\"\r\n  ) || null;\r\n}\r\n\r\nfunction tradeAdminFilteredRecords() {\r\n  const status =\r\n    TRADE_ADMIN_GROUP_STATUS[state.group] || \"all\";\r\n\r\n  const search = String(\r\n    $(\"l8cpSearch\")?.value || \"\"\r\n  ).trim().toLowerCase();\r\n\r\n  return state.tradeAdminRecords.filter(trade => {\r\n    const tradeStatus = String(trade.status || \"\");\r\n\r\n    const matchesStatus =\r\n      status === \"all\" ||\r\n      tradeStatus === status ||\r\n      (\r\n        status === \"closed\" &&\r\n        [\r\n          \"cancelled\",\r\n          \"expired\",\r\n          \"rejected\"\r\n        ].includes(tradeStatus)\r\n      );\r\n\r\n    if (!matchesStatus) {\r\n      return false;\r\n    }\r\n\r\n    if (!search) {\r\n      return true;\r\n    }\r\n\r\n    const haystack = [\r\n      trade.id,\r\n      trade.owner_id,\r\n      trade.status,\r\n      trade.offered_asset?.label,\r\n      trade.offered_asset?.property_name,\r\n      trade.wanted_asset?.label,\r\n      trade.wanted_asset?.property_name\r\n    ].join(\" \").toLowerCase();\r\n\r\n    return haystack.includes(search);\r\n  });\r\n}\r\n\r\nfunction tradeAdminCounts() {\r\n  const records = state.tradeAdminRecords;\r\n\r\n  return {\r\n    all: records.length,\r\n    open: records.filter(\r\n      trade => trade.status === \"open\"\r\n    ).length,\r\n    pending: records.filter(\r\n      trade => trade.status === \"pending_admin\"\r\n    ).length,\r\n    completed: records.filter(\r\n      trade => trade.status === \"completed\"\r\n    ).length\r\n  };\r\n}\r\n\r\nfunction renderTradeAdminSide() {\r\n  const counts = tradeAdminCounts();\r\n\r\n  $(\"l8cpSideTitle\").textContent =\r\n    \"Trade Constellation\";\r\n\r\n  $(\"l8cpGroups\").innerHTML = `\r\n    <button\r\n      class=\"l8cp-btn primary\"\r\n      type=\"button\"\r\n      data-trade-admin-refresh\r\n    >\r\n      Refresh Trades\r\n    <\/button>\r\n\r\n    <div class=\"l8cp-empty\">\r\n      <strong>Live Trade Activity<\/strong><br><br>\r\n      ${counts.all} total trades<br>\r\n      ${counts.open} open marketplace trades<br>\r\n      ${counts.pending} awaiting Property Time approval<br>\r\n      ${counts.completed} completed trades\r\n    <\/div>\r\n  `;\r\n}\r\n\r\nfunction renderTradeAdminList() {\r\n  const records = tradeAdminFilteredRecords();\r\n\r\n  $(\"l8cpListTitle\").textContent = state.group;\r\n\r\n  $(\"l8cpLive\").innerHTML = `\r\n    <div class=\"l8cp-live\">\r\n      SECURE TRADE ENGINE \u00b7 ggg_l8_admin_get_trades\r\n    <\/div>\r\n  `;\r\n\r\n  $(\"l8cpList\").innerHTML = records.length\r\n    ? records.map(trade => {\r\n        const accepted = tradeAdminAcceptedOffer(trade);\r\n        const receiving = accepted\r\n          ? accepted.offered_asset\r\n          : trade.wanted_asset;\r\n\r\n        return `\r\n          <article class=\"l8cp-card\">\r\n            <div class=\"l8cp-card-top\">\r\n              <div>\r\n                <strong>\r\n                  ${esc(tradeAdminAsset(trade.offered_asset))}\r\n                <\/strong>\r\n                <small>\r\n                  FOR ${esc(tradeAdminAsset(receiving))}\r\n                <\/small>\r\n              <\/div>\r\n\r\n              <span class=\"l8cp-status\">\r\n                ${esc(tradeAdminStatus(trade.status))}\r\n              <\/span>\r\n            <\/div>\r\n\r\n            <p>\r\n              Owner ID: ${esc(trade.owner_id || \"\")}\r\n              \u00b7 ${esc((trade.offers || []).length)} offer(s)\r\n            <\/p>\r\n\r\n            <button\r\n              class=\"l8cp-btn\"\r\n              type=\"button\"\r\n              data-trade-admin-id=\"${esc(trade.id)}\"\r\n            >\r\n              Review Trade\r\n            <\/button>\r\n          <\/article>\r\n        `;\r\n      }).join(\"\")\r\n    : `\r\n      <div class=\"l8cp-empty\">\r\n        No Trade records match this view.\r\n      <\/div>\r\n    `;\r\n}\r\n\r\nfunction renderTradeAdminEditor() {\r\n  const panel = $(\"l8cpEditorPanel\");\r\n  panel.style.display = \"block\";\r\n  panel.dataset.mode = \"trade_admin\";\r\n\r\n  const trade = state.tradeAdminSelected;\r\n\r\n  if (!trade) {\r\n    panel.innerHTML = `\r\n      <h2>Trade Verification<\/h2>\r\n\r\n      <div class=\"l8cp-empty\">\r\n        Select a Trade record from the right.\r\n        <br><br>\r\n        Digital credit and time trades complete through\r\n        the secure engine after both balances are verified.\r\n        Property Time trades stop here for Bliss\r\n        Administration approval.\r\n      <\/div>\r\n    `;\r\n    return;\r\n  }\r\n\r\n  const accepted = tradeAdminAcceptedOffer(trade);\r\n  const receiving = accepted\r\n    ? accepted.offered_asset\r\n    : trade.wanted_asset;\r\n\r\n  const offers = Array.isArray(trade.offers)\r\n    ? trade.offers\r\n    : [];\r\n\r\n  const needsReview =\r\n    trade.status === \"pending_admin\";\r\n\r\n  panel.innerHTML = `\r\n    <h2>Trade Verification<\/h2>\r\n\r\n    <div class=\"l8cp-path\">\r\n      Trade Constellation &gt;\r\n      ${esc(tradeAdminStatus(trade.status))}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-form\">\r\n      <div class=\"l8cp-field full\">\r\n        <label>Owner Offers<\/label>\r\n        <input\r\n          value=\"${esc(tradeAdminAsset(trade.offered_asset))}\"\r\n          readonly\r\n        >\r\n      <\/div>\r\n\r\n      <div class=\"l8cp-field full\">\r\n        <label>Accepted \/ Requested Value<\/label>\r\n        <input\r\n          value=\"${esc(tradeAdminAsset(receiving))}\"\r\n          readonly\r\n        >\r\n      <\/div>\r\n\r\n      <div class=\"l8cp-field\">\r\n        <label>Trade ID<\/label>\r\n        <input value=\"${esc(trade.id || \"\")}\" readonly>\r\n      <\/div>\r\n\r\n      <div class=\"l8cp-field\">\r\n        <label>Owner ID<\/label>\r\n        <input value=\"${esc(trade.owner_id || \"\")}\" readonly>\r\n      <\/div>\r\n\r\n      <div class=\"l8cp-field\">\r\n        <label>Status<\/label>\r\n        <input\r\n          value=\"${esc(tradeAdminStatus(trade.status))}\"\r\n          readonly\r\n        >\r\n      <\/div>\r\n\r\n      <div class=\"l8cp-field\">\r\n        <label>Expires<\/label>\r\n        <input value=\"${esc(trade.expires_at || \"\")}\" readonly>\r\n      <\/div>\r\n\r\n      <div class=\"l8cp-field full\">\r\n        <label>Owner Notes<\/label>\r\n        <textarea readonly>${esc(trade.notes || \"\")}<\/textarea>\r\n      <\/div>\r\n\r\n      <div class=\"l8cp-field full\">\r\n        <label>Offers Received<\/label>\r\n        <div class=\"l8cp-empty\">\r\n          ${offers.length\r\n            ? offers.map(offer => `\r\n                <strong>${esc(offer.owner_alias || \"Owner\")}<\/strong>\r\n                \u00b7 ${esc(tradeAdminAsset(offer.offered_asset))}\r\n                \u00b7 ${esc(tradeAdminStatus(offer.status))}\r\n              `).join(\"<br>\")\r\n            : \"No offers received.\"}\r\n        <\/div>\r\n      <\/div>\r\n\r\n      ${needsReview ? `\r\n        <div class=\"l8cp-field full\">\r\n          <label>Bliss Administration Note<\/label>\r\n          <textarea\r\n            id=\"l8TradeAdminNote\"\r\n            placeholder=\"Verification, agreement or date notes\"\r\n          >${esc(trade.admin_note || \"\")}<\/textarea>\r\n        <\/div>\r\n\r\n        <div class=\"l8cp-field full\">\r\n          <div class=\"l8cp-empty\">\r\n            Approving completes the verified Property Time\r\n            transfer and updates both owner accounts. Rejecting\r\n            releases the temporary Trade holds.\r\n          <\/div>\r\n        <\/div>\r\n      ` : \"\"}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-actions\">\r\n      ${needsReview ? `\r\n        <button\r\n          class=\"l8cp-btn primary\"\r\n          type=\"button\"\r\n          data-trade-admin-decision=\"approve\"\r\n        >\r\n          Approve & Complete\r\n        <\/button>\r\n\r\n        <button\r\n          class=\"l8cp-btn\"\r\n          type=\"button\"\r\n          data-trade-admin-decision=\"reject\"\r\n        >\r\n          Reject Trade\r\n        <\/button>\r\n      ` : \"\"}\r\n\r\n      <button\r\n        class=\"l8cp-btn\"\r\n        type=\"button\"\r\n        data-trade-admin-close\r\n      >\r\n        Close Record\r\n      <\/button>\r\n    <\/div>\r\n  `;\r\n}\r\n\r\nasync function loadTradeAdmin(showToast = false) {\r\n  $(\"l8cpList\").innerHTML = `\r\n    <div class=\"l8cp-empty\">\r\n      Loading secure Trade records...\r\n    <\/div>\r\n  `;\r\n\r\n  try {\r\n    const data = await post(\r\n      \"ggg_l8_admin_get_trades\"\r\n    );\r\n\r\n    state.tradeAdminRecords =\r\n      Array.isArray(data.trades)\r\n        ? data.trades\r\n        : [];\r\n\r\n    if (state.tradeAdminSelected) {\r\n      state.tradeAdminSelected =\r\n        state.tradeAdminRecords.find(\r\n          trade =>\r\n            trade.id ===\r\n            state.tradeAdminSelected.id\r\n        ) || null;\r\n    }\r\n\r\n    renderTradeAdminSide();\r\n    renderTradeAdminList();\r\n    renderTradeAdminEditor();\r\n\r\n    if (showToast) {\r\n      toast(\"Trade records refreshed.\");\r\n    }\r\n  } catch (error) {\r\n    $(\"l8cpList\").innerHTML = `\r\n      <div class=\"l8cp-error\">\r\n        ${esc(error.message)}\r\n      <\/div>\r\n    `;\r\n  }\r\n}\r\n\r\nasync function resolveTradeAdmin(decision) {\r\n  const trade = state.tradeAdminSelected;\r\n\r\n  if (!trade) {\r\n    return;\r\n  }\r\n\r\n  const actionText =\r\n    decision === \"approve\"\r\n      ? \"approve and complete\"\r\n      : \"reject\";\r\n\r\n  if (!window.confirm(\r\n    `Are you sure you want to ${actionText} this Trade?`\r\n  )) {\r\n    return;\r\n  }\r\n\r\n  try {\r\n    const data = await post(\r\n      \"ggg_l8_admin_resolve_trade\",\r\n      {\r\n        trade_id: trade.id,\r\n        decision,\r\n        admin_note:\r\n          $(\"l8TradeAdminNote\")?.value.trim() || \"\"\r\n      }\r\n    );\r\n\r\n    toast(data.message || \"Trade updated.\");\r\n    await loadTradeAdmin(false);\r\n  } catch (error) {\r\n    toast(error.message, true);\r\n  }\r\n}\r\n\r\nconst renderEditorBeforeTradeAdmin = renderEditor;\r\n\r\nrenderEditor = function() {\r\n  if (state.system === \"tradeOperations\") {\r\n    renderTradeAdminEditor();\r\n    return;\r\n  }\r\n\r\n  renderEditorBeforeTradeAdmin();\r\n};\r\n\r\nconst chooseSystemBeforeTradeAdmin = chooseSystem;\r\n\r\nchooseSystem = function(key) {\r\n  if (key !== \"tradeOperations\") {\r\n    state.tradeAdminSelected = null;\r\n    chooseSystemBeforeTradeAdmin(key);\r\n    return;\r\n  }\r\n\r\n  state.system = key;\r\n  state.group = \"All Trades\";\r\n  state.option = \"\";\r\n  state.editing = null;\r\n  state.request = null;\r\n  state.tradeAdminSelected = null;\r\n\r\n  renderSystems();\r\n  renderGroups();\r\n  renderTradeAdminEditor();\r\n  loadTradeAdmin(false);\r\n};\r\n\r\nconst chooseGroupBeforeTradeAdmin = chooseGroup;\r\n\r\nchooseGroup = function(group) {\r\n  if (state.system !== \"tradeOperations\") {\r\n    chooseGroupBeforeTradeAdmin(group);\r\n    return;\r\n  }\r\n\r\n  state.group = group;\r\n  state.option = \"\";\r\n  state.tradeAdminSelected = null;\r\n\r\n  renderGroups();\r\n  renderTradeAdminEditor();\r\n  renderTradeAdminList();\r\n};\r\n\r\n$(\"l8cpSearch\").addEventListener(\r\n  \"input\",\r\n  () => {\r\n    if (state.system === \"tradeOperations\") {\r\n      renderTradeAdminList();\r\n    }\r\n  }\r\n);\r\n\r\ndocument.addEventListener(\"click\", event => {\r\n  const review = event.target.closest(\r\n    \"[data-trade-admin-id]\"\r\n  );\r\n\r\n  if (review) {\r\n    state.tradeAdminSelected =\r\n      state.tradeAdminRecords.find(\r\n        trade =>\r\n          trade.id === review.dataset.tradeAdminId\r\n      ) || null;\r\n\r\n    renderTradeAdminEditor();\r\n    return;\r\n  }\r\n\r\n  const decision = event.target.closest(\r\n    \"[data-trade-admin-decision]\"\r\n  );\r\n\r\n  if (decision) {\r\n    resolveTradeAdmin(\r\n      decision.dataset.tradeAdminDecision\r\n    );\r\n    return;\r\n  }\r\n\r\n  if (event.target.closest(\r\n    \"[data-trade-admin-refresh]\"\r\n  )) {\r\n    loadTradeAdmin(true);\r\n    return;\r\n  }\r\n\r\n  if (event.target.closest(\r\n    \"[data-trade-admin-close]\"\r\n  )) {\r\n    state.tradeAdminSelected = null;\r\n    renderTradeAdminEditor();\r\n  }\r\n});\r\n\r\n\/* =========================================================\r\n   EXCHANGE GALAXY \u2014 CONTROL PANEL CONNECTION\r\n\r\n   PASTE THIS INSIDE the existing control-panel <script>.\r\n   Exact location: immediately BEFORE the existing line:\r\n\r\n   function initializeLevel8ControlPanel() {\r\n\r\n   Do not add another <script> tag and do not delete Trade.\r\n========================================================= *\/\r\n\r\nSYSTEMS.exchangeOperations = {\r\n  label: \"Exchange Galaxy\",\r\n  hint: \"Owner listings, live network offers, date movement and final verification\",\r\n  mode: \"exchange_admin\",\r\n  groups: {\r\n    \"All Exchanges\": [],\r\n    \"Listing Review\": [],\r\n    \"Live Orbit & Map\": [],\r\n    \"Final Verification\": [],\r\n    \"Completed\": [],\r\n    \"Closed\": []\r\n  }\r\n};\r\n\r\nstate.exchangeAdminRecords = [];\r\nstate.exchangeAdminSelected = null;\r\n\r\nconst EXCHANGE_ADMIN_GROUP_STATUS = {\r\n  \"All Exchanges\": \"all\",\r\n  \"Listing Review\": \"pending_review\",\r\n  \"Live Orbit & Map\": \"open\",\r\n  \"Final Verification\": \"pending_admin\",\r\n  \"Completed\": \"completed\",\r\n  \"Closed\": \"closed\"\r\n};\r\n\r\nfunction exchangeAdminStatus(status) {\r\n  return String(status || \"unknown\")\r\n    .replaceAll(\"_\", \" \");\r\n}\r\n\r\nfunction exchangeAdminDateRange(start, end) {\r\n  if (!start && !end) {\r\n    return \"Flexible \/ not assigned\";\r\n  }\r\n\r\n  return [start || \"Open\", end || \"Open\"]\r\n    .filter(Boolean)\r\n    .join(\" \u2192 \");\r\n}\r\n\r\nfunction exchangeAdminQuantity(item) {\r\n  const amount = Number(item?.quantity || 0);\r\n  const clean = Number.isInteger(amount)\r\n    ? String(amount)\r\n    : amount.toFixed(2);\r\n\r\n  return `${clean} ${item?.unit_label || \"nights\"}`;\r\n}\r\n\r\nfunction exchangeAdminAcceptedProposal(record) {\r\n  return (record.proposals || []).find(\r\n    proposal =>\r\n      proposal.id === record.accepted_proposal_id ||\r\n      proposal.status === \"accepted\"\r\n  ) || null;\r\n}\r\n\r\nfunction exchangeAdminType(record) {\r\n  const labels = {\r\n    listing: \"Owner-to-Owner\",\r\n    time_move: \"Move My Time\",\r\n    opportunity_request: \"Control Panel Opportunity\",\r\n    internal: \"Same Property\",\r\n    community: \"Circle Network\",\r\n    position: \"Entire Position\"\r\n  };\r\n\r\n  const workflow = String(record.record_type || \"exchange\");\r\n  const route = String(record.exchange_type || \"\");\r\n  const workflowLabel = labels[workflow] || exchangeAdminStatus(workflow);\r\n  const routeLabel = labels[route] || (route ? exchangeAdminStatus(route) : \"\");\r\n\r\n  return routeLabel && route !== workflow\r\n    ? `${workflowLabel} \u00b7 ${routeLabel}`\r\n    : workflowLabel;\r\n}\r\n\r\nfunction exchangeAdminFilteredRecords() {\r\n  const selectedStatus =\r\n    EXCHANGE_ADMIN_GROUP_STATUS[state.group] || \"all\";\r\n\r\n  const search = String(\r\n    $(\"l8cpSearch\")?.value || \"\"\r\n  ).trim().toLowerCase();\r\n\r\n  return state.exchangeAdminRecords.filter(record => {\r\n    const status = String(record.status || \"\");\r\n\r\n    const statusMatches =\r\n      selectedStatus === \"all\" ||\r\n      status === selectedStatus ||\r\n      (\r\n        selectedStatus === \"closed\" &&\r\n        [\r\n          \"changes_requested\",\r\n          \"rejected\",\r\n          \"cancelled\",\r\n          \"expired\"\r\n        ].includes(status)\r\n      );\r\n\r\n    if (!statusMatches) {\r\n      return false;\r\n    }\r\n\r\n    if (!search) {\r\n      return true;\r\n    }\r\n\r\n    const proposalProperties = (record.proposals || [])\r\n      .map(proposal => proposal.property_name || \"\")\r\n      .join(\" \");\r\n\r\n    const haystack = [\r\n      record.id,\r\n      record.owner_id,\r\n      record.owner?.name,\r\n      record.owner?.email,\r\n      record.status,\r\n      record.record_type,\r\n      record.exchange_type,\r\n      record.property_name,\r\n      record.destination_property,\r\n      record.wanted_property,\r\n      record.wanted_location,\r\n      proposalProperties\r\n    ].join(\" \").toLowerCase();\r\n\r\n    return haystack.includes(search);\r\n  });\r\n}\r\n\r\nfunction exchangeAdminCounts() {\r\n  const records = state.exchangeAdminRecords;\r\n\r\n  return {\r\n    all: records.length,\r\n    review: records.filter(\r\n      record => record.status === \"pending_review\"\r\n    ).length,\r\n    live: records.filter(\r\n      record => record.status === \"open\"\r\n    ).length,\r\n    verification: records.filter(\r\n      record => record.status === \"pending_admin\"\r\n    ).length,\r\n    completed: records.filter(\r\n      record => record.status === \"completed\"\r\n    ).length\r\n  };\r\n}\r\n\r\nfunction renderExchangeAdminSide() {\r\n  const counts = exchangeAdminCounts();\r\n\r\n  $(\"l8cpSideTitle\").textContent =\r\n    \"Exchange Galaxy\";\r\n\r\n  $(\"l8cpGroups\").innerHTML = `\r\n    <button\r\n      class=\"l8cp-btn primary\"\r\n      type=\"button\"\r\n      data-exchange-admin-refresh\r\n    >\r\n      Refresh Exchanges\r\n    <\/button>\r\n\r\n    <div class=\"l8cp-empty\">\r\n      <strong>Live Exchange Activity<\/strong><br><br>\r\n      ${counts.all} total records<br>\r\n      ${counts.review} owner listings to review<br>\r\n      ${counts.live} live in Orbit, Map and Calendar<br>\r\n      ${counts.verification} awaiting final verification<br>\r\n      ${counts.completed} completed exchanges\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-empty\">\r\n      <strong>Exchange Destinations<\/strong><br><br>\r\n      Property profiles, images, coordinates and\r\n      administrator-created opportunities remain under:<br><br>\r\n      <strong>The Circle \u2192 Exchange<\/strong>\r\n    <\/div>\r\n  `;\r\n}\r\n\r\nfunction renderExchangeAdminList() {\r\n  const records = exchangeAdminFilteredRecords();\r\n\r\n  $(\"l8cpListTitle\").textContent = state.group;\r\n\r\n  $(\"l8cpLive\").innerHTML = `\r\n    <div class=\"l8cp-live\">\r\n      SECURE EXCHANGE ENGINE \u00b7 ggg_l8_admin_get_exchanges\r\n    <\/div>\r\n  `;\r\n\r\n  $(\"l8cpList\").innerHTML = records.length\r\n    ? records.map(record => {\r\n        const accepted = exchangeAdminAcceptedProposal(record);\r\n        const destination =\r\n          accepted?.property_name ||\r\n          record.destination_property ||\r\n          record.wanted_property ||\r\n          \"Open destination\";\r\n\r\n        return `\r\n          <article class=\"l8cp-card\">\r\n            <div class=\"l8cp-card-top\">\r\n              <div>\r\n                <strong>${esc(record.property_name || \"Property Time\")}<\/strong>\r\n                <small>\r\n                  ${esc(exchangeAdminQuantity(record))}\r\n                  \u2192 ${esc(destination)}\r\n                <\/small>\r\n              <\/div>\r\n\r\n              <span class=\"l8cp-status\">\r\n                ${esc(exchangeAdminStatus(record.status))}\r\n              <\/span>\r\n            <\/div>\r\n\r\n            <p>\r\n              ${esc(exchangeAdminType(record))}\r\n              \u00b7 Owner ${esc(record.owner_id || \"\")}\r\n              \u00b7 ${esc((record.proposals || []).length)} proposal(s)\r\n            <\/p>\r\n\r\n            <button\r\n              class=\"l8cp-btn\"\r\n              type=\"button\"\r\n              data-exchange-admin-record-id=\"${esc(record.id)}\"\r\n            >\r\n              Review Exchange\r\n            <\/button>\r\n          <\/article>\r\n        `;\r\n      }).join(\"\")\r\n    : `\r\n      <div class=\"l8cp-empty\">\r\n        No Exchange records match this view.\r\n      <\/div>\r\n    `;\r\n}\r\n\r\nfunction exchangeAdminProposalHtml(record) {\r\n  const proposals = Array.isArray(record.proposals)\r\n    ? record.proposals\r\n    : [];\r\n\r\n  if (!proposals.length) {\r\n    return \"No owner proposals received.\";\r\n  }\r\n\r\n  return proposals.map(proposal => `\r\n    <strong>\r\n      ${esc(proposal.member?.name || proposal.owner_alias || \"Verified Owner\")}\r\n    <\/strong>\r\n    \u00b7 ${esc(proposal.property_name || \"Property Time\")}\r\n    \u00b7 ${esc(exchangeAdminQuantity(proposal))}\r\n    \u00b7 ${esc(exchangeAdminDateRange(proposal.start_date, proposal.end_date))}\r\n    \u00b7 ${esc(exchangeAdminStatus(proposal.status))}\r\n  `).join(\"<br><br>\");\r\n}\r\n\r\nfunction renderExchangeAdminEditor() {\r\n  const panel = $(\"l8cpEditorPanel\");\r\n  panel.style.display = \"block\";\r\n  panel.dataset.mode = \"exchange_admin\";\r\n\r\n  const record = state.exchangeAdminSelected;\r\n\r\n  if (!record) {\r\n    panel.innerHTML = `\r\n      <h2>Exchange Verification<\/h2>\r\n\r\n      <div class=\"l8cp-empty\">\r\n        Select an Exchange record from the right.<br><br>\r\n\r\n        Owner listings must be approved before they appear\r\n        in the public owner Orbit, Map or Calendar. Accepted\r\n        owner matches and date-movement requests stop here\r\n        for final Bliss Administration verification.\r\n      <\/div>\r\n    `;\r\n    return;\r\n  }\r\n\r\n  const accepted = exchangeAdminAcceptedProposal(record);\r\n  const isListing = record.record_type === \"listing\";\r\n  const isTimeMove = record.record_type === \"time_move\";\r\n  const isOpportunity =\r\n    record.record_type === \"opportunity_request\";\r\n  const pendingReview = record.status === \"pending_review\";\r\n  const live = record.status === \"open\";\r\n  const finalReview = record.status === \"pending_admin\";\r\n  const mayPublish = [\r\n    \"pending_review\",\r\n    \"changes_requested\"\r\n  ].includes(record.status) && isListing;\r\n  const requestedStart =\r\n    record.wanted_start_date ||\r\n    accepted?.start_date ||\r\n    \"\";\r\n  const requestedEnd =\r\n    record.wanted_end_date ||\r\n    accepted?.end_date ||\r\n    \"\";\r\n\r\n  panel.innerHTML = `\r\n    <h2>Exchange Verification<\/h2>\r\n\r\n    <div class=\"l8cp-path\">\r\n      Exchange Galaxy &gt;\r\n      ${esc(exchangeAdminStatus(record.status))}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-requestInfo\">\r\n      ${informationBox(\"Exchange ID\", record.id)}\r\n      ${informationBox(\"Workflow\", exchangeAdminType(record))}\r\n      ${informationBox(\"Owner\", record.owner?.name || record.owner_id)}\r\n      ${informationBox(\"Owner Email\", record.owner?.email)}\r\n      ${informationBox(\"Current Property\", record.property_name)}\r\n      ${informationBox(\"Quantity\", exchangeAdminQuantity(record))}\r\n      ${informationBox(\"Current Dates\", exchangeAdminDateRange(record.start_date, record.end_date))}\r\n      ${informationBox(\"Requested Property\", record.destination_property || record.wanted_property || \"Open\")}\r\n      ${informationBox(\"Requested Location\", record.destination_location || record.wanted_location)}\r\n      ${informationBox(\"Requested Dates\", exchangeAdminDateRange(record.wanted_start_date, record.wanted_end_date))}\r\n      ${informationBox(\"Status\", exchangeAdminStatus(record.status))}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-sectionLabel\">\r\n      Owner Notes\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-readonly\">\r\n      ${esc(record.notes || \"No owner notes.\")}\r\n    <\/div>\r\n\r\n    ${isListing ? `\r\n      <div class=\"l8cp-sectionLabel\">\r\n        Owner Proposals\r\n      <\/div>\r\n\r\n      <div class=\"l8cp-readonly\">\r\n        ${exchangeAdminProposalHtml(record)}\r\n      <\/div>\r\n    ` : \"\"}\r\n\r\n    ${accepted ? `\r\n      <div class=\"l8cp-sectionLabel\">\r\n        Accepted Match\r\n      <\/div>\r\n\r\n      <div class=\"l8cp-requestInfo\">\r\n        ${informationBox(\"Matched Owner\", accepted.member?.name || accepted.owner_alias)}\r\n        ${informationBox(\"Matched Email\", accepted.member?.email)}\r\n        ${informationBox(\"Matched Property\", accepted.property_name)}\r\n        ${informationBox(\"Matched Quantity\", exchangeAdminQuantity(accepted))}\r\n        ${informationBox(\"Matched Dates\", exchangeAdminDateRange(accepted.start_date, accepted.end_date))}\r\n      <\/div>\r\n    ` : \"\"}\r\n\r\n    <div class=\"l8cp-form\">\r\n      ${finalReview && (isTimeMove || isOpportunity) ? `\r\n        <div class=\"l8cp-field\">\r\n          <label>Approved Start Date<\/label>\r\n          <input\r\n            id=\"l8ExchangeApprovedStart\"\r\n            type=\"date\"\r\n            value=\"${esc(requestedStart)}\"\r\n          >\r\n        <\/div>\r\n\r\n        <div class=\"l8cp-field\">\r\n          <label>Approved End Date<\/label>\r\n          <input\r\n            id=\"l8ExchangeApprovedEnd\"\r\n            type=\"date\"\r\n            value=\"${esc(requestedEnd)}\"\r\n          >\r\n        <\/div>\r\n      ` : \"\"}\r\n\r\n      <div class=\"l8cp-field full\">\r\n        <label>Bliss Administration Note<\/label>\r\n        <textarea\r\n          id=\"l8ExchangeAdminNote\"\r\n          placeholder=\"Eligibility, availability, agreement or date notes\"\r\n        >${esc(record.admin_note || \"\")}<\/textarea>\r\n      <\/div>\r\n\r\n      ${pendingReview ? `\r\n        <div class=\"l8cp-field full\">\r\n          <div class=\"l8cp-empty\">\r\n            Publishing makes this verified owner listing visible\r\n            in Orbit, Map and Calendar. The owner identity remains\r\n            private in the customer view.\r\n          <\/div>\r\n        <\/div>\r\n      ` : \"\"}\r\n\r\n      ${live ? `\r\n        <div class=\"l8cp-field full\">\r\n          <div class=\"l8cp-empty\">\r\n            This owner listing is currently live. Requesting\r\n            changes removes it from the live network until it is\r\n            approved again.\r\n          <\/div>\r\n        <\/div>\r\n      ` : \"\"}\r\n\r\n      ${finalReview ? `\r\n        <div class=\"l8cp-field full\">\r\n          <div class=\"l8cp-empty\">\r\n            Approval verifies availability and completes the\r\n            Property Time record movement. It does not represent\r\n            a deed transfer. Rejecting releases all temporary holds.\r\n          <\/div>\r\n        <\/div>\r\n      ` : \"\"}\r\n    <\/div>\r\n\r\n    <div class=\"l8cp-actions\">\r\n      ${mayPublish ? `\r\n        <button\r\n          class=\"l8cp-btn primary\"\r\n          type=\"button\"\r\n          data-exchange-admin-decision=\"publish\"\r\n        >\r\n          Publish to Exchange Galaxy\r\n        <\/button>\r\n      ` : \"\"}\r\n\r\n      ${pendingReview || live ? `\r\n        <button\r\n          class=\"l8cp-btn\"\r\n          type=\"button\"\r\n          data-exchange-admin-decision=\"changes\"\r\n        >\r\n          Request Changes\r\n        <\/button>\r\n      ` : \"\"}\r\n\r\n      ${finalReview ? `\r\n        <button\r\n          class=\"l8cp-btn primary\"\r\n          type=\"button\"\r\n          data-exchange-admin-decision=\"approve\"\r\n        >\r\n          Verify & Complete\r\n        <\/button>\r\n      ` : \"\"}\r\n\r\n      ${[\r\n        \"pending_review\",\r\n        \"open\",\r\n        \"pending_admin\",\r\n        \"changes_requested\"\r\n      ].includes(record.status) ? `\r\n        <button\r\n          class=\"l8cp-btn\"\r\n          type=\"button\"\r\n          data-exchange-admin-decision=\"reject\"\r\n        >\r\n          Reject Exchange\r\n        <\/button>\r\n      ` : \"\"}\r\n\r\n      <button\r\n        class=\"l8cp-btn\"\r\n        type=\"button\"\r\n        data-exchange-admin-close\r\n      >\r\n        Close Record\r\n      <\/button>\r\n    <\/div>\r\n  `;\r\n}\r\n\r\nasync function loadExchangeAdmin(showToast = false) {\r\n  $(\"l8cpList\").innerHTML = `\r\n    <div class=\"l8cp-empty\">\r\n      Loading secure Exchange records...\r\n    <\/div>\r\n  `;\r\n\r\n  try {\r\n    const data = await post(\r\n      \"ggg_l8_admin_get_exchanges\"\r\n    );\r\n\r\n    state.exchangeAdminRecords =\r\n      Array.isArray(data.exchanges)\r\n        ? data.exchanges\r\n        : [];\r\n\r\n    if (state.exchangeAdminSelected) {\r\n      state.exchangeAdminSelected =\r\n        state.exchangeAdminRecords.find(\r\n          record =>\r\n            record.id ===\r\n            state.exchangeAdminSelected.id\r\n        ) || null;\r\n    }\r\n\r\n    renderExchangeAdminSide();\r\n    renderExchangeAdminList();\r\n    renderExchangeAdminEditor();\r\n\r\n    if (showToast) {\r\n      toast(\"Exchange records refreshed.\");\r\n    }\r\n  } catch (error) {\r\n    $(\"l8cpList\").innerHTML = `\r\n      <div class=\"l8cp-error\">\r\n        ${esc(error.message)}\r\n      <\/div>\r\n    `;\r\n  }\r\n}\r\n\r\nasync function updateExchangeAdmin(decision) {\r\n  const record = state.exchangeAdminSelected;\r\n  if (!record) return;\r\n\r\n  const labels = {\r\n    publish: \"publish this owner exchange\",\r\n    changes: \"request changes\",\r\n    approve: \"verify and complete this exchange\",\r\n    reject: \"reject this exchange\"\r\n  };\r\n\r\n  if (!window.confirm(\r\n    `Are you sure you want to ${labels[decision] || decision}?`\r\n  )) {\r\n    return;\r\n  }\r\n\r\n  const approvedStart =\r\n    $(\"l8ExchangeApprovedStart\")?.value || \"\";\r\n  const approvedEnd =\r\n    $(\"l8ExchangeApprovedEnd\")?.value || \"\";\r\n\r\n  if (\r\n    decision === \"approve\" &&\r\n    [\"time_move\", \"opportunity_request\"].includes(\r\n      record.record_type\r\n    ) &&\r\n    (!approvedStart || !approvedEnd)\r\n  ) {\r\n    toast(\"Approved starting and ending dates are required.\", true);\r\n    return;\r\n  }\r\n\r\n  try {\r\n    const data = await post(\r\n      \"ggg_l8_admin_update_exchange\",\r\n      {\r\n        record_id: record.id,\r\n        decision,\r\n        admin_note:\r\n          $(\"l8ExchangeAdminNote\")?.value.trim() || \"\",\r\n        approved_start_date: approvedStart,\r\n        approved_end_date: approvedEnd\r\n      }\r\n    );\r\n\r\n    toast(data.message || \"Exchange updated.\");\r\n    await loadExchangeAdmin(false);\r\n  } catch (error) {\r\n    toast(error.message, true);\r\n  }\r\n}\r\n\r\nconst renderEditorBeforeExchangeAdmin = renderEditor;\r\n\r\nrenderEditor = function() {\r\n  if (state.system === \"exchangeOperations\") {\r\n    renderExchangeAdminEditor();\r\n    return;\r\n  }\r\n\r\n  renderEditorBeforeExchangeAdmin();\r\n};\r\n\r\nconst chooseSystemBeforeExchangeAdmin = chooseSystem;\r\n\r\nchooseSystem = function(key) {\r\n  if (key !== \"exchangeOperations\") {\r\n    state.exchangeAdminSelected = null;\r\n    chooseSystemBeforeExchangeAdmin(key);\r\n    return;\r\n  }\r\n\r\n  state.system = key;\r\n  state.group = \"All Exchanges\";\r\n  state.option = \"\";\r\n  state.editing = null;\r\n  state.request = null;\r\n  state.exchangeAdminSelected = null;\r\n\r\n  renderSystems();\r\n  renderExchangeAdminSide();\r\n  renderExchangeAdminEditor();\r\n  loadExchangeAdmin(false);\r\n};\r\n\r\nconst chooseGroupBeforeExchangeAdmin = chooseGroup;\r\n\r\nchooseGroup = function(group) {\r\n  if (state.system !== \"exchangeOperations\") {\r\n    chooseGroupBeforeExchangeAdmin(group);\r\n    return;\r\n  }\r\n\r\n  state.group = group;\r\n  state.option = \"\";\r\n  state.exchangeAdminSelected = null;\r\n\r\n  renderSelects();\r\n  renderExchangeAdminSide();\r\n  renderExchangeAdminEditor();\r\n  renderExchangeAdminList();\r\n};\r\n\r\n$(\"l8cpSearch\").addEventListener(\r\n  \"input\",\r\n  () => {\r\n    if (state.system === \"exchangeOperations\") {\r\n      renderExchangeAdminList();\r\n    }\r\n  }\r\n);\r\n\r\ndocument.addEventListener(\"click\", event => {\r\n  const review = event.target.closest(\r\n    \"[data-exchange-admin-record-id]\"\r\n  );\r\n\r\n  if (review) {\r\n    state.exchangeAdminSelected =\r\n      state.exchangeAdminRecords.find(\r\n        record =>\r\n          record.id ===\r\n          review.dataset.exchangeAdminRecordId\r\n      ) || null;\r\n\r\n    renderExchangeAdminEditor();\r\n    return;\r\n  }\r\n\r\n  const decision = event.target.closest(\r\n    \"[data-exchange-admin-decision]\"\r\n  );\r\n\r\n  if (decision) {\r\n    updateExchangeAdmin(\r\n      decision.dataset.exchangeAdminDecision\r\n    );\r\n    return;\r\n  }\r\n\r\n  if (event.target.closest(\r\n    \"[data-exchange-admin-refresh]\"\r\n  )) {\r\n    loadExchangeAdmin(true);\r\n    return;\r\n  }\r\n\r\n  if (event.target.closest(\r\n    \"[data-exchange-admin-close]\"\r\n  )) {\r\n    state.exchangeAdminSelected = null;\r\n    renderExchangeAdminEditor();\r\n  }\r\n});\r\n\r\n\r\nfunction initializeLevel8ControlPanel() {\r\n  const parameters = new URLSearchParams(window.location.search);\r\n\r\n  if (parameters.get(\"level8panel\") !== \"1\") {\r\n    return;\r\n  }\r\n\r\n  openPanel();\r\n  loadInventory();\r\n}\r\n\r\nif (document.readyState === \"loading\") {\r\n  document.addEventListener(\r\n    \"DOMContentLoaded\",\r\n    initializeLevel8ControlPanel\r\n  );\r\n} else {\r\n  initializeLevel8ControlPanel();\r\n}\r\n})();\r\n<\/script>\r\n\r\n\r\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc51 Owners Club \ud83d\udcb3 Week Short Stay Online Penthouse Use Internally Community Year Ownership Exchange Rooms Day Weekend Week Trade Weeks Bliss Coin Travel Club City Card Buy \ud83d\udcb3 Pay with Bliss Coin Enter your digital wallet #: Send payment to: HOST-WALLET-ADDRESS-123 Close \ud83e\uddca \ud83d\udc96 Sign In \/ Sign Up My Favorites Close Show on [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-3240","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/godsgalaxygame.com\/GGG\/wp-json\/wp\/v2\/pages\/3240","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/godsgalaxygame.com\/GGG\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/godsgalaxygame.com\/GGG\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/godsgalaxygame.com\/GGG\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/godsgalaxygame.com\/GGG\/wp-json\/wp\/v2\/comments?post=3240"}],"version-history":[{"count":98,"href":"https:\/\/godsgalaxygame.com\/GGG\/wp-json\/wp\/v2\/pages\/3240\/revisions"}],"predecessor-version":[{"id":10622,"href":"https:\/\/godsgalaxygame.com\/GGG\/wp-json\/wp\/v2\/pages\/3240\/revisions\/10622"}],"wp:attachment":[{"href":"https:\/\/godsgalaxygame.com\/GGG\/wp-json\/wp\/v2\/media?parent=3240"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}