<!DOCTYPE html>
<html lang="pt">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>IG Studio</title>
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <script src="https://unpkg.com/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link href="https://fonts.googleapis.com/css2?family=Syne:wght@400;600;700;800&family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
  <style>
    :root {
      --bg:        #080808;
      --surface:   #111111;
      --border:    #1c1c1c;
      --border2:   #252525;
      --text:      #e8e8e8;
      --muted:     #555;
      --muted2:    #333;
      --accent:    #c8f551;
      --accent-dim:#8aaa2a;
      --danger:    #ff4444;
      --radius:    10px;
    }
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    body {
      font-family: 'Inter', sans-serif;
      background: var(--bg);
      color: var(--text);
      height: 100vh;
      display: flex;
      flex-direction: column;
      overflow: hidden;
      font-size: 13px;
    }

    /* ── NAVBAR ── */
    #navbar {
      height: 48px;
      min-height: 48px;
      background: var(--surface);
      border-bottom: 1px solid var(--border);
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 0 20px;
      flex-shrink: 0;
      gap: 12px;
    }
    #nav-brand {
      font-family: 'Syne', sans-serif;
      font-weight: 800;
      font-size: 15px;
      color: var(--accent);
      letter-spacing: -0.3px;
      display: flex;
      align-items: center;
      gap: 8px;
      flex-shrink: 0;
    }
    #nav-brand span {
      font-weight: 400;
      color: var(--muted);
      font-size: 12px;
      font-family: 'Inter', sans-serif;
    }
    #render-timer {
      font-size: 11px;
      color: var(--muted);
      font-family: monospace;
      min-width: 44px;
    }
    #render-timer.running { color: var(--accent); }
    #nav-center { display: flex; align-items: center; gap: 6px; }
    #nav-right  { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
    .nav-btn {
      padding: 6px 14px;
      border-radius: 20px;
      border: 1px solid var(--border2);
      background: transparent;
      color: var(--muted);
      font-size: 12px;
      font-family: 'Inter', sans-serif;
      cursor: pointer;
      transition: all 0.18s;
      white-space: nowrap;
    }
    .nav-btn:hover { border-color: var(--accent); color: var(--accent); }
    .nav-btn.active { border-color: var(--accent); color: var(--accent); background: rgba(200,245,81,0.06); }
    #works-badge {
      background: var(--accent);
      color: #000;
      font-size: 10px;
      font-weight: 700;
      padding: 1px 6px;
      border-radius: 10px;
      min-width: 18px;
      text-align: center;
      display: none;
    }
    #works-badge.show { display: inline-block; }

    /* mobile tabs */
    #mobile-tabs { display: none; }

    /* ── MAIN ── */
    #main { flex: 1; display: flex; overflow: hidden; }

    /* ── CHAT PANEL ── */
    #chat-panel {
      width: 36%;
      min-width: 280px;
      display: flex;
      flex-direction: column;
      border-right: 1px solid var(--border);
    }
    #chat-header {
      padding: 10px 16px;
      border-bottom: 1px solid var(--border);
      font-size: 10px;
      font-weight: 600;
      color: var(--muted2);
      letter-spacing: 2px;
      text-transform: uppercase;
      flex-shrink: 0;
    }
    #chat {
      flex: 1;
      overflow-y: auto;
      padding: 16px;
      display: flex;
      flex-direction: column;
      gap: 10px;
    }
    #chat::-webkit-scrollbar { width: 2px; }
    #chat::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }
    .msg {
      padding: 10px 14px;
      border-radius: 14px;
      max-width: 90%;
      line-height: 1.6;
      font-size: 13px;
      white-space: pre-wrap;
    }
    .user {
      background: var(--accent);
      color: #000;
      align-self: flex-end;
      border-bottom-right-radius: 3px;
      font-weight: 500;
    }
    .ai {
      background: var(--surface);
      border: 1px solid var(--border2);
      align-self: flex-start;
      border-bottom-left-radius: 3px;
      color: #ccc;
    }
    #input-area {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 10px 12px;
      background: var(--surface);
      border-top: 1px solid var(--border);
      flex-shrink: 0;
    }
    #message {
      flex: 1;
      padding: 9px 14px;
      border: 1px solid var(--border2);
      border-radius: 20px;
      background: var(--bg);
      color: var(--text);
      font-size: 13px;
      font-family: 'Inter', sans-serif;
      outline: none;
      transition: border-color 0.18s;
    }
    #message:focus { border-color: var(--accent); }
    #message::placeholder { color: var(--muted2); }
    #send {
      width: 38px; height: 38px;
      flex-shrink: 0;
      background: var(--accent);
      border: none;
      color: #000;
      border-radius: 50%;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 20px;
      transition: all 0.18s;
    }
    #send .material-icons-round { font-size: 20px; line-height: 1; }
    #send:hover { background: #d4f96a; transform: scale(1.06); }
    #send:active { transform: scale(0.94); }
    #send:disabled { background: var(--border2); color: var(--muted); cursor: not-allowed; transform: none; }
    #send.recording { background: var(--danger); animation: recpulse 1.4s ease-in-out infinite; }
    @keyframes recpulse { 0%,100%{box-shadow:0 0 0 0 rgba(255,68,68,.5)}50%{box-shadow:0 0 0 8px rgba(255,68,68,0)} }
    #rec-bar { display: none; align-items: center; gap: 8px; flex: 1; padding: 0 4px; }
    #rec-bar.show { display: flex; }
    .rec-dot { width: 7px; height: 7px; background: var(--danger); border-radius: 50%; animation: recdot 1s ease-in-out infinite; }
    @keyframes recdot { 0%,100%{opacity:1}50%{opacity:.2} }
    #rec-timer-txt { font-size: 12px; color: var(--muted); font-family: monospace; min-width: 36px; }
    #rec-cancel { background: none; border: none; color: var(--muted); font-size: 12px; cursor: pointer; padding: 4px 6px; border-radius: 6px; transition: color .15s; }
    #rec-cancel:hover { color: var(--danger); }

    /* ── PREVIEW PANEL ── */
    #preview-panel {
      flex: 1;
      display: flex;
      flex-direction: column;
      background: var(--bg);
      min-width: 0;
    }
    #preview-header {
      padding: 10px 16px;
      background: var(--surface);
      border-bottom: 1px solid var(--border);
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-shrink: 0;
    }
    #preview-left { display: flex; align-items: center; gap: 10px; min-width: 0; }
    #preview-title { font-size: 10px; font-weight: 600; color: var(--muted2); letter-spacing: 2px; text-transform: uppercase; white-space: nowrap; }
    #work-label { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 180px; }
    #preview-actions { display: flex; gap: 6px; align-items: center; flex-shrink: 0; }
    #slide-count { font-size: 11px; color: var(--muted2); margin-right: 2px; white-space: nowrap; }
    .btn {
      padding: 5px 12px;
      border-radius: 20px;
      border: 1px solid var(--border2);
      background: transparent;
      color: var(--muted);
      font-size: 11px;
      font-family: 'Inter', sans-serif;
      cursor: pointer;
      transition: all 0.18s;
      white-space: nowrap;
    }
    .btn:hover { border-color: var(--accent); color: var(--accent); }
    .btn.primary { background: var(--accent); border-color: var(--accent); color: #000; font-weight: 600; }
    .btn.primary:hover { background: #d4f96a; }
    .btn:disabled { opacity: .35; cursor: not-allowed; }
    .btn.save-dirty { border-color: rgba(200,245,81,.4); color: var(--accent); }
    .btn.save-dirty::before { content: '• '; }

    #slides-container {
      flex: 1;
      overflow: auto;
      padding: 28px;
      display: flex;
      gap: 20px;
      align-items: flex-start;
      flex-wrap: wrap;
      align-content: flex-start;
    }
    #slides-container::-webkit-scrollbar { width: 3px; height: 3px; }
    #slides-container::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
    #empty-state {
      width: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 320px;
      color: var(--muted2);
      gap: 12px;
    }
    #empty-state .icon { font-size: 44px; opacity: .4; }
    #empty-state p { font-size: 13px; text-align: center; line-height: 1.8; color: var(--muted2); }

    .slide-wrap { display: flex; flex-direction: column; align-items: center; gap: 7px; flex-shrink: 0; }
    .slide-label { font-size: 10px; color: var(--muted2); letter-spacing: 1px; font-family: monospace; }
    .slide {
      width: 360px;
      height: 450px;
      position: relative;
      overflow: hidden;
      border-radius: 12px;
      box-shadow: 0 6px 32px rgba(0,0,0,.6);
      cursor: default;
      transition: box-shadow 0.2s, transform 0.2s;
      background: #111;
      /* Trap position:fixed children inside the slide boundary */
      transform: translateZ(0);
      isolation: isolate;
    }
    .slide:hover { box-shadow: 0 0 0 2px var(--accent), 0 8px 40px rgba(0,0,0,.7); transform: translateY(-2px); }
    .slide-edit-overlay {
      position: absolute;
      inset: 0;
      background: rgba(0,0,0,0);
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 12px;
      font-weight: 600;
      color: transparent;
      transition: all 0.2s;
      pointer-events: none;
      font-family: 'Inter', sans-serif;
      letter-spacing: 1px;
    }
    .slide:hover .slide-edit-overlay { background: rgba(0,0,0,.35); color: #fff; }
    .slide-del-btn {
      position: absolute;
      top: 8px; right: 8px;
      width: 22px; height: 22px;
      background: rgba(0,0,0,.6);
      border: 1px solid rgba(255,255,255,.15);
      border-radius: 50%;
      display: none;
      align-items: center;
      justify-content: center;
      font-size: 12px;
      font-weight: 900;
      color: #fff;
      cursor: pointer;
      z-index: 30;
      line-height: 1;
      transition: background .15s;
    }
    .slide-del-btn:hover { background: var(--danger); border-color: var(--danger); }
    .slide:hover .slide-del-btn { display: flex; }
    .slide-content { width: 100%; height: 100%; position: relative; overflow: clip; contain: layout paint; }
    .slide-content * { box-sizing: border-box; max-width: 100vmax; }

    /* regenerate button per slide */
    .slide-regen-btn {
      position: absolute;
      bottom: 8px; right: 8px;
      padding: 3px 9px;
      background: rgba(0,0,0,.7);
      border: 1px solid rgba(255,255,255,.15);
      border-radius: 12px;
      display: none;
      align-items: center;
      gap: 4px;
      font-size: 10px;
      font-weight: 600;
      color: #fff;
      cursor: pointer;
      z-index: 30;
      transition: all .15s;
      white-space: nowrap;
    }
    .slide-regen-btn:hover { background: rgba(200,245,81,.2); border-color: var(--accent); color: var(--accent); }
    .slide:hover .slide-regen-btn { display: flex; }

    /* ── WORKS DRAWER ── */
    #works-drawer {
      width: 0;
      min-width: 0;
      overflow: hidden;
      background: var(--surface);
      border-left: 0px solid var(--border);
      display: flex;
      flex-direction: column;
      flex-shrink: 0;
      transition: width .25s ease, border-width .25s ease;
    }
    #works-drawer.open { width: 280px; min-width: 280px; border-left-width: 1px; }
    #works-drawer-inner { width: 280px; height: 100%; display: flex; flex-direction: column; }
    #works-header {
      padding: 12px 14px;
      border-bottom: 1px solid var(--border);
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-shrink: 0;
    }
    #works-header span { font-size: 10px; font-weight: 600; color: var(--muted2); letter-spacing: 2px; text-transform: uppercase; }
    #btn-clear-works { font-size: 11px; color: var(--muted2); background: none; border: none; cursor: pointer; padding: 2px 6px; border-radius: 4px; transition: color .2s; }
    #btn-clear-works:hover { color: var(--danger); }
    #works-list { flex: 1; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 7px; }
    #works-list::-webkit-scrollbar { width: 2px; }
    #works-list::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }
    .work-card { background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 10px 11px; transition: border-color .2s; }
    .work-card.active { border-color: rgba(200,245,81,.3); }
    .work-card-top { display: flex; align-items: center; gap: 9px; margin-bottom: 8px; }
    .work-dot { width: 24px; height: 24px; border-radius: 6px; flex-shrink: 0; }
    .work-info { flex: 1; min-width: 0; }
    .work-title { font-size: 12px; font-weight: 600; color: #ccc; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .work-meta { font-size: 10px; color: var(--muted2); margin-top: 2px; }
    .work-actions { display: flex; gap: 5px; }
    .work-btn { flex: 1; padding: 5px 0; border-radius: 6px; border: 1px solid var(--border2); background: transparent; color: var(--muted); font-size: 11px; font-family: 'Inter', sans-serif; cursor: pointer; transition: all .15s; text-align: center; }
    .work-btn:hover { border-color: var(--accent); color: var(--accent); }
    .work-btn.danger:hover { border-color: var(--danger); color: var(--danger); }

    /* ── SLIDE MODAL ── */
    #slide-modal {
      display: none;
      position: fixed;
      inset: 0;
      background: rgba(0,0,0,.7);
      z-index: 400;
      align-items: center;
      justify-content: center;
    }
    #slide-modal.show { display: flex; }
    #slide-modal-card {
      background: #0e0e0e;
      border: 1px solid var(--border2);
      border-radius: 16px;
      width: 720px;
      max-width: 96vw;
      max-height: 90vh;
      display: flex;
      flex-direction: column;
      box-shadow: 0 24px 80px rgba(0,0,0,.8);
    }
    #slide-modal-header {
      padding: 16px 20px;
      border-bottom: 1px solid var(--border);
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-shrink: 0;
    }
    #slide-modal-title { font-family: 'Syne', sans-serif; font-size: 15px; font-weight: 700; color: var(--text); }
    #slide-modal-close { background: none; border: none; color: var(--muted); font-size: 20px; cursor: pointer; padding: 0 4px; transition: color .2s; line-height: 1; }
    #slide-modal-close:hover { color: var(--danger); }
    #slide-modal-tabs { display: flex; padding: 10px 20px 0; gap: 4px; border-bottom: 1px solid var(--border); flex-shrink: 0; }
    .modal-tab { padding: 7px 16px; font-size: 12px; font-weight: 600; font-family: 'Inter', sans-serif; background: none; border: none; color: var(--muted); cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; transition: all .15s; }
    .modal-tab:hover { color: #888; }
    .modal-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
    #slide-modal-body { flex: 1; overflow-y: auto; }
    #slide-modal-body::-webkit-scrollbar { width: 3px; }
    #slide-modal-body::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }
    .modal-panel { padding: 18px 20px; }
    .modal-panel.hidden { display: none; }

    .form-row { display: flex; gap: 10px; margin-bottom: 12px; }
    .form-group { display: flex; flex-direction: column; gap: 5px; flex: 1; min-width: 0; }
    .form-label { font-size: 10px; font-weight: 600; color: var(--muted); letter-spacing: 1px; text-transform: uppercase; }
    .form-input {
      padding: 8px 12px;
      background: var(--bg);
      border: 1px solid var(--border2);
      border-radius: 8px;
      color: #ddd;
      font-size: 13px;
      font-family: 'Inter', sans-serif;
      outline: none;
      transition: border-color .2s;
      width: 100%;
    }
    .form-input:focus { border-color: var(--accent); }
    textarea.form-input { resize: vertical; min-height: 70px; }
    select.form-input { cursor: pointer; }
    .section-divider { height: 1px; background: var(--border); margin: 14px 0; }

    /* AI edit section */
    #slide-ai-section { margin-bottom: 4px; }
    #slide-ai-row { display: flex; gap: 8px; align-items: flex-end; }
    #slide-ai-prompt {
      flex: 1;
      padding: 9px 12px;
      background: var(--bg);
      border: 1px solid var(--border2);
      border-radius: 8px;
      color: #ddd;
      font-size: 13px;
      font-family: 'Inter', sans-serif;
      outline: none;
      resize: none;
      min-height: 58px;
      transition: border-color .2s;
    }
    #slide-ai-prompt:focus { border-color: var(--accent); }
    #slide-ai-prompt::placeholder { color: var(--muted2); }
    #btn-slide-ai {
      padding: 9px 16px;
      background: var(--accent);
      border: none;
      color: #000;
      border-radius: 8px;
      cursor: pointer;
      font-size: 13px;
      font-weight: 700;
      font-family: 'Inter', sans-serif;
      white-space: nowrap;
      transition: background .2s;
    }
    #btn-slide-ai:hover { background: #d4f96a; }
    #btn-slide-ai:disabled { background: var(--border2); color: var(--muted); cursor: not-allowed; }
    #slide-ai-status { font-size: 11px; color: var(--muted); margin-top: 5px; min-height: 16px; }

    /* image search */
    #img-search-bar { display: flex; gap: 7px; margin-bottom: 12px; }
    #img-search-input { flex: 1; padding: 8px 12px; background: var(--bg); border: 1px solid var(--border2); border-radius: 8px; color: #ddd; font-size: 13px; font-family: 'Inter', sans-serif; outline: none; }
    #img-search-input:focus { border-color: var(--accent); }
    #btn-img-search { padding: 8px 16px; background: var(--accent); border: none; color: #000; border-radius: 8px; cursor: pointer; font-size: 13px; font-weight: 700; }
    #btn-img-search:hover { background: #d4f96a; }
    #img-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
    .img-thumb { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 6px; cursor: pointer; border: 2px solid transparent; transition: all .15s; }
    .img-thumb:hover { border-color: rgba(200,245,81,.5); }
    .img-thumb.selected { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(200,245,81,.25); }
    #img-loading { text-align: center; padding: 24px; color: var(--muted); font-size: 12px; display: none; }
    #img-no-results { text-align: center; padding: 24px; color: var(--muted2); font-size: 12px; display: none; }
    #img-selected-info { margin-top: 10px; padding: 8px 12px; background: rgba(200,245,81,.07); border: 1px solid rgba(200,245,81,.2); border-radius: 8px; font-size: 11px; color: var(--accent); display: none; }
    #img-selected-info.show { display: block; }
    .upload-btn-label { display: inline-block; padding: 7px 14px; background: transparent; border: 1px solid var(--border2); border-radius: 8px; color: var(--muted); font-size: 12px; cursor: pointer; transition: all .15s; margin-bottom: 12px; }
    .upload-btn-label:hover { border-color: var(--accent); color: var(--accent); }
    .bg-img-preview { margin-top: 8px; display: flex; align-items: center; gap: 8px; }
    .bg-img-thumb { width: 44px; height: 44px; border-radius: 6px; object-fit: cover; border: 1px solid var(--border2); }
    #btn-clear-bg-img { padding: 5px 10px; border-radius: 8px; border: 1px solid var(--border2); background: transparent; color: var(--muted); font-size: 11px; cursor: pointer; }
    #btn-clear-bg-img:hover { border-color: var(--danger); color: var(--danger); }
    input[type=range] { width: 100%; accent-color: var(--accent); cursor: pointer; }
    .range-row { display: flex; align-items: center; gap: 8px; }
    .range-val { font-size: 11px; color: var(--muted); min-width: 34px; text-align: right; font-family: monospace; }
    .color-row { display: flex; align-items: center; gap: 7px; }
    .color-row input[type=color] { width: 34px; height: 30px; padding: 2px; border: 1px solid var(--border2); border-radius: 6px; background: var(--bg); cursor: pointer; flex-shrink: 0; }

    /* overlay images */
    #oi-search-bar { display: flex; gap: 7px; margin-bottom: 12px; }
    #oi-search-input { flex: 1; padding: 8px 12px; background: var(--bg); border: 1px solid var(--border2); border-radius: 8px; color: #ddd; font-size: 13px; outline: none; font-family: 'Inter', sans-serif; }
    #oi-search-input:focus { border-color: var(--accent); }
    #btn-oi-search { padding: 8px 16px; background: var(--accent); border: none; color: #000; border-radius: 8px; cursor: pointer; font-size: 13px; font-weight: 700; }
    #oi-img-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 6px; }
    #oi-img-loading, #oi-img-no-results { text-align: center; padding: 18px; color: var(--muted); font-size: 12px; display: none; }
    .oi-section-label { font-size: 10px; font-weight: 600; color: var(--muted); letter-spacing: 1px; text-transform: uppercase; margin-bottom: 8px; }
    #oi-empty { font-size: 12px; color: var(--muted2); padding: 12px 0 4px; }
    .overlay-img-wrap { position: absolute; box-sizing: border-box; cursor: move; user-select: none; z-index: 5; }
    .overlay-img-wrap:hover { outline: 2px dashed rgba(200,245,81,.5); }
    .overlay-img-wrap.oi-selected { outline: 2px dashed var(--accent); }
    .overlay-img-wrap img { width: 100%; height: 100%; object-fit: cover; display: block; pointer-events: none; border-radius: 3px; }
    .oi-resize-handle { position: absolute; bottom: -5px; right: -5px; width: 12px; height: 12px; background: var(--accent); border-radius: 3px; cursor: se-resize; z-index: 2; display: none; }
    .overlay-img-wrap.oi-selected .oi-resize-handle { display: block; }
    .oi-del-btn { position: absolute; top: -6px; right: -6px; width: 16px; height: 16px; background: var(--danger); border-radius: 50%; cursor: pointer; z-index: 3; display: none; align-items: center; justify-content: center; font-size: 9px; font-weight: 900; color: #fff; line-height: 1; }
    .overlay-img-wrap.oi-selected .oi-del-btn { display: flex; }
    .oi-list-item { display: flex; align-items: center; gap: 8px; padding: 7px 8px; background: var(--bg); border-radius: 6px; border: 1px solid var(--border); margin-bottom: 6px; }
    .oi-list-thumb { width: 36px; height: 36px; object-fit: cover; border-radius: 4px; flex-shrink: 0; }
    .oi-list-info { flex: 1; font-size: 11px; color: var(--muted); }
    .oi-list-del { background: none; border: none; color: var(--muted2); cursor: pointer; font-size: 16px; padding: 2px 6px; border-radius: 4px; transition: color .15s; }
    .oi-list-del:hover { color: var(--danger); }

    #slide-modal-footer {
      padding: 14px 20px;
      border-top: 1px solid var(--border);
      display: flex;
      justify-content: flex-end;
      gap: 8px;
      flex-shrink: 0;
    }
    .modal-btn { padding: 8px 22px; border-radius: 10px; font-size: 13px; font-weight: 600; font-family: 'Inter', sans-serif; cursor: pointer; transition: all .2s; border: 1px solid var(--border2); }
    #btn-modal-cancel { background: transparent; color: var(--muted); }
    #btn-modal-cancel:hover { color: #888; }
    #btn-modal-apply { background: var(--accent); border-color: var(--accent); color: #000; }
    #btn-modal-apply:hover { background: #d4f96a; }

    /* ── POST MODAL ── */
    #post-modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.7); z-index: 450; align-items: center; justify-content: center; }
    #post-modal.show { display: flex; }
    #post-modal-card {
      background: #0e0e0e; border: 1px solid var(--border2); border-radius: 16px;
      width: 480px; max-width: 96vw; max-height: 90vh;
      display: flex; flex-direction: column;
      box-shadow: 0 24px 80px rgba(0,0,0,.8);
    }
    #post-modal-header {
      padding: 16px 20px; border-bottom: 1px solid var(--border);
      display: flex; align-items: center; justify-content: space-between; flex-shrink: 0;
    }
    #post-modal-title { font-family: 'Syne', sans-serif; font-size: 15px; font-weight: 700; color: var(--text); display: flex; align-items: center; gap: 8px; }
    #post-modal-title .ig-icon { font-size: 18px; }
    #post-modal-close { background: none; border: none; color: var(--muted); font-size: 20px; cursor: pointer; transition: color .2s; line-height: 1; }
    #post-modal-close:hover { color: var(--danger); }
    #post-modal-body { flex: 1; overflow-y: auto; padding: 18px 20px; display: flex; flex-direction: column; gap: 14px; }
    #post-progress-bar {
      display: none; height: 3px; background: var(--border2); border-radius: 2px; overflow: hidden; flex-shrink: 0;
    }
    #post-progress-bar.show { display: block; }
    #post-progress-fill { height: 100%; width: 0%; background: var(--accent); transition: width .3s; border-radius: 2px; }
    #post-status-msg { font-size: 11px; color: var(--muted); min-height: 16px; }
    #post-modal-footer {
      padding: 14px 20px; border-top: 1px solid var(--border);
      display: flex; justify-content: flex-end; gap: 8px; flex-shrink: 0;
    }
    #btn-post-cancel { background: transparent; color: var(--muted); }
    #btn-post-cancel:hover { color: #888; }
    #btn-post-submit { background: linear-gradient(135deg,#f09433,#e6683c,#dc2743,#cc2366,#bc1888); border: none; color: #fff; font-weight: 700; }
    #btn-post-submit:hover { opacity: .88; }
    #btn-post-submit:disabled { background: var(--border2); color: var(--muted); cursor: not-allowed; opacity: 1; }
    .post-slide-thumbs { display: flex; gap: 6px; flex-wrap: wrap; }
    .post-thumb { width: 64px; height: 64px; border-radius: 8px; object-fit: cover; border: 1px solid var(--border2); }
    .post-slide-count { font-size: 11px; color: var(--muted); margin-top: 4px; }

    /* loading */
    #loading { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 300; align-items: center; justify-content: center; }
    #loading.show { display: flex; }
    #loading-box { background: #111; border: 1px solid var(--border2); border-radius: 14px; padding: 18px 32px; font-size: 13px; color: var(--accent); display: flex; align-items: center; gap: 12px; font-family: 'Inter', sans-serif; }
    .spinner { width: 16px; height: 16px; border: 2px solid var(--border2); border-top-color: var(--accent); border-radius: 50%; animation: spin .7s linear infinite; }
    @keyframes spin { to { transform: rotate(360deg); } }

    /* ── SLIDE EDIT BTN ── */
    .slide-edit-btn {
      position: absolute; top: 8px; right: 60px;
      width: 22px; height: 22px;
      background: rgba(0,0,0,.6); border: 1px solid rgba(255,255,255,.15);
      border-radius: 50%; display: none; align-items: center; justify-content: center;
      cursor: pointer; z-index: 30; transition: background .15s; color: #fff;
    }
    .slide-edit-btn .material-icons-round { font-size: 13px; line-height: 1; }
    .slide-edit-btn:hover { background: var(--accent); border-color: var(--accent); color: #000; }
    .slide:hover .slide-edit-btn { display: flex; }
    .slide-dup-btn {
      position: absolute; top: 8px; right: 34px;
      width: 22px; height: 22px;
      background: rgba(0,0,0,.6); border: 1px solid rgba(255,255,255,.15);
      border-radius: 50%; display: none; align-items: center; justify-content: center;
      cursor: pointer; z-index: 30; transition: background .15s; color: #fff;
    }
    .slide-dup-btn .material-icons-round { font-size: 13px; line-height: 1; }
    .slide-dup-btn:hover { background: rgba(200,245,81,.2); border-color: var(--accent); color: var(--accent); }
    .slide:hover .slide-dup-btn { display: flex; }

    /* Constrain AI-generated wrapper to slide bounds — the AI always puts everything
       inside one root div; this prevents it from overflowing or using position:fixed */
    .slide-html-layer > div:first-of-type {
      max-width: 360px !important;
      max-height: 450px !important;
      overflow: hidden !important;
    }

    /* ensure AI-generated css can't block element interaction */
    [data-el-id] { pointer-events: all !important; }

    /* ── ELEMENT TOOLBAR ── */
    #el-toolbar {
      position: fixed; z-index: 500; display: none; gap: 3px;
      transform: translateX(-50%);
      background: #161616; border: 1px solid var(--border2); border-radius: 10px;
      padding: 4px 5px; box-shadow: 0 4px 20px rgba(0,0,0,.8); align-items: center;
    }
    #el-toolbar.show { display: flex; }
    .el-tool-btn {
      padding: 3px 9px; border-radius: 7px; border: none;
      background: transparent; color: var(--muted); font-size: 10px; font-weight: 600;
      cursor: pointer; white-space: nowrap; font-family: 'Inter', sans-serif;
      transition: all .15s; line-height: 1.6;
    }
    .el-tool-btn:hover { background: rgba(200,245,81,.1); color: var(--accent); }
    .el-tool-btn.danger:hover { background: rgba(255,68,68,.1); color: var(--danger); }
    #el-toolbar-sep { width: 1px; height: 16px; background: var(--border2); flex-shrink: 0; }

    /* ── DRAGGABLE ELEMENTS ── */
    [data-el-id] {
      outline: 1.5px dashed transparent; outline-offset: 3px;
      transition: outline-color .12s; cursor: grab;
    }
    [data-el-id]:hover { outline-color: rgba(200,245,81,.3); }
    [data-el-id].el-sel { outline-color: rgba(200,245,81,.85); cursor: grab; }
    [data-el-id].el-edit { outline-color: rgba(96,165,250,.85); cursor: text; }
    [data-el-id].el-drag { cursor: grabbing !important; outline-color: rgba(200,245,81,.5); }

    /* slide nav (mobile) */
    #slide-nav-bar { display: flex; align-items: center; gap: 3px; flex-shrink: 0; }
    .slide-nav-btn { width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--border2); background: transparent; color: var(--muted); font-size: 16px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all .15s; flex-shrink: 0; padding: 0; line-height: 1; -webkit-tap-highlight-color: transparent; }
    .slide-nav-btn:active { background: var(--accent); color: #000; border-color: var(--accent); }
    .slide-nav-btn:disabled { opacity: .25; }
    #slide-nav-pos { font-size: 11px; color: var(--muted); min-width: 30px; text-align: center; font-family: monospace; }

    /* ── MOBILE ── */
    @media (max-width: 767px) {
      html { height: 100%; }
      body { height: 100%; min-height: -webkit-fill-available; overflow: hidden; }
      #navbar { padding: 0; flex-wrap: wrap; height: auto; min-height: 48px; }
      #nav-brand { padding: 0 12px; height: 48px; }
      #nav-brand span { display: none; }
      #render-timer { display: none; }
      #mobile-tabs { display: flex; align-items: center; gap: 2px; background: var(--bg); border: 1px solid var(--border2); border-radius: 20px; padding: 3px; height: 48px; }
      .mob-tab { padding: 5px 16px; border-radius: 16px; border: none; background: transparent; color: var(--muted); font-size: 13px; font-weight: 600; font-family: 'Inter', sans-serif; cursor: pointer; transition: all .2s; white-space: nowrap; -webkit-tap-highlight-color: transparent; }
      .mob-tab.active { background: var(--accent); color: #000; }
      /* Nav-right shown as a scrollable second row */
      #nav-right {
        display: flex;
        width: 100%;
        border-top: 1px solid var(--border);
        overflow-x: auto;
        overflow-y: hidden;
        padding: 5px 10px;
        gap: 5px;
        scrollbar-width: none;
        flex-shrink: 0;
        align-items: center;
      }
      #nav-right::-webkit-scrollbar { display: none; }
      #nav-right .nav-btn { padding: 5px 10px; font-size: 11px; flex-shrink: 0; white-space: nowrap; }
      #main { position: relative; overflow: hidden; display: block; height: calc(100vh - 94px); height: calc(100dvh - 94px); }
      /* Works drawer: fixed bottom sheet on mobile */
      #works-drawer {
        display: none;
        position: fixed;
        inset: 0;
        z-index: 600;
        width: 100% !important;
        min-width: 0 !important;
        border: none !important;
        background: rgba(0,0,0,0.6);
        align-items: flex-end;
        justify-content: stretch;
        flex-direction: column;
        transition: none;
      }
      #works-drawer.open { display: flex !important; }
      #works-drawer #works-drawer-inner {
        width: 100% !important;
        height: 72vh;
        border-radius: 18px 18px 0 0;
        border-top: 1px solid var(--border2);
        background: var(--surface);
      }
      #chat-panel, #preview-panel { position: absolute; inset: 0; width: 100%; height: 100%; min-width: 0; border-right: none; transition: transform .32s cubic-bezier(.4,0,.2,1); will-change: transform; display: flex; flex-direction: column; }
      #chat-panel { transform: translateX(0); }
      #preview-panel { transform: translateX(100%); }
      #main.show-slides #chat-panel { transform: translateX(-100%); }
      #main.show-slides #preview-panel { transform: translateX(0); }
      #chat-header { flex-shrink: 0; }
      #chat { flex: 1; min-height: 0; }
      #input-area { flex-shrink: 0; padding-bottom: max(10px, env(safe-area-inset-bottom, 10px)); }
      #slides-container { flex: 1; flex-direction: row; flex-wrap: nowrap; align-items: center; gap: 0; padding: 0; overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
      #slides-container::-webkit-scrollbar { display: none; }
      .slide-wrap { flex-shrink: 0; width: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; scroll-snap-align: center; padding: 12px 0; }
      .slide { width: min(288px, calc(100vw - 40px)); aspect-ratio: 4/5; height: auto; }
      #preview-header { padding: 6px 8px; gap: 6px; }
      #preview-title { display: none; }
      #work-label { display: none; }
      #preview-actions { overflow-x: auto; overflow-y: hidden; scrollbar-width: none; flex-wrap: nowrap; flex-shrink: 1; min-width: 0; gap: 3px; }
      #preview-actions::-webkit-scrollbar { display: none; }
      #preview-actions .btn { padding: 5px 8px; font-size: 10px; flex-shrink: 0; white-space: nowrap; }
      #slide-modal { align-items: flex-end; padding: 0; }
      #slide-modal-card { width: 100vw; max-width: 100vw; max-height: 92vh; height: 92vh; border-radius: 18px 18px 0 0; }
    }
  </style>
