<?php
/* ============================================================
   admin_publicidad.php — Canvas Publicitario (MySQL + ad_items)
   Endpoints:
     ?action=health
     ?action=list&page=...
     ?action=save
     ?action=delete
     ?action=toggle
     ?action=upload
     ?action=embed&page=...   (IMPRIME en la página)
   Tipos: image, video, html, link, section
   Claves:
     - Los items se posicionan ABSOLUTOS sobre el DOCUMENTO (px),
       no fixed: NO siguen el scroll.
     - section agrega una sección real que estira la página.
     - Links navegan EXACTAMENTE a la URL ingresada (target=_self).
   ============================================================ */


/* ---------------------------- DB ------------------------------ */
require __DIR__.'/db.php';
if (!function_exists('pdo')) { http_response_code(500); echo "db.php no define pdo()"; exit; }
$pdo = pdo();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

/* --------------------------- Paths ---------------------------- */
$SELF = rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? ''), '/').'/'.basename(__FILE__);
$BASE_DIR = rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? ''), '/');
$make = fn($file) => ($BASE_DIR?:'').'/'.$file;

/* Páginas del panel (podés sumar más si querés) */
$PAGES = [
  ['id'=>'index',        'title'=>'Inicio (index.php)',             'url'=> $make('index.php')],
  ['id'=>'notas',        'title'=>'Noticias (notas.php)',           'url'=> $make('notas.php')],
  ['id'=>'tarifas',      'title'=>'Tarifas (tarifas.php)',          'url'=> $make('tarifas.php')],
  ['id'=>'delegaciones', 'title'=>'Delegaciones (delegaciones.php)','url'=> $make('delegaciones.php')],
  ['id'=>'servicios',    'title'=>'Servicios (servicios.php)',      'url'=> $make('servicios.php')],
  ['id'=>'contacto',     'title'=>'Contacto (contacto.php)',        'url'=> $make('contacto.php')],
];

/* Uploads (respeta subcarpeta) */
$ROOT       = rtrim($_SERVER['DOCUMENT_ROOT'] ?? __DIR__, '/');
$SUBDIR     = trim($BASE_DIR, '/'); // ej. 'site' o ''
$UPLOAD_DIR = $SUBDIR ? ($ROOT.'/'.$SUBDIR.'/uploads/publicidad') : ($ROOT.'/uploads/publicidad');
$UPLOAD_URL = ($BASE_DIR?:'').'/uploads/publicidad';

