@@ -237,6 +237,11 @@ const docsCss = `/* Improve link discoverability in rendered workshop docs */
237237 * Reveal.js overrides
238238 * ---------------------------------------------------------------- */
239239
240+ /* Reduce default slide scale for desktop reading */
241+ .reveal {
242+ font-size: 1.875rem;
243+ }
244+
240245/* Align text left; with center:false slides already start at top,
241246 * so no top override is needed. */
242247.reveal .slides section {
@@ -247,15 +252,33 @@ const docsCss = `/* Improve link discoverability in rendered workshop docs */
247252 * long content does not get clipped. A single scroll container per
248253 * slide avoids nested-scrollbar confusion. */
249254.reveal .slides .slide-content {
250- --slide-vertical-gap: 5rem;
251- font-size: 0.8em;
252- padding: 0 1.5em;
253- height: calc(100vh - var(--slide-vertical-gap));
254- max-height: calc(100vh - var(--slide-vertical-gap));
255+ --slide-top-gap: 1.25rem;
256+ /* Extra bottom room keeps content clear of Reveal controls/progress UI. */
257+ --slide-bottom-gap: 4.75rem;
258+ padding: var(--slide-top-gap) 1.5em var(--slide-bottom-gap);
259+ height: calc(100vh - var(--slide-top-gap) - var(--slide-bottom-gap));
260+ max-height: calc(100vh - var(--slide-top-gap) - var(--slide-bottom-gap));
261+ min-height: 0;
255262 overflow-y: auto;
263+ overflow-x: hidden;
264+ scrollbar-gutter: stable;
256265 box-sizing: border-box;
257266}
258267
268+ @supports (height: 100dvh) {
269+ .reveal .slides .slide-content {
270+ height: calc(100dvh - var(--slide-top-gap) - var(--slide-bottom-gap));
271+ max-height: calc(100dvh - var(--slide-top-gap) - var(--slide-bottom-gap));
272+ }
273+ }
274+
275+ /* Ensure slide images fit and advertise lightbox affordance */
276+ .reveal .slides .slide-content img {
277+ max-width: 100%;
278+ height: auto;
279+ cursor: zoom-in;
280+ }
281+
259282/* Visually distinguish side-quest slides with a left border */
260283.reveal .slides .side-quest-slide {
261284 border-left: 4px solid #0969da;
@@ -264,6 +287,29 @@ const docsCss = `/* Improve link discoverability in rendered workshop docs */
264287` ;
265288fs . writeFileSync ( path . join ( distDir , 'docs.css' ) , docsCss ) ;
266289
290+ const parallaxBackgroundSvgEncoded = encodeURIComponent ( [
291+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice">' ,
292+ '<defs>' ,
293+ '<linearGradient id="primaryGradient" x1="0" y1="0" x2="1" y2="1">' ,
294+ '<stop offset="0%" stop-color="#0d1117" />' ,
295+ '<stop offset="45%" stop-color="#271449" />' ,
296+ '<stop offset="100%" stop-color="#8250df" />' ,
297+ '</linearGradient>' ,
298+ '<radialGradient id="topRadialGlow" cx="20%" cy="25%" r="40%">' ,
299+ '<stop offset="0%" stop-color="#a371f7" stop-opacity=".32" />' ,
300+ '<stop offset="100%" stop-color="#a371f7" stop-opacity="0" />' ,
301+ '</radialGradient>' ,
302+ '<radialGradient id="bottomRadialGlow" cx="82%" cy="78%" r="45%">' ,
303+ '<stop offset="0%" stop-color="#6f42c1" stop-opacity=".30" />' ,
304+ '<stop offset="100%" stop-color="#6f42c1" stop-opacity="0" />' ,
305+ '</radialGradient>' ,
306+ '</defs>' ,
307+ '<rect width="1920" height="1080" fill="url(#primaryGradient)" />' ,
308+ '<rect width="1920" height="1080" fill="url(#topRadialGlow)" />' ,
309+ '<rect width="1920" height="1080" fill="url(#bottomRadialGlow)" />' ,
310+ '</svg>' ,
311+ ] . join ( '' ) ) ;
312+
267313// Generate docs runtime JavaScript
268314const docsJs = `const legacyHashMatch = window.location.hash.match(/^#\\/([^/]+)$/);
269315let legacySectionId = null;
@@ -281,6 +327,24 @@ if (hasLegacySectionTarget) {
281327 window.history.replaceState(null, '', '#' + legacySectionId);
282328}
283329
330+ function enableImageLightbox() {
331+ const images = document.querySelectorAll('.slides section img');
332+ images.forEach((img) => {
333+ if (img.hasAttribute('data-preview-image') || img.hasAttribute('data-preview-video')) {
334+ return;
335+ }
336+ if (img.closest('a[href]')) {
337+ return;
338+ }
339+ const src = img.currentSrc || img.getAttribute('src');
340+ if (src) {
341+ img.setAttribute('data-preview-image', src);
342+ }
343+ });
344+ }
345+
346+ const parallaxBackgroundImage = ${ JSON . stringify ( `data:image/svg+xml,${ parallaxBackgroundSvgEncoded } ` ) } ;
347+
284348Reveal.initialize({
285349 // URL hash reflects current slide by section id
286350 hash: true,
@@ -290,8 +354,17 @@ Reveal.initialize({
290354 center: false,
291355 // Push slide changes into the browser history
292356 history: true,
357+ // GitHub agentic-purple themed parallax background
358+ parallaxBackgroundImage: parallaxBackgroundImage,
359+ // Use a larger virtual canvas than the viewport so motion stays subtle.
360+ parallaxBackgroundSize: '3200px 1800px',
361+ // Horizontal movement is intentionally stronger than vertical to reduce jitter.
362+ parallaxBackgroundHorizontal: 180,
363+ parallaxBackgroundVertical: 70,
293364});
294365
366+ Reveal.on('ready', enableImageLightbox);
367+
295368if (hasLegacySectionTarget) {
296369 const target = document.getElementById(legacySectionId);
297370 const indices = target ? Reveal.getIndices(target) : null;
0 commit comments