</head>
<body>

<% if (flash && flash.success && flash.success.length) { %>
<div id="flash-ok" style="position:fixed;top:12px;left:50%;transform:translateX(-50%);z-index:9999;background:#1a2e00;border:1px solid var(--accent,#c8f551);color:var(--accent,#c8f551);padding:10px 24px;border-radius:10px;font-size:13px;font-family:Inter,sans-serif;box-shadow:0 4px 24px rgba(0,0,0,.6);">
  <%= flash.success[0] %>
</div>
<script>setTimeout(()=>document.getElementById('flash-ok')&&document.getElementById('flash-ok').remove(),4000)</script>
<% } %>
<% if (flash && flash.error && flash.error.length) { %>
<div id="flash-err" style="position:fixed;top:12px;left:50%;transform:translateX(-50%);z-index:9999;background:#2e0000;border:1px solid #ff4444;color:#ff4444;padding:10px 24px;border-radius:10px;font-size:13px;font-family:Inter,sans-serif;box-shadow:0 4px 24px rgba(0,0,0,.6);">
  <%= flash.error[0] %>
</div>
<script>setTimeout(()=>document.getElementById('flash-err')&&document.getElementById('flash-err').remove(),6000)</script>
<% } %>

<nav id="navbar">
  <div id="nav-brand">IG Studio <span id="render-timer"></span></div>

  <div id="mobile-tabs">
    <button class="mob-tab active" data-panel="chat">Chat</button>
    <button class="mob-tab" data-panel="slides">Slides</button>
  </div>

  <div id="nav-right">
    <% if (user && user.ig_username) { %>
      <span class="nav-btn" style="color:var(--accent);border-color:rgba(200,245,81,.3);">@<%= user.ig_username %></span>
      <a href="/<%= lang %>/dashboard/ig-disconnect" class="nav-btn" style="color:#ff6b6b;border-color:rgba(255,107,107,.25);" onclick="return confirm('Disconnect Instagram?')">Disconnect</a>
    <% } else { %>
      <a href="/ig/connect" class="nav-btn" style="color:#e0c87a;border-color:rgba(224,200,122,.3);">Connect Instagram</a>
    <% } %>
    <button class="nav-btn" id="btn-toggle-works">Saved <span id="works-badge">0</span></button>
    <a href="/<%= lang %>/dashboard" class="nav-btn">← Dashboard</a>
  </div>