/* -------------------- Tabla si falta -------------------------- */
$pdo->exec("
CREATE TABLE IF NOT EXISTS ad_items (
  id INT AUTO_INCREMENT PRIMARY KEY,
  page_slug VARCHAR(100) NOT NULL,
  type ENUM('image','video','html','link','section') NOT NULL,
  title VARCHAR(255) DEFAULT NULL,
  media_url TEXT NULL,
  link_url  TEXT NULL,
  html MEDIUMTEXT NULL,
  x_pct DOUBLE NOT NULL DEFAULT 10,
  y_pct DOUBLE NOT NULL DEFAULT 10,
  w_pct DOUBLE NOT NULL DEFAULT 30,
  h_pct DOUBLE NULL,
  zindex INT NOT NULL DEFAULT 10,
  is_active TINYINT(1) NOT NULL DEFAULT 1,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_page (page_slug),
  INDEX idx_active (is_active),
  INDEX idx_order (page_slug, zindex, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
");

/* ------------------------- Helpers ---------------------------- */
function j($ok,$extra=[],$code=200){
  http_response_code($code);
  header('Content-Type: application/json; charset=utf-8');
  echo json_encode(['ok'=>$ok]+$extra, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
  exit;
}

/* ------------------------- API -------------------------------- */
$action = $_GET['action'] ?? $_POST['action'] ?? '';

if ($action==='health'){
  j(true, ['driver'=>$pdo->getAttribute(PDO::ATTR_DRIVER_NAME)]);
}

if ($action==='list'){
  $page = $_GET['page'] ?? 'index';
  $st = $pdo->prepare("SELECT * FROM ad_items WHERE page_slug=? ORDER BY zindex ASC, id ASC");
  $st->execute([$page]);
  j(true, ['items'=>$st->fetchAll(PDO::FETCH_ASSOC)]);
}

if ($action==='save'){
  $payload = json_decode($_POST['payload'] ?? '[]', true);
  if (!is_array($payload)) $payload = [];
  $now = date('Y-m-d H:i:s');

  $pdo->beginTransaction();
  try{
    foreach($payload as $it){
      $id   = (int)($it['id'] ?? 0);
      $page = (string)($it['page_slug'] ?? 'index');
      $type = (string)($it['type'] ?? 'image'); if ($type==='banner') $type='image';
      $title= (string)($it['title'] ?? '');
      $media= (string)($it['media_url'] ?? '');
      $link = (string)($it['link_url'] ?? '');
      $html = (string)($it['html'] ?? '');
      $x    = (float)($it['x_pct'] ?? 10);
      $y    = (float)($it['y_pct'] ?? 10);
      $w    = (float)($it['w_pct'] ?? 30);
      $h    = array_key_exists('h_pct',$it) && $it['h_pct']!=='' ? (float)$it['h_pct'] : null;
      $z    = (int)($it['zindex'] ?? 10);
      $en   = (int)($it['is_active'] ?? $it['is_enabled'] ?? 1);

      if ($id>0){
        $st = $pdo->prepare("UPDATE ad_items
          SET page_slug=?,type=?,title=?,media_url=?,link_url=?,html=?,x_pct=?,y_pct=?,w_pct=?,h_pct=?,zindex=?,is_active=?,updated_at=?
          WHERE id=?");
        $st->execute([$page,$type,$title,$media,$link,$html,$x,$y,$w,$h,$z,$en,$now,$id]);
      } else {
        $st = $pdo->prepare("INSERT INTO ad_items
          (page_slug,type,title,media_url,link_url,html,x_pct,y_pct,w_pct,h_pct,zindex,is_active,created_at,updated_at)
          VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
        $st->execute([$page,$type,$title,$media,$link,$html,$x,$y,$w,$h,$z,$en,$now,$now]);
      }
    }
    $pdo->commit();
    j(true, ['saved'=>count($payload)]);
  }catch(Throwable $e){
    $pdo->rollBack(); j(false, ['error'=>$e->getMessage()], 500);
  }
}

if ($action==='delete'){
  $id = (int)($_POST['id'] ?? 0);
  if ($id<=0) j(false, ['error'=>'ID inválido'], 400);
  $st = $pdo->prepare("DELETE FROM ad_items WHERE id=?");
  $st->execute([$id]);
  j(true, ['deleted'=>$id]);
}

if ($action==='toggle'){
  $id = (int)($_POST['id'] ?? 0);
  $en = (int)($_POST['is_active'] ?? $_POST['is_enabled'] ?? 1);
  if ($id<=0) j(false, ['error'=>'ID inválido'], 400);
  $st = $pdo->prepare("UPDATE ad_items SET is_active=?, updated_at=? WHERE id=?");
  $st->execute([$en, date('Y-m-d H:i:s'), $id]);
  j(true, ['id'=>$id,'is_active'=>$en]);
}

if ($action==='upload'){
  if (!is_dir($UPLOAD_DIR)) { @mkdir($UPLOAD_DIR, 0775, true); @chmod($UPLOAD_DIR, 0775); }
  if (!isset($_FILES['file'])) j(false, ['error'=>'Sin archivo'], 400);
  $f = $_FILES['file']; if ($f['error']!==UPLOAD_ERR_OK) j(false, ['error'=>'Error de subida'], 400);
  $ext  = strtolower(pathinfo($f['name'], PATHINFO_EXTENSION));
  $safe = preg_replace('/[^a-zA-Z0-9_\.-]/','_', pathinfo($f['name'], PATHINFO_FILENAME));
  $name = $safe.'_'.date('Ymd_His').'.'.$ext;
  $dest = $UPLOAD_DIR.'/'.$name;
  if (!move_uploaded_file($f['tmp_name'], $dest)) j(false, ['error'=>'No se pudo guardar'], 500);
  j(true, ['url'=>$UPLOAD_URL.'/'.$name]);
}

/* ------------------------ EMBED (render) ----------------------- */
/* No crea overlay fixed. Inserta:
   - sections en flujo (extienden la página).
   - image/video/html/link como absolute respecto al DOCUMENTO (px).
*/
if ($action==='embed'){
  header('Content-Type: application/javascript; charset=utf-8');
  $page = preg_replace('~[^a-z0-9_-]~i','', $_GET['page'] ?? 'index');
  ?>
(() => {
  const PAGE = <?php echo json_encode($page); ?>;
  const SRC  = <?php echo json_encode($SELF); ?>;
  const zBase = 2147482000;

  function css(el, o){ for (const k in o) el.style[k]=o[k]; }
  function dims(){
    const W = Math.max(document.documentElement.scrollWidth,  document.body.scrollWidth,  window.innerWidth);
    const H = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight, window.innerHeight);
    return {W,H};
  }
  const pct = (v)=> Number(v)||0;
  const pxFromPct = (v,total)=> pct(v)/100*total;

  function makeAbs(it, pageW, pageH){
    const box = document.createElement('div');
    css(box, {
      position:'absolute',
      left:  pxFromPct(it.x_pct, pageW) + 'px',
      top:   pxFromPct(it.y_pct, pageH) + 'px',
      width: pxFromPct(it.w_pct, pageW) + 'px',
      zIndex: String(zBase + (it.zindex||0)),
      background:'transparent', border:'none'
    });
    if (it.h_pct!=null) box.style.height = pxFromPct(it.h_pct, pageH) + 'px';

    if (it.type==='image'){
      const img = document.createElement('img');
      img.src = it.media_url||'';
      css(img,{position:'absolute', inset:'0', width:'100%', height:'100%', objectFit:'contain', display:'block'});
      box.appendChild(img);
      if (it.link_url){
        const a = document.createElement('a');
        a.href = it.link_url;         // <-- EXACTO lo que cargás
        a.target = '_self';           // misma pestaña
        a.rel = 'noopener';
        css(a,{position:'absolute', inset:'0', display:'block', textDecoration:'none'});
        // el link va por arriba del img:
        box.appendChild(a);
      }
      return box;
    }

    if (it.type==='video'){
      if (/\byoutu\.?be\b/.test(it.media_url||'')){
        const id=(it.media_url||'').match(/(?:v=|\.be\/)([\w-]+)/)?.[1]||'';
        const ifr=document.createElement('iframe');
        ifr.allow='autoplay;encrypted-media'; ifr.allowFullscreen=true;
        ifr.src = id ? 'https://www.youtube.com/embed/'+id : 'about:blank';
        css(ifr,{position:'absolute', inset:'0', width:'100%', height:'100%', border:'0'});
        box.appendChild(ifr);
      } else {
        const v=document.createElement('video');
        v.src=it.media_url||''; v.controls=true;
        css(v,{position:'absolute', inset:'0', width:'100%', height:'100%', objectFit:'cover'});
        box.appendChild(v);
      }
      return box;
    }

    if (it.type==='html'){
      const wrap=document.createElement('div');
      css(wrap,{position:'absolute', inset:'0'});
      wrap.innerHTML = it.html||'';
      box.appendChild(wrap);
      return box;
    }

    if (it.type==='link'){
      const a=document.createElement('a');
      a.href = it.link_url||'#';
      a.target = '_self';
      a.rel = 'noopener';
      css(a,{position:'absolute', inset:'0', display:'flex', alignItems:'center', justifyContent:'center',
              textDecoration:'none', color:'#1f72b6', fontWeight:'600',
              border:'2px dashed #1f72b6', borderRadius:'8px', background:'#fff'});
      a.textContent = it.title || it.link_url || 'Link';
      box.appendChild(a);
      return box;
    }

    return box;
  }

  function makeSection(it){
    const sec = document.createElement('section');
    sec.setAttribute('data-ad-section-id', String(it.id||''));
    css(sec, {position:'relative', width:'100%', margin:'24px 0', zIndex: String(zBase + (it.zindex||0))});
    const bar = document.createElement('div');
    css(bar, {background:'#15324c', color:'#fff', fontWeight:'700', padding:'12px 16px', borderRadius:'8px 8px 0 0'});
    bar.textContent = it.title || 'Sección publicitaria';
    const body = document.createElement('div');
    css(body, {background:'#fff', border:'1px solid #e7ecf3', borderTop:'none',
               minHeight:(it.h_pct!=null? it.h_pct+'vh':'160px'), padding:'16px', borderRadius:'0 0 8px 8px'});
    sec.append(bar, body);
    return sec;
  }

  async function getItems(){
    try{
      const r = await fetch(SRC + '?action=list&page=' + encodeURIComponent(PAGE), {credentials:'same-origin'});
      const js = await r.json();
      return (js && js.ok) ? (js.items||[]) : [];
    }catch(e){ return []; }
  }

  function mount(items){
    // limpiar impresiones anteriores
    document.querySelectorAll('[data-ad-mounted="1"], section[data-ad-section-id]').forEach(n=>n.remove());

    const {W, H} = dims();

    // 1) sections en flujo
    items.filter(i=>i.type==='section' && +i.is_active===1)
         .sort((a,b)=>(+a.y_pct)-(+b.y_pct))
         .forEach(s => document.body.appendChild(makeSection(s)));

    // 2) absolutos (pegados a la página, NO fixed)
    items.filter(i=>i.type!=='section' && +i.is_active===1).forEach(raw=>{
      const it = {
        id:+raw.id||0, type:String(raw.type||'image'),
        title:raw.title||'', media_url:raw.media_url||'',
        link_url:raw.link_url||'', html:raw.html||'',
        x_pct:+raw.x_pct||0, y_pct:+raw.y_pct||0,
        w_pct:+raw.w_pct||0, h_pct:(raw.h_pct===null?null:+raw.h_pct),
        zindex:+raw.zindex||0
      };
      const node = makeAbs(it, W, H);
      node.setAttribute('data-ad-mounted','1');
      document.body.appendChild(node);
    });
  }

  async function render(){
    const items = await getItems();
    mount(items);
    let to=null;
    window.addEventListener('resize', ()=>{ clearTimeout(to); to=setTimeout(()=>mount(items),150); }, {passive:true});
  }

  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', render);
  else render();
})();
<?php
  exit;
}

/* -------------------------- UI PANEL --------------------------- */
?>
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Admin Publicidad — Canvas</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
  <link rel="icon" href="img/favicon.png" type="image/png">

<style>
  :root {
    --primary: #3a86ff;
    --primary-dark: #2667cc;
    --secondary: #8338ec;
    --accent: #ff006e;
    --dark: #0f172a;
    --dark-light: #1e293b;
    --dark-lighter: #334155;
    --light: #f8fafc;
    --light-dark: #e2e8f0;
    --gray: #94a3b8;
    --success: #10b981;
    --warning: #f59e0b;
    --danger: #ef4444;
    --border-radius: 12px;
    --border-radius-sm: 8px;
    --shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
    --shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
    --transition: all 0.2s ease-in-out;
  }
  html, body { overflow-y: auto; }

  * {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
  }

  body {
    font-family: 'Segoe UI', system-ui, -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
    background: linear-gradient(135deg, var(--dark) 0%, var(--dark-light) 100%);
    color: var(--light);
    line-height: 1.6;
    min-height: 100vh;
    overflow-x: hidden;
  }

  /* Header */
  header {
    background: rgba(15, 23, 42, 0.8);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    padding: 16px 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky;
    top: 0;
    z-index: 100;
    box-shadow: var(--shadow);
  }

  .brand {
    display: flex;
    align-items: center;
    gap: 12px;
    font-weight: 700;
    font-size: 1.25rem;
  }

  .brand i {
    color: var(--primary);
    font-size: 1.5rem;
  }

  .header-actions {
    display: flex;
    gap: 12px;
  }

  /* Buttons */
  .btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border-radius: var(--border-radius-sm);
    font-weight: 600;
    font-size: 0.875rem;
    cursor: pointer;
    transition: var(--transition);
    border: none;
    outline: none;
    text-decoration: none;
  }

  .btn i {
    font-size: 1rem;
  }

  .btn-primary {
    background: var(--primary);
    color: white;
    box-shadow: 0 4px 6px -1px rgba(58, 134, 255, 0.3);
  }

  .btn-primary:hover {
    background: var(--primary-dark);
    transform: translateY(-2px);
    box-shadow: 0 10px 15px -3px rgba(58, 134, 255, 0.4);
  }

  .btn-secondary {
    background: rgba(255, 255, 255, 0.1);
    color: var(--light);
    border: 1px solid rgba(255, 255, 255, 0.2);
  }

  .btn-secondary:hover {
    background: rgba(255, 255, 255, 0.15);
    transform: translateY(-2px);
  }

  .btn-success {
    background: var(--success);
    color: white;
  }

  .btn-warning {
    background: var(--warning);
    color: white;
  }

  .btn-danger {
    background: var(--danger);
    color: white;
  }

  .btn-sm {
    padding: 6px 12px;
    font-size: 0.75rem;
  }

  /* Layout */
  .wrap {
    display: grid;
    grid-template-columns: 320px 1fr;
    min-height: calc(100vh - 73px);
  }

  /* Sidebar */
  aside {
    background: var(--dark-light);
    border-right: 1px solid rgba(255, 255, 255, 0.1);
    padding: 24px;
    overflow-y: auto;
    box-shadow: var(--shadow);
  }

  .section-title {
    font-size: 0.875rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--gray);
    margin: 24px 0 12px;
    font-weight: 600;
  }

  .section-title:first-child {
    margin-top: 0;
  }

  /* Page List */
  .page-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 24px;
  }

  .page-btn {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: var(--border-radius-sm);
    padding: 12px 16px;
    text-align: left;
    cursor: pointer;
    transition: var(--transition);
    color: var(--light);
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 0.9rem;
  }

  .page-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.2);
  }

  .page-btn.active {
    background: rgba(58, 134, 255, 0.2);
    border-color: var(--primary);
    box-shadow: 0 0 0 1px var(--primary);
  }

  .page-btn i {
    color: var(--primary);
    font-size: 1.1rem;
  }

  /* Action Buttons */
  .action-buttons {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-bottom: 24px;
  }

  .action-btn {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: var(--border-radius-sm);
    padding: 12px;
    text-align: center;
    cursor: pointer;
    transition: var(--transition);
    color: var(--light);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    font-size: 0.8rem;
  }

  .action-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    transform: translateY(-2px);
  }

  .action-btn i {
    font-size: 1.25rem;
    color: var(--primary);
  }

  /* Properties Panel */
  .properties-panel {
    background: rgba(255, 255, 255, 0.05);
    border-radius: var(--border-radius-sm);
    padding: 16px;
    margin-bottom: 24px;
  }

  .property-row {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 12px;
  }

  .property-label {
    font-size: 0.75rem;
    color: var(--gray);
    min-width: 60px;
  }

  .property-input {
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 6px;
    padding: 8px 10px;
    color: var(--light);
    font-size: 0.875rem;
    flex: 1;
    transition: var(--transition);
  }

  .property-input:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 2px rgba(58, 134, 255, 0.2);
  }

  .property-input::placeholder {
    color: var(--gray);
  }

  .property-textarea {
    min-height: 100px;
    resize: vertical;
    width: 100%;
  }

  .property-select {
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 6px;
    padding: 8px 10px;
    color: var(--light);
    font-size: 0.875rem;
    flex: 1;
  }

  /* Items List */
  .items-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .item-card {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: var(--border-radius-sm);
    padding: 12px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    transition: var(--transition);
  }

  .item-card:hover {
    background: rgba(255, 255, 255, 0.08);
  }

  .item-info {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }

  .item-id {
    font-weight: 700;
    font-size: 0.875rem;
  }

  .item-type {
    font-size: 0.75rem;
    color: var(--gray);
    text-transform: capitalize;
  }

  .item-title {
    font-size: 0.875rem;
    max-width: 180px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .item-actions {
    display: flex;
    gap: 6px;
  }

  /* Main Content */
  main {
    padding: 24px;
    overflow: auto;
  }

  .stage {
    background: var(--dark-light);
    border-radius: var(--border-radius);
    padding: 24px;
    box-shadow: var(--shadow);
    height: 100%;
    position: relative;
  }

  .frame-container {
    position: relative;
    max-width: 1280px;
    margin: 0 auto;
    border-radius: var(--border-radius);
    overflow: hidden;
    box-shadow: var(--shadow-lg);
    background: white;
  }

  iframe {
    width: 100%;
    height: 75vh;
    border: 0;
    display: block;
    background: white;
  }

  /* antes: .overlay { ... pointer-events: auto; } */
  .overlay { 
    position: absolute;
    inset: 0;
    pointer-events: none;   /* <- clave: que la rueda pase al iframe */
  }
  
  /* pero los ads sí necesitan interacción */
  .ad { pointer-events: auto; }
  .ad .bar, .ad .handle { pointer-events: auto; }


  /* Ad Elements */
  .ad {
    position: absolute;
    border: 2px dashed var(--primary);
    background: rgba(58, 134, 255, 0.1);
    border-radius: var(--border-radius-sm);
    overflow: hidden;
    user-select: none;
    pointer-events: auto;
    transition: var(--transition);
  }

  .ad:hover {
    box-shadow: 0 0 0 2px var(--primary);
  }

  .ad.ghost {
    outline: 3px solid rgba(58, 134, 255, 0.7);
    outline-offset: 2px;
  }

  .ad.disabled {
    opacity: 0.5;
    filter: grayscale(0.8);
  }

  .ad .bar {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    background: rgba(58, 134, 255, 0.9);
    color: white;
    padding: 8px 12px;
    font-size: 0.75rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: move;
    z-index: 10;
  }

  .ad .handle {
    position: absolute;
    right: 0;
    bottom: 0;
    padding: 6px 8px;
    background: rgba(58, 134, 255, 0.9);
    color: white;
    font-size: 0.75rem;
    border-top-left-radius: 6px;
    cursor: nwse-resize;
    z-index: 10;
  }

  .ad .content {
    position: relative;
    width: 100%;
    height: 100%;
    background: transparent;
    pointer-events: none;
  }

  .ad .content > * {
    pointer-events: none;
  }

  /* Empty State */
  .empty-state {
    text-align: center;
    padding: 40px 20px;
    color: var(--gray);
  }

  .empty-state i {
    font-size: 3rem;
    margin-bottom: 16px;
    opacity: 0.5;
  }

  /* Hint */
  .hint {
    font-size: 0.75rem;
    color: var(--gray);
    margin-top: 12px;
    line-height: 1.4;
  }

  /* Responsive */
  @media (max-width: 1024px) {
    .wrap {
      grid-template-columns: 1fr;
    }
    
    aside {
      display: none;
    }
  }

  /* Animations */
  @keyframes fadeIn {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
  }

  .fade-in {
    animation: fadeIn 0.3s ease-out;
  }

  /* Scrollbar */
  ::-webkit-scrollbar {
    width: 8px;
  }

  ::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.05);
  }

  ::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.2);
    border-radius: 4px;
  }

  ::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.3);
  }
  /* === Hotfix lateral + botón Subir visible === */
