<?php declare(strict_types=1); ?>
<!-- ═══════════════════════════════════════════════════════════════════
     Custom Files — in-app Help & Guide
     Fully self-contained (own markup + styles + open/close script).
     Opened by any element with [data-cf-help-open]; closed by scrim,
     the × button, or Escape. Never touches the SPA's state.
     ══════════════════════════════════════════════════════════════════ -->
<style>
    .cfh-scrim { position:fixed; inset:0; z-index:10050; background:rgba(15,23,42,.55);
        backdrop-filter:blur(3px); display:none; opacity:0; transition:opacity .18s; }
    .cfh-scrim.open { display:block; opacity:1; }
    .cfh-modal { position:fixed; z-index:10051; top:3vh; bottom:3vh; left:50%;
        width:min(1060px, 94vw); transform:translateX(-50%) translateY(14px);
        background:#fff; 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; }
    .cfh-scrim.open .cfh-modal { transform:translateX(-50%) translateY(0); opacity:1; }

    .cfh-head { flex:0 0 auto; display:flex; align-items:center; gap:14px;
        padding:16px 22px; border-bottom:1px solid #e2e8f0;
        background:linear-gradient(120deg,#0c4a6e,#0369a1 60%,#0e7490); color:#fff; }
    .cfh-head .cfh-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); }
    .cfh-head h2 { margin:0; font-size:17px; font-weight:800; letter-spacing:-.01em; }
    .cfh-head p  { margin:2px 0 0; font-size:12px; opacity:.82; }
    .cfh-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; }
    .cfh-close:hover { background:rgba(255,255,255,.28); }

    .cfh-body { flex:1; min-height:0; display:grid; grid-template-columns:230px 1fr; }
    .cfh-toc { border-right:1px solid #e2e8f0; background:#f8fafc; overflow-y:auto; padding:14px 8px 24px; }
    .cfh-toc-group { font-size:9.5px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
        color:#94a3b8; padding:14px 14px 5px; }
    .cfh-toc a { display:flex; align-items:center; gap:9px; padding:7px 14px; border-radius:8px;
        margin:1px 6px; font-size:12.5px; color:#475569; text-decoration:none; cursor:pointer;
        border-left:3px solid transparent; }
    .cfh-toc a:hover { background:#e0f2fe; color:#0369a1; }
    .cfh-toc a.active { background:#e0f2fe; color:#0369a1; font-weight:700; border-left-color:#0e7490; }
    .cfh-toc a i { font-size:14px; width:16px; flex:0 0 16px; color:#38bdf8; }

    .cfh-content { position:relative; overflow-y:auto; padding:8px 40px 80px; scroll-behavior:smooth; color:#1e293b; }
    .cfh-content section { padding-top:26px; }
    .cfh-content h3 { font-size:21px; font-weight:800; letter-spacing:-.02em; margin:6px 0 4px;
        color:#0f172a; display:flex; align-items:center; gap:10px; }
    .cfh-content h3 .num { font-size:12px; font-weight:800; color:#0369a1; background:#e0f2fe;
        border-radius:8px; padding:3px 9px; }
    .cfh-content h4 { font-size:14.5px; font-weight:800; margin:22px 0 6px; color:#0c4a6e; }
    .cfh-content p  { font-size:13.5px; line-height:1.66; color:#334155; margin:8px 0; }
    .cfh-content ul, .cfh-content ol { font-size:13.5px; line-height:1.66; color:#334155;
        margin:8px 0; padding-left:22px; }
    .cfh-content li { margin:4px 0; }
    .cfh-lead { font-size:15px; line-height:1.65; color:#475569; }
    .cfh-content code { font-family:ui-monospace,Menlo,Consolas,monospace; font-size:12px;
        background:#f1f5f9; color:#0369a1; padding:1.5px 6px; border-radius:5px; }
    .cfh-content pre { background:#1e1e2e; color:#cdd6f4; border-radius:11px; padding:15px 17px;
        overflow-x:auto; margin:12px 0; font-size:12.5px; line-height:1.62;
        font-family:ui-monospace,Menlo,Consolas,monospace; border:1px solid #313244; }
    .cfh-content pre code { background:none; color:inherit; padding:0; font-size:inherit; }
    .cfh-content pre .c { color:#6c7086; }
    .cfh-content pre .k { color:#cba6f7; }
    .cfh-content pre .s { color:#a6e3a1; }
    .cfh-content pre .f { color:#89b4fa; }
    .cfh-content pre .v { color:#f9e2af; }

    .cfh-callout { display:flex; gap:12px; padding:13px 16px; border-radius:11px; margin:14px 0;
        font-size:13px; line-height:1.6; }
    .cfh-callout i { font-size:17px; flex:0 0 auto; margin-top:1px; }
    .cfh-callout.tip  { background:#ecfdf5; color:#065f46; } .cfh-callout.tip i { color:#059669; }
    .cfh-callout.warn { background:#fffbeb; color:#854d0e; } .cfh-callout.warn i { color:#d97706; }
    .cfh-callout.info { background:#eff6ff; color:#1e40af; } .cfh-callout.info i { color:#2563eb; }
    .cfh-callout.sec  { background:#fef2f2; color:#991b1b; } .cfh-callout.sec i { color:#dc2626; }

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

    .cfh-foot { margin-top:34px; padding-top:16px; border-top:1px solid #e2e8f0;
        font-size:12px; color:#94a3b8; }

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

<div class="cfh-scrim" id="cfHelpScrim" aria-hidden="true">
  <div class="cfh-modal pp-legacy-guide" role="dialog" aria-modal="true" aria-label="Custom Files help and guide">
    <div class="cfh-head">
      <div class="cfh-badge"><i class="bi bi-folder2-open"></i></div>
      <div>
        <h2>Custom Files — Guide</h2>
        <p>Bring your own pages, sites, scripts &amp; assets into the generated application.</p>
      </div>
      <button class="cfh-close" id="cfHelpClose" title="Close (Esc)" aria-label="Close"><i class="bi bi-x-lg" aria-hidden="true"></i></button>
    </div>

    <div class="cfh-body">
      <nav class="cfh-toc" id="cfHelpToc">
        <div class="cfh-toc-group">Basics</div>
        <a data-goto="c-what"><i class="bi bi-stars"></i> What is this?</a>
        <a data-goto="c-urls"><i class="bi bi-link-45deg"></i> Files → URLs</a>
        <a data-goto="c-add"><i class="bi bi-plus-circle"></i> Adding &amp; managing files</a>

        <div class="cfh-toc-group">The editor</div>
        <a data-goto="c-editor"><i class="bi bi-code-slash"></i> Code editor &amp; tabs</a>
        <a data-goto="c-find"><i class="bi bi-search"></i> Find &amp; replace</a>
        <a data-goto="c-preview"><i class="bi bi-window-split"></i> Live preview</a>
        <a data-goto="c-check"><i class="bi bi-bug"></i> Code check</a>

        <div class="cfh-toc-group">Recipes</div>
        <a data-goto="c-site"><i class="bi bi-globe2"></i> Add an existing website</a>
        <a data-goto="c-php"><i class="bi bi-filetype-php"></i> Dynamic PHP pages</a>
        <a data-goto="c-assets"><i class="bi bi-palette"></i> Shared CSS &amp; JS</a>

        <div class="cfh-toc-group">Reference</div>
        <a data-goto="c-reserved"><i class="bi bi-shield-lock"></i> Reserved paths</a>
        <a data-goto="c-faq"><i class="bi bi-question-circle"></i> Best practices &amp; FAQ</a>
      </nav>

      <div class="cfh-content" id="cfHelpContent">

        <section id="c-what">
          <h3><span class="num">01</span> What is Custom Files?</h3>
          <p class="cfh-lead">Custom Files is a <b>file manager for your project</b>. Anything you put here —
          single files or whole folder trees — is <b>copied into your generated application at build time</b>
          and served as if it were part of the app itself.</p>
          <p>Typical uses:</p>
          <ul>
            <li>Drop in an <b>existing website</b> (landing page, docs, brochure site) and serve it alongside your app.</li>
            <li>Add <b>custom PHP pages</b> that use the app's database, auth, and helpers.</li>
            <li>Ship extra <b>CSS, JavaScript, images, fonts, or downloads</b> with every build.</li>
            <li>Override generated files (e.g. replace a favicon or add a <code>robots.txt</code> of your own).</li>
          </ul>
          <div class="cfh-callout info"><i class="bi bi-info-circle-fill"></i>
            <div>Files live with your <b>project</b>, not the output — every <b>Build</b> re-copies them, so
            rebuilding never loses your work and your app folder can always be regenerated from scratch.</div></div>

          <h4>What the editor gives you</h4>
          <ul>
            <li><b>IntelliSense for HTML, CSS, JS &amp; PHP</b> — context-aware, even mixed in one file.</li>
            <li><b>Live error checking</b> — mistakes get a red line as you type.</li>
            <li><b>Live preview</b> with responsive <b>Desktop / Tablet / Mobile</b> sizes, and a real
              <b>sandboxed run</b> for PHP.</li>
            <li><b>Image, video, audio &amp; PDF viewers</b> — click any media file to see it.</li>
            <li>Multi-file tabs, find &amp; replace, full-screen, and a desktop-style file tree (drag,
              rename-in-place, right-click menu).</li>
          </ul>
        </section>

        <section id="c-urls">
          <h3><span class="num">02</span> How files map to URLs</h3>
          <p>The folder structure you create here is preserved exactly. A file's path in Custom Files becomes
          its path in the deployed application:</p>
          <table class="cfh-table">
            <thead><tr><th>In Custom Files</th><th>In the generated app</th><th>Served at</th></tr></thead>
            <tbody>
              <tr><td><code>site/index.html</code></td><td><code>&lt;app&gt;/site/index.html</code></td><td><code>/site/index.html</code></td></tr>
              <tr><td><code>site/css/style.css</code></td><td><code>&lt;app&gt;/site/css/style.css</code></td><td><code>/site/css/style.css</code></td></tr>
              <tr><td><code>assets/brand.css</code></td><td>merged into the app's <code>assets/</code></td><td><code>/assets/brand.css</code></td></tr>
              <tr><td><code>tools/report.php</code></td><td><code>&lt;app&gt;/tools/report.php</code></td><td><code>/tools/report.php</code></td></tr>
              <tr><td><code>favicon.ico</code></td><td><code>&lt;app&gt;/favicon.ico</code></td><td><code>/favicon.ico</code></td></tr>
            </tbody>
          </table>
          <p>Where a custom file and a generated file share the same path, <b>your custom file wins</b> —
          it is copied after generation. The only exception is the reserved system paths (see
          <a style="color:#0369a1;font-weight:600;cursor:pointer" data-goto-inline="c-reserved">Reserved paths</a>).</p>
        </section>

        <section id="c-add">
          <h3><span class="num">03</span> Adding &amp; managing files</h3>
          <h4>Create — just like on your desktop</h4>
          <p>Creating files works the way it does in a desktop file manager or code editor — no path typing.
          <b>Click a folder to select it</b> (the <i class="bi bi-house-door-fill"></i> location bar at the top
          of the tree shows where you are), then:</p>
          <ul>
            <li><b>File</b> / <b>Folder</b> (toolbar), or the <i class="bi bi-file-earmark-plus"></i> that appears
              when you hover a folder — a text box appears <b>right inside that folder</b>. Type the name and press
              <kbd>Enter</kbd> to create it (<kbd>Esc</kbd> cancels). New files start from a small boilerplate for
              their type (HTML/CSS/JSON/Markdown).</li>
            <li>Need a subfolder in one step? Type a path in that box, e.g. <code>js/app.js</code> — any missing
              folders are created for you.</li>
            <li>The <i class="bi bi-house-door-fill"></i> in the location bar targets the project root; click any
              crumb to move up.</li>
          </ul>
          <h4>Upload</h4>
          <ul>
            <li><b>Upload</b> button — pick one or many files.</li>
            <li><b>Drag &amp; drop from your computer</b> — drop files anywhere on the file tree; they land in the selected folder.</li>
          </ul>
          <h4>Right-click any file or folder</h4>
          <p>The context menu is the fastest way to manage the tree:</p>
          <table class="cfh-table">
            <thead><tr><th>Action</th><th>What it does</th></tr></thead>
            <tbody>
              <tr><td><i class="bi bi-pencil-square"></i> <b>Open / Edit</b></td><td>Opens the file in a new editor tab.</td></tr>
              <tr><td><i class="bi bi-file-earmark-plus"></i> <b>New file / folder here</b></td><td>Creates an item inside the folder you clicked.</td></tr>
              <tr><td><i class="bi bi-pencil"></i> <b>Rename</b></td><td>Renames in place.</td></tr>
              <tr><td><i class="bi bi-arrows-move"></i> <b>Move to…</b></td><td>Type a target folder (leave blank for the root) to relocate the item.</td></tr>
              <tr><td><i class="bi bi-files"></i> <b>Duplicate</b></td><td>Makes a copy alongside the original.</td></tr>
              <tr><td><i class="bi bi-download"></i> <b>Download</b></td><td>Saves that single file to your computer.</td></tr>
              <tr><td><i class="bi bi-trash3"></i> <b>Delete</b></td><td>Removes the item (folders remove everything inside — you'll confirm first).</td></tr>
            </tbody>
          </table>
          <h4>Drag to move, search to find, ZIP to take it all</h4>
          <ul>
            <li><b>Drag within the tree</b> — grab any file or folder and drop it onto another folder (or the empty area at the top for the root) to move it. Open tabs follow the move automatically.</li>
            <li><b>Filter box</b> <i class="bi bi-search"></i> — type to shrink the tree to matching files; folders stay visible when something inside them matches. Clear it to drag again.</li>
            <li><b>Download ZIP</b> <i class="bi bi-file-earmark-zip"></i> (toolbar) — downloads your entire Custom Files tree as one archive, structure preserved — handy for backups or moving work between projects.</li>
          </ul>
          <div class="cfh-callout tip"><i class="bi bi-lightbulb-fill"></i>
            <div>Every rename, move and delete confirms or prompts with a styled dialog — no jarring browser
            pop-ups — and the tree refreshes instantly so you always see the real state on disk.</div></div>
        </section>

        <section id="c-editor">
          <h3><span class="num">04</span> The code editor &amp; tabs</h3>
          <p class="cfh-lead">Click any text file to open it in a full editor with <b>syntax highlighting</b>,
          a line-number gutter, and smart typing helpers. Images preview inline; binaries show their size.</p>
          <h4>Multiple files at once</h4>
          <p>Each file you open gets its own <b>tab</b> along the top. A dot on a tab means unsaved changes;
          click the <i class="bi bi-x"></i> (or middle-click the tab) to close it. You'll be warned before
          closing a tab or leaving the page with unsaved work.</p>
          <h4>IntelliSense &amp; syntax highlighting</h4>
          <p>The editor is a full <b>code editor with IntelliSense</b> for <b>HTML, CSS, JavaScript and PHP</b>
          (plus JSON, SQL, XML and Markdown). Suggestions appear as you type — press <kbd>⌘/Ctrl&nbsp;Space</kbd>
          to open them any time. It's <b>context-aware in mixed files</b>: in one <code>.php</code> or
          <code>.html</code> file you get <b>CSS</b> completions inside <code>&lt;style&gt;</code>,
          <b>JavaScript</b> inside <code>&lt;script&gt;</code>, <b>HTML</b> tags/attributes in the markup, and
          <b>PHP</b> keywords &amp; platform helpers (<code>dbAll</code>, <code>pp_send_email</code>, …) inside
          <code>&lt;?php ?&gt;</code> — automatically, based on where your cursor is. Everything is bundled —
          no internet needed.</p>
          <p><b>Example</b> — in a single <code>.php</code> file, the suggestions change with the cursor:</p>
          <pre><code><span class="c">&lt;style&gt;</span>
  .box { colo|          <span class="c">← CSS: color, color-scheme…</span>
<span class="c">&lt;/style&gt;</span>
<span class="c">&lt;script&gt;</span>
  document.qu|          <span class="c">← JS: querySelector, querySelectorAll…</span>
<span class="c">&lt;/script&gt;</span>
&lt;div cla|              <span class="c">← HTML: class, contenteditable…</span>
<span class="k">&lt;?php</span> db|            <span class="c">← PHP: dbAll, dbRow, dbValue, dbLookup…</span></code></pre>
          <h4>Smart typing</h4>
          <ul>
            <li><b>Auto-close</b> brackets, quotes and HTML tags; type the closer and it skips over.</li>
            <li><b>Auto-indent</b> on <kbd>Enter</kbd>; <b>bracket &amp; tag matching</b> highlights the pair.</li>
            <li><b>Block indent</b> — <kbd>Tab</kbd> / <kbd>Shift Tab</kbd> indent or outdent the selection.</li>
            <li><b>Toggle comment</b> — <kbd>⌘/Ctrl /</kbd> comments or uncomments the selected lines.</li>
            <li><b>Undo / Redo</b> — the <i class="bi bi-arrow-counterclockwise"></i> / <i class="bi bi-arrow-clockwise"></i>
              buttons in the header, or <kbd>⌘/Ctrl Z</kbd> and <kbd>⌘/Ctrl&nbsp;Shift Z</kbd>; the buttons grey out
              when there's nothing left to undo or redo.</li>
            <li><b>Save</b> — <kbd>⌘/Ctrl S</kbd>.</li>
          </ul>
          <h4>Around the editor</h4>
          <ul>
            <li><b>Line numbers</b> and a live <b>error gutter</b> run down the left edge.</li>
            <li><b>Images &amp; media open in a viewer</b> — click a PNG/JPG/GIF/WebP/SVG (any size) to see it on a
              transparency checkerboard with its dimensions; video, audio and PDF files play/render too.</li>
            <li>The <i class="bi bi-layout-sidebar"></i> button (top-left) <b>shows or hides the file sidebar</b> for a wider editing area.</li>
            <li>The <i class="bi bi-fullscreen"></i> <b>Full screen</b> button maximises the editor; press <kbd>Esc</kbd> to exit.</li>
            <li>The <b>status bar</b> along the bottom shows the language, the URL the file is served at, cursor line &amp; column, selection size, total lines, file size and indentation.</li>
          </ul>
        </section>

        <section id="c-find">
          <h3><span class="num">05</span> Find &amp; replace</h3>
          <p>Press <kbd>⌘/Ctrl F</kbd> to open the find bar, or <kbd>⌘/Ctrl H</kbd> to open it with the
          replace row showing. As you type you'll see a <b>match count</b>.</p>
          <ul>
            <li><i class="bi bi-chevron-down"></i> / <i class="bi bi-chevron-up"></i> — jump to the next / previous match.</li>
            <li><b>Replace</b> — swap the current match and move to the next one.</li>
            <li><b>Replace all</b> — swap every match in the file at once.</li>
            <li><kbd>Esc</kbd> closes the bar.</li>
          </ul>
          <div class="cfh-callout info"><i class="bi bi-info-circle-fill"></i>
            <div>Find &amp; replace works on the file in the active tab. Remember to <kbd>⌘/Ctrl S</kbd> to save
            your changes — nothing is written until you do.</div></div>
        </section>

        <section id="c-preview">
          <h3><span class="num">06</span> Live preview</h3>
          <p>For visual files, the editor header shows a segmented
          <b>Code&nbsp;·&nbsp;Split&nbsp;·&nbsp;Preview</b> switch:</p>
          <ul>
            <li><b>Code</b> — the code only.</li>
            <li><b>Split</b> — code on the left, a live rendering on the right that updates as you type.</li>
            <li><b>Preview</b> — the rendering only.</li>
          </ul>
          <p>When a preview is showing, a second control lets you check <b>responsive breakpoints</b> —
          <i class="bi bi-display"></i> <b>Desktop</b> (full width), <i class="bi bi-tablet-landscape"></i>
          <b>Tablet</b> (768px) and <i class="bi bi-phone"></i> <b>Mobile</b> (390px) — so you can see how a
          page reflows on different screens without leaving the editor.</p>
          <p>Previewable types include <code>.html</code>, <code>.htm</code>, <code>.svg</code>,
          <code>.css</code> (shown on a demo page), <code>.md</code> / <code>.markdown</code> (rendered
          as formatted text), and <code>.php</code> / <code>.phtml</code> — which are <b>actually executed</b>
          so you see the real output. Use <i class="bi bi-box-arrow-up-right"></i> <b>Open in new tab</b> for a
          full-screen view.</p>
          <h4>Running PHP</h4>
          <p>When you preview a PHP file it runs in a <b>locked-down sandbox</b> on the server and shows the
          real output — including <b>runtime errors</b> (e.g. a call to an undefined function). A badge at the
          top of the preview shows the result (<i class="bi bi-lightning-charge-fill"></i> ran · time,
          <i class="bi bi-bug-fill"></i> error, or timed out); <b>click the badge to re-run</b>. It also
          re-runs automatically shortly after you stop typing.</p>
          <p><b>Example</b> — this file has a typo (<code>ucword</code> instead of <code>ucwords</code>):</p>
          <pre><code><span class="k">&lt;?php</span>
<span class="v">$res</span> = <span class="f">ucword</span>(<span class="s">"ramesh khadka"</span>);
<span class="k">echo</span> <span class="v">$res</span>;</code></pre>
          <p>Syntax is valid, so <b>Check</b> passes — but the <b>preview runs it</b> and shows the real error:
          <code>Fatal error: Call to undefined function ucword()</code>. Fix it to <code>ucwords()</code> and the
          preview instantly shows <code>Ramesh Khadka</code>. That's the value of running vs. only linting.</p>
          <div class="cfh-callout info"><i class="bi bi-shield-check"></i>
            <div>The sandbox runs <b>your own project code</b> with shell/exec, networking and mail disabled,
            the filesystem confined to your Custom Files folder, and hard limits (5&nbsp;second timeout,
            64&nbsp;MB). It's for quick checks — pages that need the app's database or <code>_runtime.php</code>
            won't have them here; <b>Build</b> to run in the full app context.</div></div>
          <div class="cfh-callout warn"><i class="bi bi-exclamation-triangle-fill"></i>
            <div>The preview is a <b>safe, sandboxed render for design work</b> — it serves your files as static
            content, so <b>PHP is shown as source, not executed</b>. To see a dynamic PHP page actually run,
            <b>Build</b> and open it in the generated app.</div></div>
        </section>

        <section id="c-check">
          <h3><span class="num">07</span> Code check</h3>
          <p>Errors are flagged <b>as you type</b>: the offending line gets a <b>red marker in the gutter</b>,
          a <b>wavy underline</b> and a red tint, and hovering the marker shows the message. For a full list,
          the <b><i class="bi bi-bug"></i> Check</b> button parses the current file into a problems panel —
          <b>click a problem to jump to that line</b>. A check also runs automatically every time you save.</p>
          <table class="cfh-table">
            <thead><tr><th>File type</th><th>Checker</th><th>Catches</th></tr></thead>
            <tbody>
              <tr><td><code>.php</code></td><td>PHP linter (<code>php -l</code>)</td><td>Parse/fatal errors with the exact line.</td></tr>
              <tr><td><code>.js</code> / <code>.mjs</code></td><td>Node syntax check</td><td>Syntax errors with the line.</td></tr>
              <tr><td><code>.json</code></td><td>JSON parser</td><td>Invalid JSON (trailing commas, quotes…).</td></tr>
              <tr><td><code>.css</code></td><td>Structure scan</td><td>Unbalanced <code>{ }</code>, unclosed comments.</td></tr>
              <tr><td><code>.html</code></td><td>HTML parser</td><td>Mismatched / unclosed tags.</td></tr>
            </tbody>
          </table>
          <div class="cfh-callout tip"><i class="bi bi-lightbulb-fill"></i>
            <div>Checkers only <b>parse</b> your code — nothing is executed. Fix everything the panel reports
            before you build, and your custom pages will run cleanly in the generated app.</div></div>
        </section>

        <section id="c-site">
          <h3><span class="num">05</span> Recipe — add an existing website</h3>
          <ol>
            <li>Create a folder for it, e.g. <code>site</code> (keeps it tidy and collision-free).</li>
            <li>Select the folder, then <b>Upload</b> or drag &amp; drop your site's files
              (<code>index.html</code>, css, js, images…). Recreate subfolders with <b>Folder</b> as needed.</li>
            <li>Press <b>Build</b>. Your site is now served at <code>/site/index.html</code>.</li>
            <li>To link it from the app's navigation: <b>Style → Menu Editor</b> → add an item whose URL is
              <code>/site/index.html</code>.</li>
          </ol>
          <div class="cfh-callout info"><i class="bi bi-info-circle-fill"></i>
            <div>Use <b>relative</b> links inside your site (<code>css/style.css</code>, not
            <code>/css/style.css</code>) so it works no matter where the app is hosted.</div></div>
        </section>

        <section id="c-php">
          <h3><span class="num">06</span> Recipe — dynamic PHP pages</h3>
          <p>A custom PHP file can plug straight into the generated app's runtime — database, auth, email,
          proxy helpers — by requiring <code>_runtime.php</code>:</p>
          <pre><code><span class="c">&lt;?php</span>
<span class="c">// custom file: tools/report.php  →  served at /tools/report.php</span>
<span class="k">require_once</span> __DIR__ . <span class="s">'/../_runtime.php'</span>;   <span class="c">// one ../ per folder level</span>
\PpPhp\Core\<span class="v">Security</span>::<span class="f">RequireAuth</span>();          <span class="c">// only signed-in users</span>

<span class="v">$rows</span> = \PpPhp\Core\<span class="v">DB</span>::<span class="f">FetchAll</span>(<span class="s">'SELECT status, COUNT(*) n FROM orders GROUP BY status'</span>);
<span class="c">?&gt;</span>
&lt;h1&gt;Order report&lt;/h1&gt;
&lt;ul&gt;
&lt;?php <span class="k">foreach</span> (<span class="v">$rows</span> <span class="k">as</span> <span class="v">$r</span>): ?&gt;
    &lt;li&gt;&lt;?= <span class="f">htmlspecialchars</span>(<span class="v">$r</span>[<span class="s">'status'</span>]) ?&gt;: &lt;?= (<span class="k">int</span>) <span class="v">$r</span>[<span class="s">'n'</span>] ?&gt;&lt;/li&gt;
&lt;?php <span class="k">endforeach</span>; ?&gt;
&lt;/ul&gt;</code></pre>
          <p>Everything from the Events toolkit is available too: <code>DB::</code>, <code>Security::</code>,
          <code>pp_send_email()</code>, <code>pp_set_proxy()</code>, <code>pp_store_upload()</code>, and your
          own <b>Custom Functions</b> and <code>action_*</code> server actions.</p>
          <div class="cfh-callout sec"><i class="bi bi-shield-exclamation"></i>
            <div><b>Security:</b> a custom PHP page is public unless you guard it. Start protected pages with
            <code>Security::RequireAuth()</code>, and escape every value you print with
            <code>htmlspecialchars()</code>.</div></div>
        </section>

        <section id="c-assets">
          <h3><span class="num">07</span> Recipe — shared CSS &amp; JS for the whole app</h3>
          <p>Two ways to ship extra styles/scripts that the <b>generated pages</b> use:</p>
          <ul>
            <li><b>Merge into assets:</b> put files under <code>assets/</code> here (e.g.
              <code>assets/brand.css</code>) — they merge into the app's assets folder and are available at
              <code>/assets/brand.css</code>.</li>
            <li><b>Load them on every page:</b> in <b>Events → Application → JavaScript OnLoad</b>, inject the
              tag once for all pages:</li>
          </ul>
          <pre><code><span class="c">// Events → app → jsOnLoad (runs on every generated page)</span>
<span class="k">const</span> l = <span class="f">document</span>.<span class="f">createElement</span>(<span class="s">'link'</span>);
l.rel = <span class="s">'stylesheet'</span>; l.href = pp.base + <span class="s">'/assets/brand.css'</span>;
<span class="f">document</span>.head.<span class="f">appendChild</span>(l);</code></pre>
        </section>

        <section id="c-reserved">
          <h3><span class="num">08</span> Reserved paths</h3>
          <p>These top-level names belong to the generated runtime. Files you place under them are
          <b>skipped at build</b> (and flagged with a <span style="font-size:10px;font-weight:700;color:#b45309;background:#fef3c7;border-radius:4px;padding:0 4px;">reserved</span> badge in the tree) so a stray upload can never break your app:</p>
          <p><code>_runtime.php</code> · <code>index.php</code> · <code>app-shell.php</code> ·
          <code>cron.php</code> · <code>routes.json</code> · <code>manifest.json</code> ·
          <code>database.sql</code> · <code>core/</code> · <code>app/</code> · <code>api/</code> ·
          <code>config/</code> · <code>generated/</code> · <code>plugins/</code></p>
          <p>Everything else — including <code>assets/</code> and <code>uploads/</code> additions, new folders,
          and root-level files — is copied and may override generated output.</p>
        </section>

        <section id="c-faq">
          <h3><span class="num">09</span> Best practices &amp; FAQ</h3>
          <ul>
            <li><b>Keep your site in its own folder</b> (<code>site/</code>, <code>docs/</code>…) so it can't collide with generated pages.</li>
            <li><b>Run Check before building</b> — a PHP parse error in a custom page would 500 in the app.</li>
            <li><b>Use relative asset links</b> inside custom sites so subdirectory hosting works.</li>
            <li><b>Guard dynamic pages</b> with <code>Security::RequireAuth()</code> when they aren't public.</li>
          </ul>
          <h4>When do my changes go live?</h4>
          <p>On the next <b>Build</b> — Custom Files are copied into the output as build step 13b. Editing here
          never touches the running app directly.</p>
          <h4>I deleted a file here — is it gone from my app?</h4>
          <p>After the next Build, yes: builds regenerate the app, and only files still present get copied.</p>
          <h4>Can I edit binary files?</h4>
          <p>Images preview inline; other binaries show a notice. Replace them by uploading a file with the
          same name.</p>
          <div class="cfh-foot"><?= htmlspecialchars(\PpPhp\Core\Brand::name()) ?> Custom Files — your files, served as part of the app.
          Press <kbd>Esc</kbd> or click outside to close.</div>
        </section>

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

<script>
(function () {
    var scrim   = document.getElementById('cfHelpScrim');
    var closeB  = document.getElementById('cfHelpClose');
    var toc     = document.getElementById('cfHelpToc');
    var content = document.getElementById('cfHelpContent');
    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) {
        var t = e.target.closest('[data-cf-help-open]');
        if (t) { e.preventDefault(); open(); }
        var inline = e.target.closest('[data-goto-inline]');
        if (inline) { goTo(inline.dataset.gotoInline); }
    });
    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.PpCustomFilesHelp = { open: open, close: close };
})();
</script>
