<?php declare(strict_types=1); ?>
<!-- ═══════════════════════════════════════════════════════════════════
     Deploy — in-app Guide
     Self-contained (own markup + styles + open/close/scrollspy script).
     Colours come from the app theme tokens (--pp-*), so it follows whatever
     theme the user picked. Opened by any element with [data-dep-help-open].
     ══════════════════════════════════════════════════════════════════ -->
<style>
    .deph-scrim { position:fixed; inset:0; z-index:11500; background:rgba(15,23,42,.55);
        backdrop-filter:blur(3px); display:none; opacity:0; transition:opacity .18s; }
    .deph-scrim.open { display:block; opacity:1; }
    .deph-modal { position:fixed; z-index:11501; top:3vh; bottom:3vh; left:50%;
        width:min(1060px, 94vw); transform:translateX(-50%) translateY(14px);
        background:var(--pp-surface, #fff); color:var(--pp-text, #1e293b);
        border-radius:16px; box-shadow:0 32px 80px rgba(2,6,23,.5);
        display:flex; flex-direction:column; overflow:hidden; opacity:0;
        transition:transform .2s, opacity .2s; }
    .deph-scrim.open .deph-modal { transform:translateX(-50%) translateY(0); opacity:1; }

    .deph-head { flex:0 0 auto; display:flex; align-items:center; gap:14px;
        padding:16px 22px; border-bottom:1px solid var(--pp-border, #e2e8f0);
        background:linear-gradient(120deg,#0c4a6e,#0284c7 60%,#0891b2); color:#fff; }
    .deph-head .deph-badge { width:40px; height:40px; border-radius:11px; flex:0 0 40px;
        display:flex; align-items:center; justify-content:center; font-size:20px;
        background:rgba(255,255,255,.16); }
    .deph-head h2 { margin:0; font-size:17px; font-weight:800; letter-spacing:-.01em; }
    .deph-head p  { margin:2px 0 0; font-size:12px; opacity:.85; }
    .deph-close { margin-left:auto; width:34px; height:34px; border-radius:9px; border:0;
        background:rgba(255,255,255,.14); color:#fff; font-size:18px; cursor:pointer;
        display:flex; align-items:center; justify-content:center; transition:.15s; }
    .deph-close:hover { background:rgba(255,255,255,.28); }

    .deph-body { flex:1; min-height:0; display:grid; grid-template-columns:240px 1fr; }
    .deph-toc { border-right:1px solid var(--pp-border, #e2e8f0); background:var(--pp-surface-soft, #f8fafc);
        overflow-y:auto; padding:14px 8px 24px; }
    .deph-toc-group { font-size:9.5px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
        color:var(--pp-text-muted, #94a3b8); padding:14px 14px 5px; }
    .deph-toc a { display:flex; align-items:center; gap:9px; padding:7px 14px; border-radius:8px;
        margin:1px 6px; font-size:12.5px; color:var(--pp-text-muted, #475569); text-decoration:none;
        cursor:pointer; border-left:3px solid transparent; }
    .deph-toc a:hover,
    .deph-toc a.active { background:color-mix(in srgb, var(--pp-accent, #0284c7) 14%, var(--pp-surface, #fff));
        color:var(--pp-accent, #0369a1); }
    .deph-toc a.active { font-weight:700; border-left-color:var(--pp-accent, #0284c7); }
    .deph-toc a i { font-size:14px; width:16px; flex:0 0 16px; color:var(--pp-accent, #38bdf8); }

    .deph-content { position:relative; overflow-y:auto; padding:8px 40px 80px; scroll-behavior:smooth;
        background:var(--pp-surface, #fff); color:var(--pp-text, #1e293b); }
    .deph-content section { padding-top:26px; }
    .deph-content h3 { font-size:21px; font-weight:800; letter-spacing:-.02em; margin:6px 0 4px;
        color:var(--pp-text, #0f172a); display:flex; align-items:center; gap:10px; }
    .deph-content h3 .num { font-size:12px; font-weight:800; color:var(--pp-accent, #0369a1);
        background:color-mix(in srgb, var(--pp-accent, #0284c7) 15%, var(--pp-surface, #fff));
        border-radius:8px; padding:3px 9px; }
    .deph-content h4 { font-size:14.5px; font-weight:800; margin:22px 0 6px; color:var(--pp-accent, #0c4a6e); }
    .deph-content p  { font-size:13.5px; line-height:1.66; color:var(--pp-text, #334155); margin:8px 0; }
    .deph-content ul, .deph-content ol { font-size:13.5px; line-height:1.66; color:var(--pp-text, #334155);
        margin:8px 0; padding-left:22px; }
    .deph-content li { margin:4px 0; }
    .deph-content b, .deph-content strong { color:var(--pp-text, #0f172a); }
    .deph-lead { font-size:15px; line-height:1.65; color:var(--pp-text-muted, #475569); }
    .deph-content kbd { background:var(--pp-surface-muted, #f1f5f9); color:var(--pp-text, #0f172a);
        border-radius:4px; padding:1px 5px; font-size:11px; }
    .deph-content code { font-family:ui-monospace,Menlo,Consolas,monospace; font-size:12px;
        background:color-mix(in srgb, var(--pp-accent, #0284c7) 14%, var(--pp-surface, #fff));
        color:var(--pp-accent, #0369a1); padding:1.5px 6px; border-radius:5px; }

    /* Callouts tint the current surface, so they stay readable in every theme. */
    .deph-callout { display:flex; gap:12px; padding:13px 16px; border-radius:11px; margin:14px 0;
        font-size:13px; line-height:1.6; color:var(--pp-text, #334155); border:1px solid transparent; }
    .deph-callout i { font-size:17px; flex:0 0 auto; margin-top:1px; }
    .deph-callout.tip  { background:color-mix(in srgb, #10b981 13%, var(--pp-surface, #fff));
        border-color:color-mix(in srgb, #10b981 28%, transparent); }
    .deph-callout.tip i { color:#10b981; }
    .deph-callout.warn { background:color-mix(in srgb, #f59e0b 13%, var(--pp-surface, #fff));
        border-color:color-mix(in srgb, #f59e0b 28%, transparent); }
    .deph-callout.warn i { color:#f59e0b; }
    .deph-callout.info { background:color-mix(in srgb, #3b82f6 13%, var(--pp-surface, #fff));
        border-color:color-mix(in srgb, #3b82f6 28%, transparent); }
    .deph-callout.info i { color:#3b82f6; }
    .deph-callout.sec  { background:color-mix(in srgb, #ef4444 13%, var(--pp-surface, #fff));
        border-color:color-mix(in srgb, #ef4444 28%, transparent); }
    .deph-callout.sec i { color:#ef4444; }

    .deph-table { width:100%; border-collapse:collapse; margin:12px 0; font-size:12.5px; }
    .deph-table th { text-align:left; font-weight:800; color:var(--pp-text-muted, #475569);
        background:var(--pp-surface-soft, #f8fafc); padding:8px 11px;
        border-bottom:2px solid var(--pp-border, #e2e8f0); font-size:11px; text-transform:uppercase;
        letter-spacing:.03em; }
    .deph-table td { padding:8px 11px; border-bottom:1px solid var(--pp-border, #f1f5f9);
        vertical-align:top; color:var(--pp-text, #334155); }
    .deph-table td code { white-space:nowrap; }
    .deph-table tr:hover td { background:var(--pp-surface-soft, #f8fbff); }

    .deph-foot { margin-top:34px; padding-top:16px; border-top:1px solid var(--pp-border, #e2e8f0);
        font-size:12px; color:var(--pp-text-muted, #94a3b8); }

    @media (max-width:760px) {
        .deph-body { grid-template-columns:1fr; }
        .deph-toc { display:none; }
        .deph-content { padding:8px 20px 60px; }
    }
</style>

<div class="deph-scrim" id="depHelpScrim" aria-hidden="true">
  <div class="deph-modal pp-legacy-guide" role="dialog" aria-modal="true" aria-label="Deploy guide">
    <div class="deph-head">
      <div class="deph-badge"><i class="bi bi-cloud-arrow-up-fill"></i></div>
      <div>
        <h2>Deploy — Guide</h2>
        <p>Put your finished app on a real web server, safely and repeatedly.</p>
      </div>
      <button class="deph-close" id="depHelpClose" title="Close (Esc)" aria-label="Close"><i class="bi bi-x-lg" aria-hidden="true"></i></button>
    </div>

    <div class="deph-body">
      <nav class="deph-toc" id="depHelpToc">
        <div class="deph-toc-group">Start here</div>
        <a data-goto="d-what"><i class="bi bi-stars"></i> What this screen is</a>
        <a data-goto="d-first"><i class="bi bi-1-circle"></i> Your first upload</a>

        <div class="deph-toc-group">Connections</div>
        <a data-goto="d-conn"><i class="bi bi-hdd-network"></i> Saving a connection</a>
        <a data-goto="d-fields"><i class="bi bi-input-cursor-text"></i> What each field means</a>
        <a data-goto="d-test"><i class="bi bi-plug"></i> Test before you trust</a>

        <div class="deph-toc-group">Publishing</div>
        <a data-goto="d-browse"><i class="bi bi-folder2-open"></i> Browsing the server</a>
        <a data-goto="d-upload"><i class="bi bi-cloud-arrow-up"></i> Upload modes</a>
        <a data-goto="d-db"><i class="bi bi-database"></i> Live database</a>

        <div class="deph-toc-group">Reference</div>
        <a data-goto="d-dock"><i class="bi bi-list-task"></i> Log, history &amp; diagnostics</a>
        <a data-goto="d-trouble"><i class="bi bi-life-preserver"></i> Troubleshooting</a>
        <a data-goto="d-faq"><i class="bi bi-question-circle"></i> FAQ</a>
      </nav>

      <div class="deph-content" id="depHelpContent">

        <section id="d-what">
          <h3><span class="num">01</span> What this screen is</h3>
          <p class="deph-lead">A complete <b>FTP / FTPS / SFTP client</b>, built into <?= htmlspecialchars(\PpPhp\Core\Brand::name()) ?>. It takes the application you
          built and copies it onto your web server — so people can actually visit it.</p>
          <p>Unlike a generic FTP program, it knows about your project: it can upload <b>only the files that changed</b>
          since your last build, and it can point the uploaded copy at your <b>live database</b> without touching the
          settings you use here.</p>
          <div class="deph-callout info"><i class="bi bi-info-circle-fill"></i>
            <div>Build first. Deploy always uploads your <b>last build</b> — if you changed something, go to
            <b>Finished → Build Now</b> before publishing.</div></div>
        </section>

        <section id="d-first">
          <h3><span class="num">02</span> Your first upload</h3>
          <ol>
            <li><b>New</b> — add your server's details and save the connection.</li>
            <li><b>Test</b> — run the step-by-step check. Fix anything it reports.</li>
            <li><b>Connect</b> — the right-hand pane fills with the files on your server.</li>
            <li>Navigate to the folder your site is served from (often <code>public_html</code> or <code>www</code>),
              then use <b>Set as upload target</b>.</li>
            <li>Pick an upload mode and press <b>Upload</b>.</li>
          </ol>
          <div class="deph-callout tip"><i class="bi bi-lightbulb-fill"></i>
            <div>Not sure it'll go where you expect? Tick <b>Dry run</b> first — it lists exactly what would be
            uploaded, without sending anything.</div></div>
        </section>

        <section id="d-conn">
          <h3><span class="num">03</span> Saving a connection</h3>
          <p>The buttons in the top bar manage the servers you publish to:</p>
          <table class="deph-table">
            <thead><tr><th>Button</th><th>What it does</th></tr></thead>
            <tbody>
              <tr><td><b>New</b></td><td>Add a server. Its details are saved with your project.</td></tr>
              <tr><td><b>Edit</b></td><td>Change the selected server. Leave the password blank to keep the saved one.</td></tr>
              <tr><td><b>Delete</b></td><td>Remove the selected server.</td></tr>
              <tr><td><b>Test</b></td><td>Run a staged connection check without uploading anything.</td></tr>
              <tr><td><b>Connect</b></td><td>Sign in and browse the server's files.</td></tr>
            </tbody>
          </table>
          <div class="deph-callout sec"><i class="bi bi-shield-lock-fill"></i>
            <div>Passwords are <b>encrypted</b> before being stored and are never sent back to your browser — the editor
            shows a blank password box and keeps the saved one unless you type a new value.</div></div>
        </section>

        <section id="d-fields">
          <h3><span class="num">04</span> What each field means</h3>
          <table class="deph-table">
            <thead><tr><th>Field</th><th>What to enter</th></tr></thead>
            <tbody>
              <tr><td><b>Protocol</b></td><td><b>FTP</b> (plain), <b>FTPS</b> (FTP with encryption), or <b>SFTP</b> (over SSH — the most reliable). If your host offers SFTP, prefer it.</td></tr>
              <tr><td><b>Host</b></td><td>Just your domain, e.g. <code>example.com</code>. If your host needs <code>ftp.example.com</code>, that's found automatically.</td></tr>
              <tr><td><b>Port</b></td><td>Fills in from the protocol: 21 for FTP/FTPS, 22 for SFTP. Only change it if your host says so.</td></tr>
              <tr><td><b>Username / Password</b></td><td>Your hosting or FTP account. For SFTP this is usually the <b>main</b> account, not an FTP sub-account.</td></tr>
              <tr><td><b>Remote path</b></td><td>The folder your site is served from — often <code>/public_html</code>. You can also set this by browsing.</td></tr>
              <tr><td><b>Site URL</b></td><td>Optional. The public address, so the app can be opened right after uploading.</td></tr>
              <tr><td><b>Passive mode</b></td><td>Leave on for FTP — it's what almost every host expects.</td></tr>
            </tbody>
          </table>
        </section>

        <section id="d-test">
          <h3><span class="num">05</span> Test before you trust</h3>
          <p><b>Test</b> walks through the connection one step at a time — finding the host, opening the port, signing in,
          and opening a data channel — and tells you exactly which step failed and why.</p>
          <p>That last step matters: plenty of hosts let you sign in but quietly block the <b>data channel</b> FTP needs
          to list files. The test names the blocked port instead of leaving you guessing.</p>
          <div class="deph-callout tip"><i class="bi bi-lightbulb-fill"></i>
            <div>Run <b>Test</b> whenever something feels off. It's read-only and never changes anything on your server.</div></div>
        </section>

        <section id="d-browse">
          <h3><span class="num">06</span> Browsing the server</h3>
          <p>After <b>Connect</b> you get two panes: <b>Local site</b> (your built files) on the left, <b>Remote site</b>
          (your server) on the right.</p>
          <ul>
            <li>Double-click folders to open them; use the breadcrumbs to go back up.</li>
            <li>Right-side tools let you create a <b>new folder</b>, <b>rename</b>, or <b>delete</b>.</li>
            <li><b>Set as upload target</b> marks the current remote folder as the destination for uploads.</li>
          </ul>
          <div class="deph-callout warn"><i class="bi bi-exclamation-triangle-fill"></i>
            <div>Deleting on the remote pane deletes on your <b>live server</b> — there's no undo. Double-check the path
            in the breadcrumb first.</div></div>
        </section>

        <section id="d-upload">
          <h3><span class="num">07</span> Upload modes</h3>
          <table class="deph-table">
            <thead><tr><th>Mode</th><th>Sends</th><th>Use when</th></tr></thead>
            <tbody>
              <tr><td><b>Changed only</b></td><td>Files that changed since your last upload</td><td>Everyday updates — much faster.</td></tr>
              <tr><td><b>All output</b></td><td>Every file from your last build</td><td>First upload, or when something looks out of sync.</td></tr>
              <tr><td><b>All project</b></td><td>Everything, including extras</td><td>Rarely — a full, complete copy.</td></tr>
            </tbody>
          </table>
          <p>Two extra switches:</p>
          <ul>
            <li><b>Dry run</b> — show what would be sent, send nothing. Perfect for a first look.</li>
            <li><b>Open after upload</b> — open your Site URL when it finishes.</li>
          </ul>
          <div class="deph-callout tip"><i class="bi bi-lightbulb-fill"></i>
            <div>First upload to a brand-new server? Use <b>All output</b> once, then <b>Changed only</b> from then on.</div></div>
        </section>

        <section id="d-db">
          <h3><span class="num">08</span> Live database</h3>
          <p>Your live server almost never uses the same database as your computer. The <b>Live DB</b> picker solves this:
          choose a saved live-database connection, and the uploaded copy of your app is pointed at it.</p>
          <div class="deph-callout info"><i class="bi bi-info-circle-fill"></i>
            <div><b>Your own settings are never touched.</b> The live details are written only into the copy that goes to
            the server — the project you work on here keeps its own database exactly as it is.</div></div>
          <p>Use the gear next to the picker to add, edit, or <b>Test</b> a live database. One project can have a
          different database for every server you publish to.</p>
          <div class="deph-callout warn"><i class="bi bi-exclamation-triangle-fill"></i>
            <div>A live database often only accepts connections from its own server, so <b>Test</b> can fail from your
            computer even when the details are right. The message tells you when that's the likely cause.</div></div>
        </section>

        <section id="d-dock">
          <h3><span class="num">09</span> Log, history &amp; diagnostics</h3>
          <ul>
            <li><b>Transfer log</b> — every file as it goes up, with any failures.</li>
            <li><b>History</b> — past uploads: server, mode, file count and result.</li>
            <li><b>Diagnostics</b> — the detailed output of your last connection test.</li>
          </ul>
          <p>If an upload misbehaves, these three answer most questions before you have to ask anyone.</p>
        </section>

        <section id="d-trouble">
          <h3><span class="num">10</span> Troubleshooting</h3>
          <h4>It connects, then hangs on "Listing…"</h4>
          <p>Classic blocked FTP <b>data channel</b>. Run <b>Test</b> — it names the port. Ask your host to open passive
          FTP, or switch to <b>SFTP</b>, which doesn't have this problem.</p>
          <h4>"Login denied" on SFTP, but my FTP login works</h4>
          <p>SFTP uses your <b>SSH</b> account — usually the main hosting username, not an FTP sub-account like
          <code>user@domain.com</code>. Your host may also need to enable SSH first.</p>
          <h4>It worked, now everything times out</h4>
          <p>Many hosts ban an IP after several rapid connection attempts (fail2ban). Wait a few minutes, or ask your
          host to allow your address.</p>
          <h4>Files upload but the site looks broken</h4>
          <p>Usually the wrong <b>remote path</b> (uploaded next to your site instead of into it), or the app is pointing
          at the wrong database — check <b>Live DB</b>.</p>
        </section>

        <section id="d-faq">
          <h3><span class="num">11</span> FAQ</h3>
          <h4>Deploy or Finished → Deploy to Demo?</h4>
          <p>Use <b>Deploy</b> (this screen) for servers you publish to regularly — it remembers connections and uploads
          only what changed. <b>Deploy to Demo</b> is a quick one-off that asks for details each time.</p>
          <h4>Will uploading delete what's already on my server?</h4>
          <p>No. Files are added or overwritten; nothing else is removed. Deleting only happens if you do it yourself in
          the remote pane.</p>
          <h4>Do I need to upload the database too?</h4>
          <p>Only once, to create the tables — use <b>Finished → Generate SQL Script</b> and import it on your host. After
          that, pick the live database here.</p>
          <h4>Are my passwords safe?</h4>
          <p>They're encrypted before storage and never sent back to your browser.</p>
          <div class="deph-foot"><?= htmlspecialchars(\PpPhp\Core\Brand::name()) ?> Deploy — build it here, run it anywhere.
          Press <kbd>Esc</kbd> or click outside to close.</div>
        </section>

      </div>
    </div>
  </div>
</div>

<script>
(function () {
    var scrim   = document.getElementById('depHelpScrim');
    var closeB  = document.getElementById('depHelpClose');
    var toc     = document.getElementById('depHelpToc');
    var content = document.getElementById('depHelpContent');
    if (!scrim) return;

    function open()  { scrim.classList.add('open'); scrim.setAttribute('aria-hidden', 'false');
                       document.body.style.overflow = 'hidden'; }
    function close() { scrim.classList.remove('open'); scrim.setAttribute('aria-hidden', 'true');
                       document.body.style.overflow = ''; }

    document.addEventListener('click', function (e) {
        if (e.target.closest('[data-dep-help-open]')) { e.preventDefault(); open(); }
    });
    closeB.addEventListener('click', close);
    scrim.addEventListener('click', function (e) { if (e.target === scrim) close(); });
    document.addEventListener('keydown', function (e) {
        if (e.key === 'Escape' && scrim.classList.contains('open')) { e.stopPropagation(); close(); }
    });

    var links = Array.prototype.slice.call(toc.querySelectorAll('a[data-goto]'));
    function setActive(id) {
        links.forEach(function (a) { a.classList.toggle('active', a.dataset.goto === id); });
    }
    function goTo(id) {
        var el = document.getElementById(id);
        if (el) { content.scrollTo({ top: el.offsetTop - 8, behavior: 'smooth' }); setActive(id); }
    }
    links.forEach(function (a) { a.addEventListener('click', function () { goTo(a.dataset.goto); }); });

    var sections = links.map(function (a) { return document.getElementById(a.dataset.goto); }).filter(Boolean);
    function spy() {
        if (content.scrollTop + content.clientHeight >= content.scrollHeight - 4) {
            setActive(sections[sections.length - 1].id); return;
        }
        var y = content.scrollTop + 80, cur = sections[0];
        for (var i = 0; i < sections.length; i++) { if (sections[i].offsetTop <= y) cur = sections[i]; }
        if (cur) setActive(cur.id);
    }
    content.addEventListener('scroll', spy);
    spy();

    window.PpDeployHelp = { open: open, close: close };
})();
</script>
