Someone on your team sends you an HTML slide deck. It looks good. But a headline feels too strong, and one sentence isn’t quite how you would say it.

Do you really want to send it back—or ask AI to regenerate the file—just to change a few words?

In Part 1, I shared a lightweight template for portable, print-ready HTML slides. For Part 2, I added the missing convenience: editing the text directly in the browser.

Make the change yourself

Reveal the bottom menu and choose Edit. Click a heading or paragraph and rewrite it. Choose Done to return to presenting, then Download HTML to keep the updated deck.

Open the editor ↗Download HTML ↓

On a computer, move your pointer to the bottom center to reveal the menu. On your phone, choose Open the editor for the editing tools; zoom in if you need more room.

Still just one file

The editor travels with the slides. No account, installation, or external libraries—just HTML, CSS, and a little JavaScript using the browser’s built-in text editing.

The downloaded copy includes your changes and the same editor, so the next person can make their own corrections. Your original file stays unchanged. Edits live in the open tab until you download them.

This is for wording changes, with the layout kept in place. Long text can still outgrow a slide; the editor flags potential overflow rather than shrinking everything to fit.

AI can make the first draft. You can handle the last few words.

Copy the editing-enabled skill

Paste the complete block into Claude or ChatGPT with your content. No skill installation is required. To reuse it as a skill, save it as editable-html-slides/SKILL.md.

editable-html-slides / SKILL.mdDownload skill ↓
---
name: editable-html-slides
description: Create portable HTML presentations with direct text editing, built-in navigation, and a dedicated print layout. Use when making slides that recipients can revise in a browser and download as one HTML file.
---

# Editable HTML Slides

Create a polished, self-contained HTML presentation using the complete template below. This document also works as a prompt pasted into Claude or ChatGPT; installing a skill is optional.

## Create the deck

- Replace the sample slide content with the user's material. Use the requested language, concise headings, generous whitespace, and a white canvas. Do not invent facts.
- Keep each slide on a 1600 × 900 canvas. Use the existing layouts and CSS; add content-specific styles only when needed. Update slide labels and footer numbers.
- Preserve the supplied presentation and editing code. Keep all CSS and JavaScript inline, with no external libraries, fonts, or runtime requests. Deliver one HTML file.
- Edit enables direct plain-text editing of headings and paragraphs. Done returns to presenting. Download HTML exports a new self-contained file containing both the revised content and the editor. The original file is not overwritten.
- Keep Edit and Download HTML inside the existing bottom menu. During editing, keep the controls visible. Preserve mobile portrait controls, landscape fitting, zoom, overview, keyboard navigation, and guarded hash access.
- Text editing must not trigger navigation or swipe gestures. Preserve plain-text paste, multiline text, export cleanup, and tab-close protection for unsaved changes. Do not claim automatic saving or in-place file overwrite.
- Overflow warnings are advisory. Inspect slides for clipped text, overlaps, and footer clearance; shorten content rather than silently shrinking type.
- Keep print styles: one slide per landscape page, all slides visible, editing outlines and controls hidden. Verify PDF output when possible; distinguish actual checks from inherited behavior.

## Verify and share

Test editing a heading, navigation after Done, downloading the edited file, reopening it, and editing again. Check desktop and mobile layouts. In an embedded mobile preview, provide an Open the editor link to the standalone file. Browser or chat preview restrictions can require downloading and opening the file locally.

Return the HTML file with brief instructions: Edit → change text → Done → Download HTML. The recipient needs only a browser, with no account or installation.

## Complete template