.wrap{ grid-template-columns: 400px 1fr !important; }  /* antes 320px */
aside{ min-width: 360px !important; }                  /* evita que se achique demasiado */

/* Las filas de propiedades pueden “quebrar” a 2 líneas */
.property-row{ display:flex; flex-wrap:wrap !important; gap:8px !important; }

/* El input ocupa el espacio, el botón no se comprime */
.property-row .property-input{ min-width: 0; flex: 1 1 auto; }
.property-row .btn, 
.property-row button{ flex: 0 0 auto; }

/* En pantallas angostas, forzá el botón Subir abajo del input */
@media (max-width: 1280px){
  .property-row #btnUpload{ width:auto; }
}
/* === Hotfix: scrollbar solo en el admin === */
body.ap ::-webkit-scrollbar{ width:8px; }
body.ap ::-webkit-scrollbar-track{ background: rgba(255,255,255,.06); }
body.ap ::-webkit-scrollbar-thumb{ background: rgba(255,255,255,.2); border-radius:4px; }
body.ap ::-webkit-scrollbar-thumb:hover{ background: rgba(255,255,255,.3); }

</style>
</head>
<body>
<header>
  <div class="brand">
    <i class="bi bi-easel3-fill"></i>
    <span>Admin Publicidad — Canvas</span>
  </div>
  <div class="header-actions">
    <button class="btn btn-secondary" id="btnPing">
      <i class="bi bi-activity"></i> Health
    </button>
    <button class="btn btn-secondary" id="btnReload">
      <i class="bi bi-arrow-repeat"></i> Recargar
    </button>
    <button class="btn btn-primary" id="btnSave">
      <i class="bi bi-cloud-upload"></i> Guardar
    </button>
  </div>