</nav>

<div id="main">
  <div id="chat-panel">
    <div id="chat-header">Chat</div>
    <div id="chat"></div>
    <div id="input-area">
      <input type="text" id="message" placeholder="Describe your post or carousel..." autocomplete="off">
      <div id="rec-bar">
        <span class="rec-dot"></span>
        <span id="rec-timer-txt">0:00</span>
        <button id="rec-cancel">cancelar</button>
      </div>
      <button id="send"><span id="send-icon" class="material-icons-round">mic</span></button>
    </div>
  </div>

  <div id="preview-panel">
    <div id="preview-header">
      <div id="preview-left">
        <span id="preview-title">Preview</span>
        <span id="work-label"></span>
      </div>
      <div id="preview-actions">
        <div id="slide-nav-bar" style="display:none;">
          <button class="slide-nav-btn" id="btn-slide-prev" disabled>‹</button>
          <span id="slide-nav-pos">—</span>
          <button class="slide-nav-btn" id="btn-slide-next" disabled>›</button>
        </div>
        <span id="slide-count"></span>
        <button class="btn" id="btn-undo" disabled title="Ctrl+Z"><span class="material-icons-round" style="font-size:14px;line-height:1;vertical-align:middle;">undo</span></button>
        <button class="btn" id="btn-redo" disabled title="Ctrl+Y"><span class="material-icons-round" style="font-size:14px;line-height:1;vertical-align:middle;">redo</span></button>
        <button class="btn" id="btn-new" title="New project">+ New</button>
        <button class="btn" id="btn-save" disabled>Save</button>
        <button class="btn" id="btn-json">{ }</button>
        <button class="btn primary" id="btn-download">⬇ PNG</button>
        <button class="btn" id="btn-post" title="Post to Instagram" style="background:linear-gradient(135deg,#f09433,#e6683c,#dc2743,#cc2366,#bc1888);color:#fff;border:none;font-weight:600;">Post IG</button>
      </div>
    </div>
    <div id="slides-container">
      <div id="empty-state">
        <div class="icon">▣</div>
        <p>Slides appear here.<br>Describe a post or carousel in the chat.</p>
      </div>
    </div>
  </div>

  <div id="works-drawer">
    <div id="works-drawer-inner">
      <div id="works-header"><span>Saved</span><button id="btn-clear-works">Clear</button></div>
      <div id="works-list"></div>
    </div>
  </div>
</div>

<!-- Slide Edit Modal -->
<div id="slide-modal">
  <div id="slide-modal-card">
    <div id="slide-modal-header">
      <span id="slide-modal-title">Editar Slide</span>
      <button id="slide-modal-close">×</button>
    </div>
    <div id="slide-modal-tabs">
      <button class="modal-tab active" data-tab="edit">AI / Code</button>
      <button class="modal-tab" data-tab="background">Background</button>
      <button class="modal-tab" data-tab="images">Images</button>
    </div>
    <div id="slide-modal-body">

      <!-- Edit Tab -->
      <div class="modal-panel" id="panel-edit">
        <div id="slide-ai-section">
          <div class="form-label" style="margin-bottom:8px;">Ask AI to edit this slide</div>
          <div id="slide-ai-row">
            <textarea id="slide-ai-prompt" placeholder="E.g.: change background to dark blue gradient, enlarge the title, add a geometric decorative element in the corner..."></textarea>
            <button id="btn-slide-ai">Generate ↑</button>
          </div>
          <div id="slide-ai-status"></div>
        </div>
        <div class="section-divider"></div>
        <div class="form-row"  style="display: none;">
          <div class="form-group">
            <div class="form-label">HTML do slide (edição manual)</div>
            <textarea class="form-input" id="f-html-code" style="min-height:240px;font-family:monospace;font-size:11px;"></textarea>
          </div>
        </div>
      </div>

      <!-- Background Tab -->
      <div class="modal-panel hidden" id="panel-background">
        <label class="upload-btn-label">Upload image <input type="file" id="bg-upload-input" accept="image/*" style="display:none;"></label>
        <div id="img-search-bar">
          <input type="text" id="img-search-input" placeholder="coffee, mountain, abstract...">
          <button id="btn-img-search">Search</button>
        </div>
        <div id="img-loading">Searching...</div>
        <div id="img-no-results">No images found.</div>
        <div id="img-grid"></div>
        <div id="img-selected-info">✓ Image selected — click Apply</div>
        <div id="bg-img-preview-row" class="bg-img-preview" style="display:none;">
          <img id="bg-img-thumb" class="bg-img-thumb" src="" alt="">
          <div><div style="font-size:11px;color:var(--muted);margin-bottom:4px;">Active image</div><button id="btn-clear-bg-img">Remove</button></div>
        </div>
        <div class="section-divider"></div>
        <div class="form-row">
          <div class="form-group">
            <div class="form-label">Overlay</div>
            <div class="color-row"><input type="color" id="f-overlay-color" value="#000000"><input class="form-input" id="f-overlay-color-text" type="text" placeholder="#000000"></div>
          </div>
          <div class="form-group">
            <div class="form-label">Opacity &nbsp;<span class="range-val" id="overlay-val-label">0.50</span></div>
            <div class="range-row"><input type="range" id="f-overlay-opacity" min="0" max="1" step="0.05" value="0.5"></div>
          </div>
        </div>
        <div class="form-row">
          <div class="form-group">
            <div class="form-label">Position X &nbsp;<span class="range-val" id="bg-pos-x-label">50</span></div>
            <div class="range-row"><input type="range" id="f-bg-pos-x" min="0" max="100" step="1" value="50"></div>
          </div>
          <div class="form-group">
            <div class="form-label">Position Y &nbsp;<span class="range-val" id="bg-pos-y-label">50</span></div>
            <div class="range-row"><input type="range" id="f-bg-pos-y" min="0" max="100" step="1" value="50"></div>
          </div>
        </div>
        <div class="form-row">
          <div class="form-group">
            <div class="form-label">Mode</div>
            <select class="form-input" id="f-bg-size-mode">
              <option value="cover">Cover</option>
              <option value="contain">Contain</option>
              <option value="stretch">Stretch</option>
            </select>
          </div>
        </div>
      </div>

      <!-- Imagens overlay Tab -->
      <div class="modal-panel hidden" id="panel-images">
        <label class="upload-btn-label">Upload image <input type="file" id="oi-upload-input" accept="image/*" style="display:none;"></label>
        <div id="oi-search-bar">
          <input type="text" id="oi-search-input" placeholder="person, icon, texture...">
          <button id="btn-oi-search">Search</button>
        </div>
        <div id="oi-img-loading">Searching...</div>
        <div id="oi-img-no-results">None found.</div>
        <div id="oi-img-grid"></div>
        <div class="section-divider" style="margin-top:10px;"></div>
        <div class="oi-section-label">On slide</div>
        <div id="oi-list"></div>
        <div id="oi-empty">No images added.</div>
      </div>
    </div>

    <div id="slide-modal-footer">
      <button class="modal-btn" id="btn-modal-cancel">Cancel</button>
      <button class="modal-btn" id="btn-modal-apply">Apply</button>
    </div>
  </div>
</div>