```html
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Editable HTML Slides — Try it yourself</title>
<style>
:root{--accent:#355fdd;--muted:#62656b;--line:#dedfe3}*{box-sizing:border-box}body{margin:0;background:#eeeef0;color:#111;font-family:Arial,Helvetica,sans-serif;overflow:hidden}#stage{position:absolute;left:50%;top:50%;width:1600px;height:900px;transform:translate(-50%,-50%) scale(var(--scale,1));transform-origin:center}.slide{display:none;position:relative;width:1600px;height:900px;background:#fff;padding:126px 120px 78px;overflow:hidden}.slide.active{display:block}.eyebrow{text-transform:uppercase;letter-spacing:3px;font-size:19px;font-weight:700;color:var(--accent);margin:0 0 35px}h1{font-size:91px;line-height:1.03;letter-spacing:-4px;margin:0 0 34px;max-width:1250px}h2{font-size:65px;line-height:1.08;letter-spacing:-2px;margin:0 0 45px;max-width:1240px}h3{font-size:31px;line-height:1.2;margin:0 0 18px}p{font-size:29px;line-height:1.45;margin:0;color:var(--muted)}.lead{max-width:960px;font-size:32px}.footer{position:absolute;left:120px;right:120px;bottom:27px;display:flex;justify-content:space-between;border-top:1px solid var(--line);padding-top:14px;font-size:15px;color:var(--muted)}.hint{position:fixed;bottom:55px;left:50%;transform:translateX(-50%);max-width:calc(100% - 24px);width:max-content;text-align:center;font-size:11px;line-height:14px;color:var(--muted);pointer-events:none}.hint svg{display:block;width:28px;height:16px;margin:0 auto;overflow:visible}.hint[hidden]{display:none}.three{display:grid;grid-template-columns:repeat(3,1fr);gap:48px;margin-top:67px}.three>div{border-top:2px solid #111;padding-top:25px}.number{display:block;font-size:18px;color:var(--accent);margin-bottom:23px}.comparison{display:grid;grid-template-columns:1fr 1fr;gap:62px}.comparison>div{border-top:1px solid var(--line);padding-top:24px}.diagram{height:190px;margin-bottom:25px;display:flex;align-items:center;justify-content:center;background:#f4f5f7;gap:21px}.sheet{border:2px solid #858a94;width:108px;height:133px;padding:15px 12px;background:white}.sheet i{height:6px;background:#a8acb5;display:block;margin-bottom:10px}.sheet.narrow{width:70px}.sheet.fixed{border-color:var(--accent);width:210px;height:118px;padding:23px}.diagram b{font-size:28px;color:var(--accent)}.tag{display:inline-block;font-size:19px;padding:10px 14px;background:#eef2ff;color:var(--accent);margin-top:25px}.portable{display:grid;grid-template-columns:430px 1fr;gap:100px;align-items:center;margin-top:65px}.file{border:2px solid #111;padding:41px 37px}.file strong{display:block;font-size:43px;letter-spacing:-1px;margin:22px 0}.file small{font-size:22px;color:var(--muted)}.steps{display:flex;gap:28px;align-items:stretch;margin-top:55px}.steps>div{flex:1;border-top:2px solid #111;padding-top:25px}.steps .plus{flex:0;border:0;color:var(--accent);font-size:40px;padding-top:57px}.steps p{font-size:26px}.result{margin-top:46px;border-top:1px solid var(--line);padding-top:25px;font-size:25px;color:var(--muted)}.result strong{color:#111}#controls{position:fixed;z-index:10;bottom:8px;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:7px;padding:5px 9px;background:rgba(255,255,255,.92);border:1px solid #c6c8cd;border-radius:7px;opacity:0;transition:opacity .15s;white-space:nowrap}#controls:hover,#controls:focus-within{opacity:1}button{font:14px Arial,sans-serif;padding:6px 12px;background:transparent;color:#111;border:0;border-radius:3px;cursor:pointer}button:disabled{opacity:.3;cursor:default}button:hover:not(:disabled){background:#e9edfa}:focus-visible{outline:3px solid var(--accent);outline-offset:3px}#counter{font-size:14px;min-width:39px;text-align:center}.overview{overflow:auto}.overview #stage{position:relative;left:auto;top:auto;transform:none;width:auto;height:auto;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:22px;padding:28px 28px 90px}.overview .slide{display:block;transform:scale(var(--thumb));transform-origin:top left;margin-right:calc(1600px * (var(--thumb) - 1));margin-bottom:calc(900px * (var(--thumb) - 1));cursor:pointer}.overview .slide.active{outline:6px solid var(--accent)}.overview .hint{display:none}@media(max-width:520px){#controls{gap:3px;padding:5px}button{padding:6px 5px;font-size:12px}#counter{font-size:12px;min-width:31px}}
@page{size:16in 9in;margin:0}@media print{html,body{margin:0!important;padding:0!important;background:white;overflow:visible!important}#stage,body.overview #stage{position:static!important;display:block!important;transform:none!important;width:1600px!important;height:auto!important;padding:0!important}#stage .slide,body.overview #stage .slide{display:block!important;width:1600px!important;height:900px!important;zoom:.96;transform:none!important;margin:0!important;outline:0!important;break-after:page;page-break-after:always;break-inside:avoid;print-color-adjust:exact;-webkit-print-color-adjust:exact}#stage .slide:last-child{break-after:auto;page-break-after:auto}#controls,#control-toggle,.hint{display:none!important}}

#reading-area,#canvas-surface{display:contents}#mobile-nav,#mobile-extras{display:none}
body.mobile{overflow:auto;background:#fff}body.mobile.embedded{overflow:hidden}.mobile #reading-area{display:block;width:100%;height:var(--reading-height,calc(100vw * .5625));overflow:auto;touch-action:pan-x pan-y pinch-zoom}.mobile #canvas-surface{display:block;position:relative;width:var(--read-width);height:var(--read-height);margin-inline:auto}.mobile #stage{position:absolute;left:0;top:0;transform:scale(var(--read-scale));transform-origin:top left}.mobile #controls,.mobile .hint{display:none}.mobile #mobile-nav{height:52px;display:flex;align-items:center;justify-content:center;gap:18px;background:#fff;border-top:1px solid var(--line)}#mobile-nav button{min-width:44px;min-height:44px;font-size:20px}#mobile-counter{font-size:14px;min-width:48px;text-align:center}.mobile:not(.embedded) #mobile-extras{display:flex;flex-wrap:wrap;justify-content:center;gap:4px;padding:8px;border-top:1px solid var(--line)}#mobile-extras button{min-height:44px;padding:6px 10px}#zoom-status{align-self:center;font-size:12px;color:var(--muted)}.mobile.overview #reading-area{height:auto;overflow:visible}.mobile.overview #canvas-surface{width:auto;height:auto}.mobile.overview #stage{position:relative;transform:none;left:auto;top:auto}.mobile.overview #mobile-nav{display:none}
@media print{#reading-area,#canvas-surface,body.mobile #reading-area,body.mobile #canvas-surface{display:contents!important;width:auto!important;height:auto!important;overflow:visible!important}#mobile-nav,#mobile-extras{display:none!important}body.mobile #stage{position:static!important;transform:none!important}body.mobile #stage .slide{transform:none!important}}

#presentation-controls,#tap-cue,#standalone-present{display:none}.immersive:not(.overview){overflow:hidden;background:#fff}.immersive:not(.overview) #reading-area{display:block;position:relative;width:100%;height:var(--visible-height);overflow:auto}.immersive:not(.overview) #canvas-surface{display:block;position:relative;width:var(--read-width);height:var(--read-height);margin:0 auto;top:max(0px,calc((var(--visible-height) - var(--read-height))/2))}.immersive:not(.overview) #stage{position:absolute;left:0;top:0;transform:scale(var(--read-scale));transform-origin:top left}.immersive:not(.overview) #mobile-nav,.immersive:not(.overview) #mobile-extras,.immersive #controls,.immersive .hint{display:none!important}.immersive:not(.overview) #presentation-controls{display:flex;position:fixed;z-index:20;bottom:8px;left:50%;transform:translateX(-50%);gap:3px;padding:4px;background:rgba(255,255,255,.94);border:1px solid #ddd;border-radius:7px;opacity:0;pointer-events:none;white-space:nowrap}.immersive.overlay-visible #presentation-controls,.immersive #presentation-controls:focus-within{opacity:1;pointer-events:auto}#presentation-controls button{min-width:44px;min-height:44px;padding:4px 7px;font-size:12px}#present-counter{font-size:12px;align-self:center}.immersive:not(.overview) #tap-cue:not([hidden]){display:block;position:fixed;bottom:18px;left:50%;transform:translateX(-50%);font-size:12px;background:#fff;padding:7px 12px;border-radius:5px;pointer-events:none}.overlay-visible #tap-cue{display:none!important}#standalone-present:not([hidden]){display:block;position:fixed;z-index:30;bottom:70px;left:50%;transform:translateX(-50%);background:white;padding:14px;color:var(--accent);border:1px solid var(--line)}@media print{#presentation-controls,#tap-cue,#standalone-present{display:none!important}.immersive #reading-area,.immersive #canvas-surface{display:contents!important;position:static!important;top:auto!important}.immersive #stage{position:static!important;transform:none!important}}
</style><style>
#editor-bar{display:contents}#edit-status{display:none}
.editing #edit-status{display:block;position:static;flex:0 0 100%;order:-1;box-sizing:border-box;max-width:100%;white-space:normal;text-align:center;padding:6px 8px;color:#62656b;font:12px/1.4 Arial,sans-serif;pointer-events:none}
#controls{max-width:calc(100% - 16px);width:max-content;flex-wrap:wrap;justify-content:center}
#edit-status.warning{color:#b3261e}
[data-editable]{white-space:pre-wrap}
.editing [contenteditable]{outline:2px dashed #355fdd55;outline-offset:5px;cursor:text;white-space:pre-wrap;min-height:1em}
.editing [contenteditable]:focus{outline:3px solid #355fdd}
.editing #control-hint{visibility:hidden}.editing #overview,.editing #mobile-overview,.editing #present-overview{display:none}
.editing:not(.mobile):not(.immersive) #controls{opacity:1}
.immersive #presentation-controls{width:max-content;max-width:calc(100% - 16px);flex-wrap:wrap;justify-content:center}
.immersive.editing #presentation-controls{opacity:1;pointer-events:auto;max-width:calc(100% - 16px);flex-wrap:wrap;justify-content:center}

@media print{#editor-bar,#edit-status,[data-editor-action]{display:none!important}.editing [contenteditable]{outline:none!important}}
</style></head><body><div id="editor-bar" role="region" aria-label="Slide editor"><button id="edit-toggle" aria-pressed="false">Edit</button><button id="save-html">Download HTML</button><span id="edit-status" role="status">Edit text, then download your updated deck.</span></div>
<div id="reading-area"><div id="canvas-surface"><main id="stage" aria-label="Simple HTML Slides presentation">
<section class="slide active" aria-label="Slide 1: Make the last edit yourself"><div class="eyebrow">HTML Slides / Part 2</div><h1>A good deck.<br>One last wording change.</h1><p class="lead">Try changing this sentence.<br>Choose Edit in the bottom menu to get started.</p><footer class="footer"><span>Editable HTML slides · Try it yourself</span><span>01 / 03</span></footer></section>
<section class="slide" aria-label="Slide 2: Edit, finish, download"><div class="eyebrow">A small edit should be simple</div><h2>Your words. Same slide.</h2><div class="three"><div><span class="number">01 / EDIT</span><h3>Click the text</h3><p>Choose Edit, then change a heading or sentence directly on the slide.</p></div><div><span class="number">02 / DONE</span><h3>Return to presenting</h3><p>Choose Done. Your wording stays in place, with the existing slide layout.</p></div><div><span class="number">03 / DOWNLOAD</span><h3>Keep your changes</h3><p>Download HTML saves a new file with your edits and the editor included.</p></div></div><footer class="footer"><span>Editable HTML slides · No AI round trip</span><span>02 / 03</span></footer></section>
<section class="slide" aria-label="Slide 3: Still one portable file"><div class="eyebrow">Portable, including the editor</div><h2>Send the file.<br>The editor goes with it.</h2><div class="three"><div><h3>No installation</h3><p>Open the HTML file in a browser. No account or external libraries required.</p></div><div><h3>Editable by the recipient</h3><p>The next person can make their own wording changes and download a new copy.</p></div><div><h3>Keep the layout focused</h3><p>Edit text without moving boxes. If a passage becomes too long, shorten it to fit.</p></div></div><footer class="footer"><span>Editable HTML slides · One self-contained file</span><span>03 / 03</span></footer></section>
</main></div></div>
<div class="hint" id="control-hint"><span id="hint-copy">Move below to reveal controls</span><svg viewBox="0 0 40 24" aria-hidden="true"><g fill="none" stroke="#c3342c" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2 C25 0 28 7 24 13 L21 21 M14 14 L21 22 L29 15" stroke-width="2.4" stroke-dasharray="18 .7 9 .5 30"/><path d="M13 3 C24 1 27 7 23 14 M15 15 L21 21 L28 16" stroke-width=".7" opacity=".6"/></g></svg></div>
<nav id="controls" aria-label="Presentation controls"><button id="prev" aria-label="Previous slide">←</button><span id="counter" aria-live="polite"></span><button id="next" aria-label="Next slide">→</button><button id="overview" aria-pressed="false">Overview</button><button id="fullscreen">Fullscreen</button><button id="print">Print</button></nav>
<nav id="mobile-nav" aria-label="Slide navigation"><button id="mobile-prev" aria-label="Previous slide">←</button><span id="mobile-counter" aria-live="polite"></span><button id="mobile-next" aria-label="Next slide">→</button></nav>
<nav id="mobile-extras" aria-label="Presentation and zoom"><button id="mobile-overview" aria-pressed="false">Overview</button><button id="mobile-fullscreen">Fullscreen</button><button id="mobile-print">Print</button><button id="zoom-out" aria-label="Zoom out">−</button><span id="zoom-status" aria-live="polite">100%</span><button id="zoom-in" aria-label="Zoom in">+</button><button id="zoom-reset">Reset zoom</button></nav>
<nav id="presentation-controls" aria-label="Presentation controls"><button id="present-prev" aria-label="Previous slide">←</button><span id="present-counter"></span><button id="present-next" aria-label="Next slide">→</button><button id="present-overview">Overview</button><button id="present-fullscreen">Present</button><button id="present-exit">Exit presentation</button></nav><div id="tap-cue" hidden>Tap for controls</div><a id="standalone-present" hidden target="_blank" rel="noopener">Open standalone presentation ↗</a>
<script>
(()=>{'use strict';const $=id=>document.getElementById(id),slides=[...document.querySelectorAll('.slide')],query=matchMedia('(hover: none), (max-width: 600px)'),area=$('reading-area');let current=0,isOverview=false,mobile=query.matches,zoom=1;const embedded=window.self!==window.top;let presenting=false,immersive=false,overlayTimer=0,cueShown=false,lastSwipe=0,keyboardMode=false;const nativeSupported=()=>Boolean(document.fullscreenEnabled&&document.documentElement.requestFullscreen);document.body.classList.toggle('embedded',embedded);
let visibleHeight=innerHeight,fitFrame=0;
function fit(){updateMode();const width=document.documentElement.clientWidth||innerWidth,viewport=window.visualViewport;if(!viewport||Math.abs(viewport.scale-1)<.01)visibleHeight=viewport?Math.min(innerHeight,viewport.height):innerHeight;const pager=$('mobile-nav').getBoundingClientRect().height,extras=$('mobile-extras').getBoundingClientRect().height;let baseScale=width/1600;if(immersive&&!isOverview)baseScale=Math.min(width/1600,visibleHeight/900);else if(mobile&&!embedded&&!isOverview)baseScale=Math.min(baseScale,Math.max(0,visibleHeight-pager-extras)/900);const root=document.documentElement.style;root.setProperty('--visible-height',visibleHeight+'px');root.setProperty('--scale',Math.min(width/1600,innerHeight/900));root.setProperty('--thumb',Math.max(.08,(width-78)/3200));root.setProperty('--reading-height',baseScale*900+'px');root.setProperty('--read-scale',baseScale*zoom);root.setProperty('--read-width',baseScale*1600*zoom+'px');root.setProperty('--read-height',baseScale*900*zoom+'px');$('zoom-status').textContent=Math.round(zoom*100)+'%';$('zoom-out').disabled=zoom<=1;$('zoom-in').disabled=zoom>=3;}
function scheduleFit(){if(!fitFrame)fitFrame=requestAnimationFrame(()=>{fitFrame=0;fit();});}
function resetZoom(){zoom=1;fit();area.scrollTo(0,0);}
function render(){slides.forEach((s,i)=>{s.classList.toggle('active',i===current);s.tabIndex=isOverview?0:-1;if(isOverview)s.setAttribute('role','button');else s.removeAttribute('role');});for(const prefix of ['', 'mobile-', 'present-']){$(prefix+'counter').textContent=`${current+1} / ${slides.length}`;$(prefix+'prev').disabled=current===0;$(prefix+'next').disabled=current===slides.length-1;}for(const id of ['overview','mobile-overview'])$(id).setAttribute('aria-pressed',String(isOverview));$('control-hint').hidden=mobile||current!==0||isOverview;fit();}
function go(i){const target=Math.max(0,Math.min(slides.length-1,i));if(target!==current)resetZoom();current=target;render();try{history.replaceState(null,'',`#${current+1}`);}catch{/* Sandboxed srcdoc previews may forbid URL updates; navigation still works. */}}
function hash(){let fragment='';try{fragment=location.hash;}catch{/* URL access is optional in restricted previews. */}const match=fragment.match(/^#([1-9]\d*)$/);go(match?Number(match[1])-1:0);}
function toggle(force){if(mobile&&embedded)return;isOverview=typeof force==='boolean'?force:!isOverview;document.body.classList.toggle('overview',isOverview);render();if(isOverview)slides[current].focus();else{resetZoom();scrollTo(0,0);if(immersive){showOverlay(true);$('present-overview').focus();}else $(mobile?'mobile-overview':'overview').focus();}}
function sync(){mobile=query.matches;document.body.classList.toggle('mobile',mobile);if(mobile&&embedded&&isOverview){isOverview=false;document.body.classList.remove('overview');}resetZoom();render();}
slides.forEach((s,i)=>{function select(){if(isOverview){go(i);toggle(false);}}s.addEventListener('click',select);s.addEventListener('keydown',e=>{if(isOverview&&(e.key==='Enter'||e.key===' ')){e.preventDefault();e.stopPropagation();select();}});});
function updateMode(){const next=presenting||Boolean(document.fullscreenElement)||(mobile&&!embedded&&innerWidth>innerHeight);if(next!==immersive){immersive=next;document.body.classList.toggle('immersive',immersive);showOverlay(false);if(immersive&&!cueShown){cueShown=true;$('tap-cue').hidden=false;setTimeout(()=>{$('tap-cue').hidden=true;},3500);}}for(const id of ['fullscreen','mobile-fullscreen','present-fullscreen'])$(id).textContent=document.fullscreenElement?'Exit fullscreen':presenting?'Exit presentation':nativeSupported()?'Fullscreen':'Present';$('present-exit').hidden=!presenting&&!document.fullscreenElement;$('present-fullscreen').hidden=presenting||Boolean(document.fullscreenElement);}
function showOverlay(show){clearTimeout(overlayTimer);if(!show&&$('presentation-controls').contains(document.activeElement))document.activeElement.blur();document.body.classList.toggle('overlay-visible',show);if(show){$('tap-cue').hidden=true;overlayTimer=setTimeout(()=>{if(keyboardMode&&$('presentation-controls').contains(document.activeElement))return;if($('presentation-controls').contains(document.activeElement))document.activeElement.blur();document.body.classList.remove('overlay-visible');},3000);}}
function fallback(){if(embedded){const link=$('standalone-present');link.href=location.href;link.hidden=false;link.focus();return;}presenting=true;if(isOverview){isOverview=false;document.body.classList.remove('overview');}resetZoom();render();showOverlay(true);$('present-exit').focus();}
async function exitPresentation(){presenting=false;if(document.fullscreenElement){try{await document.exitFullscreen();}catch{}}resetZoom();render();if(immersive)showOverlay(true);else $(mobile?'mobile-fullscreen':'fullscreen').focus();}
async function fullscreen(){if(document.fullscreenElement||presenting){await exitPresentation();return;}if(!nativeSupported()){if(embedded){window.open(location.href,'_blank','noopener');return;}fallback();return;}try{await document.documentElement.requestFullscreen();}catch{fallback();}}
$('present-prev').addEventListener('click',()=>{go(current-1);showOverlay(true);});$('present-next').addEventListener('click',()=>{go(current+1);showOverlay(true);});$('present-overview').addEventListener('click',()=>toggle());$('present-fullscreen').addEventListener('click',fullscreen);$('present-exit').addEventListener('click',exitPresentation);
area.addEventListener('click',e=>{if(immersive&&!isOverview&&Date.now()-lastSwipe>500&&!e.target.closest('button,a,input,textarea,select'))showOverlay(!document.body.classList.contains('overlay-visible'));});document.addEventListener('pointerdown',()=>{keyboardMode=false;});document.addEventListener('keydown',()=>{keyboardMode=true;});$('presentation-controls').addEventListener('focusin',()=>{if(keyboardMode)showOverlay(true);});$('presentation-controls').addEventListener('focusout',()=>{if(document.body.classList.contains('overlay-visible'))showOverlay(true);});document.addEventListener('fullscreenchange',()=>{resetZoom();render();if(immersive)showOverlay(true);});
for(const prefix of ['', 'mobile-']){$(prefix+'prev').addEventListener('click',()=>go(current-1));$(prefix+'next').addEventListener('click',()=>go(current+1));$(prefix+'overview').addEventListener('click',()=>toggle());$(prefix+'fullscreen').addEventListener('click',fullscreen);$(prefix+'print').addEventListener('click',()=>window.print());}
$('zoom-in').addEventListener('click',()=>{zoom=Math.min(3,zoom+.5);fit();});$('zoom-out').addEventListener('click',()=>{zoom=Math.max(1,zoom-.5);fit();});$('zoom-reset').addEventListener('click',resetZoom);
let drag=null;area.addEventListener('pointerdown',e=>{if(e.pointerType==='touch'||!mobile||isOverview||zoom!==1||e.button!==0||e.target.closest('button,a,input,select,textarea,[contenteditable]'))return;drag={x:e.clientX,y:e.clientY,id:e.pointerId};area.setPointerCapture(e.pointerId);});area.addEventListener('pointercancel',()=>{drag=null;});area.addEventListener('pointerup',e=>{if(!drag||drag.id!==e.pointerId)return;const start=drag;drag=null;const dx=e.clientX-start.x,dy=e.clientY-start.y;if(Math.abs(dx)>=Math.max(45,innerWidth*.12)&&Math.abs(dx)>Math.abs(dy)*1.5){lastSwipe=Date.now();go(current+(dx<0?1:-1));}});
let swipe=null;area.addEventListener('touchstart',e=>{swipe=null;if(!mobile||isOverview||zoom!==1||e.touches.length!==1||e.target.closest('button,a,input,select,textarea,[contenteditable]'))return;const t=e.touches[0];swipe={x:t.clientX,y:t.clientY,id:t.identifier};},{passive:true});area.addEventListener('touchmove',e=>{if(e.touches.length!==1)swipe=null;},{passive:true});area.addEventListener('touchcancel',()=>{swipe=null;},{passive:true});area.addEventListener('touchend',e=>{if(!swipe)return;const start=swipe;swipe=null;const t=[...e.changedTouches].find(t=>t.identifier===start.id);if(!t||e.touches.length)return;const dx=t.clientX-start.x,dy=t.clientY-start.y;if(Math.abs(dx)>=Math.max(45,innerWidth*.12)&&Math.abs(dx)>Math.abs(dy)*1.5){lastSwipe=Date.now();go(current+(dx<0?1:-1));}},{passive:true});
document.addEventListener('keydown',e=>{if(e.defaultPrevented||e.ctrlKey||e.metaKey||e.altKey||e.target.closest('input,textarea,select,[contenteditable]:not([contenteditable="false"])'))return;if(e.key==='Escape'&&!isOverview&&(presenting||document.fullscreenElement)){e.preventDefault();exitPresentation();return;}if(e.key==='Escape'&&immersive&&!isOverview){e.preventDefault();showOverlay(false);return;}if(e.key==='Escape'&&isOverview){e.preventDefault();toggle(false);return;}if(e.target.closest('button')&&(e.key===' '||e.key==='Enter'))return;if(e.key.toLowerCase()==='o'){e.preventDefault();toggle();return;}if(isOverview)return;const actions={ArrowRight:()=>go(current+1),ArrowDown:()=>go(current+1),' ':()=>go(current+1),PageDown:()=>go(current+1),ArrowLeft:()=>go(current-1),ArrowUp:()=>go(current-1),PageUp:()=>go(current-1),Home:()=>go(0),End:()=>go(slides.length-1)};if(actions[e.key]){e.preventDefault();actions[e.key]();}});query.addEventListener('change',sync);addEventListener('resize',scheduleFit);addEventListener('orientationchange',scheduleFit);if(window.visualViewport)window.visualViewport.addEventListener('resize',()=>{if(Math.abs(window.visualViewport.scale-1)<.01)scheduleFit();});const controlsObserver=new ResizeObserver(scheduleFit);controlsObserver.observe($('mobile-nav'));controlsObserver.observe($('mobile-extras'));addEventListener('hashchange',hash);sync();hash();})();
</script><script>(()=>{
'use strict';
const fields=[...document.querySelectorAll('.slide h1,.slide h2,.slide h3,.slide p,.slide .eyebrow,.slide .tag,.slide .file strong,.slide .file small,.slide .result')];
const toggle=document.getElementById('edit-toggle'),save=document.getElementById('save-html'),status=document.getElementById('edit-status');
fields.forEach(el=>el.setAttribute("data-editable", ""));
let editing=false,dirty=false;
const bar=document.getElementById('editor-bar');
toggle.dataset.editorAction='edit';save.dataset.editorAction='save';
function placeEditor(){
 const target=document.getElementById(document.body.classList.contains('immersive')?'presentation-controls':document.body.classList.contains('mobile')?'mobile-extras':'controls');
 if(toggle.parentElement!==target){target.append(status,toggle,save);}
}
placeEditor();
new MutationObserver(placeEditor).observe(document.body,{attributes:true,attributeFilter:['class']});
function check(){
 const slide=document.querySelector('.slide.active');
 if(!slide||!editing)return;
 const footer=slide.querySelector('.footer').getBoundingClientRect();
 const box=slide.getBoundingClientRect();
 const overflow=[...slide.querySelectorAll('h1,h2,h3,p,.eyebrow,.tag,.file,.steps,.result')].some(el=>{const r=el.getBoundingClientRect();return r.bottom>footer.top-8||r.right>box.right||el.scrollWidth>el.clientWidth+2;});
 status.textContent=overflow?'Text may overlap or run off the slide. Shorten it before sharing.':dirty?'Changes in this tab only. Download HTML to keep them.':'Click any outlined text to edit. Download HTML to keep changes.';
 status.classList.toggle('warning',overflow);
}
function setEditing(value){
 editing=value;
 if(editing&&document.body.classList.contains('overview'))document.getElementById(document.body.classList.contains('mobile')?'mobile-overview':'overview').click();
 document.body.classList.toggle('editing',editing);
 fields.forEach((el,i)=>{if(editing){el.setAttribute('contenteditable','plaintext-only');el.setAttribute('role','textbox');el.setAttribute('aria-label','Edit '+(el.tagName.match(/^H/)?'heading':'text')+' '+(i+1));}else{el.removeAttribute('contenteditable');el.removeAttribute('role');el.removeAttribute('aria-label');}});
 toggle.textContent=editing?'Done':'Edit';toggle.setAttribute('aria-pressed',String(editing));
 status.textContent=dirty?'Changes in this tab only. Download HTML to keep them.':'Edit text, then download your updated deck.';
 check();
}
toggle.addEventListener('click',()=>setEditing(!editing));
fields.forEach(el=>{
 el.addEventListener('input',()=>{dirty=true;check();});
 el.addEventListener('paste',e=>{if(!editing)return;e.preventDefault();document.execCommand('insertText',false,e.clipboardData.getData('text/plain'));});
 el.addEventListener('drop',e=>{if(editing)e.preventDefault();});
});
// Keep editing keystrokes and gestures out of the presentation engine.
document.addEventListener('keydown',e=>{if(!editing)return;if(e.key==='Escape'){e.preventDefault();e.stopImmediatePropagation();setEditing(false);toggle.focus();}else if(e.target.closest('[contenteditable]'))e.stopPropagation();},true);
document.getElementById('reading-area').addEventListener('click',e=>{if(editing)e.stopImmediatePropagation();},true);
new MutationObserver(()=>{if(editing)requestAnimationFrame(check);}).observe(document.getElementById('stage'),{attributes:true,subtree:true,attributeFilter:['class']});
window.addEventListener('resize',check);
window.addEventListener('beforeunload',e=>{if(dirty){e.preventDefault();e.returnValue='';}});
save.addEventListener('click',()=>{
 const copy=document.documentElement.cloneNode(true);
 copy.removeAttribute('style');copy.querySelector('body').removeAttribute('class');
 copy.querySelector('#editor-bar').prepend(copy.querySelector('#edit-toggle'),copy.querySelector('#save-html'),copy.querySelector('#edit-status'));
 copy.querySelectorAll('[contenteditable]').forEach(el=>{el.removeAttribute('contenteditable');el.removeAttribute('role');el.removeAttribute('aria-label');});
 copy.querySelectorAll('.slide').forEach((el,i)=>{el.classList.toggle('active',i===0);el.removeAttribute('tabindex');el.removeAttribute('role');});
 copy.querySelector('#edit-toggle').textContent='Edit';copy.querySelector('#edit-toggle').setAttribute('aria-pressed','false');
 copy.querySelector('#edit-status').textContent='Edit text, then download your updated deck.';copy.querySelector('#edit-status').classList.remove('warning');
 const blob=new Blob(['<!doctype html>\n'+copy.outerHTML],{type:'text/html;charset=utf-8'}),url=URL.createObjectURL(blob),link=document.createElement('a');
 link.href=url;link.download='editable-slides.html';link.click();setTimeout(()=>URL.revokeObjectURL(url),60000);
 status.textContent='Download requested. Keep the downloaded file before closing this tab.';
});
})();
</script></body></html>

```