</header>

<div class="wrap">
  <aside>
    <div class="section-title">Páginas</div>
    <div class="page-list" id="pageList">
      <?php foreach($PAGES as $p): ?>
      <button class="page-btn <?= $p['id']==='index'?' active':'' ?>" data-id="<?=htmlspecialchars($p['id'])?>" data-url="<?=htmlspecialchars($p['url'])?>">
        <i class="bi bi-file-earmark"></i> <?=htmlspecialchars($p['title'])?>
      </button>
      <?php endforeach; ?>
    </div>

    <div class="section-title">Agregar Bloque</div>
    <div class="action-buttons">
      <button class="action-btn" data-add="section">
        <i class="bi bi-megaphone"></i>
        <span>Section</span>
      </button>
      <button class="action-btn" data-add="image">
        <i class="bi bi-image"></i>
        <span>Imagen</span>
      </button>
      <button class="action-btn" data-add="video">
        <i class="bi bi-play-btn"></i>
        <span>Video</span>
      </button>
      <button class="action-btn" data-add="html">
        <i class="bi bi-code-slash"></i>
        <span>HTML</span>
      </button>
      <button class="action-btn" data-add="link">
        <i class="bi bi-link-45deg"></i>
        <span>Link</span>
      </button>
    </div>

    <div class="section-title">Propiedades</div>
    <div class="properties-panel" id="prop">
      <div class="empty-state">
        <i class="bi bi-cursor"></i>
        <div>Seleccioná un bloque</div>
      </div>
    </div>

    <div class="hint">
      <i class="bi bi-lightbulb"></i> Drag para mover. ↘ redimensiona. Flechas mueven; Shift rápido; Alt micro; Ctrl+Flechas ancho/alto; PageUp/Down Z; Supr borra.
    </div>

    <div class="section-title">Listado</div>
    <div class="items-list" id="list"></div>
  </aside>

  <main>
    <div class="stage">
      <div class="frame-container">
        <iframe id="frame" src="<?= htmlspecialchars($PAGES[0]['url']) ?>"></iframe>
        <div id="overlay" class="overlay"></div>
      </div>
    </div>
  </main>
