<?php declare(strict_types=1); ?>
<!-- Tables module — in-app Help & Guide. Open with [data-tables-help-open]. -->
<style>
    .tgh-scrim { position:fixed; inset:0; z-index:10050; display:none; opacity:0; background:rgba(15,23,42,.55); backdrop-filter:blur(3px); transition:opacity .18s ease; }
    .tgh-scrim.open { display:block; opacity:1; }
    .tgh-modal { position:fixed; z-index:10051; top:3vh; bottom:3vh; left:50%; width:min(1080px,94vw); transform:translateX(-50%) translateY(14px); display:flex; flex-direction:column; overflow:hidden; background:#fff; border-radius:16px; box-shadow:0 32px 80px rgba(2,6,23,.45); opacity:0; transition:transform .2s ease, opacity .2s ease; }
    .tgh-scrim.open .tgh-modal { transform:translateX(-50%) translateY(0); opacity:1; }
    .tgh-head { flex:0 0 auto; display:flex; align-items:center; gap:14px; padding:16px 22px; color:#fff; background:linear-gradient(120deg,#0f766e,#2563eb 62%,#7c3aed); border-bottom:1px solid rgba(255,255,255,.15); }
    .tgh-badge { width:42px; height:42px; flex:0 0 42px; border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:20px; background:rgba(255,255,255,.16); }
    .tgh-head h2 { margin:0; font-size:17px; font-weight:850; letter-spacing:-.01em; }
    .tgh-head p { margin:2px 0 0; font-size:12px; opacity:.84; }
    .tgh-close { margin-left:auto; width:34px; height:34px; border:0; border-radius:9px; display:flex; align-items:center; justify-content:center; color:#fff; background:rgba(255,255,255,.14); font-size:19px; cursor:pointer; }
    .tgh-close:hover { background:rgba(255,255,255,.28); }
    .tgh-body { flex:1; min-height:0; display:grid; grid-template-columns:232px 1fr; }
    .tgh-toc { overflow-y:auto; padding:14px 8px 24px; background:#f8fafc; border-right:1px solid #e2e8f0; }
    .tgh-toc-group { padding:13px 14px 5px; color:#94a3b8; font-size:9.5px; font-weight:850; letter-spacing:.08em; text-transform:uppercase; }
    .tgh-toc a { display:flex; align-items:center; gap:9px; margin:1px 6px; padding:7px 14px; border-radius:8px; border-left:3px solid transparent; color:#475569; font-size:12.5px; text-decoration:none; cursor:pointer; }
    .tgh-toc a:hover, .tgh-toc a.active { background:#eef2ff; color:#2563eb; border-left-color:#2563eb; font-weight:700; }
    .tgh-toc a i { width:16px; flex:0 0 16px; color:#3b82f6; }
    .tgh-content { overflow-y:auto; padding:8px 40px 74px; color:#1e293b; scroll-behavior:smooth; }
    .tgh-content section { padding-top:26px; }
    .tgh-content h3 { display:flex; align-items:center; gap:10px; margin:6px 0 5px; color:#0f172a; font-size:21px; font-weight:850; letter-spacing:-.02em; }
    .tgh-content h3 .num { padding:3px 9px; border-radius:8px; background:#dbeafe; color:#1d4ed8; font-size:12px; font-weight:850; }
    .tgh-content h4 { margin:20px 0 6px; color:#1e40af; font-size:14.5px; font-weight:850; }
    .tgh-content p, .tgh-content li { color:#334155; font-size:13.4px; line-height:1.65; }
    .tgh-content ul, .tgh-content ol { margin:8px 0; padding-left:22px; }
    .tgh-content li { margin:3px 0; }
    .tgh-lead { color:#475569; font-size:15px; line-height:1.65; }
    .tgh-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:12px; margin:14px 0; }
    .tgh-card { padding:14px; border:1px solid #e2e8f0; border-radius:13px; background:#fff; box-shadow:0 1px 2px rgba(15,23,42,.04); }
    .tgh-card .ic { width:34px; height:34px; display:flex; align-items:center; justify-content:center; margin-bottom:9px; border-radius:10px; font-size:16px; }
    .tgh-card h5 { margin:0 0 4px; color:#0f172a; font-size:13.5px; font-weight:850; }
    .tgh-card p { margin:0; color:#64748b; font-size:12.2px; line-height:1.5; }
    .tgh-callout { display:flex; gap:12px; margin:14px 0; padding:13px 16px; border-radius:12px; font-size:13px; line-height:1.6; }
    .tgh-callout i { flex:0 0 auto; margin-top:1px; font-size:17px; }
    .tgh-callout.info { background:#eff6ff; color:#1e40af; }
    .tgh-callout.tip { background:#ecfdf5; color:#065f46; }
    .tgh-callout.warn { background:#fffbeb; color:#854d0e; }
    .tgh-table { width:100%; margin:12px 0; border-collapse:collapse; font-size:12.5px; }
    .tgh-table th { padding:8px 11px; color:#475569; background:#f8fafc; border-bottom:2px solid #e2e8f0; text-align:left; font-size:11px; font-weight:850; text-transform:uppercase; letter-spacing:.03em; }
    .tgh-table td { padding:8px 11px; border-bottom:1px solid #f1f5f9; vertical-align:top; color:#334155; }
    .tgh-content code { padding:1.5px 6px; border-radius:5px; background:#f1f5f9; color:#6d28d9; font-family:ui-monospace,Menlo,Consolas,monospace; font-size:12px; }
    .tgh-kbd { display:inline-flex; align-items:center; padding:1px 6px; border:1px solid #cbd5e1; border-bottom-width:2px; border-radius:5px; background:#fff; color:#334155; font-size:11px; font-weight:700; }
    /* Code blocks for worked SQL examples */
    .tgh-pre { margin:11px 0; padding:13px 16px; border-radius:11px; background:#0f172a; color:#e2e8f0; font-family:ui-monospace,Menlo,Consolas,monospace; font-size:12px; line-height:1.7; overflow-x:auto; box-shadow:0 1px 3px rgba(2,6,23,.25); }
    .tgh-pre code { padding:0; background:none; color:inherit; font-size:inherit; white-space:pre; }
    .tgh-pre .c { color:#64748b; font-style:italic; }
    .tgh-pre .k { color:#7dd3fc; font-weight:700; }
    .tgh-pre .s { color:#86efac; }
    /* Worked-example wrapper — theme-adaptive (translucent surfaces + inherited text so it reads
       correctly whether the host paints the guide light or forces light text on a dark shell). */
    .tgh-eg { margin:14px 0; border:1px solid rgba(148,163,184,.32); border-radius:13px; overflow:hidden; }
    .tgh-eg-h { display:flex; align-items:center; gap:9px; padding:9px 15px; background:rgba(148,163,184,.13); border-bottom:1px solid rgba(148,163,184,.28); color:inherit; font-size:12.8px; font-weight:800; }
    .tgh-eg-h .tag { font-size:9.5px; font-weight:850; letter-spacing:.06em; text-transform:uppercase; padding:2px 8px; border-radius:20px; background:rgba(37,99,235,.18); color:#2563eb; }
    .tgh-eg-h .tag.rec { background:rgba(22,163,74,.18); color:#16a34a; }
    .tgh-eg-b { padding:4px 15px 12px; }
    .tgh-eg-b .tgh-pre { margin-top:11px; }
    /* Tips grid */
    .tgh-tips { display:grid; grid-template-columns:repeat(auto-fit,minmax(255px,1fr)); gap:12px; margin:14px 0; }
    .tgh-tip { display:flex; gap:11px; padding:13px 15px; border:1px solid rgba(148,163,184,.3); border-radius:12px; background:rgba(148,163,184,.08); }
    .tgh-tip i { flex:0 0 auto; font-size:17px; color:#f59e0b; margin-top:1px; }
    .tgh-tip > div { min-width:0; }
    .tgh-tip > div > b { display:block; color:inherit; font-size:12.8px; margin-bottom:2px; }
    .tgh-tip span { color:inherit; opacity:.78; font-size:12px; line-height:1.55; }
    .tgh-tip span b { color:inherit; }
    /* Shortcut rows */
    .tgh-kbds { display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:2px 26px; margin:12px 0; }
    .tgh-kbd-row { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:7px 2px; border-bottom:1px dashed rgba(148,163,184,.32); font-size:12.6px; color:inherit; }
    /* Pills */
    .tgh-pill-row { display:flex; flex-wrap:wrap; gap:6px; margin:9px 0; }
    .tgh-pill { font-size:11px; font-weight:700; padding:3px 10px; border-radius:20px; background:rgba(99,102,241,.15); color:#6366f1; border:1px solid rgba(99,102,241,.3); }
    @media (max-width:760px) { .tgh-body { grid-template-columns:1fr; } .tgh-toc { display:none; } .tgh-content { padding:8px 20px 60px; } }
</style>

<div class="tgh-scrim" id="tablesHelpScrim" aria-hidden="true">
    <div class="tgh-modal pp-legacy-guide" role="dialog" aria-modal="true" aria-label="Tables help and guide">
        <div class="tgh-head">
            <div class="tgh-badge"><i class="bi bi-diagram-3-fill"></i></div>
            <div>
                <h2>Tables — Complete Guide</h2>
                <p>Model data, write views &amp; SQL, link relationships, add a calendar — with worked examples and pro tips.</p>
            </div>
            <button class="tgh-close" id="tablesHelpClose" title="Close (Esc)" aria-label="Close"><i class="bi bi-x-lg" aria-hidden="true"></i></button>
        </div>

        <div class="tgh-body">
            <nav class="tgh-toc" id="tablesHelpToc">
                <div class="tgh-toc-group">Start</div>
                <a data-goto="tg-overview"><i class="bi bi-stars"></i> What Tables does</a>
                <a data-goto="tg-interface"><i class="bi bi-layout-sidebar"></i> Interface &amp; toolbar</a>
                <a data-goto="tg-persistence"><i class="bi bi-filetype-json"></i> What is saved</a>

                <div class="tgh-toc-group">Schema</div>
                <a data-goto="tg-create"><i class="bi bi-plus-circle"></i> Create table</a>
                <a data-goto="tg-edit"><i class="bi bi-pencil-square"></i> Edit table</a>
                <a data-goto="tg-defaults"><i class="bi bi-braces"></i> Defaults &amp; field types</a>
                <a data-goto="tg-views"><i class="bi bi-eye"></i> Custom / SQL views</a>
                <a data-goto="tg-sync"><i class="bi bi-arrow-repeat"></i> Sync database</a>

                <div class="tgh-toc-group">SQL Console</div>
                <a data-goto="tg-sqleditor"><i class="bi bi-terminal"></i> SQL Editor</a>
                <a data-goto="tg-recipes"><i class="bi bi-journal-code"></i> Recipes &amp; examples</a>

                <div class="tgh-toc-group">Relationships</div>
                <a data-goto="tg-relations"><i class="bi bi-link-45deg"></i> Link tables</a>
                <a data-goto="tg-relation-options"><i class="bi bi-sliders"></i> Relation settings</a>

                <div class="tgh-toc-group">More</div>
                <a data-goto="tg-calendar"><i class="bi bi-calendar3"></i> Calendar &amp; Events</a>
                <a data-goto="tg-tips"><i class="bi bi-lightbulb"></i> Tips &amp; tricks</a>
                <a data-goto="tg-workflow"><i class="bi bi-check2-square"></i> Recommended workflow</a>
            </nav>

            <main class="tgh-content" id="tablesHelpContent">
                <section id="tg-overview">
                    <h3><span class="num">1</span> What the Tables module does</h3>
                    <p class="tgh-lead">The Tables module is the <b>data-model workspace</b> for a project. Choose which database tables and views belong to the app, create new tables, build SQL-backed views, run arbitrary SQL scripts safely, arrange everything visually, define master–detail relationships, and even provision a full event calendar — all against your project's real database, in any of the eight engines the platform supports.</p>
                    <div class="tgh-grid">
                        <div class="tgh-card"><div class="ic" style="background:#ecfeff;color:#0891b2"><i class="bi bi-table"></i></div><h5>Tables</h5><p>Create and modify physical tables — fields, types, keys, nullability, and defaults — with the right SQL emitted per engine.</p></div>
                        <div class="tgh-card"><div class="ic" style="background:#eef2ff;color:#4f46e5"><i class="bi bi-eye"></i></div><h5>Views</h5><p>SELECT-based views for reporting, joins, and read-focused pages, with a schema explorer + autocomplete to write them fast.</p></div>
                        <div class="tgh-card"><div class="ic" style="background:#fef2f2;color:#dc2626"><i class="bi bi-terminal"></i></div><h5>SQL Editor</h5><p>Paste &amp; run any script (schema, seed, migration) with a plan preview, dialect converter, dry run, and error highlighting.</p></div>
                        <div class="tgh-card"><div class="ic" style="background:#f0fdf4;color:#16a34a"><i class="bi bi-link-45deg"></i></div><h5>Relations</h5><p>Define master–detail relationships and how child/master records appear on generated pages.</p></div>
                        <div class="tgh-card"><div class="ic" style="background:#eef2ff;color:#6366f1"><i class="bi bi-calendar3"></i></div><h5>Calendar &amp; Events</h5><p>Add a complete event-management calendar app — RSVP, reminders, sharing, recurring events, iCal — provisioned at Build.</p></div>
                        <div class="tgh-card"><div class="ic" style="background:#fff7ed;color:#ea580c"><i class="bi bi-save"></i></div><h5>Project state</h5><p>Selected tables, card layout, relation settings, view SQL, and schema metadata are saved into project JSON.</p></div>
                    </div>
                    <div class="tgh-callout info"><i class="bi bi-info-circle"></i><div><b>Eight engines, one workspace.</b> Everything here runs on the project's own connection, so the same buttons work whether the project is on MySQL, MariaDB, TiDB, PostgreSQL, CockroachDB, SQL&nbsp;Server, SQLite, or Oracle — the module emits the correct SQL for each.</div></div>
                </section>

                <section id="tg-interface">
                    <h3><span class="num">2</span> Interface &amp; toolbar</h3>
                    <table class="tgh-table">
                        <tr><th>Area</th><th>Purpose</th></tr>
                        <tr><td>Left table list</td><td>Project tables/views, listed separately from protected system tables. Use search for large projects; check a table to include it in the app.</td></tr>
                        <tr><td>Workspace cards</td><td>Selected tables appear as draggable cards. Expand a card to inspect fields, types, and keys.</td></tr>
                        <tr><td>Toolbar</td><td>Create tables/views, open the SQL Editor, add a calendar, synchronize the database, link tables, and open this guide.</td></tr>
                        <tr><td>Relation arrows</td><td>Visualize master↔detail links. Double-click an arrow to edit or delete the relation.</td></tr>
                    </table>

                    <h4>Toolbar buttons at a glance</h4>
                    <table class="tgh-table">
                        <tr><th>Button</th><th>What it opens / does</th></tr>
                        <tr><td><b><i class="bi bi-plus-lg"></i> Create Table</b></td><td>Design and create a new physical database table (§4).</td></tr>
                        <tr><td><b><i class="bi bi-eye"></i> Create Custom View</b></td><td>Build a view with the smart editor + schema explorer; creates or replaces it (§7).</td></tr>
                        <tr><td><b><i class="bi bi-file-code"></i> Create SQL View</b></td><td>Same smart editor, using <code>CREATE VIEW</code> with duplicate-name protection (§7).</td></tr>
                        <tr><td><b><i class="bi bi-terminal"></i> SQL Editor</b></td><td>Paste &amp; run any SQL against the project database, with the full safety net (§9).</td></tr>
                        <tr><td><b><i class="bi bi-calendar-plus"></i> Create Calendar</b></td><td>Add a full event calendar to the generated app; provisions its own tables at Build (§13).</td></tr>
                        <tr><td><b><i class="bi bi-arrow-repeat"></i> Sync Database</b></td><td>Refresh the module's view of the live schema and reconcile drift (§8).</td></tr>
                        <tr><td><b><i class="bi bi-link-45deg"></i> Link Tables</b></td><td>Enter link mode to draw a master–detail relationship (§11).</td></tr>
                        <tr><td><b><i class="bi bi-question-circle"></i> Guide</b></td><td>Opens this guide. Press <span class="tgh-kbd">Esc</span> to close.</td></tr>
                    </table>
                    <div class="tgh-callout info"><i class="bi bi-shield-lock"></i><div>System-generated tables (security, permissions, audit, session, framework internals) are collapsed and protected from structural editing, so you can't break the platform by accident. They still show in the SQL Editor's schema explorer for reference.</div></div>
                </section>

                <section id="tg-persistence">
                    <h3><span class="num">3</span> What is saved to JSON</h3>
                    <p>The real schema lives in the project database. The module <em>also</em> records project-facing design intent to <code>config/tables.json</code> so other modules (Fields, Pages, Designer, Build) can reload it.</p>
                    <table class="tgh-table">
                        <tr><th>JSON key</th><th>Saved data</th></tr>
                        <tr><td><code>selectedTables</code></td><td>Tables/views selected for this application.</td></tr>
                        <tr><td><code>positions</code></td><td>Workspace card coordinates.</td></tr>
                        <tr><td><code>expandedTables</code></td><td>Remembered expanded/collapsed card state.</td></tr>
                        <tr><td><code>relations</code></td><td>Master/detail links, display options, pages, ordering, badge, and FK actions.</td></tr>
                        <tr><td><code>views</code></td><td>Source SQL for Custom View and SQL View definitions.</td></tr>
                        <tr><td><code>tableSchemas</code></td><td>Normalized field metadata captured when tables are created or edited.</td></tr>
                        <tr><td><code>tableListSort</code>, <code>tableListFilter</code></td><td>Table-list UI preferences.</td></tr>
                    </table>
                    <div class="tgh-callout tip"><i class="bi bi-check-circle"></i><div>Press <b>Save</b> after arranging cards. Create/edit/delete table and relation operations save their JSON automatically after a successful database change — so the design intent and the real database stay in step.</div></div>
                </section>

                <section id="tg-create">
                    <h3><span class="num">4</span> Create table</h3>
                    <p>Use <b>Create Table</b> to add a physical table. Names must start with a letter or underscore and contain only letters, numbers, and underscores.</p>
                    <ul>
                        <li><b>PK</b> marks a primary key (made <code>INT NOT NULL</code> automatically).</li>
                        <li><b>AI</b> is a database-generated identity. It forces <code>PK</code>, an integer type, and <code>NOT NULL</code>, and emits the right thing per engine: MySQL <code>AUTO_INCREMENT</code>, PostgreSQL identity, SQLite integer-key, SQL&nbsp;Server <code>IDENTITY</code>. Only one AI field per table.</li>
                        <li><code>VARCHAR</code>, <code>CHAR</code>, <code>BINARY</code>, <code>VARBINARY</code> default to length <code>255</code> when no size is given.</li>
                        <li>Only engine-supported types are offered — MySQL/MariaDB show <code>ENUM</code>/<code>SET</code>; PostgreSQL shows <code>UUID</code>/<code>JSONB</code>; SQL&nbsp;Server shows Unicode + offset-aware date/time types.</li>
                    </ul>

                    <div class="tgh-eg">
                        <div class="tgh-eg-h"><span class="tag">Example</span> A <code>customers</code> table</div>
                        <div class="tgh-eg-b">
                            <p>Fields you'd add in the dialog:</p>
                            <table class="tgh-table">
                                <tr><th>Field</th><th>Type</th><th>Flags / default</th></tr>
                                <tr><td><code>id</code></td><td>INT</td><td>PK · AI</td></tr>
                                <tr><td><code>name</code></td><td>VARCHAR(120)</td><td>NOT NULL</td></tr>
                                <tr><td><code>email</code></td><td>VARCHAR(160)</td><td>NOT NULL</td></tr>
                                <tr><td><code>phone</code></td><td>VARCHAR(40)</td><td>nullable</td></tr>
                                <tr><td><code>status</code></td><td>VARCHAR(20)</td><td>Value default <code>active</code></td></tr>
                                <tr><td><code>created_at</code></td><td>DATETIME</td><td>Current time</td></tr>
                            </table>
                            <p>…which the module emits (on MySQL) as:</p>
                            <div class="tgh-pre"><code><span class="k">CREATE TABLE</span> customers (
  id          <span class="k">INT</span> <span class="k">NOT NULL</span> AUTO_INCREMENT,
  name        <span class="k">VARCHAR</span>(120) <span class="k">NOT NULL</span>,
  email       <span class="k">VARCHAR</span>(160) <span class="k">NOT NULL</span>,
  phone       <span class="k">VARCHAR</span>(40) <span class="k">NULL</span>,
  status      <span class="k">VARCHAR</span>(20) <span class="k">DEFAULT</span> <span class="s">'active'</span>,
  created_at  <span class="k">DATETIME</span> <span class="k">DEFAULT</span> CURRENT_TIMESTAMP,
  <span class="k">PRIMARY KEY</span> (id)
);</code></div>
                            <p style="margin-bottom:2px">Prefer to hand-write it? Paste the same SQL into the <b>SQL Editor</b> — or start from <b>Snippets → Schema → Create table</b>, which produces an engine-correct skeleton with <code>IF NOT EXISTS</code>.</p>
                        </div>
                    </div>

                    <table class="tgh-table">
                        <tr><th>Database</th><th>Designer behavior</th></tr>
                        <tr><td>MySQL / MariaDB / TiDB</td><td>InnoDB tables, native alteration, auto-increment, ENUM/SET, MySQL-compatible views.</td></tr>
                        <tr><td>PostgreSQL / CockroachDB</td><td>Schema-qualified objects, identity columns, transactional DDL, UUID, JSON/JSONB, BYTEA, time-zone-aware timestamps.</td></tr>
                        <tr><td>SQLite</td><td>Portable declared types. Complex edits and FK changes use a transaction-protected table rebuild that preserves rows, indexes, and triggers.</td></tr>
                        <tr><td>SQL Server</td><td><code>dbo</code> (or configured schema), IDENTITY, NVARCHAR, DATETIME2/OFFSET, UNIQUEIDENTIFIER, VARBINARY(MAX), validated JSON.</td></tr>
                    </table>
                </section>

                <section id="tg-edit">
                    <h3><span class="num">5</span> Edit table</h3>
                    <p>The pencil button on a table card lets you rename the table, add/drop fields, change types, and adjust keys/defaults. Saving applies real database changes.</p>
                    <div class="tgh-eg">
                        <div class="tgh-eg-h"><span class="tag">Example</span> Add a <code>notes</code> column &amp; widen <code>phone</code></div>
                        <div class="tgh-eg-b">
                            <p>In the editor you'd add a <code>notes TEXT</code> field and change <code>phone</code> to <code>VARCHAR(60)</code>. The equivalent SQL (also runnable in the SQL Editor):</p>
                            <div class="tgh-pre"><code><span class="k">ALTER TABLE</span> customers <span class="k">ADD COLUMN</span> notes <span class="k">TEXT</span> <span class="k">NULL</span>;
<span class="k">ALTER TABLE</span> customers <span class="k">MODIFY</span> phone <span class="k">VARCHAR</span>(60);   <span class="c">-- Postgres: ALTER COLUMN phone TYPE VARCHAR(60)</span></code></div>
                        </div>
                    </div>
                    <div class="tgh-callout warn"><i class="bi bi-exclamation-triangle"></i><div>Editing a physical table can drop columns or change data types — <b>back up important data first</b>. Views aren't edited here (they're SQL definitions): recreate the view when its SELECT changes (Create Custom View replaces it in place).</div></div>
                </section>

                <section id="tg-defaults">
                    <h3><span class="num">6</span> Defaults &amp; field types</h3>
                    <table class="tgh-table">
                        <tr><th>Default mode</th><th>Meaning</th><th>Example</th></tr>
                        <tr><td>No default</td><td>Database applies no explicit default.</td><td>—</td></tr>
                        <tr><td>NULL</td><td><code>DEFAULT NULL</code> (nullable fields only).</td><td><code>phone</code></td></tr>
                        <tr><td>Value</td><td>Literal string/number/boolean, validated &amp; quoted by type.</td><td><code>status = 'active'</code>, <code>qty = 0</code>, <code>active = 1</code></td></tr>
                        <tr><td>Current time</td><td>The engine's current-time expression, for a temporal field.</td><td><code>created_at</code></td></tr>
                        <tr><td>Expression</td><td>SQL function/expression defaults; multi-statement &amp; mutating SQL blocked.</td><td><code>JSON_ARRAY()</code>, <code>gen_random_uuid()</code></td></tr>
                    </table>
                    <p>The adapter validates and quotes literal values per field type. Expression mode is for database functions; it rejects multiple or mutating statements.</p>
                </section>

                <section id="tg-views">
                    <h3><span class="num">7</span> Custom View and SQL View</h3>
                    <p>Both tools accept a single <code>SELECT</code> or <code>WITH</code> query and <b>Preview</b> validates it with sample rows before creation. A view is a saved query you can then treat like a read-only table on generated list/report pages.</p>
                    <div class="tgh-callout tip"><i class="bi bi-magic"></i><div>Both dialogs use the same <b>smart SQL editor</b> as the SQL Editor — syntax highlighting for your engine, a <b>Schema explorer</b> panel, and <b>column-aware autocomplete</b> so you rarely type a table or field name by hand.</div></div>

                    <h4>Schema explorer &amp; smart autocomplete</h4>
                    <p>A live <b>Schema</b> panel sits to the right of the editor listing every table and view. It turns writing a view into point-and-click:</p>
                    <table class="tgh-table">
                        <tr><th>Action</th><th>What happens</th></tr>
                        <tr><td><b>Click a table / column name</b></td><td>Inserts that identifier at the cursor.</td></tr>
                        <tr><td><b>Expand a table</b> (the <i class="bi bi-caret-right-fill"></i> caret)</td><td>Reveals its columns with data types (<code>varchar(120)</code>, <code>decimal(18,2)</code>…). Click any column to insert it.</td></tr>
                        <tr><td><b><i class="bi bi-asterisk"></i> button</b> on a table</td><td>Drops in a ready starter — <code>SELECT * FROM <i>table</i></code>.</td></tr>
                        <tr><td><b>Filter box</b></td><td>Narrows the list by table <em>or</em> column name; matches auto-expand so you see the field instantly.</td></tr>
                        <tr><td><b>Type a name</b></td><td>Autocomplete suggests matching tables and columns (with types) — or press <code>Ctrl/⌘ + Space</code>.</td></tr>
                        <tr><td><b>Type <code>alias.</code> / <code>table.</code></b></td><td>Dot-completion lists just <em>that</em> table's columns — it even follows <code>FROM cases c</code> aliases, so <code>c.</code> shows the <code>cases</code> fields.</td></tr>
                    </table>

                    <div class="tgh-eg">
                        <div class="tgh-eg-h"><span class="tag rec">Recipe</span> A simple filtered view</div>
                        <div class="tgh-eg-b">
                            <p>Only active customers, newest first — great as a read-only list page:</p>
                            <div class="tgh-pre"><code><span class="c">-- Create Custom View → name: active_customers</span>
<span class="k">SELECT</span> id, name, email, phone, created_at
<span class="k">FROM</span> customers
<span class="k">WHERE</span> status = <span class="s">'active'</span>
<span class="k">ORDER BY</span> created_at <span class="k">DESC</span>;</code></div>
                        </div>
                    </div>

                    <div class="tgh-eg">
                        <div class="tgh-eg-h"><span class="tag rec">Recipe</span> A reporting view with a JOIN + aggregate</div>
                        <div class="tgh-eg-b">
                            <p>Orders and totals per customer — bind a dashboard chart or KPI to this:</p>
                            <div class="tgh-pre"><code><span class="c">-- Create SQL View → name: customer_orders_v</span>
<span class="k">SELECT</span>  c.id            <span class="k">AS</span> customer_id,
        c.name,
        <span class="k">COUNT</span>(o.id)      <span class="k">AS</span> order_count,
        <span class="k">COALESCE</span>(<span class="k">SUM</span>(o.total), 0) <span class="k">AS</span> total_spent,
        <span class="k">MAX</span>(o.created_at) <span class="k">AS</span> last_order_at
<span class="k">FROM</span> customers c
<span class="k">LEFT JOIN</span> orders o <span class="k">ON</span> o.customer_id = c.id
<span class="k">GROUP BY</span> c.id, c.name;</code></div>
                            <p style="margin-bottom:2px">Tip: type <code>c.</code> and <code>o.</code> to let dot-completion fill the column names from each table.</p>
                        </div>
                    </div>

                    <ul>
                        <li><b>Create Custom View</b> creates or <em>replaces</em> the definition using the engine's supported strategy (native replace/alter, or a safe drop-and-create).</li>
                        <li><b>Create SQL View</b> uses <code>CREATE VIEW</code> — best when you want the database to reject a duplicate name.</li>
                        <li>Non-read statements (<code>DELETE</code>, multiple statements, <code>INTO OUTFILE</code>, locking clauses) are blocked here — use the SQL Editor for those.</li>
                        <li>The view SQL is saved to <code>tables.json</code> under <code>views</code>, so it rebuilds with the project.</li>
                    </ul>
                </section>

                <section id="tg-sync">
                    <h3><span class="num">8</span> Sync database</h3>
                    <p><b>Sync Database</b> reconciles the module with the live database. Use it whenever the schema changed outside this screen — after running DDL in the <b>SQL Editor</b>, importing a dump, or someone altered a table directly.</p>
                    <ul>
                        <li>Re-reads the real tables, views, and columns from the project connection.</li>
                        <li>Refreshes the left list, the card fields, and the cached schema that powers autocomplete and the Fields/Designer modules.</li>
                        <li>Surfaces <b>drift</b> — objects that exist in the database but aren't captured in the design (or vice-versa) — so nothing silently goes stale.</li>
                    </ul>
                    <div class="tgh-callout tip"><i class="bi bi-lightbulb"></i><div>Ran a <code>CREATE TABLE</code> in the SQL Editor and don't see the new table as a card? Click <b>Sync Database</b>, then check it in the left list to add it to the project.</div></div>
                </section>

                <section id="tg-sqleditor">
                    <h3><span class="num">9</span> SQL Editor</h3>
                    <p class="tgh-lead">Have a ready-made SQL script — a schema, a seed, a migration — and just want to paste and run it? Click <strong><i class="bi bi-terminal"></i> SQL Editor</strong>. It runs SQL <b>directly against this project's database</b>, works with every supported engine, and wraps it in a full safety net: plan preview, dialect conversion, dry runs, and inline error highlighting.</p>

                    <div class="tgh-grid">
                        <div class="tgh-card"><div class="ic" style="background:#eef2ff;color:#4f46e5"><i class="bi bi-play-fill"></i></div><h5>Run anything</h5><p>Paste or load a <code>.sql</code> file and run the whole script or the selection. Every statement reports success, rows affected, timing, and a grid for <code>SELECT</code>s.</p></div>
                        <div class="tgh-card"><div class="ic" style="background:#ecfeff;color:#0891b2"><i class="bi bi-list-check"></i></div><h5>Preview the plan</h5><p>See what a script <em>will</em> do before it runs — statement types, row-count estimates, and clear warnings for destructive operations.</p></div>
                        <div class="tgh-card"><div class="ic" style="background:#fff7ed;color:#ea580c"><i class="bi bi-magic"></i></div><h5>Fix the dialect</h5><p>Pasted a PostgreSQL script into a MySQL project? One click converts it, with a change log you review before running.</p></div>
                        <div class="tgh-card"><div class="ic" style="background:#f0fdf4;color:#16a34a"><i class="bi bi-shield-check"></i></div><h5>Dry run</h5><p>On engines with transactional DDL, run the whole script inside a transaction and roll it all back — a rehearsal that saves nothing.</p></div>
                    </div>

                    <h4>How to use it</h4>
                    <ol>
                        <li>Open it from the <b>SQL Editor</b> toolbar button. The badge shows the project's active engine (e.g. <b>MySQL</b>).</li>
                        <li>Type, paste, or <b>Load .sql</b> a script. The editor highlights SQL for your engine and <b>auto-completes</b> keywords, your table names, and their <b>columns</b> (with <code>alias.</code> / <code>table.</code> dot-completion) — also <code>Ctrl/⌘ + Space</code>.</li>
                        <li><b>Buttons are split into two zones so nothing runs by accident:</b> the top row (<b>Safe</b>) never touches the database — Preview, Dry run, and editing tools. The bottom-right <b>Run</b> button is the only one that <b>writes</b>.</li>
                        <li>Preview first, then click <b>Run · writes to DB</b> (<code>⌘/Ctrl + Enter</code>), or <b>Run selection</b> for just the highlighted text.</li>
                        <li>Read the results: a green/amber summary, one row per statement (click to jump to its line), and a CSV-exportable grid for each <code>SELECT</code>.</li>
                    </ol>

                    <div class="tgh-eg">
                        <div class="tgh-eg-h"><span class="tag">Walkthrough</span> Paste a PostgreSQL dump into a MySQL project</div>
                        <div class="tgh-eg-b">
                            <ol>
                                <li>Paste the script. A banner appears under the editor: <em>"This looks like PostgreSQL, but this project's database is MySQL."</em></li>
                                <li>Click <b>Fix — convert to MySQL</b>. A panel shows a plain-language change log (<code>serial → AUTO_INCREMENT</code>, <code>jsonb → JSON</code>, quoting, <code>public.</code> stripped…) plus any "review by hand" notes.</li>
                                <li>Click <b>Apply</b> to drop the converted SQL into the editor.</li>
                                <li><b>Preview</b> to see the plan, then <b>Run · writes to DB</b>.</li>
                            </ol>
                        </div>
                    </div>

                    <h4>Toolbar reference</h4>
                    <p><b>Top row — “Safe”, never writes to the database:</b></p>
                    <table class="tgh-table">
                        <tr><th>Control</th><th>What it does</th></tr>
                        <tr><td><b>Preview</b></td><td>Read-only plan: statement classification, insert row-estimates, destructive-operation warnings. Touches nothing.</td></tr>
                        <tr><td><b>Dry run</b></td><td>Runs everything in a transaction and rolls it back. Enabled only on engines with transactional DDL (PostgreSQL, SQLite, SQL&nbsp;Server); disabled on MySQL/MariaDB, which auto-commit schema changes.</td></tr>
                        <tr><td><b>Load .sql</b></td><td>Loads a local <code>.sql</code> / <code>.txt</code> file (up to 5&nbsp;MB) into the editor.</td></tr>
                        <tr><td><b>Snippets</b></td><td>A categorised menu (Schema · Data · Query · Utility) of engine-aware SQL. Schema ones are <b>safe by default</b> (<code>CREATE TABLE IF NOT EXISTS</code>, <code>DROP TABLE IF EXISTS</code>, <code>CREATE OR REPLACE VIEW</code>).</td></tr>
                        <tr><td><b>History</b></td><td>Scripts you ran recently (saved in this browser) — click one to load it back.</td></tr>
                        <tr><td><b>Format</b></td><td>Cosmetic tidy — uppercases keywords, breaks major clauses onto their own lines. Never changes string/identifier contents.</td></tr>
                        <tr><td><b>Stop on error</b> / <b>Transaction</b></td><td>Options applied when you Run: stop at the first failure, and/or wrap in a transaction (see safety note).</td></tr>
                    </table>
                    <p><b>Bottom row — writes to your database:</b></p>
                    <table class="tgh-table">
                        <tr><th>Control</th><th>What it does</th></tr>
                        <tr><td><b>Run · writes to DB</b> <code>⌘⏎</code></td><td>Executes the whole script, statement by statement — this saves changes.</td></tr>
                        <tr><td><b>Run selection</b></td><td>Executes only the highlighted text — handy for one statement.</td></tr>
                    </table>

                    <h4>Preview &amp; safety</h4>
                    <p><b>Preview</b> classifies every statement (create table, insert&nbsp;~N&nbsp;rows, alter, drop, query…) and flags <b>destructive operations</b> — <code>DROP</code>, <code>TRUNCATE</code>, and <code>DELETE</code>/<code>UPDATE</code> without a <code>WHERE</code> — in red. Nothing runs during Preview.</p>
                    <div class="tgh-callout warn"><i class="bi bi-exclamation-triangle"></i><div>The SQL Editor runs against your project's <b>real database</b>. On MySQL/MariaDB a mid-script failure can leave earlier <code>CREATE</code>/<code>ALTER</code> statements applied (those engines auto-commit DDL), so Preview first, keep <b>Stop on error</b> on, and back up before destructive changes.</div></div>

                    <h4>Fixing a mismatched dialect (any engine → any engine)</h4>
                    <p>The editor watches what you type <b>in real time</b>. The moment a script looks like it was written for a different engine, a banner offers <b>Fix — convert to&nbsp;…</b> <em>before you ever run it</em>. It works in every direction (MySQL↔PostgreSQL↔SQL&nbsp;Server↔SQLite) and shows a reviewable result:</p>
                    <ul>
                        <li><b>Data types</b> — <code>uuid</code>→<code>CHAR(36)</code>, <code>serial</code>→<code>AUTO_INCREMENT</code>, <code>timestamptz</code>→<code>TIMESTAMP</code>, <code>jsonb</code>→<code>JSON</code>, <code>boolean</code>→<code>TINYINT(1)</code>, and the reverse for other targets.</li>
                        <li><b>Identifiers &amp; schemas</b> — quoting style (<code>`col`</code> ↔ <code>"col"</code> ↔ <code>[col]</code>) and stripping <code>public.</code>/<code>dbo.</code> prefixes.</li>
                        <li><b>Keys, defaults &amp; indexes</b> — auto-increment/serial/identity, unsupported defaults, inline foreign keys, <code>CREATE INDEX IF NOT EXISTS</code>, Postgres-only statements, and engine-only options like <code>ENGINE=</code>.</li>
                    </ul>
                    <p>A <b>“From”</b> dropdown in the panel lets you set the source engine yourself — including <b>Oracle</b> or a <b>Generic/ANSI</b> script from a database beyond the ones we host — and it re-converts instantly.</p>
                    <div class="tgh-callout info"><i class="bi bi-info-circle"></i><div><b>The converter is best-effort.</b> It handles typical schema+seed dumps and lists anything it couldn't translate (stored-procedure bodies, upserts, extensions, trigram indexes) as "review by hand". It <b>never runs automatically</b> — you always Apply and review. For complex scripts, treat the result as a strong first draft.</div></div>

                    <h4>When a statement fails</h4>
                    <p>The failing statement is highlighted right in the editor (red line + gutter marker), the cursor jumps to it, and the results panel shows the database's own error message. Each result row carries a line chip (<code>L12</code>) you can click to jump straight to that statement.</p>

                    <h4>For developers</h4>
                    <p>The SQL Console is a thin, reusable core plus a modal UI. Access is gated by <code>TablesController::initProject()</code> (login + project ownership); everything runs on <code>DB::Pdo()</code> — the project's own connection — so it's dialect-agnostic by construction.</p>
                    <table class="tgh-table">
                        <tr><th>Piece</th><th>Role</th></tr>
                        <tr><td><code>core/Database/SqlScriptRunner</code></td><td>Dialect-agnostic splitter (comments, quotes with <code>''</code>/backslash escapes, Postgres <code>$tag$</code> dollar-quotes) + PDO executor. Per-statement report (status, kind, affected, ms, bounded grid, start line) with <code>stopOnError</code>, <code>transaction</code>, <code>dryRun</code>.</td></tr>
                        <tr><td><code>core/Database/SqlScriptAnalyzer</code></td><td>Read-only plan: classifies statements, estimates insert rows, flags destructive ops. Powers <b>Preview</b>; never connects to a DB.</td></tr>
                        <tr><td><code>core/Database/SqlDialectConverter</code></td><td>Best-effort transpiler. Masks strings/comments, applies type/quoting/key/default rules, returns <code>{sql, changes[], warnings[]}</code>; <code>::detect()</code> guesses the source.</td></tr>
                        <tr><td><code>TablesController::schema</code></td><td><code>POST tables/schema</code> — returns every table/view + typed columns; powers the schema explorer &amp; column autocomplete.</td></tr>
                        <tr><td>Endpoints</td><td><code>tables/run-sql</code> (execute + dry run), <code>tables/sql-plan</code> (preview), <code>tables/convert-sql</code> (fix), <code>tables/schema</code>. Client: <code>Views/scripts/sqlEditor.js</code> on the bundled CodeMirror (<code>window.__PPCM</code>).</td></tr>
                    </table>
                    <div class="tgh-callout tip"><i class="bi bi-lightbulb"></i><div>Reuse <code>SqlScriptRunner</code> for any "run a .sql file" need instead of re-splitting SQL, and <code>SqlDialectConverter</code> whenever you move DDL between engines. Both are pure, testable, and connection-free except at execution time.</div></div>
                </section>

                <section id="tg-recipes">
                    <h3><span class="num">10</span> Recipes &amp; examples</h3>
                    <p class="tgh-lead">Copy-paste starting points for the SQL Editor. All are available engine-aware from <b>Snippets</b> — these show the shape and the cross-engine differences to watch.</p>

                    <h4>Add a column safely</h4>
                    <div class="tgh-pre"><code><span class="k">ALTER TABLE</span> customers <span class="k">ADD COLUMN</span> loyalty_tier <span class="k">VARCHAR</span>(20) <span class="k">DEFAULT</span> <span class="s">'bronze'</span>;</code></div>

                    <h4>Create an index (engine-aware existence guard)</h4>
                    <div class="tgh-pre"><code><span class="c">-- MySQL / PostgreSQL / SQLite</span>
<span class="k">CREATE INDEX</span> idx_customers_email <span class="k">ON</span> customers (email);
<span class="c">-- PostgreSQL &amp; SQLite also allow: CREATE INDEX IF NOT EXISTS …</span></code></div>

                    <h4>Seed a few rows</h4>
                    <div class="tgh-pre"><code><span class="k">INSERT INTO</span> customers (name, email, status) <span class="k">VALUES</span>
  (<span class="s">'Asha Rai'</span>,   <span class="s">'asha@example.com'</span>,   <span class="s">'active'</span>),
  (<span class="s">'Bijay Karki'</span>,<span class="s">'bijay@example.com'</span>,  <span class="s">'active'</span>),
  (<span class="s">'Chandra Sherpa'</span>,<span class="s">'chandra@example.com'</span>, <span class="s">'inactive'</span>);</code></div>

                    <h4>Upsert — insert or update on conflict</h4>
                    <div class="tgh-pre"><code><span class="c">-- MySQL / MariaDB / TiDB</span>
<span class="k">INSERT INTO</span> customers (email, name) <span class="k">VALUES</span> (<span class="s">'asha@example.com'</span>, <span class="s">'Asha R.'</span>)
<span class="k">ON DUPLICATE KEY UPDATE</span> name = <span class="k">VALUES</span>(name);

<span class="c">-- PostgreSQL / CockroachDB / SQLite</span>
<span class="k">INSERT INTO</span> customers (email, name) <span class="k">VALUES</span> (<span class="s">'asha@example.com'</span>, <span class="s">'Asha R.'</span>)
<span class="k">ON CONFLICT</span> (email) <span class="k">DO UPDATE SET</span> name = EXCLUDED.name;</code></div>
                    <div class="tgh-callout tip"><i class="bi bi-magic"></i><div>Not sure which your project needs? Pick <b>Snippets → Data → Upsert</b> — it emits the correct form for the current engine automatically.</div></div>

                    <h4>Paginate results</h4>
                    <div class="tgh-pre"><code><span class="c">-- MySQL / PostgreSQL / SQLite</span>
<span class="k">SELECT</span> * <span class="k">FROM</span> customers <span class="k">ORDER BY</span> id <span class="k">LIMIT</span> 20 <span class="k">OFFSET</span> 40;

<span class="c">-- SQL Server</span>
<span class="k">SELECT</span> * <span class="k">FROM</span> customers <span class="k">ORDER BY</span> id <span class="k">OFFSET</span> 40 <span class="k">ROWS FETCH NEXT</span> 20 <span class="k">ROWS ONLY</span>;</code></div>

                    <h4>Find orphaned rows (a child pointing at a missing parent)</h4>
                    <div class="tgh-pre"><code><span class="k">SELECT</span> o.id, o.customer_id
<span class="k">FROM</span> orders o
<span class="k">LEFT JOIN</span> customers c <span class="k">ON</span> c.id = o.customer_id
<span class="k">WHERE</span> c.id <span class="k">IS NULL</span>;</code></div>

                    <h4>Bulk update — always with a WHERE</h4>
                    <div class="tgh-pre"><code><span class="k">UPDATE</span> customers
<span class="k">SET</span> status = <span class="s">'inactive'</span>
<span class="k">WHERE</span> created_at &lt; <span class="s">'2024-01-01'</span>;   <span class="c">-- Preview flags this as destructive if the WHERE is missing</span></code></div>
                    <div class="tgh-callout warn"><i class="bi bi-shield-exclamation"></i><div>An <code>UPDATE</code> or <code>DELETE</code> with no <code>WHERE</code> touches every row. Preview highlights it in red — select just the statement and use <b>Run selection</b>, or add a <code>WHERE</code> first.</div></div>
                </section>

                <section id="tg-relations">
                    <h3><span class="num">11</span> Link tables</h3>
                    <ol>
                        <li>Select the tables you want in the workspace and expand their cards.</li>
                        <li>Click <b>Link Tables</b>.</li>
                        <li>Click the key field on the <b>master</b> table (e.g. <code>customers.id</code>), then the matching field on the <b>detail</b> table (e.g. <code>orders.customer_id</code>).</li>
                        <li>Configure display, page placement, order, count badge, and optional foreign-key behavior.</li>
                    </ol>
                    <p>A relation arrow appears between the cards. Double-click it later to edit or delete the relation.</p>
                    <div class="tgh-eg">
                        <div class="tgh-eg-h"><span class="tag">Example</span> Customers → Orders (one-to-many)</div>
                        <div class="tgh-eg-b">
                            <p>Link <code>customers.id</code> → <code>orders.customer_id</code>. On the generated app, opening a customer's <b>View</b> page now shows their orders as an inline child grid, with an <b>Add</b> button that pre-fills <code>customer_id</code>, and a count badge on the list.</p>
                        </div>
                    </div>
                </section>

                <section id="tg-relation-options">
                    <h3><span class="num">12</span> Relation settings</h3>
                    <table class="tgh-table">
                        <tr><th>Setting</th><th>Use</th></tr>
                        <tr><td>Display option</td><td>Whether child records appear inline, in a popup, or via a compact icon/action.</td></tr>
                        <tr><td>Master pages</td><td>Where detail records appear on the master table: List, Add, Edit, View, Print.</td></tr>
                        <tr><td>Detail pages</td><td>Where the master record appears on the detail table.</td></tr>
                        <tr><td>Display order</td><td>Lower numbers first when one master has several detail tables.</td></tr>
                        <tr><td>Details link style</td><td>One combined details link, or individual links per detail table.</td></tr>
                        <tr><td>Child record count</td><td>A colored badge showing the number of child rows.</td></tr>
                        <tr><td>Foreign key</td><td>Optionally creates database-level referential rules with delete/update actions.</td></tr>
                    </table>
                    <div class="tgh-callout warn"><i class="bi bi-shield-exclamation"></i><div>Only enable a foreign key when the master field is primary/unique and the detail field holds compatible values — otherwise the database rejects the constraint. To clean up mismatches first, run the <b>orphaned rows</b> recipe (§10).</div></div>
                </section>

                <section id="tg-calendar">
                    <h3><span class="num">13</span> Calendar &amp; Events</h3>
                    <p class="tgh-lead">Click <b>Create Calendar</b> to add a complete event-management app to your generated site — no extra coding. Enable it, then <b>Build</b>: it provisions its own tables and pages.</p>
                    <div class="tgh-grid">
                        <div class="tgh-card"><div class="ic" style="background:#eef2ff;color:#6366f1"><i class="bi bi-calendar-week"></i></div><h5>Multiple views</h5><p>Month, week, day, and agenda views your users switch between.</p></div>
                        <div class="tgh-card"><div class="ic" style="background:#ecfdf5;color:#059669"><i class="bi bi-people"></i></div><h5>Invites &amp; RSVP</h5><p>Invite people to an event and track responses; share calendars with everyone, groups, or selected users.</p></div>
                        <div class="tgh-card"><div class="ic" style="background:#fff7ed;color:#ea580c"><i class="bi bi-bell"></i></div><h5>Reminders</h5><p>Set reminders so attendees get notified ahead of time.</p></div>
                        <div class="tgh-card"><div class="ic" style="background:#eff6ff;color:#2563eb"><i class="bi bi-arrow-repeat"></i></div><h5>Recurring &amp; iCal</h5><p>Repeating events plus iCal import/export to interoperate with other calendars.</p></div>
                    </div>
                    <ol>
                        <li>Click <b>Create Calendar</b> and enable it for the project.</li>
                        <li><b>Build</b> the app — the calendar's tables and pages are generated automatically.</li>
                        <li>Style and place it like any other page from the Designer / Pages modules.</li>
                    </ol>
                    <div class="tgh-callout info"><i class="bi bi-info-circle"></i><div>The calendar manages its own tables — you don't design them by hand. They appear as protected system-style tables after Build; leave their structure to the calendar feature.</div></div>
                </section>

                <section id="tg-tips">
                    <h3><span class="num">14</span> Tips &amp; tricks</h3>
                    <div class="tgh-tips">
                        <div class="tgh-tip"><i class="bi bi-magic"></i><div><b>Let the schema panel type for you</b><span>In the view/SQL editors, click tables and columns from the right panel instead of typing. The <i class="bi bi-asterisk"></i> button writes a whole <code>SELECT * FROM …</code> starter.</span></div></div>
                        <div class="tgh-tip"><i class="bi bi-cursor-text"></i><div><b>Alias, then dot</b><span>Write <code>FROM orders o</code> first, then type <code>o.</code> — autocomplete lists exactly that table's columns, with types.</span></div></div>
                        <div class="tgh-tip"><i class="bi bi-shield-check"></i><div><b>Preview before every Run</b><span>Preview is free and read-only. It catches a missing <code>WHERE</code> or an accidental <code>DROP</code> before it can touch data.</span></div></div>
                        <div class="tgh-tip"><i class="bi bi-arrow-counterclockwise"></i><div><b>Rehearse with Dry run</b><span>On PostgreSQL, SQLite, and SQL&nbsp;Server, Dry run executes the whole script in a transaction and rolls it back — perfect for testing a migration.</span></div></div>
                        <div class="tgh-tip"><i class="bi bi-crosshair"></i><div><b>Run just one statement</b><span>Select the lines you want and use <b>Run selection</b> — great for stepping through a big script one piece at a time.</span></div></div>
                        <div class="tgh-tip"><i class="bi bi-translate"></i><div><b>Don't rewrite foreign SQL by hand</b><span>Paste a dump from any engine and hit <b>Fix</b>. Set the <b>From</b> engine (even Oracle/Generic) if auto-detect guesses wrong.</span></div></div>
                        <div class="tgh-tip"><i class="bi bi-clock-history"></i><div><b>History is your undo-buffer</b><span>Re-open a script you ran earlier from the <b>History</b> menu instead of retyping it. It's kept per project in this browser.</span></div></div>
                        <div class="tgh-tip"><i class="bi bi-database-check"></i><div><b>Sync after external changes</b><span>Ran DDL in the editor or imported a dump? Click <b>Sync Database</b> so the cards, Fields, and autocomplete pick up the new shape.</span></div></div>
                        <div class="tgh-tip"><i class="bi bi-input-cursor"></i><div><b>Start from a Snippet</b><span>Snippets are engine-aware and use existence guards (<code>IF NOT EXISTS</code>), so they're safe to run twice while you iterate.</span></div></div>
                        <div class="tgh-tip"><i class="bi bi-eye"></i><div><b>Views make clean report pages</b><span>Push joins and aggregates into a view, then bind a generated list/dashboard to it — the app stays simple and fast.</span></div></div>
                        <div class="tgh-tip"><i class="bi bi-hash"></i><div><b>Keys before relations</b><span>Give tables a primary key (PK · AI) before linking them — foreign keys need a primary/unique master field.</span></div></div>
                        <div class="tgh-tip"><i class="bi bi-filetype-csv"></i><div><b>Export any result</b><span>Every <code>SELECT</code> grid has a <b>CSV</b> button — a quick way to pull a slice of data out for a report or a spreadsheet.</span></div></div>
                    </div>

                    <h4>Keyboard shortcuts (SQL &amp; view editors)</h4>
                    <div class="tgh-kbds">
                        <div class="tgh-kbd-row"><span>Run whole script</span><span><span class="tgh-kbd">⌘/Ctrl</span> + <span class="tgh-kbd">Enter</span></span></div>
                        <div class="tgh-kbd-row"><span>Run selection</span><span><span class="tgh-kbd">⇧</span> + <span class="tgh-kbd">⌘/Ctrl</span> + <span class="tgh-kbd">Enter</span></span></div>
                        <div class="tgh-kbd-row"><span>Trigger autocomplete</span><span><span class="tgh-kbd">Ctrl/⌘</span> + <span class="tgh-kbd">Space</span></span></div>
                        <div class="tgh-kbd-row"><span>Toggle line comment</span><span><span class="tgh-kbd">Ctrl/⌘</span> + <span class="tgh-kbd">/</span></span></div>
                        <div class="tgh-kbd-row"><span>Indent selection</span><span><span class="tgh-kbd">Tab</span></span></div>
                        <div class="tgh-kbd-row"><span>Close this guide</span><span><span class="tgh-kbd">Esc</span></span></div>
                    </div>
                </section>

                <section id="tg-workflow">
                    <h3><span class="num">15</span> Recommended workflow</h3>
                    <ol>
                        <li>Create or sync your database tables (Create Table, or paste DDL in the SQL Editor → <b>Sync Database</b>).</li>
                        <li>Select only the project tables/views the generated app needs.</li>
                        <li>Arrange cards and press <b>Save</b>.</li>
                        <li>Create relations and configure page visibility/order.</li>
                        <li>Add views for reporting pages; add a Calendar if the app needs one.</li>
                        <li>Move to <b>Fields</b>, <b>Pages</b>, <b>Designer</b>, <b>Events</b>, and <b>Security</b> for display controls and behavior.</li>
                        <li>Build the generated app once the table model is stable.</li>
                    </ol>
                    <div class="tgh-callout tip"><i class="bi bi-check-circle"></i><div>Model your data here first. A clean, well-keyed schema with the right relations makes every downstream module — Fields, Designer, Security — simpler and more reliable.</div></div>
                    <p><span class="tgh-kbd">Esc</span> closes this guide.</p>
                </section>

                <div class="tgh-foot">Tables Guide — local documentation for the current RAD workspace.</div>
            </main>
        </div>
    </div>
</div>

<script>
(function () {
    var scrim = document.getElementById('tablesHelpScrim');
    var close = document.getElementById('tablesHelpClose');
    var toc = document.getElementById('tablesHelpToc');
    var content = document.getElementById('tablesHelpContent');
    if (!scrim || !close || !toc || !content) return;

    function openGuide() {
        scrim.classList.add('open');
        scrim.setAttribute('aria-hidden', 'false');
    }

    function closeGuide() {
        scrim.classList.remove('open');
        scrim.setAttribute('aria-hidden', 'true');
    }

    document.addEventListener('click', function (e) {
        var trigger = e.target.closest('[data-tables-help-open]');
        if (trigger) {
            e.preventDefault();
            openGuide();
            return;
        }
        if (e.target === scrim) closeGuide();
    });

    close.addEventListener('click', closeGuide);
    document.addEventListener('keydown', function (e) {
        if (e.key === 'Escape' && scrim.classList.contains('open')) closeGuide();
    });

    toc.addEventListener('click', function (e) {
        var link = e.target.closest('[data-goto]');
        if (!link) return;
        var target = document.getElementById(link.dataset.goto);
        if (!target) return;
        content.scrollTo({ top: target.offsetTop - 12, behavior: 'smooth' });
    });

    var links = Array.from(toc.querySelectorAll('[data-goto]'));
    content.addEventListener('scroll', function () {
        var current = links[0];
        links.forEach(function (link) {
            var section = document.getElementById(link.dataset.goto);
            if (section && section.offsetTop - content.scrollTop < 80) current = link;
        });
        links.forEach(function (link) { link.classList.toggle('active', link === current); });
    });
})();
</script>