<!-- Post to Instagram Modal -->
<div id="post-modal">
  <div id="post-modal-card">
    <div id="post-modal-header">
      <span id="post-modal-title"><span class="ig-icon">📸</span> Post to Instagram</span>
      <button id="post-modal-close">×</button>
    </div>
    <div id="post-modal-body">
      <div>
        <div class="form-label" style="margin-bottom:6px;">Slides to post</div>
        <div class="post-slide-thumbs" id="post-thumbs"></div>
        <div class="post-slide-count" id="post-slide-count-label"></div>
      </div>
      <div class="form-group">
        <div class="form-label">Caption</div>
        <textarea class="form-input" id="post-caption" rows="4" placeholder="Write your caption (hashtags, etc)..."></textarea>
      </div>
      <div id="post-progress-bar"><div id="post-progress-fill"></div></div>
      <div id="post-status-msg"></div>
    </div>
    <div id="post-modal-footer">
      <button class="modal-btn" id="btn-post-cancel">Cancel</button>
      <button class="modal-btn" id="btn-post-submit">Post →</button>
    </div>
  </div>
</div>

<div id="el-toolbar">
  <button class="el-tool-btn" id="btn-el-all">Apply to all</button>
  <div id="el-toolbar-sep"></div>
  <button class="el-tool-btn danger" id="btn-el-del">Delete</button>
</div>

<div id="loading"><div id="loading-box"><div class="spinner"></div> <span id="loading-text">Generating...</span></div></div>

<script>
// ── CONFIG ────────────────────────────────────────────────────────────
const DEEPSEEK_KEY  = 'sk-33643be5a8654f2ca30b429286e43cc9';
const DEEPSEEK_URL  = 'https://api.deepseek.com/chat/completions';
const PEXELS_KEY    = 'NUEcKDrE0vj5GpqZIxKjqOqWJoZ2uvYOrszTseXASIW3dbYPVcJQgIwm';
const PIXABAY_KEY   = '44566501-56eb91ca4fddf9e45b9825f9e';
const LEMONFOX_KEY  = '4K9ZhgawrV4iBnZZFPMOufwXwWtSdtM9';
const LS_KEY        = 'igstudio_works_v2';
const MAX_WORKS     = 30;
const SLIDE_W       = 360;
const SLIDE_H       = 450; // 4:5 portrait (exports to 1080×1350 at scale 3)

let currentData   = null;
let currentWorkId = null;
let undoStack     = [];
let redoStack     = [];
let isDirty       = false;
let editingIdx    = null;
let editData      = null;
let selectedImgUrl = null;
let oiDrag = null, oiResize = null, selectedOiEl = null;
let bgDragActive = false;

// ── DEEPSEEK API ──────────────────────────────────────────────────────
async function callDeepSeek(messages, maxTokens = 4000, temperature = 0.85) {
  const res = await fetch(DEEPSEEK_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + DEEPSEEK_KEY },
    body: JSON.stringify({ model: 'deepseek-chat', messages, max_tokens: maxTokens, temperature })
  });
  const d = await res.json();
  if (!d.choices || !d.choices[0]) throw new Error('DeepSeek error: ' + JSON.stringify(d));
  return d.choices[0].message.content;
}

// Captures a slide as a base64 JPEG (small, for vision API)
async function captureSlideBase64(idx) {
  var el = document.getElementById('slide-' + idx);
  if (!el) return null;
  var canvas = await html2canvas(el, { scale: 1.5, useCORS: true, allowTaint: true, backgroundColor: '#111' });
  return canvas.toDataURL('image/jpeg', 0.75).split(',')[1]; // raw base64
}

// Calls DeepSeek with vision (image + text). Falls back to text-only if model rejects image.
async function callDeepSeekVision(systemPrompt, userText, base64Jpeg, maxTokens = 3000, temperature = 0.8) {
  var userContent = base64Jpeg
    ? [
        { type: 'image_url', image_url: { url: 'data:image/jpeg;base64,' + base64Jpeg } },
        { type: 'text', text: userText }
      ]
    : userText;

  var tryModels = ['deepseek-vl2', 'deepseek-chat'];
  var lastErr = null;
  for (var m of tryModels) {
    try {
      var res = await fetch(DEEPSEEK_URL, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + DEEPSEEK_KEY },
        body: JSON.stringify({ model: m, messages: [{ role: 'system', content: systemPrompt }, { role: 'user', content: userContent }], max_tokens: maxTokens, temperature })
      });
      var d = await res.json();
      if (d.choices && d.choices[0]) return { reply: d.choices[0].message.content, model: m };
      // Model might not support vision — strip image and retry with next model
      if (base64Jpeg && (d.error || !d.choices)) { userContent = userText; lastErr = d; continue; }
      throw new Error(JSON.stringify(d));
    } catch(e) { lastErr = e; }
  }
  throw new Error('Vision call failed: ' + JSON.stringify(lastErr));
}

// ── MOBILE ────────────────────────────────────────────────────────────
function isMobile() { return window.innerWidth <= 767; }

$('#mobile-tabs').on('click', '.mob-tab', function() {
  var panel = $(this).data('panel');
  $('.mob-tab').removeClass('active'); $(this).addClass('active');
  if (panel === 'slides') { $('#main').addClass('show-slides'); updateNavBar(); setTimeout(scrollToActiveSlide, 350); }
  else { $('#main').removeClass('show-slides'); updateNavBar(); }
});

function switchToSlides() {
  if (!isMobile()) return;
  $('#main').addClass('show-slides');
  $('.mob-tab[data-panel="slides"]').addClass('active');
  $('.mob-tab[data-panel="chat"]').removeClass('active');
  updateNavBar(); setTimeout(scrollToActiveSlide, 350);
}

var activeSlideIdx = 0;
function updateNavBar() {
  if (!isMobile()) { $('#slide-nav-bar').hide(); return; }
  var total = currentData && currentData.slides ? currentData.slides.length : 0;
  if (total > 1) {
    $('#slide-nav-bar').show();
    $('#btn-slide-prev').prop('disabled', activeSlideIdx <= 0);
    $('#btn-slide-next').prop('disabled', activeSlideIdx >= total - 1);
    $('#slide-nav-pos').text((activeSlideIdx + 1) + '/' + total);
  } else { $('#slide-nav-bar').hide(); }
}
function scrollToActiveSlide(idx) {
  if (idx !== undefined) activeSlideIdx = idx;
  var $c = $('#slides-container');
  if (!$c.length) return;
  $c[0].scrollTo({ left: activeSlideIdx * $c[0].offsetWidth, behavior: 'smooth' });
  updateNavBar();
}
$(document).on('click','#btn-slide-prev', function(){ if(activeSlideIdx>0) scrollToActiveSlide(activeSlideIdx-1); });
$(document).on('click','#btn-slide-next', function(){
  var total = currentData && currentData.slides ? currentData.slides.length : 0;
  if(activeSlideIdx<total-1) scrollToActiveSlide(activeSlideIdx+1);
});
$('#slides-container').on('scroll', function(){
  if(!isMobile()) return;
  var best = Math.round(this.scrollLeft / (this.offsetWidth||1));
  if(best !== activeSlideIdx){ activeSlideIdx=best; updateNavBar(); }
});

// ── TIMER ─────────────────────────────────────────────────────────────
let timerInterval=null, timerStart=null;
function startTimer(){ timerStart=performance.now(); clearInterval(timerInterval); $('#render-timer').addClass('running'); timerInterval=setInterval(function(){ $('#render-timer').text(((performance.now()-timerStart)/1000).toFixed(1)+'s'); },100); }
function stopTimer(){ clearInterval(timerInterval); if(timerStart!==null){ $('#render-timer').text(((performance.now()-timerStart)/1000).toFixed(1)+'s').removeClass('running'); timerStart=null; } }

// ── FONT LOADER ───────────────────────────────────────────────────────
const loadedFonts = new Set();
function loadFont(name) {
  if (!name || loadedFonts.has(name)) return;
  var link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = 'https://fonts.googleapis.com/css2?family=' + encodeURIComponent(name.replace(/ /g,'+')) + ':wght@300;400;500;600;700;800;900&display=swap';
  document.head.appendChild(link);
  loadedFonts.add(name);
}

// ── SLIDE RENDERING ───────────────────────────────────────────────────
// Each slide stores its complete inner HTML (generated freely by AI)
// plus bg_image, overlay_color, overlay_opacity for easy background editing
// plus overlay_images array for drag/drop images on top

function buildBgLayer(s) {
  var ov = buildOverlayColor(s);
  var bgHtml = '';
  if (s.bg_image) {
    var bpx = (s.bg_position && s.bg_position.x !== undefined) ? s.bg_position.x : 50;
    var bpy = (s.bg_position && s.bg_position.y !== undefined) ? s.bg_position.y : 50;
    var mode = s.bg_size_mode || 'cover';
    var sizeStr = mode === 'contain' ? 'contain' : mode === 'stretch' ? '100% 100%' : 'cover';
    bgHtml = '<div class="bg-img-layer" style="position:absolute;inset:0;background:url(\''+s.bg_image+'\') '+bpx+'% '+bpy+'% / '+sizeStr+' no-repeat;background-color:#111;"></div>';
  }
  return bgHtml + '<div class="bg-overlay-layer" style="position:absolute;inset:0;background:'+ov+';pointer-events:none;"></div>';
}

function buildOverlayColor(s) {
  var col = s.overlay_color || '#000000';
  var op  = s.overlay_opacity !== undefined ? parseFloat(s.overlay_opacity) : 0;
  var r=0,g=0,b=0;
  if (col.startsWith('#') && col.length>=7){ r=parseInt(col.slice(1,3),16); g=parseInt(col.slice(3,5),16); b=parseInt(col.slice(5,7),16); }
  return 'rgba('+r+','+g+','+b+','+op+')';
}

function buildOILayer(s) {
  return (s.overlay_images || []).map(function(img){
    return '<div class="overlay-img-wrap" data-oi-id="'+img.id+'" style="left:'+img.x+'px;top:'+img.y+'px;width:'+img.w+'px;height:'+img.h+'px;">' +
      '<img src="'+img.url+'" draggable="false">' +
      '<div class="oi-resize-handle"></div>' +
      '<div class="oi-del-btn">×</div>' +
    '</div>';
  }).join('');
}

// ── SLIDE HTML SANITIZER ─────────────────────────────────────────────────────
// Prevents AI-generated CSS from escaping the 360×450 slide boundary.
function sanitizeSlideHtml(html) {
  if (!html) return html;
  // 1. Fix <style> blocks: position:fixed → absolute, vw/vh → px (360w × 450h)
  html = html.replace(/<style([^>]*)>([\s\S]*?)<\/style>/gi, function(_, attrs, css) {
    css = css
      .replace(/position\s*:\s*fixed/gi, 'position:absolute')
      .replace(/\b(\d*\.?\d+)vw\b/gi, function(_, n) { return (parseFloat(n) * 3.6).toFixed(1) + 'px'; })
      .replace(/\b(\d*\.?\d+)vh\b/gi, function(_, n) { return (parseFloat(n) * 4.5).toFixed(1) + 'px'; })
      .replace(/\b(\d*\.?\d+)vmin\b/gi, function(_, n) { return (parseFloat(n) * 3.6).toFixed(1) + 'px'; })
      .replace(/\b(\d*\.?\d+)vmax\b/gi, function(_, n) { return (parseFloat(n) * 4.5).toFixed(1) + 'px'; });
    return '<style' + attrs + '>' + css + '</style>';
  });
  // 2. Fix inline styles: position:fixed → absolute
  html = html.replace(/(<[^>]+style\s*=\s*["'])([^"']*)(["'])/gi, function(_, pre, style, close) {
    style = style.replace(/position\s*:\s*fixed/gi, 'position:absolute');
    return pre + style + close;
  });
  return html;
}