</div>

<input type="file" id="uploader" accept="image/*,video/*" hidden>

<script>
const $=s=>document.querySelector(s), $$=s=>[...document.querySelectorAll(s)];
let currentPage='<?=htmlspecialchars($PAGES[0]['id'])?>', items=[], selected=null;
const overlay=$('#overlay'), prop=$('#prop'), list=$('#list'), uploader=$('#uploader');

function clamp01(v){ return Math.max(0, Math.min(100, v)); }
function byId(id){ return items.find(i=>i.id===id); }
function select(id){ selected=id; $$('.ad').forEach(n=> n.classList.toggle('ghost', +n.dataset.id===selected)); renderProps(); }
function drawAll(){ overlay.innerHTML=''; items.filter(i=>i.page_slug===currentPage).forEach(draw); renderList(); }

function draw(it){
  const box=document.createElement('div'); 
  box.className='ad fade-in'+(it.is_active?'':' disabled'); 
  box.dataset.id=it.id;
  box.style.left=it.x_pct+'%'; 
  box.style.top=it.y_pct+'%';
  box.style.width=it.w_pct+'%'; 
  if(it.h_pct!=null) box.style.height=it.h_pct+'%'; 
  box.style.zIndex=it.zindex;

  const bar=document.createElement('div'); 
  bar.className='bar';
  bar.innerHTML=`<div><b>${it.type}</b> <span style="opacity:.85">${it.title||''}</span></div>
                 <div class="item-actions">
                   <button data-act="zup" class="btn btn-sm btn-secondary" type="button" title="Subir Z-index">▲</button>
                   <button data-act="zdown" class="btn btn-sm btn-secondary" type="button" title="Bajar Z-index">▼</button>
                   <button data-act="toggle" class="btn btn-sm ${it.is_active?'btn-warning':'btn-success'}" type="button" title="Activar/Desactivar">${it.is_active?'<i class="bi bi-pause-fill"></i>':'<i class="bi bi-play-fill"></i>'}</button>
                   <button data-act="del" class="btn btn-sm btn-danger" type="button" title="Eliminar"><i class="bi bi-trash"></i></button>
                 </div>`;

  const content=document.createElement('div'); 
  content.className='content';

  if (it.type==='section'){
    content.innerHTML = `<div style="position:absolute;inset:0;background:#15324c;color:#fff;display:flex;align-items:center;padding:12px 16px;font-weight:700">${it.title || 'Sección publicitaria'}</div>`;
  } else if (it.type==='image' && it.media_url){
    content.innerHTML=`<img src="${it.media_url}" style="position:absolute;inset:0;width:100%;height:100%;object-fit:contain;display:block">`;
  } else if (it.type==='video'){
    if(/youtu\.?be/.test(it.media_url||'')){
      const id=(it.media_url||'').match(/(?:v=|\.be\/)([\w-]+)/)?.[1]||'';
      content.innerHTML = id? `<iframe src="https://www.youtube.com/embed/${id}" allow="autoplay;encrypted-media" allowfullscreen style="position:absolute;inset:0;width:100%;height:100%;border:0"></iframe>`:'<div style="padding:12px;color:#333;display:flex;align-items:center;justify-content:center;height:100%">URL YouTube inválida</div>';
    } else if(it.media_url) {
      content.innerHTML=`<video src="${it.media_url}" controls style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover"></video>`;
    }
  } else if (it.type==='html' && it.html){
    content.innerHTML = `<div style="position:absolute;inset:0">${it.html}</div>`;
  } else if (it.type==='link'){
    const label=it.title||it.link_url||'Link'; 
    const href=it.link_url||'#';
    content.innerHTML=`<a href="${href}" target="_self" style="position:absolute;inset:8px;display:flex;align-items:center;justify-content:center;border:2px dashed #1f72b6;border-radius:8px;text-decoration:none;color:#1f72b6;font-weight:600;background:#fff">${label}</a>`;
  }

  const handle=document.createElement('div'); 
  handle.className='handle'; 
  handle.innerHTML='<i class="bi bi-arrows-angle-expand"></i>';
  box.append(bar,content,handle);

  box.addEventListener('pointerdown', e=>{ select(it.id); });
  box.addEventListener('pointerdown', e=>{ if (e.target.closest('button') || e.target.closest('.handle')) return; startDrag(it,box,e); });
  bar.addEventListener('pointerdown', e=>{ if (e.target.closest('button')) return; startDrag(it,box,e); });
  handle.addEventListener('pointerdown', e=>{ startResize(it,box,e); });

  bar.addEventListener('click', async (e)=>{
    const b=e.target.closest('button'); if(!b) return;
    const act=b.dataset.act;
    if(act==='del'){ await delItem(it.id); return; }
    if(act==='toggle'){
      it.is_active = it.is_active ? 0 : 1; 
      drawAll();
      if (it.id > 0) {
        const fd = new FormData(); 
        fd.append('action','toggle'); 
        fd.append('id', it.id); 
        fd.append('is_active', it.is_active);
        const r = await fetch('<?=htmlspecialchars($SELF)?>', {method:'POST', body:fd});
        const js = await r.json(); 
        if(!js.ok){ alert(js.error||'No se pudo cambiar estado'); }
        await load();
      }
      return;
    }
    if(act==='zup'){ it.zindex++; drawAll(); return; }
    if(act==='zdown'){ it.zindex=Math.max(0,it.zindex-1); drawAll(); return; }
  });

  overlay.appendChild(box);
}

