{"id":5747,"date":"2026-06-26T11:55:57","date_gmt":"2026-06-26T11:55:57","guid":{"rendered":"https:\/\/primetoolhub.com\/?page_id=5747"},"modified":"2026-07-18T16:01:49","modified_gmt":"2026-07-18T16:01:49","slug":"ai-code-studio","status":"publish","type":"page","link":"https:\/\/schoolict.net\/tools\/ai-code-studio\/","title":{"rendered":"AI Code Editor | Free Browser-Based AI Code Generator"},"content":{"rendered":"<div class=\"pth-hero-section\">\n<div class=\"pth-hero-content\">\n<h2>Browser-Based AI Code Editor<\/h2>\n<p>Free AI code editor \u2014 Monaco editor with Claude, Gemini &#038; Groq AI. Live preview, 7 magic buttons, Woody export &#038; auto-save. 100% private, no install.<\/p>\n<div id=\"pth-toc-placeholder\"><\/div>\n<\/p>\n<\/div>\n<div class=\"pth-hero-image\">\n    <img data-no-lazy=\"1\"\n         src=\"https:\/\/schoolict.net\/tools\/wp-content\/uploads\/2026\/06\/AI-Code-Studio-800x447.jpeg\"\n         width=\"800\"\n         height=\"447\"\n         alt=\"AI Code Studio\"\n         fetchpriority=\"high\"\n         loading=\"eager\"\n         decoding=\"async\"\n         style=\"width:100%; height:auto; display:block;\">\n  <\/div>\n<\/div>\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>Table of Contents<\/h2><nav><ul><li><a href=\"#\ud83d\udd34-what-bring-your-own-key-actually-means-for-you\">\ud83d\udd34\u00a0What &#8220;Bring Your Own Key&#8221; Actually Means for You<\/a><\/li><li><a href=\"#\ud83d\udfe1-three-providers-three-different-reasons-to-pick-them\">\ud83d\udfe1\u00a0Three Providers, Three Different Reasons to Pick Them<\/a><\/li><li><a href=\"#\ud83d\udd34-an-honest-word-this-tool-is-not-offline\">\ud83d\udd34\u00a0An Honest Word: This Tool Is Not Offline<\/a><ul><li><a href=\"#\ud83d\udfe2-where-your-key-lives\">\ud83d\udfe2\u00a0Where Your Key Lives<\/a><\/li><\/ul><\/li><li><a href=\"#\ud83d\udfe1-live-preview-and-the-language-modes\">\ud83d\udfe1\u00a0Live Preview and the Language Modes<\/a><\/li><\/ul><\/nav><\/div>\n\n\n<!-- LSCACHE_DISABLE -->\r\n<style>\r\n\/* PTH AI CODE STUDIO v2.0 PRO \u2014 Zero Dependencies, Pure JS *\/\r\n#pthcs{font-family:'Inter',system-ui,sans-serif;background:#0f172a;color:#e2e8f0;border-radius:14px;overflow:hidden;max-width:100%}\r\n#pthcs *{box-sizing:border-box;min-width:0}\r\n\/* Top bar *\/\r\n#pthcs .cs-top{background:#1e293b;border-bottom:1px solid #334155;padding:10px 16px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}\r\n#pthcs .cs-logo{font-size:.95rem;font-weight:900;color:#e2e8f0;display:flex;align-items:center;gap:7px;white-space:nowrap}\r\n#pthcs .cs-v{font-size:.62rem;background:linear-gradient(135deg,#8b5cf6,#6d28d9);color:#fff;padding:2px 8px;border-radius:999px;font-weight:800}\r\n#pthcs .cs-prv{font-size:.62rem;background:rgba(16,185,129,.15);color:#6ee7b7;border:1px solid rgba(16,185,129,.3);padding:2px 7px;border-radius:4px;font-weight:700}\r\n#pthcs .cs-tr{margin-left:auto;display:flex;gap:6px;flex-wrap:wrap}\r\n\/* Status *\/\r\n#pthcs .cs-stat{background:#162032;border-bottom:1px solid #334155;padding:6px 16px;display:flex;gap:8px;align-items:center;font-size:.72rem;flex-wrap:wrap}\r\n#pthcs .cs-pname{color:#a78bfa;font-weight:800}\r\n#pthcs .cs-kdot{width:8px;height:8px;border-radius:50%;background:#dc2626;display:inline-block;margin:0 3px}\r\n#pthcs .cs-kdot.on{background:#10b981}\r\n#pthcs .cs-klbl{font-weight:600}\r\n#pthcs .cs-klbl.on{color:#6ee7b7}\r\n#pthcs .cs-klbl.off{color:#fca5a5}\r\n\/* Magic bar *\/\r\n#pthcs .cs-magic{background:#1e293b;border-bottom:1px solid #334155;padding:7px 14px;display:flex;gap:5px;flex-wrap:wrap;align-items:center}\r\n#pthcs .cs-mlbl{font-size:.62rem;font-weight:800;color:#475569;text-transform:uppercase;letter-spacing:.4px;white-space:nowrap;margin-right:2px}\r\n#pthcs .mbtn{padding:5px 12px;border-radius:6px;font-size:.73rem;font-weight:800;cursor:pointer;border:none;font-family:'Inter',sans-serif;transition:.15s;white-space:nowrap;color:#fff}\r\n#pthcs .mbtn:hover{opacity:.85;transform:translateY(-1px)}\r\n#pthcs .mbtn:active{transform:translateY(0)}\r\n#pthcs .mb1{background:linear-gradient(135deg,#8b5cf6,#6d28d9)}\r\n#pthcs .mb2{background:linear-gradient(135deg,#3b82f6,#1d4ed8)}\r\n#pthcs .mb3{background:linear-gradient(135deg,#dc2626,#991b1b)}\r\n#pthcs .mb4{background:linear-gradient(135deg,#059669,#047857)}\r\n#pthcs .mb5{background:linear-gradient(135deg,#0ea5e9,#0284c7)}\r\n#pthcs .mb6{background:linear-gradient(135deg,#f59e0b,#d97706)}\r\n#pthcs .mb7{background:linear-gradient(135deg,#ec4899,#be185d)}\r\n\/* Main grid *\/\r\n#pthcs .cs-grid{display:grid;grid-template-columns:1fr 1fr;height:680px;min-height:680px}\r\n#pthcs.pth-fullw .cs-grid{grid-template-columns:1fr}\r\n#pthcs.pth-fullw .cs-rpanel{display:none}\r\n@media(max-width:780px){#pthcs .cs-grid{grid-template-columns:1fr;height:auto;min-height:auto}}\r\n\/* Editor panel *\/\r\n#pthcs .cs-epanel{display:flex;flex-direction:column;border-right:1px solid #334155}\r\n#pthcs .cs-etbar{background:#263548;border-bottom:1px solid #334155;padding:5px 10px;display:flex;align-items:center;gap:6px;flex-shrink:0;flex-wrap:wrap}\r\n#pthcs .cs-lsel{padding:4px 8px;background:#0f172a;border:1px solid #475569;border-radius:5px;color:#e2e8f0;font-size:.73rem;outline:none;cursor:pointer;font-family:'Inter',sans-serif}\r\n#pthcs .cs-cur{font-size:.65rem;color:#475569;font-family:'Courier New',monospace;flex:1}\r\n#pthcs .cs-eacts{display:flex;gap:4px;margin-left:auto}\r\n#pthcs .abtn{padding:3px 9px;border-radius:4px;font-size:.68rem;font-weight:700;cursor:pointer;border:1px solid #475569;background:#1e293b;color:#94a3b8;font-family:'Inter',sans-serif;transition:.15s}\r\n#pthcs .abtn:hover{background:#334155;color:#e2e8f0}\r\n\/* Editor wrap with line numbers *\/\r\n#pthcs .cs-ewrap{flex:1;display:flex;overflow:hidden;position:relative;min-height:0}\r\n#pthcs .cs-lnums{background:#161b22;border-right:1px solid #30363d;padding:12px 0;font-family:'Courier New',monospace;font-size:13px;line-height:1.65;color:#484f58;text-align:right;min-width:44px;overflow:hidden;flex-shrink:0;user-select:none;white-space:pre}\r\n#pthcs .cs-editor{flex:1;padding:12px 14px;background:#0d1117;border:none;outline:none;color:#e2e8f0;font-family:'Courier New',Consolas,monospace;font-size:13px;line-height:1.65;resize:none;tab-size:2;overflow:auto;white-space:pre;word-wrap:normal}\r\n#pthcs .cs-editor::selection{background:rgba(99,102,241,.4)}\r\n\/* Statusbar *\/\r\n#pthcs .cs-sbar{background:#1e293b;border-top:1px solid #334155;padding:3px 10px;display:flex;gap:12px;font-size:.62rem;color:#475569;font-family:'Courier New',monospace;flex-shrink:0}\r\n\/* Right panel *\/\r\n#pthcs .cs-rpanel{display:flex;flex-direction:column;min-height:0}\r\n#pthcs .cs-rtabs{display:flex;background:#1e293b;border-bottom:1px solid #334155;flex-shrink:0}\r\n#pthcs .rtab{flex:1;padding:8px 4px;font-size:.72rem;font-weight:800;color:#64748b;background:transparent;border:none;cursor:pointer;font-family:'Inter',sans-serif;border-bottom:2px solid transparent;transition:.15s;white-space:nowrap}\r\n#pthcs .rtab.on{color:#8b5cf6;border-bottom-color:#8b5cf6}\r\n#pthcs .rtab:hover{background:#263548}\r\n\/* Preview *\/\r\n#pthcs .cs-prevwrap{flex:1;display:flex;flex-direction:column;min-height:0;height:100%;background:#fff;overflow:hidden}\r\n#pthcs .cs-prevbar{background:#263548;padding:5px 10px;display:flex;align-items:center;gap:5px;flex-shrink:0}\r\n#pthcs .dot{width:9px;height:9px;border-radius:50%}\r\n#pthcs .cs-prevtitle{font-size:.68rem;color:#64748b;flex:1;text-align:center;font-weight:700}\r\n#pthcs #cs-frame{flex:1;width:100%;height:calc(100% - 32px);min-height:600px;border:none;background:#fff;display:block;overflow:auto;scrollbar-width:thin;scrollbar-color:#8b5cf6 #e2e8f0}\r\n\/* Chat *\/\r\n#pthcs .cs-chat{flex:1;display:flex;flex-direction:column;min-height:0;overflow:hidden}\r\n#pthcs .cs-msgs{flex:1;overflow-y:auto;padding:10px;display:flex;flex-direction:column;gap:8px;scrollbar-width:thin;scrollbar-color:#334155 transparent;min-height:0;max-height:420px}\r\n#pthcs .msg{max-width:92%;padding:9px 12px;border-radius:10px;font-size:.8rem;line-height:1.6;word-break:break-word}\r\n#pthcs .msg-u{background:#3730a3;color:#e0e7ff;align-self:flex-end;border-radius:10px 10px 2px 10px}\r\n#pthcs .msg-a{background:#1e293b;color:#e2e8f0;align-self:flex-start;border:1px solid #334155;border-radius:10px 10px 10px 2px}\r\n#pthcs .msg-s{background:rgba(139,92,246,.08);color:#a78bfa;align-self:center;font-size:.72rem;font-weight:600;padding:8px 14px;border-radius:10px;border:1px solid rgba(139,92,246,.2);text-align:center;max-width:95%;line-height:1.5}\r\n#pthcs .msg-a pre{background:#0f172a;border:1px solid #334155;border-radius:6px;padding:10px;overflow-x:auto;font-size:.72rem;margin:6px 0;font-family:'Courier New',monospace;white-space:pre-wrap;word-break:break-all}\r\n#pthcs .codeblock{background:#0d1117;border:1px solid #30363d;border-radius:8px;margin:8px 0;overflow:hidden}\r\n#pthcs .cbhead{display:flex;align-items:center;justify-content:space-between;padding:6px 12px;background:#161b22;border-bottom:1px solid #30363d}\r\n#pthcs .cblang{font-size:.65rem;font-weight:800;color:#8b5cf6;text-transform:uppercase;letter-spacing:.5px}\r\n#pthcs .cbcopy{background:#1e293b;color:#94a3b8;border:1px solid #334155;border-radius:5px;padding:3px 9px;font-size:.67rem;font-weight:700;cursor:pointer;font-family:'Inter',sans-serif;transition:.15s}\r\n#pthcs .cbcopy:hover{background:#334155;color:#e2e8f0}\r\n#pthcs .cbpre{margin:0;padding:12px;background:#0d1117;color:#e2e8f0;font-family:'Courier New',monospace;font-size:.73rem;line-height:1.6;overflow-x:auto;white-space:pre;max-height:320px;overflow-y:auto}\r\n#pthcs .applybtn{margin-top:10px;padding:10px 16px;background:linear-gradient(135deg,#059669,#047857);color:#fff;border:none;border-radius:7px;font-size:.78rem;font-weight:800;cursor:pointer;display:block;width:100%;font-family:'Inter',sans-serif;transition:.2s;text-align:center;position:sticky;bottom:0;z-index:10;box-shadow:0 -2px 10px rgba(5,150,105,.3)}\r\n#pthcs .applybtn:hover{transform:translateY(-1px);box-shadow:0 4px 12px rgba(5,150,105,.4)}\r\n#pthcs .msg-a code{background:rgba(0,0,0,.3);padding:1px 5px;border-radius:3px;font-family:'Courier New',monospace;font-size:.74rem}\r\n#pthcs .cs-cin-wrap{border-top:1px solid #334155;padding:8px;background:#1e293b;display:flex;gap:6px;flex-shrink:0;position:relative;z-index:5}\r\n#pthcs .cs-cin{flex:1;padding:8px 11px;background:#0f172a;border:1px solid #475569;border-radius:7px;color:#e2e8f0;font-size:.8rem;font-family:'Inter',sans-serif;outline:none;resize:none;max-height:80px}\r\n#pthcs .cs-cin:focus{border-color:#8b5cf6}\r\n#pthcs .sendbtn{padding:8px 14px;background:linear-gradient(135deg,#8b5cf6,#6d28d9);color:#fff;border:none;border-radius:7px;font-weight:800;font-size:.78rem;cursor:pointer;font-family:'Inter',sans-serif}\r\n#pthcs .sendbtn:disabled{opacity:.4;cursor:not-allowed}\r\n\/* History *\/\r\n#pthcs .cs-hist{flex:1;overflow-y:auto;padding:10px}\r\n#pthcs .hitem{background:#1e293b;border:1px solid #334155;border-radius:7px;padding:8px 10px;margin-bottom:6px;cursor:pointer;transition:.15s}\r\n#pthcs .hitem:hover{border-color:#8b5cf6}\r\n#pthcs .hlang{font-size:.62rem;font-weight:800;color:#8b5cf6;text-transform:uppercase}\r\n#pthcs .hprev{font-size:.7rem;color:#64748b;font-family:'Courier New',monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px}\r\n\/* Buttons *\/\r\n#pthcs .btn{padding:5px 12px;border-radius:7px;font-weight:800;font-size:.75rem;cursor:pointer;border:none;font-family:'Inter',sans-serif;transition:.15s;white-space:nowrap;display:inline-flex;align-items:center;gap:5px}\r\n#pthcs .btn-p{background:#8b5cf6;color:#fff}\r\n#pthcs .btn-p:hover{background:#7c3aed}\r\n#pthcs .btn-g{background:#059669;color:#fff}\r\n#pthcs .btn-g:hover{background:#047857}\r\n#pthcs .btn-gh{background:transparent;color:#94a3b8;border:1px solid #475569}\r\n#pthcs .btn-gh:hover{background:#334155;color:#e2e8f0}\r\n#pthcs .btn-sm{padding:4px 10px;font-size:.7rem}\r\n\/* Thinking dots *\/\r\n#pthcs .think{display:inline-flex;align-items:center;gap:5px;color:#a78bfa;font-size:.78rem}\r\n#pthcs .thdot{width:5px;height:5px;border-radius:50%;background:#8b5cf6;animation:thb 1.2s infinite}\r\n#pthcs .thdot:nth-child(2){animation-delay:.2s}\r\n#pthcs .thdot:nth-child(3){animation-delay:.4s}\r\n@keyframes thb{0%,60%,100%{transform:translateY(0)}30%{transform:translateY(-5px)}}\r\n\/* Modals *\/\r\n.pthcs-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.78);z-index:99999;display:none;justify-content:center;align-items:center;backdrop-filter:blur(5px)}\r\n.pthcs-overlay.open{display:flex}\r\n.pthcs-modal{background:#1e293b;border:1px solid #334155;border-radius:18px;padding:28px 30px;width:90%;max-width:520px;color:#e2e8f0;box-shadow:0 24px 60px rgba(0,0,0,.6)}\r\n\/* API modal *\/\r\n#cs-api-modal .cs-micon{font-size:2.6rem;text-align:center;display:block;margin-bottom:10px}\r\n#cs-api-modal h3{text-align:center;margin:0 0 5px;font-size:1.2rem;font-weight:900}\r\n#cs-api-modal .cs-msub{text-align:center;color:#94a3b8;font-size:.85rem;margin:0 0 20px}\r\n\/* Provider tabs *\/\r\n#cs-api-modal .pvtabs{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:16px}\r\n#cs-api-modal .pvtab{border:2px solid #334155;background:#0f172a;border-radius:10px;padding:10px 6px;cursor:pointer;text-align:center;transition:.2s;font-family:'Inter',sans-serif}\r\n#cs-api-modal .pvtab:hover{border-color:#6d28d9}\r\n#cs-api-modal .pvtab.sel{border-color:#8b5cf6;background:rgba(139,92,246,.12)}\r\n#cs-api-modal .pvicon{font-size:1.4rem;display:block;margin-bottom:4px}\r\n#cs-api-modal .pvname{font-size:.78rem;font-weight:800;color:#e2e8f0;display:block}\r\n#cs-api-modal .pvtag{font-size:.62rem;font-weight:700;padding:1px 7px;border-radius:999px;display:inline-block;margin-top:3px}\r\n#cs-api-modal .free{background:rgba(16,185,129,.15);color:#6ee7b7;border:1px solid rgba(16,185,129,.3)}\r\n#cs-api-modal .paid{background:rgba(245,158,11,.1);color:#fcd34d;border:1px solid rgba(245,158,11,.25)}\r\n\/* API info box *\/\r\n#cs-api-modal .pvinfo{background:#0f172a;border:1px solid #334155;border-radius:8px;padding:10px 14px;margin-bottom:14px;font-size:.78rem;color:#94a3b8;line-height:1.7}\r\n#cs-api-modal .pvinfo strong{color:#a78bfa}\r\n#cs-api-modal .pvinfo a{color:#38bdf8;text-decoration:none;font-weight:700}\r\n\/* Key input *\/\r\n#cs-api-modal .kinput{width:100%;padding:11px 40px 11px 13px;background:#0f172a;border:1.5px solid #475569;border-radius:9px;color:#e2e8f0;font-family:'Courier New',monospace;font-size:.82rem;outline:none;transition:.2s;margin-bottom:12px}\r\n#cs-api-modal .kinput:focus{border-color:#8b5cf6;box-shadow:0 0 0 3px rgba(139,92,246,.15)}\r\n#cs-api-modal .kiwrap{position:relative;margin-bottom:12px}\r\n#cs-api-modal .kiwrap .kinput{margin-bottom:0}\r\n#cs-api-modal .eyebtn{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;color:#64748b;font-size:.9rem;padding:0}\r\n#cs-api-modal .eyebtn:hover{color:#a78bfa}\r\n\/* Privacy note *\/\r\n#cs-api-modal .priv{display:flex;align-items:flex-start;gap:8px;background:rgba(16,185,129,.06);border:1px solid rgba(16,185,129,.2);border-radius:8px;padding:9px 12px;margin-bottom:16px;font-size:.74rem;color:#6ee7b7;font-weight:600;line-height:1.5}\r\n\/* Modal buttons *\/\r\n#cs-api-modal .mbtns{display:flex;gap:8px}\r\n#cs-api-modal .msave{flex:1;padding:12px;background:linear-gradient(135deg,#8b5cf6,#6d28d9);color:#fff;border:none;border-radius:9px;font-size:.9rem;font-weight:900;cursor:pointer;font-family:'Inter',sans-serif;transition:.2s}\r\n#cs-api-modal .msave:hover{transform:translateY(-1px);box-shadow:0 6px 20px rgba(139,92,246,.4)}\r\n#cs-api-modal .mskip{padding:12px 16px;background:transparent;color:#64748b;border:1px solid #334155;border-radius:9px;font-size:.82rem;font-weight:700;cursor:pointer;font-family:'Inter',sans-serif}\r\n#cs-api-modal .mskip:hover{background:#334155;color:#e2e8f0}\r\n\/* Woody modal *\/\r\n#cs-woody-modal .wtabs{display:flex;gap:6px;margin-bottom:11px;flex-wrap:wrap}\r\n#cs-woody-modal textarea{width:100%;min-height:170px;padding:10px;background:#0f172a;border:1px solid #475569;border-radius:8px;color:#a5f3fc;font-family:'Courier New',monospace;font-size:.72rem;outline:none;resize:vertical}\r\n#cs-woody-modal .wacts{display:flex;gap:7px;margin-top:10px;flex-wrap:wrap}\r\n\/* Toast *\/\r\n#pthcs-toast{position:fixed;bottom:20px;right:20px;background:#1e293b;color:#fff;padding:10px 18px;border-radius:10px;font-weight:800;font-size:.84rem;box-shadow:0 8px 24px rgba(0,0,0,.5);z-index:999999;display:none;align-items:center;gap:8px;border:1px solid #334155;max-width:300px}\r\n#pthcs-toast.show{display:flex}\r\n\r\n\/* Generate Prompt Modal *\/\r\n#cs-gen-modal .pthcs-modal{max-width:600px}\r\n#cs-gen-modal h3{margin:0 0 4px;font-size:1.1rem;font-weight:900}\r\n#cs-gen-modal .gmsub{color:#94a3b8;font-size:.82rem;margin:0 0 16px}\r\n#cs-gen-modal .gtasks{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:16px}\r\n#cs-gen-modal .gtask{padding:6px 12px;background:#1e293b;border:1px solid #334155;border-radius:7px;font-size:.75rem;font-weight:700;color:#94a3b8;cursor:pointer;transition:.15s;font-family:'Inter',sans-serif}\r\n#cs-gen-modal .gtask:hover{background:#334155;color:#e2e8f0;border-color:#475569}\r\n#cs-gen-modal .gtask.sel{background:rgba(139,92,246,.15);border-color:#8b5cf6;color:#a78bfa}\r\n#cs-gen-modal .ginput{width:100%;padding:12px 14px;background:#0f172a;border:1.5px solid #475569;border-radius:9px;color:#e2e8f0;font-family:'Inter',sans-serif;font-size:.9rem;outline:none;transition:.2s;margin-bottom:14px;resize:none;min-height:80px}\r\n#cs-gen-modal .ginput:focus{border-color:#8b5cf6;box-shadow:0 0 0 3px rgba(139,92,246,.15)}\r\n#cs-gen-modal .gbtns{display:flex;gap:8px}\r\n#cs-gen-modal .grun{flex:1;padding:12px;background:linear-gradient(135deg,#8b5cf6,#6d28d9);color:#fff;border:none;border-radius:9px;font-size:.92rem;font-weight:900;cursor:pointer;font-family:'Inter',sans-serif;transition:.2s}\r\n#cs-gen-modal .grun:hover{transform:translateY(-1px)}\r\n#cs-gen-modal .gcancel{padding:12px 16px;background:transparent;color:#64748b;border:1px solid #334155;border-radius:9px;font-size:.82rem;font-weight:700;cursor:pointer;font-family:'Inter',sans-serif}\r\n#cs-gen-modal .gcancel:hover{background:#334155;color:#e2e8f0}\r\n#cs-gen-modal .glang-row{display:flex;gap:8px;align-items:center;margin-bottom:14px;font-size:.8rem;color:#94a3b8}\r\n#cs-gen-modal .glang-sel{padding:5px 8px;background:#0f172a;border:1px solid #475569;border-radius:5px;color:#e2e8f0;font-size:.78rem;font-family:'Inter',sans-serif;outline:none}\r\n<\/style>\r\n\r\n<!-- API Key Modal -->\r\n<div class=\"pthcs-overlay\" id=\"cs-api-modal\" role=\"dialog\" aria-modal=\"true\" aria-label=\"AI API Key Setup\">\r\n <div class=\"pthcs-modal\">\r\n  <span class=\"cs-micon\">\ud83e\udd16<\/span>\r\n  <h3>Connect Your AI Engine<\/h3>\r\n  <p class=\"cs-msub\">Choose a provider and paste your API key. Gemini &amp; Groq are completely free.<\/p>\r\n  <div class=\"pvtabs\" id=\"cs-pvtabs\">\r\n   <div class=\"pvtab sel\" data-pv=\"gemini\" role=\"button\" tabindex=\"0\" aria-label=\"Gemini Flash \u2014 Free\">\r\n    <span class=\"pvicon\">\ud83d\udca0<\/span>\r\n    <span class=\"pvname\">Gemini Flash<\/span>\r\n    <span class=\"pvtag free\">FREE<\/span>\r\n   <\/div>\r\n   <div class=\"pvtab\" data-pv=\"groq\" role=\"button\" tabindex=\"0\" aria-label=\"Groq Llama 3 \u2014 Free\">\r\n    <span class=\"pvicon\">\u26a1<\/span>\r\n    <span class=\"pvname\">Groq \/ Llama<\/span>\r\n    <span class=\"pvtag free\">FREE<\/span>\r\n   <\/div>\r\n   <div class=\"pvtab\" data-pv=\"claude\" role=\"button\" tabindex=\"0\" aria-label=\"Claude \u2014 Paid\">\r\n    <span class=\"pvicon\">\ud83e\udde0<\/span>\r\n    <span class=\"pvname\">Claude<\/span>\r\n    <span class=\"pvtag paid\">PAID<\/span>\r\n   <\/div>\r\n  <\/div>\r\n  <div class=\"pvinfo\" id=\"cs-pvinfo\">\r\n   <strong>Google Gemini 1.5 Flash<\/strong> \u2014 Free, no credit card needed.<br>\r\n   Get free key \u2192 <a href=\"https:\/\/aistudio.google.com\/app\/apikey\" target=\"_blank\" rel=\"noopener\">aistudio.google.com<\/a>\r\n  <\/div>\r\n  <div class=\"kiwrap\">\r\n   <input type=\"password\" id=\"cs-kinput\" class=\"kinput\" placeholder=\"Paste your API key here...\" aria-label=\"API key input\">\r\n   <button class=\"eyebtn\" id=\"cs-eyebtn\" aria-label=\"Toggle key visibility\">\ud83d\udc41<\/button>\r\n  <\/div>\r\n  <div class=\"priv\">\r\n   <span>\ud83d\udd12<\/span>\r\n   <span>Key stored in <code style=\"background:rgba(255,255,255,.1);padding:1px 5px;border-radius:3px;\">sessionStorage<\/code> only \u2014 clears on tab close, <strong>never sent to PTH servers<\/strong>.<\/span>\r\n  <\/div>\r\n  <div class=\"mbtns\">\r\n   <button class=\"msave\" id=\"cs-msave\" aria-label=\"Save key and start coding\">\ud83d\udcbe Save Key &amp; Start Coding<\/button>\r\n   <button class=\"mskip\" id=\"cs-mskip\" aria-label=\"Skip for now\">Skip<\/button>\r\n  <\/div>\r\n <\/div>\r\n<\/div>\r\n\r\n<!-- Generate Prompt Modal -->\r\n<div class=\"pthcs-overlay\" id=\"cs-gen-modal\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Generate Code\">\r\n <div class=\"pthcs-modal\">\r\n  <h3>\u2728 Generate with AI<\/h3>\r\n  <p class=\"gmsub\">Choose a task below or describe your own idea. The AI will write complete, working code.<\/p>\r\n  <!-- Task chips -->\r\n  <div class=\"gtasks\" id=\"cs-gtasks\">\r\n   <button class=\"gtask\" data-task=\"Build a pricing table with 3 plans (Basic, Pro, Enterprise)\" aria-label=\"Pricing table\">\ud83d\udcb0 Pricing Table<\/button>\r\n   <button class=\"gtask\" data-task=\"Create a dashboard with 4 stat cards showing users, revenue, orders, and growth\" aria-label=\"Dashboard\">\ud83d\udcca Dashboard Cards<\/button>\r\n   <button class=\"gtask\" data-task=\"Build a todo app with add, complete, and delete functionality\" aria-label=\"Todo app\">\u2705 Todo App<\/button>\r\n   <button class=\"gtask\" data-task=\"Create a responsive navigation bar with logo, links, and hamburger menu for mobile\" aria-label=\"Navbar\">\ud83e\udded Responsive Navbar<\/button>\r\n   <button class=\"gtask\" data-task=\"Build an animated hero section with headline, subtitle, CTA button, and gradient background\" aria-label=\"Hero section\">\ud83c\udfaf Hero Section<\/button>\r\n   <button class=\"gtask\" data-task=\"Create a contact form with name, email, message fields and validation\" aria-label=\"Contact form\">\ud83d\udceb Contact Form<\/button>\r\n   <button class=\"gtask\" data-task=\"Build a WordPress shortcode for a testimonial card with photo, name, role, and quote\" aria-label=\"WP shortcode\">\ud83d\udd0c WP Shortcode<\/button>\r\n   <button class=\"gtask\" data-task=\"Create a card grid layout with 6 product cards showing image placeholder, title, price, and buy button\" aria-label=\"Card grid\">\ud83c\udccf Card Grid<\/button>\r\n   <button class=\"gtask\" data-task=\"Build a dark mode toggle button that switches between light and dark themes using CSS variables\" aria-label=\"Dark mode toggle\">\ud83c\udf19 Dark Mode Toggle<\/button>\r\n   <button class=\"gtask\" data-task=\"Create a modal popup with overlay, close button, title, and content area\" aria-label=\"Modal popup\">\ud83e\ude9f Modal Popup<\/button>\r\n   <button class=\"gtask\" data-task=\"Build a countdown timer showing days, hours, minutes, and seconds\" aria-label=\"Countdown timer\">\u23f1\ufe0f Countdown Timer<\/button>\r\n   <button class=\"gtask\" data-task=\"Create an animated CSS loading spinner with 3 different styles\" aria-label=\"Loading spinner\">\u26a1 Loading Spinner<\/button>\r\n  <\/div>\r\n  <!-- Language selector -->\r\n  <div class=\"glang-row\">\r\n   <span>Generate as:<\/span>\r\n   <select id=\"cs-glang\" class=\"glang-sel\" aria-label=\"Language for generation\">\r\n    <option value=\"html\">HTML + CSS + JS<\/option>\r\n    <option value=\"php\">PHP (WordPress)<\/option>\r\n    <option value=\"javascript\">JavaScript only<\/option>\r\n    <option value=\"css\">CSS only<\/option>\r\n    <option value=\"python\">Python<\/option>\r\n   <\/select>\r\n  <\/div>\r\n  <!-- Custom input -->\r\n  <textarea id=\"cs-ginput\" class=\"ginput\" placeholder=\"Or type your custom idea here... e.g. 'Build a recipe card with ingredients list and cooking steps'\" aria-label=\"Custom generate prompt\"><\/textarea>\r\n  <div class=\"gbtns\">\r\n   <button class=\"grun\" id=\"cs-grun\" aria-label=\"Generate code now\">\u2728 Generate Code<\/button>\r\n   <button class=\"gcancel\" id=\"cs-gcancel\" aria-label=\"Cancel\">Cancel<\/button>\r\n  <\/div>\r\n  <p style=\"text-align:center;color:#475569;font-size:.7rem;margin-top:8px;\">\ud83d\udca1 Tip: Press <kbd style=\"background:#0f172a;border:1px solid #334155;padding:1px 5px;border-radius:3px;font-size:.7rem;color:#94a3b8;\">Ctrl+Enter<\/kbd> to generate quickly<\/p>\r\n <\/div>\r\n<\/div>\r\n\r\n<!-- Woody Export Modal -->\r\n<div class=\"pthcs-overlay\" id=\"cs-woody-modal\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Export to WordPress\">\r\n <div class=\"pthcs-modal\">\r\n  <h3 style=\"margin:0 0 14px;font-size:1rem;font-weight:800;\">\ud83c\udf3f Export to WordPress<\/h3>\r\n  <div class=\"wtabs\">\r\n   <button class=\"btn btn-p btn-sm\" id=\"cs-w-html\" aria-label=\"HTML Snippet \u2014 paste into Woody\">\ud83d\udcc4 HTML Snippet<\/button>\r\n   <button class=\"btn btn-gh btn-sm\" id=\"cs-w-short\" aria-label=\"PHP Shortcode for WordPress\">\u26a1 PHP Shortcode<\/button>\r\n  <\/div>\r\n  <p style=\"font-size:.72rem;color:#64748b;margin:0 0 10px;\">Copy the HTML and paste into your Woody Code Snippet editor.<\/p>\r\n  <textarea id=\"cs-wout\" readonly aria-label=\"Export output\"><\/textarea>\r\n  <div class=\"wacts\">\r\n   <button class=\"btn btn-p btn-sm\" id=\"cs-w-copy\" aria-label=\"Copy export\">\ud83d\udccb Copy<\/button>\r\n   <button class=\"btn btn-g btn-sm\" id=\"cs-w-dl\" aria-label=\"Download\">\u2b07 Download<\/button>\r\n   <button class=\"btn btn-gh btn-sm\" id=\"cs-w-close\" aria-label=\"Close\">\u2715 Close<\/button>\r\n  <\/div>\r\n <\/div>\r\n<\/div>\r\n\r\n<!-- Toast -->\r\n<div id=\"pthcs-toast\" role=\"alert\" aria-live=\"polite\"><\/div>\r\n\r\n<!-- MAIN TOOL (NEW DEFAULT SAMPLE IN BASE64 - RESPONSIVE PRICING TABLE) -->\r\n<span id=\"pthcs-sample\" data-s=\"PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ+CjxtZXRhIGNoYXJzZXQ9IlVURi04Ij4KPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiPgo8dGl0bGU+UFRIIEFJIENvZGUgU3R1ZGlvIOKAlCBEZW1vPC90aXRsZT4KPHN0eWxlPgoqe21hcmdpbjowO3BhZGRpbmc6MDtib3gtc2l6aW5nOmJvcmRlci1ib3h9CmJvZHl7bWluLWhlaWdodDoxMDB2aDtkaXNwbGF5OmZsZXg7YWxpZ24taXRlbXM6Y2VudGVyO2p1c3RpZnktY29udGVudDpjZW50ZXI7YmFja2dyb3VuZDpsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCMwZjE3MmEgMCUsIzFlMWI0YiAxMDAlKTtmb250LWZhbWlseTonSW50ZXInLHN5c3RlbS11aSxzYW5zLXNlcmlmO3BhZGRpbmc6MjBweH0KLmNhcmR7YmFja2dyb3VuZDpyZ2JhKDI1NSwyNTUsMjU1LC4wNSk7Ym9yZGVyOjFweCBzb2xpZCByZ2JhKDI1NSwyNTUsMjU1LC4xKTtib3JkZXItcmFkaXVzOjIwcHg7cGFkZGluZzozNnB4O21heC13aWR0aDo1MDBweDt3aWR0aDoxMDAlO3RleHQtYWxpZ246Y2VudGVyfQouYmFkZ2V7ZGlzcGxheTppbmxpbmUtZmxleDthbGlnbi1pdGVtczpjZW50ZXI7Z2FwOjZweDtiYWNrZ3JvdW5kOnJnYmEoMTM5LDkyLDI0NiwuMik7Ym9yZGVyOjFweCBzb2xpZCByZ2JhKDEzOSw5MiwyNDYsLjQpO2NvbG9yOiNhNzhiZmE7cGFkZGluZzo1cHggMTRweDtib3JkZXItcmFkaXVzOjk5OXB4O2ZvbnQtc2l6ZTouNzJyZW07Zm9udC13ZWlnaHQ6ODAwO21hcmdpbi1ib3R0b206MjBweDt0ZXh0LXRyYW5zZm9ybTp1cHBlcmNhc2U7bGV0dGVyLXNwYWNpbmc6LjVweH0KaDJ7Zm9udC1zaXplOjEuOHJlbTtmb250LXdlaWdodDo5MDA7Y29sb3I6I2YxZjVmOTttYXJnaW4tYm90dG9tOjEwcHg7bGluZS1oZWlnaHQ6MS4yNX0KaDIgc3BhbntiYWNrZ3JvdW5kOmxpbmVhci1ncmFkaWVudCgxMzVkZWcsIzhiNWNmNiwjMDZiNmQ0KTstd2Via2l0LWJhY2tncm91bmQtY2xpcDp0ZXh0Oy13ZWJraXQtdGV4dC1maWxsLWNvbG9yOnRyYW5zcGFyZW50O2JhY2tncm91bmQtY2xpcDp0ZXh0fQouc3Vie2NvbG9yOiM5NGEzYjg7Zm9udC1zaXplOi45cmVtO2xpbmUtaGVpZ2h0OjEuNjU7bWFyZ2luLWJvdHRvbToyNHB4fQouZmVhdHN7ZGlzcGxheTpncmlkO2dyaWQtdGVtcGxhdGUtY29sdW1uczoxZnIgMWZyO2dhcDo5cHg7bWFyZ2luLWJvdHRvbToyNHB4O3RleHQtYWxpZ246bGVmdH0KLmZlYXR7YmFja2dyb3VuZDpyZ2JhKDI1NSwyNTUsMjU1LC4wNCk7Ym9yZGVyOjFweCBzb2xpZCByZ2JhKDI1NSwyNTUsMjU1LC4wNyk7Ym9yZGVyLXJhZGl1czo5cHg7cGFkZGluZzoxMXB4IDEzcHg7ZGlzcGxheTpmbGV4O2FsaWduLWl0ZW1zOmNlbnRlcjtnYXA6OXB4O2NvbG9yOiNjYmQ1ZTE7Zm9udC1zaXplOi44cmVtO2ZvbnQtd2VpZ2h0OjYwMH0KLmJ0bntkaXNwbGF5OmlubGluZS1ibG9jaztwYWRkaW5nOjEycHggMjZweDtiYWNrZ3JvdW5kOmxpbmVhci1ncmFkaWVudCgxMzVkZWcsIzhiNWNmNiwjNmQyOGQ5KTtjb2xvcjojZmZmO2JvcmRlcjpub25lO2JvcmRlci1yYWRpdXM6OXB4O2ZvbnQtc2l6ZTouOXJlbTtmb250LXdlaWdodDo4MDA7Y3Vyc29yOnBvaW50ZXI7dHJhbnNpdGlvbjouMnM7Zm9udC1mYW1pbHk6aW5oZXJpdH0KLmJ0bjpob3Zlcnt0cmFuc2Zvcm06dHJhbnNsYXRlWSgtMnB4KTtib3gtc2hhZG93OjAgOHB4IDI0cHggcmdiYSgxMzksOTIsMjQ2LC40KX0KLmhpbnR7bWFyZ2luLXRvcDoxNHB4O2NvbG9yOiM0NzU1Njk7Zm9udC1zaXplOi43NXJlbX0KLmRvdHtkaXNwbGF5OmlubGluZS1ibG9jazt3aWR0aDo2cHg7aGVpZ2h0OjZweDtib3JkZXItcmFkaXVzOjUwJTtiYWNrZ3JvdW5kOiMxMGI5ODE7bWFyZ2luLXJpZ2h0OjRweDt2ZXJ0aWNhbC1hbGlnbjptaWRkbGU7YW5pbWF0aW9uOnB1bHNlIDJzIGluZmluaXRlfQpAa2V5ZnJhbWVzIHB1bHNlezAlLDEwMCV7b3BhY2l0eToxfTUwJXtvcGFjaXR5Oi40fX0KPC9zdHlsZT4KPC9oZWFkPgo8Ym9keT4KPGRpdiBjbGFzcz0iY2FyZCI+CiAgPGRpdiBjbGFzcz0iYmFkZ2UiPvCfpJYgQUkgQ29kZSBTdHVkaW88L2Rpdj4KICA8aDI+QnVpbGQgQ29kZSB3aXRoIDxzcGFuPkFJIE1hZ2ljPC9zcGFuPjwvaDI+CiAgPHAgY2xhc3M9InN1YiI+VGhpcyBpcyB5b3VyIGxpdmUgcHJldmlldy4gV3JpdGUgSFRNTCBpbiB0aGUgZWRpdG9yLCBvciBjbGljayDinKggR2VuZXJhdGUgYWJvdmUgdG8gbGV0IEFJIGJ1aWxkIHNvbWV0aGluZyBhbWF6aW5nIGZvciB5b3UuPC9wPgogIDxkaXYgY2xhc3M9ImZlYXRzIj4KICAgIDxkaXYgY2xhc3M9ImZlYXQiPuKcqCBBSSBHZW5lcmF0ZTwvZGl2PgogICAgPGRpdiBjbGFzcz0iZmVhdCI+8J+Rge+4jyBMaXZlIFByZXZpZXc8L2Rpdj4KICAgIDxkaXYgY2xhc3M9ImZlYXQiPvCfkJsgRmluZCBCdWdzPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJmZWF0Ij7wn5KFIFRhaWx3aW5kIENTUzwvZGl2PgogICAgPGRpdiBjbGFzcz0iZmVhdCI+8J+TnSBBZGQgQ29tbWVudHM8L2Rpdj4KICAgIDxkaXYgY2xhc3M9ImZlYXQiPvCfjL8gV1AgRXhwb3J0PC9kaXY+CiAgPC9kaXY+CiAgPGJ1dHRvbiBjbGFzcz0iYnRuIiBpZD0iZGVtby1idG4iPlRyeSDinKggR2VuZXJhdGUgTm93PC9idXR0b24+CiAgPHAgY2xhc3M9ImhpbnQiPjxzcGFuIGNsYXNzPSJkb3QiPjwvc3Bhbj5DbGljayDinKggR2VuZXJhdGUgYWJvdmUgdG8gc3RhcnQgYnVpbGRpbmcgd2l0aCBBSTwvcD4KPC9kaXY+CjxzY3JpcHQ+CmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkZW1vLWJ0bicpLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJyxmdW5jdGlvbigpewogIHRoaXMudGV4dENvbnRlbnQ9J0NsaWNrIOKcqCBHZW5lcmF0ZSBidXR0b24gYWJvdmUhJzsKICB0aGlzLnN0eWxlLmJhY2tncm91bmQ9J2xpbmVhci1ncmFkaWVudCgxMzVkZWcsIzA1OTY2OSwjMDQ3ODU3KSc7Cn0pOwo8XC9zY3JpcHQ+CjwvYm9keT4KPC9odG1sPg==\" aria-hidden=\"true\" style=\"display:none\"><\/span>\r\n\r\n<div id=\"pthcs\">\r\n <!-- Top bar -->\r\n <div class=\"cs-top\">\r\n  <div class=\"cs-logo\">\ud83e\udd16 PTH AI Code Studio <span class=\"cs-v\">v2.0 PRO<\/span> <span class=\"cs-prv\">\ud83d\udd12 Private<\/span><\/div>\r\n  <div class=\"cs-tr\">\r\n   <button class=\"btn btn-gh btn-sm\" id=\"cs-new\" aria-label=\"New file\">\ud83d\udcc4 New<\/button>\r\n   <button class=\"btn btn-gh btn-sm\" id=\"cs-fullw\" aria-label=\"Toggle full width\">\u26f6 Full Width<\/button>\r\n   <button class=\"btn btn-gh btn-sm\" id=\"cs-apikey\" aria-label=\"API Key settings\">\ud83d\udd11 API Key<\/button>\r\n   <button class=\"btn btn-g btn-sm\" id=\"cs-wpexport\" aria-label=\"Export to WordPress\">\ud83c\udf3f WP Export<\/button>\r\n  <\/div>\r\n <\/div>\r\n\r\n <!-- Status row -->\r\n <div class=\"cs-stat\">\r\n  <span style=\"color:#64748b;font-weight:700;text-transform:uppercase;letter-spacing:.4px;font-size:.65rem;\">AI:<\/span>\r\n  <span class=\"cs-pname\" id=\"cs-pname\">Not set<\/span>\r\n  <span class=\"cs-kdot\" id=\"cs-kdot\"><\/span>\r\n  <span class=\"cs-klbl off\" id=\"cs-klbl\">No key \u2014 click \ud83d\udd11 API Key to add<\/span>\r\n <\/div>\r\n\r\n <!-- Magic buttons -->\r\n <div class=\"cs-magic\">\r\n  <span class=\"cs-mlbl\">Magic:<\/span>\r\n  <button class=\"mbtn mb1\" id=\"cs-m1\" aria-label=\"Generate code with AI\">\u2728 Generate<\/button>\r\n  <button class=\"mbtn mb2\" id=\"cs-m2\" aria-label=\"Optimize code\">\u26a1 Optimize<\/button>\r\n  <button class=\"mbtn mb3\" id=\"cs-m3\" aria-label=\"Find bugs\">\ud83d\udc1b Find Bugs<\/button>\r\n  <button class=\"mbtn mb4\" id=\"cs-m4\" aria-label=\"Add comments\">\ud83d\udcdd Comments<\/button>\r\n  <button class=\"mbtn mb5\" id=\"cs-m5\" aria-label=\"Format with Tailwind CSS\">\ud83d\udc85 Tailwind<\/button>\r\n  <button class=\"mbtn mb6\" id=\"cs-m6\" aria-label=\"Explain code\">\u2753 Explain<\/button>\r\n  <button class=\"mbtn mb7\" id=\"cs-m7\" aria-label=\"Convert language\">\ud83d\udd04 Convert<\/button>\r\n <\/div>\r\n\r\n <!-- Main grid -->\r\n <div class=\"cs-grid\">\r\n\r\n  <!-- LEFT: Editor -->\r\n  <div class=\"cs-epanel\">\r\n   <div class=\"cs-etbar\">\r\n    <select id=\"cs-lang\" class=\"cs-lsel\" aria-label=\"Select language\">\r\n     <option value=\"html\">HTML<\/option>\r\n     <option value=\"css\">CSS<\/option>\r\n     <option value=\"javascript\">JavaScript<\/option>\r\n     <option value=\"php\">PHP<\/option>\r\n     <option value=\"python\">Python<\/option>\r\n     <option value=\"typescript\">TypeScript<\/option>\r\n     <option value=\"sql\">SQL<\/option>\r\n     <option value=\"json\">JSON<\/option>\r\n     <option value=\"markdown\">Markdown<\/option>\r\n     <option value=\"shell\">Shell<\/option>\r\n    <\/select>\r\n    <span class=\"cs-cur\" id=\"cs-cur\">Ln 1, Col 1<\/span>\r\n    <div class=\"cs-eacts\">\r\n     <button class=\"abtn\" id=\"cs-copy\" aria-label=\"Copy code\">\ud83d\udccb Copy<\/button>\r\n     <button class=\"abtn\" id=\"cs-dl\" aria-label=\"Download\">\u2b07 DL<\/button>\r\n     <button class=\"abtn\" id=\"cs-clr\" aria-label=\"Clear editor\">\ud83d\uddd1 Clear<\/button>\r\n    <\/div>\r\n   <\/div>\r\n   <div class=\"cs-ewrap\">\r\n    <div class=\"cs-lnums\" id=\"cs-lnums\" aria-hidden=\"true\">  1<\/div>\r\n    <textarea id=\"cs-editor\" class=\"cs-editor\" spellcheck=\"false\" autocorrect=\"off\" autocapitalize=\"off\" aria-label=\"Code editor\" placeholder=\"\/\/ Start coding here or click \u2728 Generate to build something with AI\"><\/textarea>\r\n   <\/div>\r\n   <div class=\"cs-sbar\">\r\n    <span id=\"cs-sb-lang\">HTML<\/span>\r\n    <span id=\"cs-sb-lines\">0 lines<\/span>\r\n    <span id=\"cs-sb-chars\">0 chars<\/span>\r\n    <span style=\"margin-left:auto;\" id=\"cs-sb-ai\">AI: No key saved<\/span>\r\n   <\/div>\r\n  <\/div>\r\n\r\n  <!-- RIGHT: Preview \/ Chat \/ History -->\r\n  <div class=\"cs-rpanel\">\r\n   <div class=\"cs-rtabs\">\r\n    <button class=\"rtab on\" data-rp=\"prev\" aria-label=\"Live Preview\">\ud83d\udc41\ufe0f Live Preview<\/button>\r\n    <button class=\"rtab\" data-rp=\"chat\" aria-label=\"AI Chat\">\ud83d\udcac AI Chat<\/button>\r\n    <button class=\"rtab\" data-rp=\"hist\" aria-label=\"History\">\ud83d\udd52 History<\/button>\r\n   <\/div>\r\n\r\n   <!-- Preview -->\r\n   <div class=\"cs-prevwrap\" id=\"cs-rp-prev\">\r\n    <div class=\"cs-prevbar\">\r\n     <div class=\"dot\" style=\"background:#dc2626\"><\/div>\r\n     <div class=\"dot\" style=\"background:#f59e0b\"><\/div>\r\n     <div class=\"dot\" style=\"background:#10b981\"><\/div>\r\n     <span class=\"cs-prevtitle\">Live Preview<\/span>\r\n     <button class=\"abtn\" id=\"cs-refr\" aria-label=\"Refresh preview\" style=\"padding:2px 7px;font-size:.65rem;\">\u21bb Refresh<\/button>\r\n     <button class=\"abtn\" id=\"cs-newtab\" aria-label=\"Open in new tab\" style=\"padding:2px 7px;font-size:.65rem;\">\u29c9 New Tab<\/button>\r\n    <\/div>\r\n    <iframe id=\"cs-frame\" title=\"Live preview\" sandbox=\"allow-scripts allow-same-origin\"><\/iframe>\r\n   <\/div>\r\n\r\n   <!-- Chat -->\r\n   <div class=\"cs-chat\" id=\"cs-rp-chat\" style=\"display:none;\">\r\n    <div class=\"cs-msgs\" id=\"cs-msgs\"><\/div>\r\n    <div class=\"cs-cin-wrap\">\r\n     <textarea id=\"cs-cin\" class=\"cs-cin\" rows=\"2\" placeholder=\"Ask AI about your code...\" aria-label=\"Chat message input\"><\/textarea>\r\n     <button class=\"sendbtn\" id=\"cs-send\" aria-label=\"Send message\">Send \u21b5<\/button>\r\n    <\/div>\r\n   <\/div>\r\n\r\n   <!-- History -->\r\n   <div class=\"cs-hist\" id=\"cs-rp-hist\" style=\"display:none;\">\r\n    <div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;\">\r\n     <span style=\"font-size:.72rem;font-weight:800;color:#64748b;text-transform:uppercase;\">Saved Sessions<\/span>\r\n     <button class=\"btn btn-gh btn-sm\" id=\"cs-clrhist\" aria-label=\"Clear history\">\ud83d\uddd1 Clear All<\/button>\r\n    <\/div>\r\n    <div id=\"cs-histlist\"><p style=\"font-size:.75rem;color:#475569;text-align:center;margin:20px 0;\">No sessions yet. Code auto-saves as you type.<\/p><\/div>\r\n   <\/div>\r\n  <\/div>\r\n\r\n <\/div>\r\n<\/div>\r\n\r\n<script data-no-optimize=\"1\" data-no-minify=\"1\" data-cfasync=\"false\">\r\n(function(){\r\n\"use strict\";\r\n\r\n\/* \u2500\u2500 PTH AI Code Studio v2.0 PRO \u2014 Zero External Dependencies \u2500\u2500 *\/\r\nwindow.pthCS = {\r\n  ok: false,\r\n  lang: 'html',\r\n  panel: 'prev',\r\n  prov: 'gemini',\r\n  busy: false,\r\n  hist: [],\r\n  SK: 'pthcs17',\r\n  HK: 'pthcs17h',\r\n\r\n  PVINFO: {\r\n    gemini: '<strong>Google Gemini Flash<\/strong> \u2014 Free, no credit card.<br>Get key \u2192 <a href=\"https:\/\/aistudio.google.com\/app\/apikey\" target=\"_blank\" rel=\"noopener\">aistudio.google.com<\/a>',\r\n    groq:   '<strong>Groq \/ Llama 3<\/strong> \u2014 Free, fastest responses.<br>Get key \u2192 <a href=\"https:\/\/console.groq.com\/keys\" target=\"_blank\" rel=\"noopener\">console.groq.com<\/a>',\r\n    claude: '<strong>Claude (Anthropic)<\/strong> \u2014 Best quality, paid API.<br>Get key \u2192 <a href=\"https:\/\/console.anthropic.com\/\" target=\"_blank\" rel=\"noopener\">console.anthropic.com<\/a>'\r\n  },\r\n\r\n  PVNAMES: { gemini: '\ud83d\udca0 Gemini Flash', groq: '\u26a1 Groq \/ Llama', claude: '\ud83e\udde0 Claude' },\r\n\r\n  SAMPLE: '',\r\n\r\n  g: function(id){ return document.getElementById(id); },\r\n  bev: function(id, ev, fn){ var el = this.g(id); if(el) el.addEventListener(ev, fn); },\r\n\r\n  getKey: function(){ try{ return sessionStorage.getItem('pthcs_k_' + this.prov) || ''; }catch(e){ return ''; } },\r\n\r\n  toast: function(msg, type){\r\n    var t = this.g('pthcs-toast');\r\n    if(!t) return;\r\n    var ic = {ok:'\u2705',err:'\u274c',info:'\u2139\ufe0f',warn:'\u26a0\ufe0f'};\r\n    t.innerHTML = (ic[type]||'\u2705') + ' ' + msg;\r\n    t.style.borderColor = type==='err'?'#7f1d1d':type==='warn'?'#78350f':'#334155';\r\n    t.classList.add('show');\r\n    clearTimeout(this._tt);\r\n    var self = this;\r\n    this._tt = setTimeout(function(){ t.classList.remove('show'); }, 3000);\r\n  },\r\n\r\n  \/* \u2500\u2500 EDITOR \u2500\u2500 *\/\r\n  getCode: function(){\r\n    var ed = this.g('cs-editor');\r\n    return ed ? ed.value : '';\r\n  },\r\n  setCode: function(newCode, lang){\r\n    var ed = this.g('cs-editor');\r\n    if(ed) ed.value = newCode || '';\r\n    if(lang){ this.lang = lang; var sel = this.g('cs-lang'); if(sel) sel.value = lang; }\r\n    else {\r\n      \/* Auto-detect HTML *\/\r\n      var trimmed = (newCode||'').trim().toLowerCase();\r\n      if(trimmed.indexOf('\\x3C!doctype') === 0 || trimmed.indexOf('\\x3Chtml') === 0){\r\n        this.lang = 'html'; var sel2 = this.g('cs-lang'); if(sel2) sel2.value = 'html';\r\n      }\r\n    }\r\n    this.updateSB();\r\n    this.updateLines();\r\n    \/* Immediate preview on setCode, not debounced *\/\r\n    this.doPreview();\r\n  },\r\n  updateLines: function(){\r\n    var ed = this.g('cs-editor');\r\n    var ln = this.g('cs-lnums');\r\n    if(!ed || !ln) return;\r\n    var lines = ed.value.split('\\n').length;\r\n    var nums = '';\r\n    for(var i=1;i<=lines;i++) nums += (i < 10 ? '  ' : i < 100 ? ' ' : '') + i + '\\n';\r\n    ln.textContent = nums;\r\n  },\r\n  updateCursor: function(){\r\n    var ed = this.g('cs-editor');\r\n    if(!ed) return;\r\n    var txt = ed.value.substring(0, ed.selectionStart);\r\n    var lines = txt.split('\\n');\r\n    var ln = lines.length;\r\n    var col = lines[lines.length-1].length + 1;\r\n    var cur = this.g('cs-cur');\r\n    if(cur) cur.textContent = 'Ln ' + ln + ', Col ' + col;\r\n  },\r\n  updateSB: function(){\r\n    var code = this.getCode();\r\n    var lines = code ? code.split('\\n').length : 0;\r\n    var wc = code ? code.trim().split(\/\\s+\/).filter(function(w){return w.length>0;}).length : 0;\r\n    var sb1 = this.g('cs-sb-lang'); if(sb1) sb1.textContent = this.lang.toUpperCase();\r\n    var sb2 = this.g('cs-sb-lines'); if(sb2) sb2.textContent = lines + (lines===1?' line':' lines');\r\n    var sb3 = this.g('cs-sb-chars'); if(sb3) sb3.textContent = (code?code.length:0) + ' chars | ' + wc + ' tokens';\r\n  },\r\n\r\n  \/* \u2500\u2500 PREVIEW \u2500\u2500 *\/\r\n  _pt: null,\r\n  debPreview: function(){\r\n    clearTimeout(this._pt);\r\n    var self = this;\r\n    this._pt = setTimeout(function(){ self.doPreview(); }, 700);\r\n  },\r\n  doPreview: function(){\r\n    var frame = this.g('cs-frame');\r\n    if(!frame) return;\r\n    var src = this.getCode();\r\n    var html = '';\r\n    \/* Auto-detect: if code has <!DOCTYPE or <html, always render as HTML *\/\r\n    var isHTML = this.lang === 'html' || src.trim().toLowerCase().indexOf('\\x3C!doctype') === 0 || src.trim().toLowerCase().indexOf('\\x3Chtml') === 0;\r\n    if(isHTML){\r\n      \/* Inject scrollbar CSS into preview so it scrolls with styled scrollbar *\/\r\n      var injectCSS = '<style>::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:#f1f5f9}::-webkit-scrollbar-thumb{background:#8b5cf6;border-radius:3px}::-webkit-scrollbar-thumb:hover{background:#6d28d9}body{scrollbar-width:thin;scrollbar-color:#8b5cf6 #f1f5f9}<\/style>';\r\n      var injectMeta = '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">';\r\n      \/* Override full-height CSS that breaks small iframe *\/\r\n      var iframeResetCSS = '<style>html,body{min-height:0!important;height:auto!important}body{min-height:0!important}<\/style>';\r\n      \/* Inject viewport + scrollbar CSS into preview *\/\r\n      if(src.indexOf('<\/head>') > -1){\r\n        html = src.replace('<\/head>', injectMeta + iframeResetCSS + injectCSS + '<\/head>');\r\n      } else if(src.indexOf('<head>') > -1){\r\n        html = src.replace('<head>', '<head>' + injectMeta + iframeResetCSS + injectCSS);\r\n      } else {\r\n        html = injectMeta + iframeResetCSS + injectCSS + src;\r\n      }\r\n    } else if(this.lang === 'css'){\r\n      html = '\\x3C!DOCTYPE html\\x3E\\x3Chtml\\x3E\\x3Chead\\x3E\\x3Cstyle\\x3Ebody{padding:20px;font-family:sans-serif}' + src + '\\x3C\/style\\x3E\\x3C\/head\\x3E\\x3Cbody\\x3E\\x3Cdiv style=\"border:2px dashed #e2e8f0;padding:20px;border-radius:8px;color:#64748b\"\\x3ECSS applied to this box. Add HTML elements in editor to see them styled.\\x3C\/div\\x3E\\x3C\/body\\x3E\\x3C\/html\\x3E';\r\n    } else if(this.lang === 'javascript'){\r\n      html = '\\x3C!DOCTYPE html\\x3E\\x3Chtml\\x3E\\x3Chead\\x3E\\x3Cstyle\\x3Ebody{padding:16px;font-family:monospace;background:#0f172a;color:#a5f3fc;font-size:13px}#o{margin-top:10px}\\x3C\/style\\x3E\\x3C\/head\\x3E\\x3Cbody\\x3E\\x3Cb style=\"color:#8b5cf6\"\\x3EConsole Output:\\x3C\/b\\x3E\\x3Cdiv id=\"o\"\\x3E\\x3C\/div\\x3E\\x3Cscript\\x3Etry{' + src + '}catch(e){document.getElementById(\"o\").innerHTML=\"\\x3Cspan style=color:#f87171\\x3EError: \"+e.message+\"\\x3C\/span\\x3E\";}var ol=console.log;console.log=function(){var d=document.getElementById(\"o\");if(d)d.innerHTML+=Array.prototype.slice.call(arguments).join(\" \")+\"\\x3Cbr\\x3E\";};\\x3C\/script\\x3E\\x3C\/body\\x3E\\x3C\/html\\x3E';\r\n    } else {\r\n      html = '\\x3C!DOCTYPE html\\x3E\\x3Chtml\\x3E\\x3Cbody style=\"padding:16px;font-family:monospace;background:#1e293b;color:#e2e8f0;white-space:pre-wrap;font-size:13px;line-height:1.6\"\\x3E' + (src||'').replace(\/&\/g,'&amp;').replace(\/<\/g,'&lt;').replace(\/>\/g,'&gt;') + '\\x3C\/body\\x3E\\x3C\/html\\x3E';\r\n    }\r\n    try{ frame.srcdoc = html; }catch(e){}\r\n  },\r\n\r\n  \/* \u2500\u2500 AUTOSAVE \u2500\u2500 *\/\r\n  _st: null,\r\n  debSave: function(){\r\n    clearTimeout(this._st);\r\n    var self = this;\r\n    this._st = setTimeout(function(){\r\n      var c = self.getCode();\r\n      if(c && c.trim().length > 2){\r\n        try{ localStorage.setItem(self.SK, JSON.stringify({c:c, l:self.lang, t:Date.now()})); }catch(e){}\r\n      }\r\n    }, 2000);\r\n  },\r\n\r\n  \/* \u2500\u2500 AI CALL \u2500\u2500 *\/\r\n  callAI: async function(sys, usr){\r\n    var p = this.prov;\r\n    var k = this.getKey();\r\n    if(!k){ this.openApiModal(); throw new Error('No API key saved.'); }\r\n    var resp = '';\r\n    if(p === 'gemini'){\r\n      var GBASE = 'https:\/\/generativelanguage.googleapis.com\/v1beta\/models\/';\r\n      var GMODELS = ['gemini-2.5-flash','gemini-2.5-flash-preview-05-20','gemini-2.0-flash','gemini-2.0-flash-exp','gemini-1.5-flash','gemini-1.5-flash-latest','gemini-1.5-flash-8b','gemini-1.5-pro'];\r\n      var gd = null; var gOK = false;\r\n      for(var gi=0;gi<GMODELS.length;gi++){\r\n        try{\r\n          var gr = await fetch(GBASE+GMODELS[gi]+':generateContent?key='+k, {\r\n            method:'POST', headers:{'Content-Type':'application\/json'},\r\n            body:JSON.stringify({contents:[{parts:[{text:sys+'\\n\\n'+usr}]}],generationConfig:{maxOutputTokens:4096,temperature:0.7}})\r\n          });\r\n          gd = await gr.json();\r\n          if(gd.candidates && gd.candidates[0] && gd.candidates[0].content){ gOK=true; break; }\r\n        }catch(ge){}\r\n      }\r\n      if(!gOK) throw new Error('Gemini: No model worked. Check key at aistudio.google.com');\r\n      resp = gd.candidates[0].content.parts[0].text;\r\n    } else if(p === 'groq'){\r\n      var QMODELS = ['llama-3.3-70b-versatile','llama-3.1-70b-versatile','llama3-70b-8192','mixtral-8x7b-32768','llama3-8b-8192'];\r\n      var qd = null; var qOK = false;\r\n      for(var qi=0;qi<QMODELS.length;qi++){\r\n        try{\r\n          var qr = await fetch('https:\/\/api.groq.com\/openai\/v1\/chat\/completions',{\r\n            method:'POST',headers:{'Content-Type':'application\/json','Authorization':'Bearer '+k},\r\n            body:JSON.stringify({model:QMODELS[qi],messages:[{role:'system',content:sys},{role:'user',content:usr}],max_tokens:4096})\r\n          });\r\n          qd = await qr.json();\r\n          if(qd.choices && qd.choices[0]){ qOK=true; break; }\r\n        }catch(qe){}\r\n      }\r\n      if(!qOK) throw new Error('Groq: No model worked. Check key at console.groq.com');\r\n      resp = qd.choices[0].message.content;\r\n    } else {\r\n      var cr = await fetch('https:\/\/api.anthropic.com\/v1\/messages',{\r\n        method:'POST',headers:{'Content-Type':'application\/json','x-api-key':k,'anthropic-version':'2023-06-01'},\r\n        body:JSON.stringify({model:'claude-sonnet-4-6',max_tokens:4096,system:sys,messages:[{role:'user',content:usr}]})\r\n      });\r\n      var cd = await cr.json();\r\n      if(cd.error) throw new Error('Claude: '+cd.error.message);\r\n      resp = cd.content[0].text;\r\n    }\r\n    return resp;\r\n  },\r\n\r\n  extractCode: function(text){\r\n    var m = (text||'').match(\/```(?:\\w+)?\\n?([\\s\\S]+?)```\/);\r\n    return m ? m[1].trim() : (text||'').trim();\r\n  },\r\n\r\n  \/* \u2500\u2500 MAGIC BUTTONS \u2500\u2500 *\/\r\n  magic: async function(type){\r\n    if(this.busy){ this.toast('AI is busy \u2014 wait!','warn'); return; }\r\n    if(!this.getKey()){ this.openApiModal(); return; }\r\n    var code = this.getCode();\r\n    var lang = this.lang;\r\n    var prompts = {\r\n      gen:  {s:'You are an expert '+lang+' developer. Return ONLY complete working code inside a code fence, no explanations.', u:'Build something great in '+lang+'. Return only the code.'},\r\n      opt:  {s:'You are a code expert. Return only the improved code.', u:'Improve this '+lang+' code for performance and readability:\\n```'+lang+'\\n'+code+'\\n```\\nReturn only the code.'},\r\n      bug:  {s:'You are an expert debugger. List bugs and return corrected code.', u:'Find and fix all bugs in this '+lang+' code:\\n```'+lang+'\\n'+code+'\\n```'},\r\n      cmt:  {s:'You are a '+lang+' expert. Return only the fully commented code.', u:'Add comprehensive inline comments to this code:\\n```'+lang+'\\n'+code+'\\n```'},\r\n      tw:   {s:'You are a Tailwind CSS expert. ALWAYS include <scr'+'ipt src=\"https:\/\/cdn.tailwindcss.com\"><'+'\/script> in <head>. Return complete self-contained HTML.', u:'Rewrite this using Tailwind CSS classes, include Tailwind CDN in head, make it look modern and professional:\\n```'+lang+'\\n'+code+'\\n```'},\r\n      exp:  {s:'You are a clear technical explainer.', u:'Explain this '+lang+' code in simple terms:\\n```'+lang+'\\n'+code+'\\n```'},\r\n      conv: {s:'You are a multi-language expert. Return only the converted code.', u:'Convert this '+lang+' code to Python or most suitable alternative:\\n```'+lang+'\\n'+code+'\\n```'}\r\n    };\r\n    if(type === 'gen'){\r\n      this.openGenModal();\r\n      return; \r\n    }\r\n    var p = prompts[type];\r\n    if(!p) return;\r\n    var labels = {gen:'Generate',opt:'Optimize',bug:'Find Bugs',cmt:'Comments',tw:'Tailwind',exp:'Explain',conv:'Convert'};\r\n    this.switchPanel('chat');\r\n    this.addMsg('u', '\u2728 Magic: '+(labels[type]||type));\r\n    var tid = this.addMsg('think','');\r\n    this.busy = true;\r\n    var sb = this.g('cs-send'); if(sb) sb.disabled = true;\r\n    try{\r\n      var result = await this.callAI(p.s, p.u);\r\n      this.removeMsg(tid);\r\n      var hasCode = (result||'').includes('```');\r\n      var extracted = hasCode ? this.extractCode(result) : null;\r\n      this.addMsg('a', result, extracted);\r\n      if(extracted) this.saveHist('Magic:'+labels[type], extracted);\r\n    }catch(e){\r\n      this.removeMsg(tid);\r\n      this.addMsg('a', '\u274c '+e.message);\r\n    }\r\n    this.busy = false;\r\n    if(sb) sb.disabled = false;\r\n  },\r\n\r\n  \/* \u2500\u2500 CHAT \u2500\u2500 *\/\r\n  chat: async function(){\r\n    if(this.busy) return;\r\n    var inp = this.g('cs-cin');\r\n    var msg = inp ? inp.value.trim() : '';\r\n    if(!msg) return;\r\n    if(!this.getKey()){ this.openApiModal(); return; }\r\n    if(inp) inp.value = '';\r\n    var code = this.getCode();\r\n    var sys = 'You are PTH AI Code Studio, an expert '+this.lang+' developer in a browser editor. When writing code use a code fence (```'+this.lang+'). Current editor code:\\n```'+this.lang+'\\n'+code+'\\n```';\r\n    this.addMsg('u', msg);\r\n    var tid = this.addMsg('think','');\r\n    this.busy = true;\r\n    var sb = this.g('cs-send'); if(sb) sb.disabled = true;\r\n    try{\r\n      var result = await this.callAI(sys, msg);\r\n      this.removeMsg(tid);\r\n      var hasCode = (result||'').includes('```');\r\n      var extracted = hasCode ? this.extractCode(result) : null;\r\n      this.addMsg('a', result, extracted);\r\n    }catch(e){\r\n      this.removeMsg(tid);\r\n      this.addMsg('a','\u274c '+e.message);\r\n    }\r\n    this.busy = false;\r\n    if(sb) sb.disabled = false;\r\n  },\r\n\r\n  \/* \u2500\u2500 MESSAGES \u2500\u2500 *\/\r\n  _mid: 0,\r\n  addMsg: function(type, text, applyCode){\r\n    var box = this.g('cs-msgs');\r\n    if(!box) return '';\r\n    this._mid++;\r\n    var id = 'csm'+this._mid;\r\n    var div = document.createElement('div');\r\n    div.id = id;\r\n    var self = this;\r\n    if(type==='u'){ div.className='msg msg-u'; div.textContent=text; }\r\n    else if(type==='s'){ div.className='msg msg-s'; div.textContent=text; }\r\n    else if(type==='think'){\r\n      div.className='msg msg-a';\r\n      div.innerHTML='\\x3Cdiv class=\"think\"\\x3E\\x3Cdiv class=\"thdot\"\\x3E\\x3C\/div\\x3E\\x3Cdiv class=\"thdot\"\\x3E\\x3C\/div\\x3E\\x3Cdiv class=\"thdot\"\\x3E\\x3C\/div\\x3E\\x3Cspan\\x3EAI thinking...\\x3C\/span\\x3E\\x3C\/div\\x3E';\r\n    } else {\r\n      div.className='msg msg-a';\r\n      var fmt = (text||'')\r\n        .replace(\/```(\\w+)?\\n?([\\s\\S]+?)```\/g,function(m,l,c){\r\n          var lang2 = l||'code';\r\n          var escaped = c.replace(\/&\/g,'&amp;').replace(\/<\/g,'&lt;').replace(\/>\/g,'&gt;');\r\n          return '\\x3Cdiv class=\"codeblock\"\\x3E\\x3Cdiv class=\"cbhead\"\\x3E\\x3Cspan class=\"cblang\"\\x3E'+lang2+'\\x3C\/span\\x3E\\x3Cbutton class=\"cbcopy\" data-code=\"'+btoa(unescape(encodeURIComponent(c)))+'\" aria-label=\"Copy code block\"\\x3E\ud83d\udccb Copy\\x3C\/button\\x3E\\x3C\/div\\x3E\\x3Cpre class=\"cbpre\"\\x3E'+escaped+'\\x3C\/pre\\x3E\\x3C\/div\\x3E';\r\n        })\r\n        .replace(\/`([^`]+)`\/g,'\\x3Ccode\\x3E$1\\x3C\/code\\x3E')\r\n        .replace(\/\\n\/g,'\\x3Cbr\\x3E');\r\n      div.innerHTML = fmt;\r\n      if(applyCode){\r\n        var ab = document.createElement('button');\r\n        ab.className='applybtn';\r\n        ab.innerHTML='\u2b06 Apply Code to Editor &amp; Preview';\r\n        ab.setAttribute('aria-label','Apply code to editor');\r\n        ab.addEventListener('click',function(){\r\n          \/* 1. Switch panel first \u2014 makes iframe visible *\/\r\n          self.switchPanel('prev');\r\n          \/* 2. Wait 200ms (ensures panel fully painted in all browsers) *\/\r\n          setTimeout(function(){\r\n            \/* 3. setCode \u2192 sets editor \u2192 calls doPreview \u2192 injects CSS \u2192 sets srcdoc *\/\r\n            self.setCode(applyCode);\r\n            \/* 4. Belt-and-suspenders: also set srcdoc directly after brief delay *\/\r\n            setTimeout(function(){\r\n              var fr = self.g('cs-frame');\r\n              if(fr && !fr.srcdoc) fr.srcdoc = applyCode;\r\n            }, 150);\r\n          }, 200);\r\n          self.saveHist('AI Response', applyCode);\r\n          setTimeout(function(){\r\n            var tw = document.getElementById('pthcs');\r\n            if(tw) tw.scrollIntoView({behavior:'smooth',block:'start'});\r\n          }, 500);\r\n          self.toast('\u2705 Code applied! Live Preview updating\u2026');\r\n        });\r\n        div.appendChild(ab);\r\n      }\r\n    }\r\n    box.appendChild(div);\r\n    box.scrollTop = box.scrollHeight;\r\n    return id;\r\n  },\r\n  removeMsg: function(id){ var el=this.g(id); if(el) el.remove(); },\r\n\r\n  \/* \u2500\u2500 PANELS \u2500\u2500 *\/\r\n  switchPanel: function(pn){\r\n    this.panel = pn;\r\n    document.querySelectorAll('.rtab').forEach(function(b){ b.classList.toggle('on', b.getAttribute('data-rp')===pn); });\r\n    ['prev','chat','hist'].forEach(function(p){\r\n      var el = document.getElementById('cs-rp-'+p);\r\n      if(el) el.style.display = p===pn ? '' : 'none';\r\n    });\r\n    if(pn==='prev'){\r\n      var pr=this.g('cs-rp-prev'); if(pr) pr.style.display='';\r\n      \/* doPreview called by setCode after panel visible \u2014 no duplicate call here *\/\r\n    }\r\n    if(pn==='hist') this.renderHist();\r\n  },\r\n\r\n  \/* \u2500\u2500 API MODAL \u2500\u2500 *\/\r\n  openApiModal: function(){\r\n    var m = this.g('cs-api-modal');\r\n    if(m) m.classList.add('open');\r\n    var ki = this.g('cs-kinput');\r\n    if(ki){ ki.value=''; ki.placeholder = this.getKey() ? 'Key saved \u2014 paste new to update' : 'Paste your API key here...'; ki.focus(); }\r\n  },\r\n  closeApiModal: function(){\r\n    var m = this.g('cs-api-modal');\r\n    if(m) m.classList.remove('open');\r\n  },\r\n  setProv: function(pv){\r\n    this.prov = pv;\r\n    document.querySelectorAll('#cs-pvtabs .pvtab').forEach(function(t){ t.classList.toggle('sel', t.getAttribute('data-pv')===pv); });\r\n    var info = this.g('cs-pvinfo');\r\n    if(info) info.innerHTML = window.pthCS.PVINFO[pv] || '';\r\n    var ki = this.g('cs-kinput');\r\n    if(ki) ki.placeholder = this.getKey() ? 'Key saved \u2014 paste new to update' : 'Paste your API key here...';\r\n  },\r\n  saveKey: function(){\r\n    var k = this.g('cs-kinput') ? this.g('cs-kinput').value.trim() : '';\r\n    if(!k && !this.getKey()){ this.toast('Paste your API key first!','err'); return; }\r\n    if(k){\r\n      try{ sessionStorage.setItem('pthcs_k_'+this.prov, k); }catch(e){ this.toast('Could not save key','err'); return; }\r\n    }\r\n    this.updateKeyStatus();\r\n    this.closeApiModal();\r\n    this.toast(this.PVNAMES[this.prov]+' key saved!');\r\n    \/* Scroll tool into view so user can start immediately *\/\r\n    setTimeout(function(){\r\n      var el = document.getElementById('pthcs');\r\n      if(el) el.scrollIntoView({behavior:'smooth', block:'start'});\r\n    }, 350);\r\n    if(this._pending){\r\n      this.switchPanel('chat');\r\n      this.addMsg('s','\u267b\ufe0f Previous session found ('+this._pending.l.toUpperCase()+'). Restore?');\r\n      var self = this;\r\n      var pd = this._pending;\r\n      var wrap = document.createElement('div');\r\n      wrap.style.cssText='display:flex;gap:6px;padding:0 10px 8px;';\r\n      var rb=document.createElement('button'); rb.className='btn btn-p btn-sm'; rb.textContent='\u267b\ufe0f Restore'; rb.setAttribute('aria-label','Restore session');\r\n      rb.addEventListener('click',function(){ self.setCode(pd.c, pd.l); self._pending=null; wrap.remove(); self.toast('Session restored!'); });\r\n      var sk=document.createElement('button'); sk.className='btn btn-gh btn-sm'; sk.textContent='Skip'; sk.setAttribute('aria-label','Skip restore');\r\n      sk.addEventListener('click',function(){ self._pending=null; wrap.remove(); });\r\n      wrap.appendChild(rb); wrap.appendChild(sk);\r\n      var msgs = this.g('cs-msgs');\r\n      if(msgs) msgs.appendChild(wrap);\r\n    }\r\n  },\r\n  updateKeyStatus: function(){\r\n    var hasKey = !!this.getKey();\r\n    var dot = this.g('cs-kdot'), lbl = this.g('cs-klbl'), pn = this.g('cs-pname'), sbai = this.g('cs-sb-ai');\r\n    var name = this.PVNAMES[this.prov] || this.prov;\r\n    if(dot){ dot.classList.toggle('on', hasKey); }\r\n    if(lbl){ lbl.textContent = hasKey ? name+' key saved' : 'No key \u2014 click \ud83d\udd11 API Key to add'; lbl.className='cs-klbl '+(hasKey?'on':'off'); }\r\n    if(pn) pn.textContent = name;\r\n    if(sbai) sbai.textContent = 'AI: '+(hasKey?name:'No key');\r\n  },\r\n\r\n  \/* \u2500\u2500 GENERATE MODAL \u2500\u2500 *\/\r\n  openGenModal: function(){\r\n    var m = this.g('cs-gen-modal');\r\n    if(m) m.classList.add('open');\r\n    var gl = this.g('cs-glang');\r\n    if(gl){\r\n      var langMap = {html:'html',css:'css',javascript:'javascript',php:'php',python:'python'};\r\n      gl.value = langMap[this.lang] || 'html';\r\n    }\r\n    var gi = this.g('cs-ginput'); if(gi){ gi.value=''; gi.focus(); }\r\n    document.querySelectorAll('#cs-gtasks .gtask').forEach(function(t){ t.classList.remove('sel'); });\r\n  },\r\n  closeGenModal: function(){\r\n    var m = this.g('cs-gen-modal');\r\n    if(m) m.classList.remove('open');\r\n  },\r\n  runGenModal: async function(){\r\n    var gi = this.g('cs-ginput');\r\n    var prompt = gi ? gi.value.trim() : '';\r\n    if(!prompt){\r\n      var selTask = document.querySelector('#cs-gtasks .gtask.sel');\r\n      if(selTask) prompt = selTask.getAttribute('data-task');\r\n    }\r\n    if(!prompt){ this.toast('Type a prompt or select a task!','warn'); return; }\r\n    var gl = this.g('cs-glang');\r\n    var genLang = gl ? gl.value : this.lang;\r\n    this.closeGenModal();\r\n    var toolEl = document.getElementById('pthcs');\r\n    if(toolEl) toolEl.scrollIntoView({behavior:'smooth', block:'start'});\r\n    this.switchPanel('chat');\r\n    this.lang = genLang;\r\n    var lsel = this.g('cs-lang'); if(lsel) lsel.value = genLang;\r\n    var sys = 'You are an expert ' + genLang + ' developer. Return ONLY complete working code inside a code fence. No explanations before or after. Just the code.';\r\n    var usr = 'Build this in ' + genLang + ': ' + prompt + '\\nReturn complete working code inside a code fence for ' + genLang + '.';\r\n    this.addMsg('u', '\u2728 Generate: ' + prompt.substring(0,60) + (prompt.length>60?'...':''));\r\n    var tid = this.addMsg('think','');\r\n    this.busy = true;\r\n    var sb = this.g('cs-send'); if(sb) sb.disabled = true;\r\n    try{\r\n      var result = await this.callAI(sys, usr);\r\n      this.removeMsg(tid);\r\n      var extracted = this.extractCode(result);\r\n      this.addMsg('a', result, extracted);\r\n      if(extracted) this.saveHist('Generate', extracted);\r\n    }catch(e){\r\n      this.removeMsg(tid);\r\n      this.addMsg('a','\u274c '+e.message);\r\n    }\r\n    this.busy = false;\r\n    if(sb) sb.disabled = false;\r\n  },\r\n\r\n  \/* \u2500\u2500 WOODY EXPORT \u2500\u2500 *\/\r\n  openWoody: function(){\r\n    var m = this.g('cs-woody-modal');\r\n    if(m) m.classList.add('open');\r\n    this.setWoody('html');\r\n  },\r\n  setWoody: function(type){\r\n    var out = this.g('cs-wout');\r\n    if(!out) return;\r\n    var code = this.getCode();\r\n    if(type==='html'){ out.value = code; }\r\n    else if(type==='json'){\r\n      var sn = {generator:'PHP Code Snippets v2.7.5',date_created:new Date().toISOString().split('T')[0],snippets:[{name:'pth-ai-'+this.lang+'-'+Date.now(),title:'PTH AI Generated \u2014 '+this.lang.toUpperCase(),content:code,location:'php_snippet',type:'html',filters:{everywhere:false,is_front:false,is_single:true,is_page:true,is_singular:false},changed_filters:{is_single:true,is_page:true},scope:[],priority:'140',description:'Generated by PTH AI Code Studio v1.5',attributes:'',tags:[]}]};\r\n      out.value = JSON.stringify(sn,null,2);\r\n    } else {\r\n      out.value = '\\x3C?php\\nfunction pth_ai_shortcode() {\\n    ob_start();\\n    ?\\x3E\\n'+code+'\\n    \\x3C?php\\n    return ob_get_clean();\\n}\\nadd_shortcode( \"pth_ai_generated\", \"pth_ai_shortcode\" );\\n?\\x3E';\r\n    }\r\n  },\r\n\r\n  \/* \u2500\u2500 HISTORY \u2500\u2500 *\/\r\n  saveHist: function(label, code){\r\n    this.hist.unshift({lb:label, c:code, l:this.lang, t:new Date().toLocaleTimeString()});\r\n    if(this.hist.length>20) this.hist.pop();\r\n    try{ localStorage.setItem(this.HK, JSON.stringify(this.hist)); }catch(e){}\r\n  },\r\n  loadHist: function(){\r\n    try{ var r=localStorage.getItem(this.HK); if(r) this.hist=JSON.parse(r)||[]; }catch(e){}\r\n  },\r\n  renderHist: function(){\r\n    var list = this.g('cs-histlist');\r\n    if(!list) return;\r\n    if(!this.hist.length){ list.innerHTML='\\x3Cp style=\"font-size:.75rem;color:#475569;text-align:center;margin:20px 0;\"\\x3ENo sessions yet.\\x3C\/p\\x3E'; return; }\r\n    var self = this;\r\n    list.innerHTML='';\r\n    this.hist.forEach(function(h){\r\n      var d=document.createElement('div'); d.className='hitem';\r\n      d.innerHTML='\\x3Cdiv class=\"hlang\"\\x3E'+(h.l||'').toUpperCase()+' \u2014 '+h.lb+'\\x3C\/div\\x3E'\r\n        +'\\x3Cdiv class=\"hprev\"\\x3E'+(h.c||'').substring(0,60).replace(\/<\/g,'&lt;')+'...\\x3C\/div\\x3E'\r\n        +'\\x3Cdiv style=\"font-size:.6rem;color:#334155;margin-top:2px;\"\\x3E'+(h.t||'')+'\\x3C\/div\\x3E';\r\n      d.addEventListener('click',function(){ self.setCode(h.c,h.l); self.switchPanel('prev'); self.toast('Loaded from history!'); });\r\n      list.appendChild(d);\r\n    });\r\n  },\r\n\r\n  \/* \u2500\u2500 INIT \u2500\u2500 *\/\r\n  init: function(){\r\n    var self = this;\r\n    this.loadHist();\r\n    try{\r\n      var raw = localStorage.getItem(this.SK);\r\n      if(raw){ var d=JSON.parse(raw); if(d&&d.c&&(Date.now()-d.t)<604800000) this._pending=d; }\r\n    }catch(e){}\r\n    var sampleEl = this.g('pthcs-sample');\r\n    if(sampleEl){\r\n      try{\r\n        var b64 = sampleEl.getAttribute('data-s');\r\n        if(b64) this.SAMPLE = decodeURIComponent(escape(atob(b64)));\r\n      }catch(se){}\r\n    }\r\n    var ed = this.g('cs-editor');\r\n    if(ed){\r\n      ed.value = this.SAMPLE;\r\n      ed.addEventListener('input',function(){ self.updateLines(); self.updateCursor(); self.updateSB(); self.debPreview(); self.debSave(); });\r\n      ed.addEventListener('click',function(){ self.updateCursor(); });\r\n      ed.addEventListener('keyup',function(){ self.updateCursor(); });\r\n      ed.addEventListener('keydown',function(e){\r\n        if(e.key==='Tab'){\r\n          e.preventDefault();\r\n          var s=ed.selectionStart, en=ed.selectionEnd;\r\n          ed.value=ed.value.substring(0,s)+'  '+ed.value.substring(en);\r\n          ed.selectionStart=ed.selectionEnd=s+2;\r\n          self.updateLines();\r\n        }\r\n      });\r\n      this.updateLines();\r\n      this.updateSB();\r\n    }\r\n    this.doPreview();\r\n    this.addMsg('s','\ud83e\udd16 PTH AI Code Studio v2.0 PRO \u2014 Ready!');\r\n    this.addMsg('s','\ud83c\udfaf Pricing Table layout loaded in editor \u2014 see Live Preview \u2192\\n\\n\ud83d\udca1 Task ideas for \u2728 Generate:\\n\u2022 \"Build a pricing table with 3 plans\"\\n\u2022 \"Create a dashboard with stats cards\"\\n\u2022 \"Build a todo app with add\/delete\"\\n\u2022 \"Make a responsive navbar\"\\n\u2022 \"Create an animated hero section\"\\n\u2022 \"Build a WordPress testimonial shortcode\"');\r\n    var provs = ['gemini','groq','claude'];\r\n    var found = false;\r\n    for(var i=0;i<provs.length;i++){\r\n      try{\r\n        if(sessionStorage.getItem('pthcs_k_'+provs[i])){ this.prov=provs[i]; found=true; break; }\r\n      }catch(e){}\r\n    }\r\n    this.updateKeyStatus();\r\n    if(!found){\r\n      setTimeout(function(){ self.openApiModal(); }, 600);\r\n    } else if(this._pending){\r\n      this.switchPanel('chat');\r\n    }\r\n    this.bev('cs-m1','click',function(){ self.magic('gen'); });\r\n    this.bev('cs-m2','click',function(){ self.magic('opt'); });\r\n    this.bev('cs-m3','click',function(){ self.magic('bug'); });\r\n    this.bev('cs-m4','click',function(){ self.magic('cmt'); });\r\n    this.bev('cs-m5','click',function(){ self.magic('tw'); });\r\n    this.bev('cs-m6','click',function(){ self.magic('exp'); });\r\n    this.bev('cs-m7','click',function(){ self.magic('conv'); });\r\n    this.bev('cs-new','click',function(){ var c=self.getCode(); if(c&&c.trim()) self.saveHist('Manual Save',c); self.setCode(self.SAMPLE,'html'); self.toast('New file \u2014 previous saved to History'); });\r\n    this.bev('cs-apikey','click',function(){ self.openApiModal(); });\r\n    this.bev('cs-wpexport','click',function(){ self.openWoody(); });\r\n    this.bev('cs-copy','click',function(){ try{navigator.clipboard.writeText(self.getCode());}catch(e){} self.toast('Code copied!'); });\r\n    this.bev('cs-dl','click',function(){\r\n      var ext={html:'html',css:'css',javascript:'js',php:'php',python:'py',typescript:'ts',sql:'sql',json:'json',markdown:'md',shell:'sh'};\r\n      var a=document.createElement('a'); a.href=URL.createObjectURL(new Blob([self.getCode()],{type:'text\/plain'})); a.download='pth-code.'+(ext[self.lang]||'txt'); a.click(); self.toast('Downloaded!');\r\n    });\r\n    this.bev('cs-clr','click',function(){ self.setCode(self.SAMPLE,'html'); self.toast('Reset to Pricing Table sample'); });\r\n    this.bev('cs-refr','click',function(){ self.doPreview(); });\r\n    this.bev('cs-newtab','click',function(){\r\n      var src = self.getCode();\r\n      if(!src || !src.trim()){\r\n        self.toast('Editor is empty \u2014 nothing to open','warn'); return;\r\n      }\r\n      var blob = new Blob([src], {type:'text\/html'});\r\n      var url = URL.createObjectURL(blob);\r\n      var w = window.open(url,'_blank');\r\n      if(!w) self.toast('Please allow popups for this site','warn');\r\n      setTimeout(function(){ URL.revokeObjectURL(url); }, 5000);\r\n    });\r\n    this.bev('cs-lang','change',function(){ var sel=self.g('cs-lang'); if(sel){ self.lang=sel.value; self.updateSB(); self.doPreview(); } });\r\n    document.querySelectorAll('.rtab').forEach(function(btn){ btn.addEventListener('click',function(){ self.switchPanel(btn.getAttribute('data-rp')); }); });\r\n    this.bev('cs-send','click',function(){ self.chat(); });\r\n    var msgsBox = this.g('cs-msgs');\r\n    if(msgsBox){\r\n      msgsBox.addEventListener('click',function(e){\r\n        var btn = e.target.closest('.cbcopy');\r\n        if(!btn) return;\r\n        try{\r\n          var b64 = btn.getAttribute('data-code');\r\n          if(b64) navigator.clipboard.writeText(decodeURIComponent(escape(atob(b64)))).catch(function(){});\r\n          var prev = btn.parentElement ? btn.parentElement.nextElementSibling : null;\r\n          if(prev && prev.classList.contains('cbpre')) navigator.clipboard.writeText(prev.textContent).catch(function(){});\r\n          btn.textContent = '\u2705 Copied!';\r\n          setTimeout(function(){ btn.textContent = '\ud83d\udccb Copy'; }, 1500);\r\n        }catch(ce){ btn.textContent = '\ud83d\udccb Copy'; }\r\n      });\r\n    }\r\n    this.bev('cs-cin','keydown',function(e){ if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();self.chat();} });\r\n    this.bev('cs-clrhist','click',function(){ self.hist=[]; try{localStorage.removeItem(self.HK);}catch(e){} self.renderHist(); self.toast('History cleared!'); });\r\n    document.querySelectorAll('#cs-pvtabs .pvtab').forEach(function(tab){ tab.addEventListener('click',function(){ self.setProv(tab.getAttribute('data-pv')); }); });\r\n    document.querySelectorAll('#cs-pvtabs .pvtab').forEach(function(tab){ tab.addEventListener('keydown',function(e){ if(e.key==='Enter'||e.key===' '){ e.preventDefault(); self.setProv(tab.getAttribute('data-pv')); } }); });\r\n    this.bev('cs-eyebtn','click',function(){ var ki=self.g('cs-kinput'); if(!ki)return; ki.type=ki.type==='password'?'text':'password'; self.g('cs-eyebtn').textContent=ki.type==='password'?'\ud83d\udc41':'\ud83d\ude48'; });\r\n    this.bev('cs-msave','click',function(){ self.saveKey(); });\r\n    this.bev('cs-mskip','click',function(){ self.closeApiModal(); if(!self.getKey()) self.addMsg('s','\u26a0\ufe0f No API key \u2014 click \ud83d\udd11 API Key to add one.'); });\r\n    this.bev('cs-kinput','keydown',function(e){ if(e.key==='Enter'){e.preventDefault();self.saveKey();} });\r\n    var am=this.g('cs-api-modal');\r\n    if(am) am.addEventListener('click',function(e){ if(e.target===am) self.closeApiModal(); });\r\n    this.bev('cs-w-html','click',function(){ self.setWoody('html'); });\r\n    this.bev('cs-w-short','click',function(){ self.setWoody('short'); });\r\n    this.bev('cs-w-copy','click',function(){ var o=self.g('cs-wout'); if(o){ try{navigator.clipboard.writeText(o.value);}catch(e){} self.toast('Copied!'); } });\r\n    this.bev('cs-w-dl','click',function(){\r\n      var o=self.g('cs-wout'); if(!o)return;\r\n      var txt=o.value; var n=txt.includes('\"generator\"')?'pth-woody.json':txt.includes('\\x3C?php')?'pth-shortcode.php':'pth-snippet.html';\r\n      var a=document.createElement('a'); a.href=URL.createObjectURL(new Blob([txt],{type:'text\/plain'})); a.download=n; a.click(); self.toast('Downloaded: '+n);\r\n    });\r\n    this.bev('cs-w-close','click',function(){ var m=self.g('cs-woody-modal'); if(m) m.classList.remove('open'); });\r\n    var wm=this.g('cs-woody-modal');\r\n    if(wm) wm.addEventListener('click',function(e){ if(e.target===wm) wm.classList.remove('open'); });\r\n    document.querySelectorAll('#cs-gtasks .gtask').forEach(function(btn){\r\n      btn.addEventListener('click',function(){\r\n        document.querySelectorAll('#cs-gtasks .gtask').forEach(function(b){ b.classList.remove('sel'); });\r\n        btn.classList.add('sel');\r\n        var gi2 = self.g('cs-ginput');\r\n        if(gi2) gi2.value = btn.getAttribute('data-task');\r\n      });\r\n    });\r\n    this.bev('cs-grun','click',function(){ self.runGenModal(); });\r\n    this.bev('cs-gcancel','click',function(){ self.closeGenModal(); });\r\n    this.bev('cs-ginput','keydown',function(e){ if(e.key==='Enter'&&e.ctrlKey){ e.preventDefault(); self.runGenModal(); } });\r\n    var gm = this.g('cs-gen-modal');\r\n    if(gm) gm.addEventListener('click',function(e){ if(e.target===gm) self.closeGenModal(); });\r\n\r\n    document.addEventListener('keydown',function(e){\r\n      if(e.key==='Escape'){\r\n        self.closeApiModal();\r\n        self.closeGenModal();\r\n        var wm2=self.g('cs-woody-modal'); if(wm2) wm2.classList.remove('open');\r\n      }\r\n      if(e.ctrlKey&&e.key==='Enter'){ e.preventDefault(); self.doPreview(); }\r\n    });\r\n  }\r\n};\r\n\r\n\/* Bulletproof Elite Master Initialization \u2014 100% Cache Resilient *\/\r\nfunction pthcsRun() {\r\n    if (!window.pthCS.ok && document.getElementById('pthcs') && document.getElementById('cs-editor')) {\r\n        window.pthCS.ok = true;\r\n        window.pthCS.init();\r\n    }\r\n}\r\nif (document.readyState === 'complete' || document.readyState === 'interactive') {\r\n    setTimeout(pthcsRun, 1);\r\n} else {\r\n    document.addEventListener('DOMContentLoaded', pthcsRun);\r\n    window.addEventListener('load', pthcsRun);\r\n}\r\n\/* Delayed fallbacks for hard-cached environments *\/\r\nsetTimeout(pthcsRun, 300);\r\nsetTimeout(pthcsRun, 1000);\r\nvar _mo = new MutationObserver(function() { pthcsRun(); });\r\nif (document.body) { _mo.observe(document.body, { childList: true, subtree: true }); }\r\nsetTimeout(function() { _mo.disconnect(); }, 8000);\r\n\r\n})();\r\n<\/script>\n\n\n\n<br>\n<style>\n.pth-feature-wrap{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:20px;margin-bottom:40px}\n.pth-feat-box{border:1px solid #e2e8f0;background:#fff;padding:24px;border-radius:12px;box-shadow:0 4px 6px -1px rgba(0,0,0,0.02);transition:all .3s ease}\n.pth-feat-box:hover{border-color:#bfdbfe;transform:translateY(-3px);box-shadow:0 10px 15px -3px rgba(0,0,0,0.05)}\n.pth-feat-title{font-size:1.05rem;font-weight:800;color:#0f172a;margin:0 0 10px;display:flex;align-items:center;gap:10px}\n.pth-feat-text{font-size:.9rem;color:#1e293b;line-height:1.6;margin:0;font-weight:500}\n.pth-steps-wrap{border:1px solid #e2e8f0;background:#fff;padding:40px 30px;border-radius:16px;text-align:center;box-shadow:0 4px 6px -1px rgba(0,0,0,0.02);margin-bottom:40px;width:100%;box-sizing:border-box}\n.pth-steps-title{font-size:1.2rem;font-weight:800;color:#0f172a;text-transform:uppercase;margin:0 0 35px;letter-spacing:1px}\n.pth-steps-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:30px}\n.pth-step-item{display:flex;flex-direction:column;align-items:center}\n.pth-step-num{width:45px;height:45px;background:#2563eb;color:#fff;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:1.2rem;margin-bottom:15px;box-shadow:0 4px 10px rgba(37,99,235,.3)}\n.pth-step-name{font-weight:800;color:#0f172a;margin:0 0 8px;font-size:1rem}\n.pth-step-desc{font-size:.9rem;color:#1e293b;line-height:1.5;margin:0;font-weight:500}\n<\/style>\n<div class=\"pth-feature-wrap\">\n  <div class=\"pth-feat-box\">\n    <p class=\"pth-feat-title\"><span aria-hidden=\"true\">\ud83d\udfe2<\/span> Bring Your Own Key, Pay Nothing<\/p>\n    <p class=\"pth-feat-text\">Two of the three supported providers \u2014 Google Gemini and Groq \u2014 hand out API keys free, no credit card, in about two minutes. You paste your key once and it stays in your browser. There is no PrimeToolHub account, no subscription, and no per-generation charge from us: you talk directly to the AI provider on your own free tier.<\/p>\n  <\/div>\n  <div class=\"pth-feat-box\">\n    <p class=\"pth-feat-title\"><span aria-hidden=\"true\">\ud83d\udd35<\/span> Five One-Click Actions<\/p>\n    <p class=\"pth-feat-text\">Beyond plain generation, the action row does the jobs developers actually repeat: <strong>Optimize<\/strong> rewrites for performance and readability, <strong>Find Bugs<\/strong> lists each problem with its fix, <strong>Comments<\/strong> adds docblocks and inline notes, and <strong>Tailwind<\/strong> converts a plain layout to utility classes and injects the CDN so it renders immediately. No prompt-writing required for any of them.<\/p>\n  <\/div>\n  <div class=\"pth-feat-box\">\n    <p class=\"pth-feat-title\"><span aria-hidden=\"true\">\ud83d\udfe3<\/span> Straight Into WordPress<\/p>\n    <p class=\"pth-feat-text\">Export the result three ways depending on your workflow: a <strong>Woody Code Snippets JSON<\/strong> file you import in one click, a ready-made <strong>PHP shortcode<\/strong> wrapped in <code>add_shortcode()<\/code> for <code>functions.php<\/code>, or plain <strong>HTML<\/strong> for a non-technical site manager. The same generated component reaches the page whichever route suits the person doing the pasting.<\/p>\n  <\/div>\n<\/div>\n \n<div class=\"pth-steps-wrap\">\n  <p class=\"pth-steps-title\">How to Use AI Code Studio<\/p>\n  <div class=\"pth-steps-grid\">\n    <div class=\"pth-step-item\">\n      <div class=\"pth-step-num\" aria-hidden=\"true\">1<\/div>\n      <p class=\"pth-step-name\">Connect an Engine<\/p>\n      <p class=\"pth-step-desc\">Click API Key, pick Gemini, Groq or Claude, and paste a key from that provider&#8217;s console. Gemini and Groq are free. The key is saved in your browser session only.<\/p>\n    <\/div>\n    <div class=\"pth-step-item\">\n      <div class=\"pth-step-num\" aria-hidden=\"true\">2<\/div>\n      <p class=\"pth-step-name\">Describe or Pick a Preset<\/p>\n      <p class=\"pth-step-desc\">Set the output language, then click Generate and type what you want \u2014 or tap a preset like Pricing Table, Navbar, or WP Shortcode to skip writing the prompt from scratch.<\/p>\n    <\/div>\n    <div class=\"pth-step-item\">\n      <div class=\"pth-step-num\" aria-hidden=\"true\">3<\/div>\n      <p class=\"pth-step-name\">Refine and Preview<\/p>\n      <p class=\"pth-step-desc\">Use Optimize, Find Bugs, Comments or Tailwind on the result. For HTML, CSS and JavaScript the live preview renders the output as you go so you see the component, not just the code.<\/p>\n    <\/div>\n    <div class=\"pth-step-item\">\n      <div class=\"pth-step-num\" aria-hidden=\"true\">4<\/div>\n      <p class=\"pth-step-name\">Export<\/p>\n      <p class=\"pth-step-desc\">Copy it, download it with the right file extension, or open WP Export and choose Woody JSON, PHP shortcode, or HTML to drop it straight into your site.<\/p>\n    <\/div>\n  <\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Last updated: July 2026<\/p>\n\n\n\n<h2 id=\"\ud83d\udd34-what-bring-your-own-key-actually-means-for-you\" class=\"wp-block-heading\">\ud83d\udd34&nbsp;<strong>What &#8220;Bring Your Own Key&#8221; Actually Means for You<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Most AI coding tools work on a subscription. You pay the tool&#8217;s owner a monthly fee, they hold the relationship with the AI provider, and your requests flow through their servers on the way to the model. That is convenient, and it also means a middleman sits between your code and the AI, seeing everything that passes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This tool takes the other approach, called BYOK \u2014 bring your own key. You get an API key directly from the AI provider, paste it here, and your browser then talks to that provider&#8217;s API&nbsp;<em>directly<\/em>. PrimeToolHub is not in the middle. The page&#8217;s code loads once, and from then on the request goes from your machine to Google, Groq, or Anthropic and back, carrying your key and your code but never routing through our servers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The practical upside is cost and control. Gemini and Groq both offer genuinely free tiers with no card required, so for personal and small-project work you pay nothing at all. And because the key is yours, you see exactly what it is spending in your own provider dashboard, rather than trusting a third party&#8217;s usage meter. The honest trade is that you do the two-minute setup of fetching a key yourself \u2014 which the next section walks through.<\/p>\n\n\n\n<h2 id=\"\ud83d\udfe1-three-providers-three-different-reasons-to-pick-them\" class=\"wp-block-heading\">\ud83d\udfe1&nbsp;<strong>Three Providers, Three Different Reasons to Pick Them<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The tool supports three AI backends, and they are not interchangeable \u2014 each earns its place for a different situation.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ud83d\udd35&nbsp;<strong>Google Gemini (free).<\/strong>&nbsp;Get a key from&nbsp;<a href=\"https:\/\/aistudio.google.com\/app\/api-keys\" target=\"_blank\" rel=\"noreferrer noopener\">Google AI Studio<\/a>&nbsp;with no credit card. Its Flash-tier models are fast and produce strong HTML, CSS, JavaScript and Python. This is the best default for most people because it is free and capable.<\/li>\n\n\n\n<li>\ud83d\udfe0&nbsp;<strong>Groq \/ Llama (free).<\/strong>&nbsp;Get a key from&nbsp;<a href=\"https:\/\/console.groq.com\/keys\" target=\"_blank\" rel=\"noreferrer noopener\">Groq Console<\/a>. Groq runs open Llama models on specialised hardware that returns answers strikingly fast \u2014 often in a second or two. Reach for it when you are iterating rapidly and latency matters more than squeezing out the very best answer.<\/li>\n\n\n\n<li>\ud83d\udfe3&nbsp;<strong>Claude (Anthropic, paid).<\/strong>&nbsp;Get a key from the&nbsp;<a href=\"https:\/\/platform.claude.com\/login?returnTo=%2F%3F\" target=\"_blank\" rel=\"noreferrer noopener\">Anthropic Console<\/a>. Claude is pay-as-you-go rather than free, and tends to produce the most reliable output for complex logic and WordPress PHP, where correct escaping and structure matter. Choose it when one high-quality answer is worth more than several fast approximate ones.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">One caveat worth stating plainly: AI providers rename and retire their models often. The tool ships current model names with sensible fallbacks, but the exact version you get may shift over time as providers update their line-ups. That is normal, and it does not change how you use the tool.<\/p>\n\n\n\n<h2 id=\"\ud83d\udd34-an-honest-word-this-tool-is-not-offline\" class=\"wp-block-heading\">\ud83d\udd34&nbsp;<strong>An Honest Word: This Tool Is Not Offline<\/strong><\/h2>\n\n\n<figure class=\"pth-article-figure pth-img-left\" style=\"float:left; width:700px; max-width:100%; margin:4px 28px 16px 0; clear:left;\"><img decoding=\"async\" src=\"https:\/\/schoolict.net\/tools\/wp-content\/uploads\/2026\/07\/byok-data-flow-800x447.jpeg\" alt=\"Diagram showing code and API key going from the browser directly to the AI provider, bypassing the PrimeToolHub server\" width=\"700\" height=\"394\" loading=\"lazy\" data-no-lazy=\"1\" class=\"pth-article-img\" style=\"width:100%;height:auto;display:block;border-radius:10px;border:1px solid #e2e8f0;\"><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Most tools on this site run entirely in your browser with no network calls \u2014 you can pull the plug on your internet and they keep working. This one is different, and it would be dishonest to pretend otherwise. Generating code&nbsp;<em>requires<\/em>&nbsp;sending your prompt and your current code to an AI provider over the internet. There is no way around that: the intelligence lives on the provider&#8217;s servers, not in your browser.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So the accurate privacy claim is narrower than &#8220;100% offline&#8221;, and it is this: your API key and your code never touch PrimeToolHub&#8217;s servers. They go from your browser directly to the provider you chose \u2014 Google, Groq, or Anthropic \u2014 and what happens to them there is governed by&nbsp;<em>that provider&#8217;s<\/em>&nbsp;data policy, not ours. If you are working with genuinely confidential or client-owned code, read the data-retention terms of whichever provider you select, and treat the AI features accordingly. The&nbsp;<a href=\"https:\/\/schoolict.net\/tools\/secure-offline-web-development-utilities-guide\/\">guide to secure offline development utilities<\/a>&nbsp;covers the fully-local tools for when you cannot send code anywhere at all.<\/p>\n\n\n\n<h3 id=\"\ud83d\udfe2-where-your-key-lives\" class=\"wp-block-heading\">\ud83d\udfe2&nbsp;<strong>Where Your Key Lives<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The API key you paste is held in your browser&#8217;s session storage. That means it survives while the tab is open but is cleared when you close it \u2014 a deliberate trade that favours safety over convenience, since a key that does not persist to disk cannot be read back later by anything else. The cost is that you re-paste it next visit, which for a credential you should be guarding is a fair exchange. The key is sent only as part of a request to the provider, never anywhere else.<\/p>\n\n\n\n<h2 id=\"\ud83d\udfe1-live-preview-and-the-language-modes\" class=\"wp-block-heading\">\ud83d\udfe1&nbsp;<strong>Live Preview and the Language Modes<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For the three languages a browser can actually run \u2014 HTML, CSS and JavaScript \u2014 the live preview renders your code as a real, isolated page beside the editor, updating shortly after you stop typing. It does this with a sandboxed inline frame, which keeps the preview&#8217;s scripts walled off from the rest of the page while still letting buttons, forms and animations behave as they will on a real site.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The other supported languages \u2014 PHP, Python, TypeScript, SQL, JSON, Markdown, Shell \u2014 cannot execute in a browser, so for those the preview shows the code cleanly formatted rather than pretending to run it. This is the honest behaviour: a browser genuinely cannot execute PHP or Python, and any tool claiming to &#8220;run&#8221; them client-side is doing something misleading. What the AI gives you for those languages is code to take elsewhere \u2014 into WordPress, a server, or a local interpreter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your work is pure front-end prototyping without AI, the site&#8217;s&nbsp;<a href=\"https:\/\/schoolict.net\/tools\/free-web-tools-by-category\/\">offline tools directory<\/a>&nbsp;lists a plain HTML\/CSS\/JS editor that needs no key at all. AI Code Studio is the right choice specifically when you want the model to write, fix or explain the code for you.<\/p>\n\n\n\n<style>\n.pth-faq-section{margin-top:50px;margin-bottom:40px;font-family:inherit}\n.pth-faq-header{font-size:1.8rem;font-weight:800;color:#0f172a;margin-bottom:25px;border-bottom:2px solid #e2e8f0;padding-bottom:10px;display:flex;align-items:center;gap:10px}\n.pth-faq-grid{display:grid;grid-template-columns:100%;gap:20px}\n@media(min-width:768px){.pth-faq-grid{grid-template-columns:repeat(2,1fr)}}\n@media(min-width:1024px){.pth-faq-grid{grid-template-columns:repeat(3,1fr)}}\n.pth-faq-card{background:#f8fafc;padding:24px;border-radius:12px;border:1px solid #e2e8f0;transition:transform .2s ease;break-inside:avoid}\n.pth-faq-card:hover{transform:translateY(-3px);box-shadow:0 4px 12px rgba(0,0,0,.05)}\n.pth-faq-q{color:#0f172a;font-size:1rem;font-weight:700;margin:0 0 12px;line-height:1.4}\n.pth-faq-a{margin:0;font-size:.95rem;color:#1e293b;line-height:1.6;font-weight:500}\n<\/style>\n<div class=\"pth-faq-section\">\n  <div class=\"pth-faq-header\"><span aria-hidden=\"true\">\u2753<\/span> Frequently Asked Questions<\/div>\n  <div class=\"pth-faq-grid\">\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Is this tool free?<\/p>\n      <p class=\"pth-faq-a\">The tool itself is free with no account. The AI features need an API key: Gemini and Groq both have free tiers with no credit card, so you can generate code at no cost. Claude is pay-as-you-go and optional, for when you want its higher-quality output.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Does my code get sent to PrimeToolHub?<\/p>\n      <p class=\"pth-faq-a\">No. When you use an AI feature, your code and key go directly from your browser to the provider you chose \u2014 Google, Groq or Anthropic. They never pass through PrimeToolHub&#8217;s servers. What the provider does with them is set by that provider&#8217;s own policy.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Is this a fully offline tool like the others here?<\/p>\n      <p class=\"pth-faq-a\">No, and we say so plainly. Generating code requires contacting an AI provider over the internet \u2014 the intelligence lives on their servers. Most other PrimeToolHub tools are fully offline; this one cannot be, by its nature.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Where is my API key stored?<\/p>\n      <p class=\"pth-faq-a\">In your browser&#8217;s session storage, which clears when you close the tab. That is deliberate: a key that is not written to disk is harder to leak. The trade is that you paste it again next visit.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">How do I get a free Gemini key?<\/p>\n      <p class=\"pth-faq-a\">Visit Google AI Studio, sign in with a Google account, and create a key \u2014 no card needed. Click API Key in the tool, choose Gemini, paste it, and save. It takes about two minutes.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Which provider is best for WordPress PHP?<\/p>\n      <p class=\"pth-faq-a\">Claude tends to produce the most reliable WordPress PHP, following escaping and sanitization conventions with little prompting. Gemini handles standard shortcodes well and is free; Groq is fastest but may need a follow-up prompt to tighten security details.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Why does the preview not run my PHP or Python?<\/p>\n      <p class=\"pth-faq-a\">Because browsers cannot execute those languages \u2014 only HTML, CSS and JavaScript run client-side. For PHP, Python and the rest, the preview shows formatted code instead. Any tool claiming to run PHP in the browser is misleading you.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Can I put the generated code straight into WordPress?<\/p>\n      <p class=\"pth-faq-a\">Yes. WP Export gives you a Woody Code Snippets JSON to import, a PHP shortcode wrapped in <code>add_shortcode()<\/code> for functions.php, or plain HTML. Pick whichever matches how you add code to your site.<\/p>\n    <\/div>\n  <\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Browser-Based AI Code Editor Free AI code editor \u2014 Monaco editor with Claude, Gemini &#038; Groq AI. Live preview, 7 magic buttons, Woody export &#038; auto-save. 100% private, no install. \ud83d\udfe2 Bring Your Own Key, Pay Nothing Two of the three supported providers \u2014 Google Gemini and Groq \u2014 hand out API keys free, no &#8230; <a title=\"AI Code Editor | Free Browser-Based AI Code Generator\" class=\"read-more\" href=\"https:\/\/schoolict.net\/tools\/ai-code-studio\/\" aria-label=\"Read more about AI Code Editor | Free Browser-Based AI Code Generator\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":5757,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-5747","page","type-page","status-publish","has-post-thumbnail"],"_links":{"self":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/5747","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/comments?post=5747"}],"version-history":[{"count":4,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/5747\/revisions"}],"predecessor-version":[{"id":6708,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/5747\/revisions\/6708"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/media\/5757"}],"wp:attachment":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/media?parent=5747"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}