function renderSlide(s, idx, total) {
  // Extract fonts from html_content and preload
  var fontMatches = (s.html_content || '').match(/font-family:\s*['"]?([^'";,)]+)/g) || [];
  fontMatches.forEach(function(m){ var f=m.replace(/font-family:\s*['"]?/,'').trim(); if(f && !f.match(/^(serif|sans-serif|monospace|inherit|initial)/i)) loadFont(f); });

  var bgLayer  = buildBgLayer(s);
  var oiLayer  = buildOILayer(s);
  var progress = '';
  if (total && total > 1) {
    var pct = Math.round(((idx+1)/total)*100);
    var accentCol = s.accent_color || '#c8f551';
    progress = '<div style="position:absolute;bottom:0;left:0;right:0;z-index:10;pointer-events:none;">' +
      '<div style="height:2px;background:'+accentCol+';width:'+pct+'%;opacity:.8;"></div>' +
      '<div style="position:absolute;bottom:6px;right:10px;font-size:9px;color:rgba(255,255,255,.3);font-family:monospace;">'+(idx+1)+'/'+total+'</div>' +
    '</div>';
  }

  return '<div class="slide-wrap">' +
    '<div class="slide-label">'+String(idx+1).padStart(2,'0')+'</div>' +
    '<div class="slide" id="slide-'+idx+'" data-idx="'+idx+'">' +
      '<div class="slide-content">' +
        bgLayer +
        '<div class="slide-html-layer" style="position:relative;z-index:1;width:100%;height:100%;overflow:hidden;">' + sanitizeSlideHtml(s.html_content||'') + '</div>' +
        oiLayer +
        progress +
      '</div>' +
      '<div class="slide-edit-btn" data-idx="'+idx+'"><span class="material-icons-round">edit</span></div>' +
      '<div class="slide-dup-btn" data-idx="'+idx+'"><span class="material-icons-round">content_copy</span></div>' +
      '<div class="slide-del-btn" data-idx="'+idx+'">×</div>' +
      '<div class="slide-regen-btn" data-idx="'+idx+'">↻ Regen</div>' +
    '</div>' +
  '</div>';
}

// ── RENDER ALL ────────────────────────────────────────────────────────
function updateUndoRedoBtns(){ $('#btn-undo').prop('disabled',undoStack.length===0); $('#btn-redo').prop('disabled',redoStack.length===0); }

function renderAll(data, fromHistory) {
if (!fromHistory && currentData) {
    serializeAllSlides();   // ← ADICIONE ESTA LINHA AQUI
    undoStack.push(JSON.stringify(currentData));
    if (undoStack.length > 30) undoStack.shift(); // cap at 30 steps
    redoStack = [];
  }
  currentData = data; updateUndoRedoBtns();
  
  // Garante que overlay_images não sejam perdidos em renderizações
if (data && data.slides && currentData && currentData.slides) {
  data.slides.forEach((s, i) => {
    if (currentData.slides[i] && currentData.slides[i].overlay_images) {
      s.overlay_images = currentData.slides[i].overlay_images;
    }
  });
}

  var $c = $('#slides-container').empty();
  if (!data || !data.slides || !data.slides.length) {
    $c.html('<div id="empty-state"><div class="icon">▣</div><p>No slides.</p></div>');
    $('#slide-count').text(''); updateNavBar(); return;
  }
  var total = data.slides.length;
  data.slides.forEach(function(s,i){ $c.append(renderSlide(s,i,total)); if(s.bg_image) injectBgOverride(i,true); });
  setTimeout(initAllSlideInteractions, 0);
  $('#slide-count').text(total===1?'1 slide':total+' slides');
  activeSlideIdx=0; updateNavBar(); markDirty();
  if(isMobile()) setTimeout(switchToSlides, 200);
}

// ── SERVER STORAGE ─────────────────────────────────────────────────────
var worksCache = []; // in-memory index; synced with server
var _saveTimer = null;

function loadWorks() { return worksCache; }

function formatDate(iso){ var d=new Date(iso),now=new Date(),diff=(now-d)/1000; if(diff<60)return'now'; if(diff<3600)return Math.floor(diff/60)+'min'; if(diff<86400)return Math.floor(diff/3600)+'h'; return d.toLocaleDateString('en-US',{day:'2-digit',month:'short'}); }

function renderWorksList() {
  var $list=$('#works-list').empty();
  worksCache.length ? $('#works-badge').text(worksCache.length).addClass('show') : $('#works-badge').text('0').removeClass('show');
  if(!worksCache.length){ $list.html('<div style="text-align:center;padding:40px 20px;color:var(--muted2);font-size:12px;line-height:2;">No saved works.</div>'); return; }
  worksCache.forEach(function(w){
    var safe=$('<span>').text(w.label).html();
    $list.append('<div class="work-card'+(w.id===currentWorkId?' active':'')+'">'+
      '<div class="work-card-top"><div class="work-dot" style="background:'+w.bg_sample+';"></div>'+
      '<div class="work-info"><div class="work-title">'+safe+'</div><div class="work-meta">'+w.count+' slides · '+formatDate(w.created_at)+'</div></div></div>'+
      '<div class="work-actions">'+
        '<button class="work-btn btn-load-work" data-id="'+w.id+'">Load</button>'+
        '<button class="work-btn btn-copy-work" data-id="'+w.id+'">JSON</button>'+
        '<button class="work-btn danger btn-delete-work" data-id="'+w.id+'">×</button>'+
      '</div></div>');
  });
}

async function fetchWorksIndex() {
  try { worksCache = await (await fetch('/api/works')).json(); } catch(e) { worksCache = []; }
  renderWorksList();
}

async function saveCurrentWork() {
  if (!currentData) return;
  clearTimeout(_saveTimer);
  var first = (currentData.slides && currentData.slides[0]) || {};
  var meta = worksCache.find(function(w){ return w.id === currentWorkId; });
  try {
    var r = await fetch('/api/works', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        id:         currentWorkId || undefined,
        label:      first.title || 'Untitled',
        count:      (currentData.slides || []).length,
        bg_sample:  first.bg_sample || '#1a1a1a',
        created_at: meta ? meta.created_at : new Date().toISOString(),
        data:       currentData,
        chatHistory: chatHistory.slice(),
        undoStack:  undoStack.slice()
      })
    });
    var result = await r.json();
    if (result.id) {
      currentWorkId = result.id;
      // Server may have converted base64 → real URLs; use returned data
      if (result.data) currentData = result.data;
    }
    worksCache = await (await fetch('/api/works')).json();
    renderWorksList();
  } catch(e) { console.error('Auto-save failed:', e); }
  markClean();
}

function scheduleServerSave() {
  clearTimeout(_saveTimer);
  _saveTimer = setTimeout(saveCurrentWork, 2000);
}

function markDirty(){
  isDirty=true; setWorkLabel();
  if(currentData){ $('#btn-save').prop('disabled',false); scheduleServerSave(); }
}
function markClean(){ isDirty=false; clearTimeout(_saveTimer); setWorkLabel(); }
function setWorkLabel(){
  if(!currentWorkId){ $('#work-label').text(''); return; }
  var w=worksCache.find(function(x){ return x.id===currentWorkId; });
  if(w) $('#work-label').text((isDirty?'• ':'')+w.label);
}

// ── SYSTEM PROMPT ─────────────────────────────────────────────────────
var SYSTEM = `Você é um diretor de arte sênior especializado em conteúdo visual para Instagram. Cria carrosseis com design PROFISSIONAL e ORIGINAL — não templates genéricos.

FORMATO DE RESPOSTA:
Comentário criativo curto (1-2 frases) + bloco JSON.

ESTRUTURA JSON:
{
  "type": "single" | "carousel",
  "slides": [
    {
      "title": "string curto (para metadados)",
      "bg_sample": "#hexcolor (cor dominante do slide, para miniatura)",
      "accent_color": "#hex",
      "image_query": "termos em inglês para foto stock (OPCIONAL)",
      "overlay_color": "#hex",
      "overlay_opacity": 0.0-1.0,
      "html_content": "HTML COMPLETO do interior do slide"
    }
  ]
}

REGRAS PARA html_content:
• O slide tem EXATAMENTE 360×450px (formato 4:5 portrait do Instagram 2026). html_content ocupa esse espaço.
• Use position:absolute para posicionamento criativo e livre
• Pode usar qualquer CSS inline: gradientes, clip-path, pseudo-elements via style tags internos, transforms, mix-blend-mode, backdrop-filter
• Tipografia com CONTRASTE EXTREMO de tamanhos (ex: 8px ao lado de 72px)
• Elementos decorativos: linhas, formas geométricas, bordas parciais, grids, padrões SVG inline
• ZERO emojis no conteúdo visual
• Fontes Google Fonts via @import no style tag (ex: Bebas Neue, DM Sans, Playfair Display, Oswald, Space Mono, Clash Display, etc)
• Cada slide deve ter identidade visual coesa com os outros MAS com composição única

EXEMPLOS DE TÉCNICAS AVANÇADAS:
- Número enorme como elemento decorativo de fundo (opacity baixa)
- Texto rotacionado (-90deg) como elemento lateral
- Linha diagonal como divisor
- Círculo/elipse como shape decorativo
- Grid de pontos em SVG como textura de fundo
- Gradiente de texto (-webkit-background-clip: text)
- Bordas com traço duplo ou parcial
- Overlay com mix-blend-mode
- Tipografia condensed + bold em contraste com body light

IMAGENS STOCK:
• image_query: termos em inglês (Pexels/Pixabay)
• Use em: cover com foto de impacto, CTA final
• Com imagem: overlay_opacity entre 0.45-0.65
• Sem imagem: html_content define próprio background via CSS

PALETA E FONTE:
• Define UMA paleta no início, usa em todos os slides
• Mesma família tipográfica em todos
• Nunca mistura claro e escuro no mesmo carrossel

CARROSSEL: cover impactante → conteúdo → CTA poderoso. Mínimo 4 slides, máximo 8.
Se pedido EDIÇÃO: retorne JSON completo atualizado.`;

// ── CHAT ──────────────────────────────────────────────────────────────
var chatHistory = [{ role:'system', content: SYSTEM }];

function addMsg(text, cls) {
  $('<div>').addClass('msg '+cls).text(text).appendTo('#chat');
  document.getElementById('chat').scrollTop = 999999;
}

function extractJSON(t) {
  var m = t.match(/```json\s*([\s\S]*?)```/);
  if (m) { try{ return JSON.parse(m[1]); }catch(e){} }
  // Try raw JSON
  var start = t.indexOf('{');
  if (start >= 0) { try{ return JSON.parse(t.slice(start)); }catch(e){} }
  return null;
}
function cleanChat(t) { return t.replace(/```json[\s\S]*?(?:```|$)/g,'').replace(/```[\s\S]*?(?:```|$)/g,'').trim(); }

async function fetchStockImage(query) {
  var res = await fetch('https://api.pexels.com/v1/search?query='+encodeURIComponent(query)+'&per_page=5&orientation=square', { headers:{ Authorization: PEXELS_KEY } });
  var d = await res.json();
  if (!d.photos || !d.photos.length) throw new Error('no photos');
  var pick = d.photos[Math.floor(Math.random() * Math.min(d.photos.length, 3))];
  return pick.src.large2x;
}

async function send(userMsg) {
  addMsg(userMsg, 'user');
  chatHistory.push({ role:'user', content: userMsg });

  var contextContent = userMsg;
  if (currentData) {
    var slim = { type: currentData.type, slides: (currentData.slides||[]).map(function(s){
      return { title: s.title, bg_sample: s.bg_sample, accent_color: s.accent_color, html_content: s.html_content ? s.html_content.slice(0,300)+'...' : '' };
    })};
    contextContent = 'Estado atual (resumido):\n```json\n'+JSON.stringify(slim)+'\n```\n\nPedido: '+userMsg;
  }

  var apiMsgs = chatHistory.slice(0,-1).concat([{role:'user', content: contextContent}]);

  $('#send').prop('disabled',true); $('#loading').addClass('show'); setLoadingText('Generating...');
  startTimer();
  try {
    var reply = await callDeepSeek(apiMsgs, 6000, 0.85);
    chatHistory.push({ role:'assistant', content: reply });
    // Keep only system prompt + last 20 messages to avoid unbounded memory growth
    if (chatHistory.length > 21) chatHistory = [chatHistory[0]].concat(chatHistory.slice(-20));
    var txt = cleanChat(reply); if(txt) addMsg(txt,'ai');
    var json = extractJSON(reply);

    if (!json) {
      setLoadingText('Fetching JSON...');
      var reply2 = await callDeepSeek(apiMsgs.concat([{role:'assistant',content:reply},{role:'user',content:'Return ONLY the JSON block now, no other text.'}]), 3500, 0.3);
      chatHistory.push({role:'user',content:'Return ONLY the JSON.'});
      chatHistory.push({role:'assistant',content:reply2});
      json = extractJSON(reply2);
    }

    if (json) {
      undoStack=[]; redoStack=[];
      // Preserve overlay_images from existing slides
      (json.slides||[]).forEach(function(s,i){
        var orig = currentData && currentData.slides[i];
        if (orig && orig.overlay_images) s.overlay_images = orig.overlay_images;
        if (s.bg_image === '(imagem ativa)' && orig) s.bg_image = orig.bg_image || null;
      });
      // Fetch stock images
      var imgSlides = (json.slides||[]).filter(function(s){ return s.image_query; });
      if (imgSlides.length) {
        setLoadingText('Fetching '+(imgSlides.length===1?'1 photo':imgSlides.length+' photos')+'...');
        await Promise.allSettled(imgSlides.map(async function(s){
          try {
            s.bg_image = await fetchStockImage(s.image_query);
            if (!s.overlay_color) s.overlay_color = '#000000';
            if (s.overlay_opacity === undefined) s.overlay_opacity = 0.55;
          } catch(e) {}
          delete s.image_query;
        }));
      }
      renderAll(json, true);
    }
  } catch(e) {
    addMsg('Connection error. Please try again.', 'ai');
    console.error(e);
  } finally {
    stopTimer(); $('#send').prop('disabled',false); $('#loading').removeClass('show');
  }
}

function setLoadingText(t) { $('#loading-text').text(t); }

// ── SLIDE EVENTS ──────────────────────────────────────────────────────
$(document).on('click', '.slide-del-btn', function(e){
  e.stopPropagation();
  if(!currentData) return;
  serializeAllSlides();   // ← ADICIONE AQUI
  var idx = parseInt($(this).data('idx'));
  if(currentData.slides.length <= 1) return;
  var nd = JSON.parse(JSON.stringify(currentData));
  nd.slides.splice(idx, 1);
  renderAll(nd);
});

$(document).on('click', '.slide-dup-btn', function(e){
  e.stopPropagation();
  if(!currentData) return;
  serializeAllSlides();   // ← ADICIONE AQUI
  var idx = parseInt($(this).data('idx'));
  var nd = JSON.parse(JSON.stringify(currentData));
  nd.slides.splice(idx+1, 0, JSON.parse(JSON.stringify(nd.slides[idx])));
  renderAll(nd);
});

$(document).on('click', '.slide-regen-btn', async function(e){
  e.stopPropagation();
  if(!currentData) return;
  var idx=parseInt($(this).data('idx'));
  var s=currentData.slides[idx];
  $(this).text('...').prop('disabled',true);
  try {
    var prompt='Regenere visualmente este slide (idx '+idx+') com um design diferente e mais impactante. Mantenha o conteúdo/mensagem. Retorne SOMENTE o JSON do slide.\n\nSlide atual:\n'+JSON.stringify({title:s.title,html_content:(s.html_content||'').slice(0,400)},null,2);
    var reply = await callDeepSeek([{role:'system',content:SYSTEM},{role:'user',content:prompt}],3000,0.9);
    var json=extractJSON(reply);
    if(json){
      var nd=JSON.parse(JSON.stringify(currentData));
      nd.slides[idx]=Object.assign({},nd.slides[idx],json);
      if(json.image_query){
        try{ nd.slides[idx].bg_image=await fetchStockImage(json.image_query); }catch(e){}
        delete nd.slides[idx].image_query;
      }
      renderAll(nd);
    }
  } catch(e){}
  $(this).text('↻ Regen').prop('disabled',false);
});

$(document).on('click', '.slide-edit-btn', function(e){
  e.stopPropagation();
  if(!currentData) return;
  openSlideEdit(parseInt($(this).data('idx')));
});

// ── SLIDE MODAL ───────────────────────────────────────────────────────
function openSlideEdit(idx) {
  editingIdx = idx;
  editData   = JSON.parse(JSON.stringify(currentData.slides[idx]));
  if (!editData.overlay_images) editData.overlay_images = [];
  selectedImgUrl = editData.bg_image || null;
  // Populate HTML editor
  $('#f-html-code').val(editData.html_content || '');
  $('#slide-ai-prompt').val(''); $('#slide-ai-status').text('');
  // Background tab
  $('#f-overlay-color').val(editData.overlay_color||'#000000');
  $('#f-overlay-color-text').val(editData.overlay_color||'#000000');
  var op=editData.overlay_opacity!==undefined?editData.overlay_opacity:0;
  $('#f-overlay-opacity').val(op); $('#overlay-val-label').text(parseFloat(op).toFixed(2));
  var bpx=(editData.bg_position&&editData.bg_position.x!==undefined)?editData.bg_position.x:50;
  var bpy=(editData.bg_position&&editData.bg_position.y!==undefined)?editData.bg_position.y:50;
  $('#f-bg-pos-x').val(bpx); $('#bg-pos-x-label').text(bpx);
  $('#f-bg-pos-y').val(bpy); $('#bg-pos-y-label').text(bpy);
  $('#f-bg-size-mode').val(editData.bg_size_mode||'cover');
  updateBgImgPreview();
  // Images tab
  $('#img-grid').empty(); $('#img-no-results,#img-loading').hide(); $('#img-selected-info').removeClass('show');
  $('#img-search-input').val(editData.title||'');
  if(selectedImgUrl) $('#img-selected-info').addClass('show');
  renderOIList();
  switchModalTab('edit');
  $('#slide-modal-title').text('Slide '+(idx+1));
  $('#slide-modal').addClass('show');
}

function updateBgImgPreview(){
  if(editData&&editData.bg_image){ $('#bg-img-thumb').attr('src',editData.bg_image); $('#bg-img-preview-row').show(); }
  else{ $('#bg-img-preview-row').hide(); }
}

function switchModalTab(tab){
  $('.modal-tab').removeClass('active'); $('.modal-tab[data-tab="'+tab+'"]').addClass('active');
  $('.modal-panel').addClass('hidden'); $('#panel-'+tab).removeClass('hidden');
  if(tab==='background'&&!$('#img-grid').children().length){
    var q=$('#img-search-input').val().trim()||$('#f-html-code').val().slice(0,30);
    if(q) searchImages(q.substring(0,40));
  }
}

$('.modal-tab').on('click',function(){ switchModalTab($(this).data('tab')); });

$('#f-overlay-color').on('input',function(){ $('#f-overlay-color-text').val($(this).val()); liveUpdateBgPreview(); });
$('#f-overlay-color-text').on('input',function(){ var v=$(this).val(); if(/^#[0-9a-f]{6}$/i.test(v)){ $('#f-overlay-color').val(v); liveUpdateBgPreview(); } });
$('#f-overlay-opacity').on('input',function(){ $('#overlay-val-label').text(parseFloat($(this).val()).toFixed(2)); liveUpdateBgPreview(); });
$('#f-bg-pos-x').on('input',function(){ var v=parseInt($(this).val()); $('#bg-pos-x-label').text(v); if(!editData.bg_position) editData.bg_position={x:50,y:50}; editData.bg_position.x=v; liveUpdateBgPreview(); });
$('#f-bg-pos-y').on('input',function(){ var v=parseInt($(this).val()); $('#bg-pos-y-label').text(v); if(!editData.bg_position) editData.bg_position={x:50,y:50}; editData.bg_position.y=v; liveUpdateBgPreview(); });
$('#f-bg-size-mode').on('change',liveUpdateBgPreview);
$('#btn-clear-bg-img').on('click',function(){ editData.bg_image=null; selectedImgUrl=null; updateBgImgPreview(); injectBgOverride(editingIdx,false); });

function liveUpdateBgPreview(){
  if(editingIdx===null||!editData) return;
  if(!editData.bg_image) {
    // still update overlay even without bg image
    var col2=$('#f-overlay-color-text').val()||$('#f-overlay-color').val()||'#000000';
    var op2=parseFloat($('#f-overlay-opacity').val())||0;
    var r2=0,g2=0,b2=0;
    if(col2.startsWith('#')&&col2.length>=7){r2=parseInt(col2.slice(1,3),16);g2=parseInt(col2.slice(3,5),16);b2=parseInt(col2.slice(5,7),16);}
    $('#slide-'+editingIdx+' .bg-overlay-layer').css('background','rgba('+r2+','+g2+','+b2+','+op2+')');
    return;
  }
  var mode=$('#f-bg-size-mode').val();
  var posX=parseInt($('#f-bg-pos-x').val())||50;
  var posY=parseInt($('#f-bg-pos-y').val())||50;
  var sizeStr=mode==='contain'?'contain':mode==='stretch'?'100% 100%':'cover';
  var $layer=$('#slide-'+editingIdx+' .bg-img-layer');
  if($layer.length) $layer.css({'background-size':sizeStr,'background-position':posX+'% '+posY+'%'});
  // live-update overlay color + opacity
  var col=$('#f-overlay-color-text').val()||$('#f-overlay-color').val()||'#000000';
  var op=parseFloat($('#f-overlay-opacity').val())||0;
  var r=0,g=0,b=0;
  if(col.startsWith('#')&&col.length>=7){r=parseInt(col.slice(1,3),16);g=parseInt(col.slice(3,5),16);b=parseInt(col.slice(5,7),16);}
  $('#slide-'+editingIdx+' .bg-overlay-layer').css('background','rgba('+r+','+g+','+b+','+op+')');
}

$('#btn-modal-apply').on('click',function(){
  editData.html_content = $('#f-html-code').val();
  editData.overlay_color  = $('#f-overlay-color-text').val()||$('#f-overlay-color').val();
  editData.overlay_opacity = parseFloat($('#f-overlay-opacity').val());
  editData.bg_position    = { x:parseInt($('#f-bg-pos-x').val()), y:parseInt($('#f-bg-pos-y').val()) };
  editData.bg_size_mode   = $('#f-bg-size-mode').val();
  if(selectedImgUrl) editData.bg_image=selectedImgUrl;
  var nd=JSON.parse(JSON.stringify(currentData));
  nd.slides[editingIdx]=editData;
  renderAll(nd); closeModal();
});

function closeModal(){ $('#slide-modal').removeClass('show'); editingIdx=null; editData=null; selectedImgUrl=null; }
$('#btn-modal-cancel, #slide-modal-close').on('click',closeModal);
$('#slide-modal').on('click',function(e){ if($(e.target).is('#slide-modal')) closeModal(); });

// ── SLIDE AI EDIT (deepseek-reasoner) ────────────────────────────────
async function callSlideReasoner(sysPrompt, userText) {
  var res = await fetch(DEEPSEEK_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + DEEPSEEK_KEY },
    body: JSON.stringify({
      model: 'deepseek-reasoner',
      messages: [
        { role: 'system', content: sysPrompt },
        { role: 'user',   content: userText }
      ],
      max_tokens: 8000
    })
  });
  var d = await res.json();
  if (!d.choices || !d.choices[0]) throw new Error('Reasoner error: ' + JSON.stringify(d));
  return d.choices[0].message.content; // reasoning_content is separate; content has the answer
}

$('#btn-slide-ai').on('click', async function(){
  var prompt = $('#slide-ai-prompt').val().trim(); if (!prompt) return;
  $(this).prop('disabled', true).text('...');
  var $status = $('#slide-ai-status');

  try {
    $status.text('Thinking… (R1 reasoner, may take ~30s)');

    var sysPrompt =
      'You are an expert HTML/CSS slide designer for Instagram (360×450px portrait slides, 4:5 ratio).\n' +
      'The user will give you the current slide HTML and an edit instruction.\n' +
      'Apply the instruction carefully and return ONLY valid JSON — no markdown, no extra text:\n' +
      '{"html_content":"<full updated slide HTML>","bg_sample":"#hex","accent_color":"#hex"}\n\n' +
      'Rules for html_content:\n' +
      '• Slide is exactly 360×450px (4:5 portrait). Use position:absolute freely.\n' +
      '• Keep the same overall layout/identity unless told otherwise.\n' +
      '• Preserve all text content unless the instruction says to change it.\n' +
      '• Use Google Fonts via @import inside a <style> tag if needed.\n' +
      '• No position:fixed, no vw/vh units, no emojis in the visual content.\n' +
      '• bg_sample = dominant background color of the slide.';

    var userText =
      'Current slide HTML:\n```html\n' + (editData.html_content || '(empty)') + '\n```\n\n' +
      'Edit instruction: ' + prompt;

    var reply = await callSlideReasoner(sysPrompt, userText);
    var json = extractJSON(reply);

    if (json) {
      if (json.html_content) { editData.html_content = json.html_content; $('#f-html-code').val(json.html_content); }
      if (json.bg_sample)    editData.bg_sample    = json.bg_sample;
      if (json.accent_color) editData.accent_color = json.accent_color;
      $status.text('✓ Done (R1) — click Apply to confirm.');
      $('#slide-ai-prompt').val('');
    } else {
      $status.text('Parse error. Please try again.');
      console.error('Reasoner raw reply:', reply);
    }
  } catch(e) {
    $status.text('Error: ' + (e.message || 'please try again.'));
    console.error(e);
  } finally {
    $(this).prop('disabled', false).text('Generate ↑');
  }
});
$('#slide-ai-prompt').on('keydown',function(e){ if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();$('#btn-slide-ai').click();} });

// ── IMAGE SEARCH ──────────────────────────────────────────────────────
$('#btn-img-search').on('click',function(){ var q=$('#img-search-input').val().trim(); if(q) searchImages(q); });
$('#img-search-input').on('keypress',function(e){ if(e.which===13){var q=$(this).val().trim();if(q)searchImages(q);} });

async function searchImages(query){
  $('#img-grid').empty(); $('#img-no-results').hide(); $('#img-loading').show();
  try{
    var results=await Promise.allSettled([
      fetch('https://api.pexels.com/v1/search?query='+encodeURIComponent(query)+'&per_page=14&orientation=square',{headers:{Authorization:PEXELS_KEY}}).then(r=>r.json()),
      fetch('https://pixabay.com/api/?key='+PIXABAY_KEY+'&q='+encodeURIComponent(query)+'&per_page=14&image_type=photo&safesearch=true').then(r=>r.json())
    ]);
    var pex=results[0].status==='fulfilled'?(results[0].value.photos||[]).map(p=>({thumb:p.src.medium,full:p.src.large2x})):[];
    var pix=results[1].status==='fulfilled'?(results[1].value.hits||[]).map(p=>({thumb:p.webformatURL,full:p.largeImageURL})):[];
    var photos=[],max=Math.max(pex.length,pix.length);
    for(var i=0;i<max;i++){if(i<pex.length)photos.push(pex[i]);if(i<pix.length)photos.push(pix[i]);}
    $('#img-loading').hide();
    if(!photos.length){$('#img-no-results').show();return;}
    photos.forEach(function(p){
      var $img=$('<img class="img-thumb'+(selectedImgUrl===p.full?' selected':'')+'" src="'+p.thumb+'" data-full="'+p.full+'" loading="lazy">');
      $img.on('click',function(){
        $('.img-thumb').removeClass('selected');$(this).addClass('selected');
        selectedImgUrl=$(this).data('full'); editData.bg_image=selectedImgUrl;
        updateBgImgPreview(); $('#img-selected-info').addClass('show');
        injectBgOverride(editingIdx,true);
      });
      $('#img-grid').append($img);
    });
  }catch(e){$('#img-loading').hide();$('#img-no-results').text('Search error.').show();}
}

$('#bg-upload-input').on('change',function(){
  var file=this.files[0];if(!file)return;
  var reader=new FileReader();
  reader.onload=function(e){selectedImgUrl=e.target.result;editData.bg_image=e.target.result;updateBgImgPreview();$('#img-selected-info').addClass('show');injectBgOverride(editingIdx,true);};
  reader.readAsDataURL(file); this.value='';
});

// ── OVERLAY IMAGES ────────────────────────────────────────────────────
function renderOIList(){
  var $list=$('#oi-list').empty();
  var imgs=editData?(editData.overlay_images||[]):[];
  if(!imgs.length){$('#oi-empty').show();return;}
  $('#oi-empty').hide();
  imgs.forEach(function(img,i){
    $list.append('<div class="oi-list-item"><img class="oi-list-thumb" src="'+img.url+'"><div class="oi-list-info">'+img.w+'×'+img.h+'px</div><button class="oi-list-del" data-oi-idx="'+i+'">×</button></div>');
  });
}
$(document).on('click','#oi-list .oi-list-del',function(){
  var idx=parseInt($(this).data('oi-idx'));
  if(editData&&editData.overlay_images){editData.overlay_images.splice(idx,1);renderOIList();}
});
function addOverlayImage(url){
  if(!editData)return;
  if(!editData.overlay_images)editData.overlay_images=[];
  editData.overlay_images.push({id:Date.now(),url:url,x:60,y:60,w:140,h:140});
  renderOIList();
}
$('#oi-upload-input').on('change',function(){
  var file=this.files[0];if(!file)return;
  var reader=new FileReader();reader.onload=function(e){addOverlayImage(e.target.result);};
  reader.readAsDataURL(file);this.value='';
});
$('#btn-oi-search').on('click',function(){var q=$('#oi-search-input').val().trim();if(q)searchOverlayImages(q);});
$('#oi-search-input').on('keypress',function(e){if(e.which===13){var q=$(this).val().trim();if(q)searchOverlayImages(q);}});

async function searchOverlayImages(query){
  $('#oi-img-grid').empty();$('#oi-img-no-results').hide();$('#oi-img-loading').show();
  try{
    var results=await Promise.allSettled([
      fetch('https://api.pexels.com/v1/search?query='+encodeURIComponent(query)+'&per_page=12&orientation=square',{headers:{Authorization:PEXELS_KEY}}).then(r=>r.json()),
      fetch('https://pixabay.com/api/?key='+PIXABAY_KEY+'&q='+encodeURIComponent(query)+'&per_page=12&image_type=photo&safesearch=true').then(r=>r.json())
    ]);
    var pex=results[0].status==='fulfilled'?(results[0].value.photos||[]).map(p=>({thumb:p.src.medium,full:p.src.large2x})):[];
    var pix=results[1].status==='fulfilled'?(results[1].value.hits||[]).map(p=>({thumb:p.webformatURL,full:p.largeImageURL})):[];
    var photos=[],max=Math.max(pex.length,pix.length);
    for(var i=0;i<max;i++){if(i<pex.length)photos.push(pex[i]);if(i<pix.length)photos.push(pix[i]);}
    $('#oi-img-loading').hide();
    if(!photos.length){$('#oi-img-no-results').show();return;}
    photos.forEach(function(p){
      var $img=$('<img class="img-thumb" src="'+p.thumb+'" data-full="'+p.full+'" loading="lazy" title="Click to add">');
      $img.on('click',function(){addOverlayImage($(this).data('full'));});
      $('#oi-img-grid').append($img);
    });
  }catch(e){$('#oi-img-loading').hide();$('#oi-img-no-results').text('Search error.').show();}
}

// Overlay img drag/resize
$(document).on('mousedown touchstart','.overlay-img-wrap',function(e){
  if($(e.target).hasClass('oi-resize-handle')||$(e.target).hasClass('oi-del-btn'))return;
  e.stopPropagation();e.preventDefault();
  var $wrap=$(this),slideIdx=parseInt($wrap.closest('.slide').data('idx')),imgId=parseInt($wrap.data('oi-id'));
  if(!currentData)return;
  var sl=currentData.slides[slideIdx],im=(sl.overlay_images||[]).find(i=>i.id===imgId);
  if(!im)return;
  var touch=e.originalEvent.touches?e.originalEvent.touches[0]:e.originalEvent;
  if(selectedOiEl&&selectedOiEl!==this)$(selectedOiEl).removeClass('oi-selected');
  selectedOiEl=this;$(this).addClass('oi-selected');
  oiDrag={el:this,slideIdx,imgId,startX:touch.clientX,startY:touch.clientY,origX:im.x,origY:im.y};
});
$(document).on('mousedown touchstart','.oi-resize-handle',function(e){
  e.stopPropagation();e.preventDefault();
  var $wrap=$(this).closest('.overlay-img-wrap'),slideIdx=parseInt($wrap.closest('.slide').data('idx')),imgId=parseInt($wrap.data('oi-id'));
  if(!currentData)return;
  var sl=currentData.slides[slideIdx],im=(sl.overlay_images||[]).find(i=>i.id===imgId);
  if(!im)return;
  var touch=e.originalEvent.touches?e.originalEvent.touches[0]:e.originalEvent;
  oiResize={el:$wrap[0],slideIdx,imgId,startX:touch.clientX,startY:touch.clientY,origW:im.w,origH:im.h};
});
$(document).on('click','.oi-del-btn',function(e){
  e.stopPropagation();
  var $wrap=$(this).closest('.overlay-img-wrap'),slideIdx=parseInt($wrap.closest('.slide').data('idx')),imgId=parseInt($wrap.data('oi-id'));
  if(!currentData)return;
  var sl=currentData.slides[slideIdx];
  sl.overlay_images=(sl.overlay_images||[]).filter(i=>i.id!==imgId);
  $wrap.remove();if(selectedOiEl===$wrap[0])selectedOiEl=null;markDirty();
});

document.addEventListener('mousemove',function(e){
  if(!oiDrag&&!oiResize)return;e.preventDefault();
  var cx=e.clientX,cy=e.clientY;
  if(oiDrag){$(oiDrag.el).css({left:(oiDrag.origX+cx-oiDrag.startX)+'px',top:(oiDrag.origY+cy-oiDrag.startY)+'px'});oiDrag._cx=oiDrag.origX+cx-oiDrag.startX;oiDrag._cy=oiDrag.origY+cy-oiDrag.startY;}
  if(oiResize){var nw=Math.max(40,oiResize.origW+cx-oiResize.startX),nh=Math.max(40,oiResize.origH+cy-oiResize.startY);$(oiResize.el).css({width:nw+'px',height:nh+'px'});oiResize._w=nw;oiResize._h=nh;}
});
document.addEventListener('touchmove',function(e){
  if(!oiDrag&&!oiResize)return;e.preventDefault();
  var cx=e.touches[0].clientX,cy=e.touches[0].clientY;
  if(oiDrag){$(oiDrag.el).css({left:(oiDrag.origX+cx-oiDrag.startX)+'px',top:(oiDrag.origY+cy-oiDrag.startY)+'px'});oiDrag._cx=oiDrag.origX+cx-oiDrag.startX;oiDrag._cy=oiDrag.origY+cy-oiDrag.startY;}
  if(oiResize){var nw=Math.max(40,oiResize.origW+cx-oiResize.startX),nh=Math.max(40,oiResize.origH+cy-oiResize.startY);$(oiResize.el).css({width:nw+'px',height:nh+'px'});oiResize._w=nw;oiResize._h=nh;}
},{passive:false});
document.addEventListener('mouseup',oiDragEnd);
document.addEventListener('touchend',oiDragEnd);
function oiDragEnd() {
  if (oiDrag && oiDrag._cx !== undefined && currentData) {
    var sl = currentData.slides[oiDrag.slideIdx];
    var im = (sl.overlay_images || []).find(i => i.id === oiDrag.imgId);
    if (im) {
      im.x = Math.round(oiDrag._cx);
      im.y = Math.round(oiDrag._cy);
    }
  }
  if (oiResize && oiResize._w !== undefined && currentData) {
    var sl = currentData.slides[oiResize.slideIdx];
    var im = (sl.overlay_images || []).find(i => i.id === oiResize.imgId);
    if (im) {
      im.w = Math.round(oiResize._w);
      im.h = Math.round(oiResize._h);
    }
  }
  oiDrag = null;
  oiResize = null;

  // Força serialização completa após qualquer mudança em overlay
  if (currentData) {
    serializeAllSlides();
    markDirty();
  }
}
$(document).on('click',function(e){
  if(!$(e.target).closest('.overlay-img-wrap').length&&selectedOiEl){$(selectedOiEl).removeClass('oi-selected');selectedOiEl=null;}
});

// ── UNDO / REDO ───────────────────────────────────────────────────────
function applyHistory(data){
  currentData=data;updateUndoRedoBtns();
  var $c=$('#slides-container').empty();
  data.slides.forEach(function(s,i){$c.append(renderSlide(s,i,data.slides.length)); if(s.bg_image) injectBgOverride(i,true); });
  setTimeout(initAllSlideInteractions, 0);
  $('#slide-count').text(data.slides.length===1?'1 slide':data.slides.length+' slides');
  activeSlideIdx=0;updateNavBar();markDirty();
}
$('#btn-undo').on('click',function(){if(!undoStack.length)return;serializeAllSlides();redoStack.push(JSON.stringify(currentData));applyHistory(JSON.parse(undoStack.pop()));});
$('#btn-redo').on('click',function(){if(!redoStack.length)return;serializeAllSlides();undoStack.push(JSON.stringify(currentData));applyHistory(JSON.parse(redoStack.pop()));});
$(document).on('keydown',function(e){
  if($(e.target).is('input,textarea,select'))return;
  if((e.ctrlKey||e.metaKey)&&!e.shiftKey&&e.key==='z'){e.preventDefault();$('#btn-undo').click();}
  if((e.ctrlKey||e.metaKey)&&(e.key==='y'||(e.shiftKey&&e.key==='z'))){e.preventDefault();$('#btn-redo').click();}
});

// ── WORKS ─────────────────────────────────────────────────────────────
$('#btn-new').on('click',function(){
  clearTimeout(_saveTimer);
  currentWorkId=null; currentData=null; undoStack=[]; redoStack=[];
  chatHistory=[{role:'system',content:SYSTEM}];
  $('#chat').empty();
  addMsg('Hello! Describe the carousel or post you want to create. I will generate slides with professional and original design using HTML/CSS.', 'ai');
  $('#slides-container').html('<div id="empty-state"><div class="icon">▣</div><p>No slides.</p></div>');
  $('#slide-count').text(''); $('#work-label').text(''); isDirty=false;
  updateUndoRedoBtns(); updateNavBar(); $('#btn-save').prop('disabled',true);
  renderWorksList();
});
$('#btn-save').on('click',function(){ if(currentData) saveCurrentWork(); });
$('#btn-toggle-works').on('click',function(){var o=$('#works-drawer').toggleClass('open').hasClass('open');$(this).toggleClass('active',o);});
// Close works drawer on mobile when tapping the backdrop
$('#works-drawer').on('click',function(e){if(isMobile()&&!$(e.target).closest('#works-drawer-inner').length){$('#works-drawer').removeClass('open');$('#btn-toggle-works').removeClass('active');}});
$('#works-list').on('click','.btn-load-work',async function(){
  var id=String($(this).data('id'));
  try {
    var work = await (await fetch('/api/works/'+id)).json();
    if(work.error) return;
    clearTimeout(_saveTimer);
    currentWorkId=id;
    undoStack=(work.undoStack||[]).slice();redoStack=[];
    // Restore chat history for this work
    if(work.chatHistory&&work.chatHistory.length){
      chatHistory=work.chatHistory.slice();
      $('#chat').empty();
      chatHistory.forEach(function(m){
        if(m.role==='user') addMsg(m.content,'user');
        else if(m.role==='assistant'){ var txt=cleanChat(m.content); if(txt) addMsg(txt,'ai'); }
      });
    } else {
      chatHistory=[{role:'system',content:SYSTEM}];
      $('#chat').empty();
      addMsg('Work loaded. Continue editing or describe changes.','ai');
    }
    currentData=null;renderAll(work.data,true);markClean();renderWorksList();
    // Close drawer after loading
    $('#works-drawer').removeClass('open');
    $('#btn-toggle-works').removeClass('active');
  } catch(e) { console.error('Load failed:', e); }
});
$('#works-list').on('click','.btn-copy-work',async function(e){
  e.stopPropagation();var id=String($(this).data('id'));
  var $b=$(this);
  try {
    var work = await (await fetch('/api/works/'+id)).json();
    if(!work.error){
      navigator.clipboard.writeText(JSON.stringify(work.data,null,2));
      $b.text('✓');setTimeout(()=>$b.text('JSON'),1500);
    }
  } catch(e) {}
});
$('#works-list').on('click','.btn-delete-work',async function(e){
  e.stopPropagation();var id=String($(this).data('id'));
  if(id===currentWorkId){clearTimeout(_saveTimer);currentWorkId=null;markClean();}
  try {
    await fetch('/api/works/'+id, {method:'DELETE'});
    worksCache = worksCache.filter(function(w){ return w.id!==id; });
    renderWorksList();
  } catch(e) {}
});
$('#btn-clear-works').on('click',async function(){
  if(!worksCache.length)return;
  clearTimeout(_saveTimer);
  try {
    await Promise.all(worksCache.map(function(w){ return fetch('/api/works/'+w.id, {method:'DELETE'}); }));
    worksCache=[];currentWorkId=null;markClean();renderWorksList();
  } catch(e) {}
});

// ── DOWNLOAD / JSON ───────────────────────────────────────────────────
$('#btn-download').on('click', async function(){
  if(!currentData || !currentData.slides || !currentData.slides.length) return;
  var $btn = $(this).text('…').prop('disabled', true);

  // Resolve project name from saved work label
  var projectName = 'project';
  if(currentWorkId){
    var works = worksCache;
    var w = works.find(function(x){ return x.id === currentWorkId; });
    if(w && w.label) projectName = w.label;
  } else if(currentData.slides[0] && currentData.slides[0].title){
    projectName = currentData.slides[0].title;
  }
  var safeName = projectName.replace(/[^\w\u00C0-\u024F _-]/g,'').trim().replace(/\s+/g,'_') || 'project';

  // Only capture the exact indexed slide elements — avoids picking up
  // any .slide class that may appear inside AI-generated HTML content
  var total = currentData.slides.length;
  var zip = new JSZip();
  for(var i = 0; i < total; i++){
    var el = document.getElementById('slide-' + i);
    if(!el) continue;
    var canvas = await html2canvas(el, {scale:3, useCORS:true, allowTaint:true, backgroundColor:null});
    var blob = await new Promise(function(res){ canvas.toBlob(res, 'image/png'); });
    zip.file('slide-' + String(i+1).padStart(2,'0') + '.png', blob);
  }

  var zipBlob = await zip.generateAsync({type:'blob'});
  var a = document.createElement('a');
  a.download = safeName + '.zip';
  a.href = URL.createObjectURL(zipBlob);
  a.click();
  setTimeout(function(){ URL.revokeObjectURL(a.href); }, 2000);

  $btn.text('⬇ PNG').prop('disabled', false);
});
$('#btn-json').on('click',function(){
  if(!currentData)return;navigator.clipboard.writeText(JSON.stringify(currentData,null,2));
  $(this).text('✓');setTimeout(()=>$('#btn-json').text('{ }'),1500);
});

// ── MIC ───────────────────────────────────────────────────────────────
let mediaRecorder=null,recChunks=[],recTimerInterval=null,isRecording=false;

function updateSendIcon(){var hasText=$('#message').val().trim().length>0;$('#send-icon').addClass('material-icons-round').text(isRecording?'stop_circle':(hasText?'arrow_upward':'mic'));}
$('#message').on('input',updateSendIcon);
$('#message').on('keypress',function(e){if(e.which===13){var m=$(this).val().trim();if(m){send(m);$(this).val('');updateSendIcon();}}});
$('#send').on('click',function(){
  if(isRecording){stopRecording();return;}
  var m=$('#message').val().trim();
  if(m){send(m);$('#message').val('');updateSendIcon();return;}
  startRecording();
});
$('#rec-cancel').on('click',cancelRecording);

async function startRecording(){
  try{
    var stream=await navigator.mediaDevices.getUserMedia({audio:true});
    recChunks=[];
    var mimeType=MediaRecorder.isTypeSupported('audio/webm')?'audio/webm':'audio/mp4';
    mediaRecorder=new MediaRecorder(stream,{mimeType});
    mediaRecorder.ondataavailable=function(e){if(e.data.size>0)recChunks.push(e.data);};
    mediaRecorder.onstop=async function(){
      stream.getTracks().forEach(t=>t.stop());
      if(!mediaRecorder._cancelled){var ext=mimeType==='audio/webm'?'webm':'mp4';await transcribeAudio(new Blob(recChunks,{type:mimeType}),ext);}
    };
    mediaRecorder.start();isRecording=true;$('#send').addClass('recording');updateSendIcon();
    $('#message').hide();$('#rec-bar').addClass('show');
    var secs=0;$('#rec-timer-txt').text('0:00');
    recTimerInterval=setInterval(function(){secs++;$('#rec-timer-txt').text(Math.floor(secs/60)+':'+String(secs%60).padStart(2,'0'));},1000);
  }catch(e){addMsg('Microphone access denied.','ai');}
}
function stopRecording(){if(mediaRecorder&&mediaRecorder.state!=='inactive')mediaRecorder.stop();clearInterval(recTimerInterval);isRecording=false;$('#send').removeClass('recording');$('#rec-bar').removeClass('show');$('#message').show().focus();updateSendIcon();}
function cancelRecording(){if(mediaRecorder)mediaRecorder._cancelled=true;stopRecording();}

async function transcribeAudio(blob,ext){
  $('#send').prop('disabled',true);
  var $status=$('<div>').addClass('msg ai').text('Transcribing...').appendTo('#chat');
  document.getElementById('chat').scrollTop=999999;
  try{
    var body=new FormData();body.append('file',blob,'audio.'+ext);body.append('language','portuguese');body.append('response_format','json');
    var res=await fetch('https://api.lemonfox.ai/v1/audio/transcriptions',{method:'POST',headers:{'Authorization':'Bearer '+LEMONFOX_KEY},body});
    var d=await res.json();$status.remove();
    if(d.text&&d.text.trim())send(d.text.trim());else addMsg("Couldn't understand the audio.",'ai');
  }catch(e){$status.remove();addMsg('Transcription error.','ai');}
  finally{$('#send').prop('disabled',false);}
}

// ── ELEMENT DRAG / INLINE EDIT ───────────────────────────────────────
var elDrag=null, elSel=null, elSlideIdx=null, elContainer=null;

// Inject / remove CSS override that makes AI wrapper transparent so bg-img-layer shows through
function injectBgOverride(idx, enable){
  var id='bg-ov-'+idx; $('#'+id).remove();
  if(enable) $('<style id="'+id+'">#slide-'+idx+' .slide-html-layer > :not(style){background-color:transparent!important;background-image:none!important;}</style>').appendTo('head');
}

function initAllSlideInteractions(){
  document.querySelectorAll('.slide-html-layer').forEach(function(layer){
    var slideIdx=parseInt(layer.closest('.slide').dataset.idx);
    // AI typically wraps everything in a single <div>; skip style/script tags to find it
    var directKids=Array.from(layer.children).filter(function(el){return el.tagName!=='STYLE'&&el.tagName!=='SCRIPT';});
    // If single wrapper with children, go one level deeper (AI pattern)
    var container=(directKids.length===1&&directKids[0].children.length>0)?directKids[0]:layer;
    Array.from(container.children).forEach(function(child,i){
      if(!child.getAttribute('data-el-id')) child.setAttribute('data-el-id',slideIdx+'-'+i);
    });
  });
}

// mousedown on elements → select + start drag
$(document).on('mousedown touchstart','[data-el-id]',function(e){
  if($(e.target).is('a,button,input,select,textarea')) return;
  if($(this).attr('contenteditable')==='true') return;
  e.stopPropagation(); e.preventDefault();
  var $el=$(this);
  var slideIdx=parseInt($el.closest('.slide')[0].dataset.idx);
  selectEl($el,slideIdx);
  var touch=e.originalEvent.touches?e.originalEvent.touches[0]:e.originalEvent;
  var tx=parseFloat($(this).data('drag-tx')||0), ty=parseFloat($(this).data('drag-ty')||0);
  elDrag={el:this,slideIdx:slideIdx,startX:touch.clientX,startY:touch.clientY,origTx:tx,origTy:ty,moved:false};
});

// dblclick → inline text edit
$(document).on('dblclick','[data-el-id]',function(e){
  e.stopPropagation();
  var $el=$(this);
  var slideIdx=parseInt($el.closest('.slide')[0].dataset.idx);
  if(elSel&&elSel!==$el[0]){$(elSel).removeClass('el-sel el-edit').removeAttr('contenteditable');}
  elSel=$el[0]; elSlideIdx=slideIdx; elContainer=$el[0].parentElement;
  $el.removeClass('el-sel').addClass('el-edit').attr('contenteditable','true').focus();
  hideElToolbar();
  try{var r=document.createRange();r.selectNodeContents(this);r.collapse(false);var s=window.getSelection();s.removeAllRanges();s.addRange(r);}catch(ex){}
});

// blur from contenteditable → save
$(document).on('blur','[data-el-id][contenteditable="true"]',function(){
  var slideIdx=parseInt($(this).closest('.slide')[0].dataset.idx);
  $(this).removeAttr('contenteditable').removeClass('el-edit');
  serializeSlideEdits(slideIdx);
});

function selectEl($el,slideIdx){
  if(elSel&&elSel!==$el[0]) $(elSel).removeClass('el-sel el-edit').removeAttr('contenteditable');
  elSel=$el[0]; elSlideIdx=slideIdx; elContainer=$el[0].parentElement;
  $el.addClass('el-sel').removeClass('el-edit').removeAttr('contenteditable');
  showElToolbar($el);
}

function showElToolbar($el){
  var rect=$el[0].getBoundingClientRect();
  var x=rect.left+rect.width/2;
  var y=Math.max(8,rect.top-6);
  $('#el-toolbar').css({left:x+'px',top:y+'px'}).addClass('show');
}
function hideElToolbar(){ $('#el-toolbar').removeClass('show'); }

function deselectEl(){
  if(elSel){$(elSel).removeClass('el-sel el-edit').removeAttr('contenteditable');}
  elSel=null; elSlideIdx=null; hideElToolbar();
}

function serializeSlideEdits(slideIdx, skipUndo) {
  if (!currentData || slideIdx === undefined || slideIdx === null) return;

  var layer = document.querySelector('#slide-' + slideIdx + ' .slide-html-layer');
  if (!layer) return;

  if (!skipUndo) {
    undoStack.push(JSON.stringify(currentData));
    if (undoStack.length > 30) undoStack.shift(); // cap at 30 steps
    redoStack = [];
    updateUndoRedoBtns();
  }

  var clone = layer.cloneNode(true);

  // Limpeza
  clone.querySelectorAll('[contenteditable]').forEach(el => el.removeAttribute('contenteditable'));
  clone.querySelectorAll('.el-sel, .el-edit, .el-drag').forEach(el => {
    el.classList.remove('el-sel', 'el-edit', 'el-drag');
  });
  clone.querySelectorAll('[data-el-id]').forEach(el => el.removeAttribute('data-el-id'));

  currentData.slides[slideIdx].html_content = clone.innerHTML;
  markDirty(); // schedules debounced server save via scheduleServerSave()
}

// Flush all live DOM edits (drags, text) into currentData before snapshotting
function serializeAllSlides(){
  if(!currentData) return;
  currentData.slides.forEach(function(_,i){
    var layer=document.querySelector('#slide-'+i+' .slide-html-layer');
    if(!layer) return;
    var clone=layer.cloneNode(true);
    clone.querySelectorAll('[contenteditable]').forEach(function(el){el.removeAttribute('contenteditable');});
    clone.querySelectorAll('.el-sel,.el-edit,.el-drag').forEach(function(el){el.classList.remove('el-sel','el-edit','el-drag');});
    clone.querySelectorAll('[data-el-id]').forEach(function(el){el.removeAttribute('data-el-id');});
    clone.querySelectorAll('[data-base-tx],[data-base-ty]').forEach(function(el){el.removeAttribute('data-base-tx');el.removeAttribute('data-base-ty');});
    currentData.slides[i].html_content=clone.innerHTML;
  });
}

// global mousemove for element drag (shares listener with oiDrag)
document.addEventListener('mousemove',function(e){
  if(!elDrag||oiDrag||oiResize) return;
  var dx=e.clientX-elDrag.startX, dy=e.clientY-elDrag.startY;
  if(!elDrag.moved&&Math.abs(dx)+Math.abs(dy)<4) return;
  elDrag.moved=true;
  var tx=elDrag.origTx+dx, ty=elDrag.origTy+dy;
  $(elDrag.el).data('drag-tx',tx).data('drag-ty',ty);
  $(elDrag.el).css('transform','translate('+tx+'px,'+ty+'px)').addClass('el-drag');
  hideElToolbar();
});
document.addEventListener('touchmove',function(e){
  if(!elDrag||oiDrag||oiResize) return;
  e.preventDefault();
  var cx=e.touches[0].clientX,cy=e.touches[0].clientY;
  var dx=cx-elDrag.startX,dy=cy-elDrag.startY;
  if(!elDrag.moved&&Math.abs(dx)+Math.abs(dy)<4) return;
  elDrag.moved=true;
  var tx=elDrag.origTx+dx,ty=elDrag.origTy+dy;
  $(elDrag.el).data('drag-tx',tx).data('drag-ty',ty);
  $(elDrag.el).css('transform','translate('+tx+'px,'+ty+'px)').addClass('el-drag');
  hideElToolbar();
},{passive:false});
document.addEventListener('mouseup',elDragEnd);
document.addEventListener('touchend',elDragEnd);
function elDragEnd(){
  if(!elDrag) return;
  var moved=elDrag.moved,slideIdx=elDrag.slideIdx,el=elDrag.el;
  $(el).removeClass('el-drag');
  elDrag=null;
  if(moved){ serializeSlideEdits(slideIdx); if(elSel===el) showElToolbar($(el)); }
  // removed unconditional second call — was creating duplicate undo entries
}

// click outside → deselect
$(document).on('click',function(e){
  if(!elSel) return;
  if($(e.target).closest('.slide-html-layer').length||$(e.target).closest('#el-toolbar').length) return;
  deselectEl();
});

// Toolbar: Apply current element to same index in all slides
$('#btn-el-all').on('click',function(){
  if(!elSel||elSlideIdx===null||!currentData||!elContainer) return;
  serializeSlideEdits(elSlideIdx);
  // Index of this element within its container, and of container within slide-html-layer
  var myIdx=Array.from(elContainer.children).indexOf(elSel);
  var myContainerIdx=Array.from(elContainer.parentElement.children).indexOf(elContainer);
  var outerHTML=elSel.outerHTML
    .replace(/\s+class="([^"]*)"/g,function(m,c){var cl=c.replace(/\b(el-sel|el-edit|el-drag)\b/g,'').replace(/\s+/g,' ').trim();return cl?' class="'+cl+'"':''})
    .replace(/\s*contenteditable="[^"]*"/g,'')
    .replace(/\s*data-el-id="[^"]*"/g,'');
  currentData.slides.forEach(function(s,i){
    if(i===elSlideIdx) return;
    var layer=document.querySelector('#slide-'+i+' .slide-html-layer');
    if(!layer) return;
    var containers=layer.children;
    var targetContainer=containers[myContainerIdx]||layer;
    var ch=targetContainer.children;
    if(myIdx<ch.length) $(ch[myIdx]).replaceWith(outerHTML);
    else $(targetContainer).append(outerHTML);
    serializeSlideEdits(i, true); // batch: one undo entry for the whole operation
  });
  var $b=$(this);$b.text('✓');setTimeout(function(){$b.text('Apply to all');},1200);
});