let drag=null, rez=null;
function stageRect(){ const r=overlay.getBoundingClientRect(); return {W:r.width,H:r.height}; }
function startDrag(it, el, ev){ ev.preventDefault(); const {W,H}=stageRect(); drag={it,el,sx:ev.clientX,sy:ev.clientY,ox:it.x_pct,oy:it.y_pct,W,H}; window.addEventListener('pointermove', onDrag); window.addEventListener('pointerup', endDrag, {once:true}); }
function onDrag(ev){ if(!drag) return; const speed=ev.shiftKey?2:1; const dx=(ev.clientX-drag.sx)*speed, dy=(ev.clientY-drag.sy)*speed; let nx=drag.ox+(dx/drag.W)*100, ny=drag.oy+(dy/drag.H)*100; drag.it.x_pct=clamp01(nx); drag.it.y_pct=clamp01(ny); drag.el.style.left=drag.it.x_pct+'%'; drag.el.style.top=drag.it.y_pct+'%'; }
function endDrag(){ window.removeEventListener('pointermove', onDrag); drag=null; renderProps(); }
function startResize(it, el, ev){ ev.preventDefault(); const {W,H}=stageRect(); rez={it,el,sx:ev.clientX,sy:ev.clientY,ow:it.w_pct,oh:it.h_pct??null,W,H}; window.addEventListener('pointermove', onResize); window.addEventListener('pointerup', endResize, {once:true}); }
function onResize(ev){ if(!rez) return; const dx=ev.clientX-rez.sx, dy=ev.clientY-rez.sy; let nw=rez.ow+(dx/rez.W)*100; nw=Math.max(5,clamp01(nw)); rez.it.w_pct=nw; if(rez.it.h_pct!=null){ let nh=(rez.oh??rez.it.h_pct)+(dy/rez.H)*100; nh=Math.max(5,clamp01(nh)); rez.it.h_pct=nh; } drawAll(); select(rez.it.id); }
function endResize(){ window.removeEventListener('pointermove', onResize); rez=null; renderProps(); }

// Crear item con alturas por defecto (evita "línea azul")
function addItem(type){
  if(type==='banner') type='image';
  const it={ id:0, page_slug:currentPage, type, title:'', media_url:'', link_url:'', html:'',
             x_pct:10, y_pct:10, w_pct:30, h_pct:null, zindex:10, is_active:1 };
  if(type==='link'){ it.title='Ver más'; it.link_url='#'; it.w_pct=15; it.h_pct=10; }
  if(type==='video'){ it.w_pct=35; it.h_pct=20; }
  if(type==='image'){ it.w_pct=30; it.h_pct=20; }
  if(type==='html'){  it.w_pct=40; it.h_pct=20; }
  if(type==='section'){ it.title='Sección publicitaria'; it.x_pct=0; it.w_pct=100; it.h_pct=20; it.zindex=5; }
  items.push(it); drawAll(); select(it.id);
}

async function delItem(id){
  const it = byId(id); if(!it) return;
  if(!confirm('¿Eliminar este elemento?')) return;
  if (it.id > 0) {
    const fd = new FormData(); fd.append('action','delete'); fd.append('id', it.id);
    const r = await fetch('<?=htmlspecialchars($SELF)?>',{method:'POST',body:fd});
    const js = await r.json(); if(!js.ok){ alert(js.error||'No se pudo borrar'); return; }
  }
  await load();
}