// Toolbar: Delete element
$('#btn-el-del').on('click',function(){
  if(!elSel||elSlideIdx===null||!currentData) return;
  var slideIdx=elSlideIdx;
  $(elSel).remove();
  deselectEl();
  serializeSlideEdits(slideIdx);
});

// ── POST TO INSTAGRAM ─────────────────────────────────────────────────

var IG_CONNECTED = <%= (user && user.ig_token) ? 'true' : 'false' %>;

$('#btn-post').on('click', async function(){
  if (!currentData || !currentData.slides || !currentData.slides.length) return;
  if (!IG_CONNECTED) {
    if(confirm('Instagram not connected. Connect now?')) window.location.href='/ig/connect';
    return;
  }
  // Populate modal
  $('#post-thumbs').empty();
  $('#post-status-msg').text('');
  $('#post-progress-bar').removeClass('show');
  $('#post-progress-fill').css('width','0%');
  var n = currentData.slides.length;
  $('#post-slide-count-label').text(n===1?'1 slide (single image)':n+' slides (carousel)');
  // Generate small thumbnails
  for(var i=0;i<Math.min(n,10);i++){
    var el=document.getElementById('slide-'+i);
    if(!el) continue;
    try{
      var c=await html2canvas(el,{scale:.5,useCORS:true,allowTaint:true,backgroundColor:'#111'});
      $('#post-thumbs').append('<img class="post-thumb" src="'+c.toDataURL('image/jpeg',.7)+'">');
    }catch(e){}
  }
  $('#btn-post-submit').prop('disabled',false).text('Post →');
  $('#post-modal').addClass('show');
});

$('#post-modal-close, #btn-post-cancel').on('click', function(){ $('#post-modal').removeClass('show'); });
$('#post-modal').on('click', function(e){ if($(e.target).is('#post-modal')) $('#post-modal').removeClass('show'); });

$('#btn-post-submit').on('click', async function(){
  var caption   = $('#post-caption').val().trim();

  var $btn = $(this).prop('disabled',true).text('Publishing...');
  var $status = $('#post-status-msg').css('color','var(--muted)');
  $('#post-progress-bar').addClass('show');

  try {
    var total = Math.min(currentData.slides.length, 10);
    var imageUrls = [];
    var tmpId = Date.now() + Math.random().toString(36).slice(2,7);

    for(var i=0;i<total;i++){
      var pct = Math.round(((i+.5)/total)*70);
      $('#post-progress-fill').css('width',pct+'%');
      $status.text('Rendering slide '+(i+1)+'/'+total+'...');

      var el = document.getElementById('slide-'+i);
      if(!el) continue;
      var canvas = await html2canvas(el,{scale:3,useCORS:true,allowTaint:true,backgroundColor:'#111'});
      var base64 = canvas.toDataURL('image/jpeg', 0.92);
      var filename = 'slide_'+String(i+1).padStart(2,'0')+'.jpg';

      $status.text('Uploading slide '+(i+1)+'/'+total+'...');
      var upRes = await fetch('/api/ig/upload',{
        method:'POST',
        headers:{'Content-Type':'application/json'},
        body:JSON.stringify({base64,filename,tmpId})
      });
      if(!upRes.ok){ var e=await upRes.json(); throw new Error(e.error||'Upload failed'); }
      var upData = await upRes.json();
      imageUrls.push(upData.url);
    }

    $('#post-progress-fill').css('width','80%');
    $status.text('Publishing to Instagram...');

    var postRes = await fetch('/api/ig/post',{
      method:'POST',
      headers:{'Content-Type':'application/json'},
      body:JSON.stringify({imageUrls,caption,tmpId})
    });
    var postText = await postRes.text();
    var postData; try { postData = JSON.parse(postText); } catch(e) { throw new Error('Invalid response: '+postText.slice(0,300)); }
    if(!postData.success) throw new Error(postData.error||'Publishing error');

    $('#post-progress-fill').css('width','100%');
    $status.css('color','var(--accent)').text('✓ Published! Post ID: '+postData.postId);
    $btn.text('Published ✓');

  } catch(e) {
    $status.css('color','var(--danger)').text('Error: '+(e.message||'please try again.'));
    $btn.prop('disabled',false).text('Try again');
    $('#post-progress-fill').css('width','0%');
  }
});

// ── BOOT ──────────────────────────────────────────────────────────────
fetchWorksIndex();
updateNavBar();
updateSendIcon();
addMsg('Hello! Describe the carousel or post you want to create. I will generate slides with professional and original design using HTML/CSS.', 'ai');
// Start blank — user creates new work from prompt or loads from Works panel
</script>
</body>
</html>