async function ping(){ 
  const r=await fetch('<?=htmlspecialchars($SELF)?>?action=health'); 
  const js=await r.json(); 
  if(js.ok) {
    showNotification('DB OK ('+(js.driver||'?')+')', 'success');
  } else {
    showNotification('DB FAIL', 'error');
  }
}

function showNotification(message, type = 'info') {
  const notification = document.createElement('div');
  notification.className = `notification ${type}`;
  notification.innerHTML = `
    <div class="notification-content">
      <i class="bi bi-${type === 'success' ? 'check-circle' : type === 'error' ? 'exclamation-circle' : 'info-circle'}"></i>
      <span>${message}</span>
    </div>
  `;
  
  document.body.appendChild(notification);
  
  // Animación de entrada
  setTimeout(() => {
    notification.classList.add('show');
  }, 10);
  
  // Eliminar después de 3 segundos
  setTimeout(() => {
    notification.classList.remove('show');
    setTimeout(() => {
      if (notification.parentNode) {
        notification.parentNode.removeChild(notification);
      }
    }, 300);
  }, 3000);
}

async function load(){
  const r=await fetch('<?=htmlspecialchars($SELF)?>?action=list&page='+encodeURIComponent(currentPage));
  const js=await r.json();
  items=(js.items||[]).map(r=>({
    ...r, id:+r.id||r.id, x_pct:+r.x_pct, y_pct:+r.y_pct, w_pct:+r.w_pct,
    h_pct:r.h_pct===null?null:+r.h_pct, zindex:+r.zindex, is_active:+r.is_active
  }));
  selected=null; drawAll();
}

async function save(){
  const payload=items.filter(i=>i.page_slug===currentPage);
  const fd=new FormData(); fd.append('action','save'); fd.append('payload',JSON.stringify(payload));
  const r=await fetch('<?=htmlspecialchars($SELF)?>',{method:'POST',body:fd});
  const js=await r.json(); 
  if(js.ok){ 
    showNotification('Guardado correctamente', 'success');
    await load(); 
  } else {
    showNotification(js.error||'Error al guardar', 'error');
  }
}

async function uploadFile(file){
  const fd=new FormData(); fd.append('action','upload'); fd.append('file',file);
  const r=await fetch('<?=htmlspecialchars($SELF)?>',{method:'POST',body:fd}); const js=await r.json();
  if(js.ok) return js.url; 
  showNotification(js.error||'Error de subida', 'error');
  return null;
}

function renderProps(){
  const it=byId(selected);
  if(!it){ 
    prop.innerHTML='<div class="empty-state"><i class="bi bi-cursor"></i><div>Seleccioná un bloque</div></div>'; 
    return; 
  }
  
  let spec='';
  if (it.type!=='html' && it.type!=='section')
    spec += `<div class="property-row">
              <span class="property-label">Media</span>
              <input id="p_media" class="property-input" type="url" placeholder="Media URL (o subir)" value="${it.media_url||''}">
              <button class="btn btn-sm btn-secondary" id="btnUpload" type="button" title="Subir archivo"><i class="bi bi-upload"></i></button>
            </div>`;
  if(it.type==='link' || it.type==='image')
    spec += `<div class="property-row">
              <span class="property-label">Link</span>
              <input id="p_link" class="property-input" type="url" placeholder="Link URL" value="${it.link_url||''}">
            </div>`;
  if(it.type==='html')
    spec += `<div class="property-row" style="flex-direction:column;align-items:flex-start;">
              <span class="property-label">HTML</span>
              <textarea id="p_html" class="property-input property-textarea" placeholder="Código HTML">${(it.html||'').replaceAll('<','&lt;')}</textarea>
            </div>`;

  prop.innerHTML = `
    <div class="property-row">
      <span class="property-label">ID</span>
      <input class="property-input" value="#${it.id}" readonly style="background:rgba(255,255,255,0.05);color:var(--gray)">
    </div>
    <div class="property-row">
      <span class="property-label">Tipo</span>
      <input class="property-input" value="${it.type}" readonly style="background:rgba(255,255,255,0.05);color:var(--gray);text-transform:capitalize">
    </div>
    <div class="property-row">
      <span class="property-label">Título</span>
      <input id="p_title" class="property-input" type="text" placeholder="Título" value="${it.title||''}">
    </div>
    ${spec}
    <div class="property-row">
      <span class="property-label">X%</span>
      <input id="p_x" class="property-input" type="text" value="${it.x_pct}" style="width:70px">
      <span class="property-label">Y%</span>
      <input id="p_y" class="property-input" type="text" value="${it.y_pct}" style="width:70px">
    </div>
    <div class="property-row">
      <span class="property-label">W%</span>
      <input id="p_w" class="property-input" type="text" value="${it.w_pct}" style="width:70px">
      <span class="property-label">H%</span>
      <input id="p_h" class="property-input" type="text" value="${it.h_pct??''}" style="width:70px" placeholder="${it.h_pct==null?'(auto)':''}">
    </div>
    <div class="property-row">
      <span class="property-label">Z</span>
      <input id="p_z" class="property-input" type="text" value="${it.zindex}" style="width:70px">
    </div>
    <div class="property-row">
      <span class="property-label">Estado</span>
      <select id="p_en" class="property-select">
        <option value="1" ${it.is_active? 'selected':''}>Activo</option>
        <option value="0" ${!it.is_active? 'selected':''}>Inactivo</option>
      </select>
      <button class="btn btn-primary" id="p_apply" type="button">Aplicar</button>
    </div>
  `;

  $('#btnUpload')?.addEventListener('click',()=>{ uploader.value=''; uploader.click(); });
  uploader.onchange=async()=>{ 
    const f=uploader.files?.[0]; 
    if(!f) return; 
    showNotification('Subiendo archivo...', 'info');
    const url=await uploadFile(f); 
    if(url){ 
      it.media_url=url; 
      renderProps(); 
      drawAll(); 
      select(it.id); 
      showNotification('Archivo subido correctamente', 'success');
    }
  };
  
  $('#p_apply').onclick=()=>{
    it.title=$('#p_title')?.value||'';
    if(it.type!=='html' && it.type!=='section') it.media_url=$('#p_media')?.value||'';
    if(it.type==='link' || it.type==='image') it.link_url=$('#p_link')?.value||'';
    if(it.type==='html') it.html=($('#p_html')?.value||'').replaceAll('&lt;','<');
    it.x_pct=+($('#p_x')?.value||it.x_pct);
    it.y_pct=+($('#p_y')?.value||it.y_pct);
    it.w_pct=+($('#p_w')?.value||it.w_pct);
    const hv=$('#p_h')?.value; it.h_pct=hv===''? null : +hv;
    it.zindex=+($('#p_z')?.value||it.zindex);
    it.is_active=+($('#p_en')?.value||it.is_active);
    drawAll();
    showNotification('Propiedades aplicadas', 'success');
  };
}

function renderList(){
  const pageItems = items.filter(i=>i.page_slug===currentPage);
  
  if (pageItems.length === 0) {
    list.innerHTML = '<div class="empty-state"><i class="bi bi-inbox"></i><div>No hay bloques en esta página</div></div>';
    return;
  }
  
  list.innerHTML = pageItems.map(i=>`
    <div class="item-card fade-in">
      <div class="item-info">
        <div class="item-id">#${i.id}</div>
        <div class="item-type">${i.type}</div>
        <div class="item-title">${i.title || '(Sin título)'}</div>
      </div>
      <div class="item-actions">
        <button class="btn btn-sm btn-secondary" data-jump="${i.id}" type="button" title="Ir al elemento"><i class="bi bi-arrow-right"></i></button>
        <button class="btn btn-sm btn-danger" data-del="${i.id}" type="button" title="Eliminar"><i class="bi bi-trash"></i></button>
      </div>
    </div>`).join('');
    
  list.querySelectorAll('[data-jump]').forEach(b=> b.onclick=()=>{ select(+b.dataset.jump); });
  list.querySelectorAll('[data-del]').forEach(b=> b.onclick=()=> delItem(+b.dataset.del));
}

// Inicialización
$$('.page-btn').forEach((b,i)=>{
  b.onclick=()=>{
    $$('.page-btn').forEach(x=>x.classList.remove('active'));
    b.classList.add('active');
    currentPage=b.dataset.id;
    selected=null;
    overlay.innerHTML='';
    $('#frame').src=b.dataset.url;
    load();
  };
  if(i===0) b.classList.add('active');
});

$$('[data-add]').forEach(b=> b.onclick=()=> addItem(b.dataset.add));
$('#btnReload').onclick=load; 
$('#btnSave').onclick=save; 
$('#btnPing').onclick=ping;

// Click en cualquier lado que no sea un ad ni el aside => deseleccionar
document.addEventListener('pointerdown', (e) => {
  if (!e.target.closest('.ad') && !e.target.closest('aside')) {
    select(null);
  }
});

function nudge(sel,{dx=0,dy=0,dw=0,dh=0,dz=0}={}){ 
  const it=byId(sel); 
  if(!it) return; 
  it.x_pct=clamp01(it.x_pct+dx); 
  it.y_pct=clamp01(it.y_pct+dy); 
  if(dw) it.w_pct=Math.max(5,clamp01(it.w_pct+dw)); 
  if(it.h_pct!=null&&dh) it.h_pct=Math.max(5,clamp01(it.h_pct+dh)); 
  if(dz) it.zindex=Math.max(0,it.zindex+dz); 
  drawAll(); 
  select(it.id); 
}

window.addEventListener('keydown',(e)=>{
  if(!selected) return;
  const step=e.altKey?0.2:(e.shiftKey?5:1);
  if(['ArrowLeft','ArrowRight','ArrowUp','ArrowDown','Delete','PageUp','PageDown'].includes(e.key)) e.preventDefault();
  if(e.key==='ArrowLeft'){ if(e.ctrlKey) nudge(selected,{dw:-step}); else nudge(selected,{dx:-step}); }
  if(e.key==='ArrowRight'){ if(e.ctrlKey) nudge(selected,{dw:+step}); else nudge(selected,{dx:+step}); }
  if(e.key==='ArrowUp'){ if(e.ctrlKey) nudge(selected,{dh:-step}); else nudge(selected,{dy:-step}); }
  if(e.key==='ArrowDown'){ if(e.ctrlKey) nudge(selected,{dh:+step}); else nudge(selected,{dy:+step}); }
  if(e.key==='Delete'){ delItem(selected); }
  if(e.key==='PageUp'){ nudge(selected,{dz:+1}); }
  if(e.key==='PageDown'){ nudge(selected,{dz:-1}); }
});

// Añadir estilos para notificaciones
const notificationStyles = document.createElement('style');
notificationStyles.textContent = `
  .notification {
    position: fixed;
    top: 20px;
    right: 20px;
    background: var(--dark-light);
    border-left: 4px solid var(--primary);
    color: var(--light);
    padding: 16px;
    border-radius: var(--border-radius-sm);
    box-shadow: var(--shadow-lg);
    z-index: 1000;
    transform: translateX(100%);
    opacity: 0;
    transition: transform 0.3s ease, opacity 0.3s ease;
    max-width: 350px;
  }
  
  .notification.show {
    transform: translateX(0);
    opacity: 1;
  }
  
  .notification.success {
    border-left-color: var(--success);
  }
  
  .notification.error {
    border-left-color: var(--danger);
  }
  
  .notification.info {
    border-left-color: var(--primary);
  }
  
  .notification-content {
    display: flex;
    align-items: center;
    gap: 10px;
  }
  
  .notification-content i {
    font-size: 1.25rem;
  }
  
  .notification.success .notification-content i {
    color: var(--success);
  }
  
  .notification.error .notification-content i {
    color: var(--danger);
  }
  
  .notification.info .notification-content i {
    color: var(--primary);
  }
`;

document.head.appendChild(notificationStyles);

// Cargar datos iniciales
load();
</script>
</body>
</html>