jekyll-slides 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +62 -7
- data/assets/css/presentation.css +1 -1
- data/assets/js/presentation.js +109 -13
- data/doc/CHANGELOG.md +21 -0
- data/doc/Jekyll/Slides/JekyllIntegration.md +0 -3
- data/doc/Jekyll/Slides.md +16 -3
- data/doc/README.md +62 -7
- data/doc/index.csv +3 -1
- data/lib/jekyll/slides/component_renderer.rb +35 -5
- data/lib/jekyll/slides/jekyll_integration.rb +2 -3
- data/lib/jekyll/slides/version.rb +1 -1
- data/lib/jekyll/slides.rb +16 -2
- data/{llm.txt → llms.txt} +16 -3
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5720dd4de74c508f824918884060b1a5c8bdf5643cafa25db668611bcf6a8268
|
|
4
|
+
data.tar.gz: 562ecd070ac52320774fa5b1d3385f011ad2402212f29903bd82f2fb681fb78d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3b678341657718ef82c5c87fe60c30e3ea90c68625099fd7d209f1df9bf2513f17c183d44f41082204be1eafcf77ba7e97d0708ccbf437880b1f713495b15d0d
|
|
7
|
+
data.tar.gz: c853e1f0f7b793aa2e22558bf515a40208b31d9e97d5368eacdfd0b600a3ac680059f582f15a46abe9dd301da89917ff9f3ca2da3f0564845874e5815e934b61
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Jekyll Slides are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.4.0 — 2026-09-10
|
|
6
|
+
|
|
7
|
+
- Add opt-in paragraph reveals: mark a paragraph `{: .fragment}` and it is held back until the next step. Forward steps (`ArrowRight`, `PageDown`, `Space`, the next button, or a click on the slide) reveal one paragraph before moving to the next slide; backward steps hide the most recent reveal first. Slide numbers, the progress bar, the URL hash, and browser history keep counting slides, not reveals. Hidden paragraphs keep their space, cannot be focused or reached by assistive technology, and fade in over 180ms unless the reader prefers reduced motion. The overview, print, no-JavaScript output, and browsers without the slide canvas show every paragraph.
|
|
8
|
+
- Add `macos-light`, a flat light code-window palette. It is component-only: a block selects it with `theme="macos-light"`, a deck cannot, and it repaints that window alone so it can sit inside a deck of any color.
|
|
9
|
+
- Give slides more usable space. Content insets drop from `108px 132px 100px`, and from the `180px` title and statement overrides, to one shared 72px/80px pair used by both the presented slide and the overview preview.
|
|
10
|
+
- Repaint `minimal-light` as a flat neutral near-white deck instead of a warm paper tint, including its plain, gradient, and code surfaces.
|
|
11
|
+
- Keep 28px between a block and the prose after it. Plain fenced code, Rouge output, and figures previously carried no bottom margin, so following prose sat flush against them. A plain fence also now uses the deck's monospace face rather than the browser default.
|
|
12
|
+
- Stop capping `content` slides at a 920px column. Headings, paragraphs, lists, and quotes each carry their own measure, so the column cap only ever clipped the code blocks and tables that have none.
|
|
13
|
+
- Flatten the window chrome to match macOS: a solid title-bar fill with no gradient, a 1px border, a restrained shadow, and traffic lights with a rim but no gloss.
|
|
14
|
+
- Move the editor and terminal title from the center of the title bar to just after the traffic lights, offset by a control run derived from the bar height so `sm`, `md`, and `lg` stay aligned. A long filename truncates before the language label.
|
|
15
|
+
- Remove `--slide-surface-shine`, `--slide-code-inset`, and `--slide-dot-gloss`. The flat chrome reads none of them. Sites that forked the stylesheet and set these tokens should drop them.
|
|
16
|
+
|
|
17
|
+
## 0.3.0 — 2026-09-10
|
|
18
|
+
|
|
19
|
+
- Add the four Catppuccin flavors as presentation themes: `catppuccin-latte`, `catppuccin-frappe`, `catppuccin-macchiato`, and `catppuccin-mocha`, ported from the palette shared by [catppuccin/ghostty](https://github.com/catppuccin/ghostty). Hues are the published values; lightness is adjusted only where a token cannot otherwise clear the 4.5:1 contrast checked on every code surface.
|
|
20
|
+
- Add a `theme` attribute to editor and terminal blocks, so one window can carry any theme while the deck around it keeps its own. The override repaints that window's surface, title bar, syntax colors, prompt, and body text. An unknown name warns and falls back to the deck theme.
|
|
21
|
+
- Give terminal windows a real title bar. It was previously an empty `::before` bar that could hold neither the window controls nor the title, which floated above it.
|
|
22
|
+
- Center editor and terminal titles inside the title bar, and size the controls and bar with the component `size`.
|
|
23
|
+
- Use the macOS traffic-light colors for the window controls in every theme, the way a real title bar does; only the window surface follows the theme. Themes no longer set `--slide-dot-close`, `--slide-dot-minimize`, or `--slide-dot-maximize`.
|
|
24
|
+
- Rename the generated LLM index from `llm.txt` to `llms.txt`, matching the llmstxt.org convention used across these plugins.
|
|
25
|
+
|
|
5
26
|
## 0.2.0 — 2026-09-06
|
|
6
27
|
|
|
7
28
|
- Add folder decks: author a presentation as one Markdown file per slide, ordered by a numeric filename prefix and alphabetically otherwise, opted into with `slides:` in the entry file's front matter.
|
data/README.md
CHANGED
|
@@ -33,7 +33,7 @@ title: A short talk
|
|
|
33
33
|
|
|
34
34
|
<!--
|
|
35
35
|
layout: title
|
|
36
|
-
background:
|
|
36
|
+
background: plain
|
|
37
37
|
-->
|
|
38
38
|
# A short talk
|
|
39
39
|
|
|
@@ -136,7 +136,7 @@ ruby 3.4.1
|
|
|
136
136
|
{: .terminal #ruby-version title="terminal" size="sm"}
|
|
137
137
|
````
|
|
138
138
|
|
|
139
|
-
Editor/terminal attributes are `title`, `id` (or `#id`), `size` (`sm`, `md`, `lg`), `line_numbers` (`true`/`false`), `focus`, and `highlight`. Ranges accept comma-separated lines and ranges such as `2,4-6,9`; invalid values fall back safely with a Jekyll warning. Terminal prompts beginning with `$ `, `> `, or `❯ ` are styled separately. Source remains server-rendered and copyable.
|
|
139
|
+
Editor/terminal attributes are `title`, `id` (or `#id`), `size` (`sm`, `md`, `lg`), `theme`, `line_numbers` (`true`/`false`), `focus`, and `highlight`. Ranges accept comma-separated lines and ranges such as `2,4-6,9`; invalid values fall back safely with a Jekyll warning. Terminal prompts beginning with `$ `, `> `, or `❯ ` are styled separately. Source remains server-rendered and copyable.
|
|
140
140
|
|
|
141
141
|
Long editor and terminal blocks scroll within the slide. Blocks over 20 lines produce an advisory build warning; the amount that fits depends on the layout and font size. Split long examples across slides for print, where scrolling is unavailable.
|
|
142
142
|
|
|
@@ -144,9 +144,29 @@ Liquid runs before slide rendering, just as it does on ordinary Jekyll pages. Wr
|
|
|
144
144
|
|
|
145
145
|
Code remains selectable and copyable with normal browser controls; version 0.1 does not add a copy button.
|
|
146
146
|
|
|
147
|
+
## Paragraph reveals
|
|
148
|
+
|
|
149
|
+
Mark a paragraph `.fragment` to hold it back until the next step. Everything else on the slide is visible from the start.
|
|
150
|
+
|
|
151
|
+
```markdown
|
|
152
|
+
This paragraph is visible immediately.
|
|
153
|
+
|
|
154
|
+
This explanation appears on the next click.
|
|
155
|
+
{: .fragment}
|
|
156
|
+
|
|
157
|
+
This conclusion appears on the following click.
|
|
158
|
+
{: .fragment}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Each forward step — `ArrowRight`, `PageDown`, `Space`, the next button, or a click on the slide — reveals one more marked paragraph. Once the slide has none left, the same step moves to the next slide. Backward steps hide the most recent reveal first, and stepping onto an earlier slide arrives with it fully revealed. Slide numbers, the progress bar, the URL hash, and browser history keep counting slides, not reveals.
|
|
162
|
+
|
|
163
|
+
A hidden paragraph keeps its space, so revealing one moves nothing else on the slide. It cannot be focused or read by assistive technology until it is revealed, and it fades in over 180ms unless the reader prefers reduced motion. The overview, print output, no-JavaScript output, and browsers without the slide canvas show every paragraph, because none of them can reveal one; leaving the overview or the print dialog restores the reveals for the session.
|
|
164
|
+
|
|
165
|
+
Reveals are opt-in per paragraph, and version 0.1 marks paragraphs only. The [presentation polish example](https://github.com/lucianghinda/jekyll-slides/blob/main/examples/presentation-polish.md) shows them on a flat light deck.
|
|
166
|
+
|
|
147
167
|
## Themes and configuration
|
|
148
168
|
|
|
149
|
-
Presentation themes are `minimal-light`, `minimal-dark`, `midnight` (the default), and `
|
|
169
|
+
Presentation themes are `minimal-light`, `minimal-dark`, `midnight` (the default), `ruby`, and the four Catppuccin flavors `catppuccin-latte`, `catppuccin-frappe`, `catppuccin-macchiato`, and `catppuccin-mocha`. These style the slides without replacing the site's Jekyll theme. Configure defaults under `slides:`:
|
|
150
170
|
|
|
151
171
|
```yaml
|
|
152
172
|
slides:
|
|
@@ -162,17 +182,52 @@ The same keys can be overridden per presentation in front matter (`theme`, `aspe
|
|
|
162
182
|
|
|
163
183
|
For a light presentation, set `slides: { theme: minimal-light }` in `_config.yml`, or `theme: minimal-light` in the deck's front matter. The [readability example](https://github.com/lucianghinda/jekyll-slides/blob/main/examples/readability.md) demonstrates the light theme with code, terminal output, tables, and prose.
|
|
164
184
|
|
|
185
|
+
### Terminal themes
|
|
186
|
+
|
|
187
|
+
The Catppuccin flavors are ported from the palette shared by [catppuccin/ghostty](https://github.com/catppuccin/ghostty). Hues are the published values; lightness is adjusted only where a token cannot otherwise clear the 4.5:1 contrast the project checks on every code surface. Latte, the light flavor, needed the most adjustment.
|
|
188
|
+
|
|
189
|
+
Any theme also works on a single editor or terminal block through a `theme` attribute, so one window can carry a different palette from the deck around it:
|
|
190
|
+
|
|
191
|
+
````markdown
|
|
192
|
+
```console
|
|
193
|
+
$ ghostty --version
|
|
194
|
+
ghostty 1.0.1
|
|
195
|
+
```
|
|
196
|
+
{: .terminal title="ghostty" theme="catppuccin-latte"}
|
|
197
|
+
````
|
|
198
|
+
|
|
199
|
+
The override repaints that window completely: surface, title bar, syntax colors, prompt, and body text. Everything outside it keeps the deck theme. An unknown name warns during the build and falls back to the deck theme. The [terminal themes example](https://github.com/lucianghinda/jekyll-slides/blob/main/examples/terminal-themes.md) shows a deck-wide flavor next to per-window overrides.
|
|
200
|
+
|
|
201
|
+
### The macOS light window
|
|
202
|
+
|
|
203
|
+
`macos-light` is a component-only palette: a flat near-white code window with a pale title bar, purple keywords, green strings, and blue functions. It is meant to sit inside a deck of any color, so it defines no slide background and no type scale, and a deck cannot select it.
|
|
204
|
+
|
|
205
|
+
````markdown
|
|
206
|
+
```ruby
|
|
207
|
+
class Invoice
|
|
208
|
+
def total = items.sum(&:price)
|
|
209
|
+
end
|
|
210
|
+
```
|
|
211
|
+
{: .editor title="app/models/invoice.rb" theme="macos-light" line_numbers="true"}
|
|
212
|
+
````
|
|
213
|
+
|
|
214
|
+
Because `theme` is one shared attribute, `macos-light` works on a terminal too. Omitting `theme` continues to inherit the deck palette, and naming it in front matter or `_config.yml` is not a deck theme — that warns and falls back like any other unknown deck name. The [editor themes example](https://github.com/lucianghinda/jekyll-slides/blob/main/examples/editor-themes.md) shows it on a dark deck across all three sizes.
|
|
215
|
+
|
|
216
|
+
### Window chrome
|
|
217
|
+
|
|
218
|
+
Editors and terminals render the same macOS-style title bar: traffic lights on the left, then the `title`, and for editors the language on the right. The bar is a single flat fill from the palette with a hairline under it; the window has a 1px border and a restrained shadow. The traffic lights keep the macOS red, amber, and green in every theme, the way a real title bar does; only the window surface follows the theme. Bar height, control size, and the title's offset all scale with the component `size`, so `sm`, `md`, and `lg` stay aligned. A long filename truncates before it reaches the language label.
|
|
219
|
+
|
|
165
220
|
## Typography and readability
|
|
166
221
|
|
|
167
222
|
The gem bundles Atkinson Hyperlegible Next for text and Atkinson Hyperlegible Mono for code, including variable upright and italic faces. Fonts load from the site's own assets and work offline. The font files retain their SIL Open Font License; source revisions, checksums, and notices are in [assets/fonts](https://github.com/lucianghinda/jekyll-slides/blob/main/assets/fonts/README.md).
|
|
168
223
|
|
|
169
|
-
On the 1920×1080 slide canvas, body text is 44px, section headings are 72px, and code sizes `sm`, `md`, and `lg` are 32px, 38px, and 42px. These sizes scale with the slide. Filenames and line numbers remain readable, and focused lines use borders and background color while keeping surrounding code fully visible. All
|
|
224
|
+
On the 1920×1080 slide canvas, body text is 44px, section headings are 72px, and code sizes `sm`, `md`, and `lg` are 32px, 38px, and 42px. These sizes scale with the slide. Filenames and line numbers remain readable, and focused lines use borders and background color while keeping surrounding code fully visible. All eight deck themes, plus the component-only `macos-light`, check syntax-token contrast against normal, highlighted, and focused code surfaces, both deck-wide and as a single-window override, and check the filename and language against the title bar.
|
|
170
225
|
|
|
171
226
|
Prefer medium or large code and short examples for projection. Long blocks can scroll, but an audience cannot reveal hidden lines independently; split examples when presenting or printing. Screen contrast tests do not replace checking the actual projector and viewing distance.
|
|
172
227
|
|
|
173
228
|
## Navigation and accessibility
|
|
174
229
|
|
|
175
|
-
Use `ArrowLeft`/`ArrowRight`, `PageUp`/`PageDown`, `Home`, and `End` to navigate. `Space` advances, `O` toggles overview, and `F` toggles fullscreen. The current slide is synchronized in the URL hash (`#3` for slide three), so links and browser history work. The controls include accessible labels and focus states; reduced-motion preferences are respected. Print the deck with the browser print dialog (slides are paginated and chrome is hidden). If JavaScript is disabled, all slides remain in document order as complete aspect-ratio frames with readable content.
|
|
230
|
+
Use `ArrowLeft`/`ArrowRight`, `PageUp`/`PageDown`, `Home`, and `End` to navigate. `Space` advances, `O` toggles overview, and `F` toggles fullscreen. A click on the slide advances too; links, buttons, modified clicks, and text selection keep their own behavior. On a slide with [paragraph reveals](#paragraph-reveals), a forward step reveals the next paragraph before it changes slide. `Home` and `End` always jump to a slide. The current slide is synchronized in the URL hash (`#3` for slide three), so links and browser history work. The controls include accessible labels and focus states; reduced-motion preferences are respected. Print the deck with the browser print dialog (slides are paginated and chrome is hidden). If JavaScript is disabled, all slides remain in document order as complete aspect-ratio frames with readable content.
|
|
176
231
|
|
|
177
232
|
## Demo and development
|
|
178
233
|
|
|
@@ -207,7 +262,7 @@ bundle exec rake docs
|
|
|
207
262
|
```
|
|
208
263
|
|
|
209
264
|
This replaces `doc/` with fresh YARD Markdown, updates the documentation index in
|
|
210
|
-
`doc/Jekyll/Slides.md`, and writes `
|
|
265
|
+
`doc/Jekyll/Slides.md`, and writes `llms.txt` with links relative to the gem root.
|
|
211
266
|
The generated files are checked in and shipped with the gem. Internal plans,
|
|
212
267
|
temporary files, and Node dependencies are excluded. YARD and `yard-markdown`
|
|
213
268
|
are development tools only.
|
|
@@ -229,7 +284,7 @@ Maintainers can follow the [release instructions](https://github.com/lucianghind
|
|
|
229
284
|
|
|
230
285
|
## 0.1 limitations and extension
|
|
231
286
|
|
|
232
|
-
Version 0.1 intentionally supports Markdown/Kramdown, a fixed 16:9 canvas, the curated layouts/themes above, and a small dependency-free browser runtime. It does not provide speaker notes, transitions, nested slide sections, a theme editor, or an authoring UI. JavaScript is enhancement-only; server-side HTML is the source of truth.
|
|
287
|
+
Version 0.1 intentionally supports Markdown/Kramdown, a fixed 16:9 canvas, the curated layouts/themes above, and a small dependency-free browser runtime. It does not provide speaker notes, slide transitions, nested slide sections, a theme editor, or an authoring UI. Reveals mark paragraphs only; other blocks and grouped sequences are not covered. JavaScript is enhancement-only; server-side HTML is the source of truth.
|
|
233
288
|
|
|
234
289
|
The plugin injects its `_layouts`, `_includes`, and `assets` into Jekyll without participating in theme resolution. A site can override the `presentation` layout, any `slides/*` include, or either compiled asset by placing a file with the same path in its own source tree. Copy the stylesheet only when you need a complete CSS fork; otherwise add a custom slide class and site CSS after the gem stylesheet. Keep `plugins: [jekyll-slides]` enabled even when overriding the layout so Markdown rendering and normalized slide settings remain active.
|
|
235
290
|
|
data/assets/css/presentation.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--font-slide-sans:"Atkinson Hyperlegible Next", "Avenir Next", "Segoe UI Variable", "Segoe UI", system-ui, sans-serif;--font-slide-mono:"Atkinson Hyperlegible Mono", "JetBrains Mono", "SFMono-Regular", Consolas, monospace;--slide-canvas-width:1920px;--slide-canvas-height:1080px;--slide-radius:28px}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.block{display:block}.grid{display:grid}.hidden{display:none}}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-weight:200 800;font-display:swap;src:url(../fonts/atkinson-hyperlegible-next.woff2)format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:italic;font-weight:200 800;font-display:swap;src:url(../fonts/atkinson-hyperlegible-next-italic.woff2)format("woff2")}@font-face{font-family:Atkinson Hyperlegible Mono;font-style:normal;font-weight:200 800;font-display:swap;src:url(../fonts/atkinson-hyperlegible-mono.woff2)format("woff2")}@font-face{font-family:Atkinson Hyperlegible Mono;font-style:italic;font-weight:200 800;font-display:swap;src:url(../fonts/atkinson-hyperlegible-mono-italic.woff2)format("woff2")}:root,[data-theme=midnight]{--slide-bg:#10141d;--slide-fg:#f3f5f8;--slide-muted:#b4bdca;--slide-accent:#ff6b4a;--slide-accent-strong:#ff8a65;--slide-code-surface:#151b26;--slide-code-header:#1c2532;--slide-code-border:#364354;--slide-code-shadow:#0000006b;--slide-syntax-comment:#aab5c5;--slide-syntax-keyword:#ff9e7a;--slide-syntax-string:#b8d98e;--slide-syntax-number:#c6a9ff;--slide-syntax-function:#75c9db;--slide-syntax-operator:#f3f5f8;--slide-syntax-punctuation:#b9c4d2;--slide-syntax-name:#f3f5f8;--slide-syntax-variable:#f3f5f8;--slide-syntax-symbol:#75c9db;--slide-syntax-builtin:#75c9db;--slide-syntax-constant:#c6a9ff;--slide-syntax-error:#ff8675;--slide-highlight:#ff6b4a2b;--slide-focus:#ff9e7a;--slide-selection:#ff6b4a47;--slide-grid-line:#ffffff0e;--slide-spotlight:#ff6b4a26;--slide-gradient-start:#191d2c;--slide-gradient-end:#10141d;--slide-link:#9edbea;--slide-quote:#c8d1dc;--slide-dot-close:#ef806d;--slide-dot-minimize:#e6b566;--slide-dot-maximize:#87c899;--slide-heading-font-size:72px;--slide-title-font-size:108px;--slide-body-font-size:44px;--slide-statement-font-size:88px;--slide-code-font-size:38px;--slide-code-highlight-surface:#ff6b4a1a;--slide-code-highlight-border:#ff6b4a;--slide-code-focus-surface:#ff9e7a1a;--slide-code-inset:#ffffff0f;--slide-surface-shine:#ffffff0f}[data-theme=minimal-light]{--slide-bg:#f4f1eb;--slide-fg:#1c2027;--slide-muted:#4d5660;--slide-accent:#bc3e27;--slide-accent-strong:#8d2919;--slide-code-surface:#e9e6df;--slide-code-header:#dedbd4;--slide-code-border:#c8c4bb;--slide-code-shadow:#302c242e;--slide-syntax-comment:#50564f;--slide-syntax-keyword:#9d3e28;--slide-syntax-string:#325c35;--slide-syntax-number:#6b4ca0;--slide-syntax-function:#12586a;--slide-syntax-operator:#343b45;--slide-syntax-punctuation:#4d5863;--slide-syntax-name:#1c2027;--slide-syntax-variable:#1c2027;--slide-syntax-symbol:#12586a;--slide-syntax-builtin:#12586a;--slide-syntax-constant:#6b4ca0;--slide-syntax-error:#a52121;--slide-highlight:#bc3e2721;--slide-focus:#9d3e28;--slide-selection:#bc3e2733;--slide-grid-line:#1c202714;--slide-spotlight:#bc3e271f;--slide-gradient-start:#fffdf8;--slide-gradient-end:#e9e5dc;--slide-link:#176d82;--slide-quote:#424a54;--slide-dot-close:#cf6753;--slide-dot-minimize:#c09243;--slide-dot-maximize:#579966;--slide-heading-font-size:72px;--slide-title-font-size:96px;--slide-body-font-size:44px;--slide-statement-font-size:88px;--slide-code-font-size:38px;--slide-code-highlight-surface:#bc3e2712;--slide-code-highlight-border:#bc3e27;--slide-code-focus-surface:#9d3e2812;--slide-code-inset:#1c202714;--slide-surface-shine:#ffffff0f}[data-theme=minimal-dark]{--slide-bg:#171717;--slide-fg:#f4f1ea;--slide-muted:#bcb8b0;--slide-accent:#e6b566;--slide-accent-strong:#f2c57a;--slide-code-surface:#202020;--slide-code-header:#2b2b2a;--slide-code-border:#454441;--slide-code-shadow:#00000080;--slide-syntax-comment:#b2afa9;--slide-syntax-keyword:#f0bd75;--slide-syntax-string:#b8d094;--slide-syntax-number:#d1a9e8;--slide-syntax-function:#83ced1;--slide-syntax-operator:#f4f1ea;--slide-syntax-punctuation:#c5c1b9;--slide-syntax-name:#f4f1ea;--slide-syntax-variable:#f4f1ea;--slide-syntax-symbol:#83ced1;--slide-syntax-builtin:#83ced1;--slide-syntax-constant:#d1a9e8;--slide-syntax-error:#f28272;--slide-highlight:#e6b56629;--slide-focus:#f0bd75;--slide-selection:#e6b56640;--slide-grid-line:#ffffff0f;--slide-spotlight:#e6b56621;--slide-gradient-start:#25221e;--slide-gradient-end:#171717;--slide-link:#83ced1;--slide-quote:#d3cec4;--slide-dot-close:#d97762;--slide-dot-minimize:#d4a052;--slide-dot-maximize:#70ad7e;--slide-heading-font-size:72px;--slide-title-font-size:108px;--slide-body-font-size:44px;--slide-statement-font-size:88px;--slide-code-font-size:38px;--slide-code-highlight-surface:#e6b5661a;--slide-code-highlight-border:#e6b566;--slide-code-focus-surface:#f0bd751a;--slide-code-inset:#ffffff0f;--slide-surface-shine:#ffffff0f}[data-theme=ruby]{--slide-bg:#210f18;--slide-fg:#fff4ed;--slide-muted:#dfbcc3;--slide-accent:#ff7a68;--slide-accent-strong:#ffb09a;--slide-code-surface:#2a1520;--slide-code-header:#3a1c2a;--slide-code-border:#613348;--slide-code-shadow:#0a020780;--slide-syntax-comment:#cba8b0;--slide-syntax-keyword:#ff9f80;--slide-syntax-string:#c6e19c;--slide-syntax-number:#d9afff;--slide-syntax-function:#8ed9e0;--slide-syntax-operator:#fff4ed;--slide-syntax-punctuation:#e0bdc3;--slide-syntax-name:#fff4ed;--slide-syntax-variable:#fff4ed;--slide-syntax-symbol:#8ed9e0;--slide-syntax-builtin:#8ed9e0;--slide-syntax-constant:#d9afff;--slide-syntax-error:#ff8176;--slide-highlight:#ff7a682e;--slide-focus:#ffb09a;--slide-selection:#ff7a6847;--slide-grid-line:#ffe5dc11;--slide-spotlight:#ff7a6829;--slide-gradient-start:#3a1828;--slide-gradient-end:#210f18;--slide-link:#8ed9e0;--slide-quote:#f1c7c9;--slide-dot-close:#f07769;--slide-dot-minimize:#dca25a;--slide-dot-maximize:#71b587;--slide-heading-font-size:72px;--slide-title-font-size:108px;--slide-body-font-size:44px;--slide-statement-font-size:88px;--slide-code-font-size:38px;--slide-code-highlight-surface:#ff7a681a;--slide-code-highlight-border:#ff7a68;--slide-code-focus-surface:#ffb09a1a;--slide-code-inset:#ffffff0f;--slide-surface-shine:#ffffff0f}*{box-sizing:border-box}::selection{background:var(--slide-selection);color:var(--slide-fg)}html,body{min-height:100%;margin:0}body{background:var(--slide-bg);color:var(--slide-fg);font-family:var(--font-slide-sans);font-synthesis:none;text-rendering:optimizelegibility;font-weight:400}.presentation-root{background:var(--slide-bg);min-height:100dvh;color:var(--slide-fg)}.presentation-root:not(.js) .slide-deck{flex-direction:column;align-items:center;gap:2rem;width:100%;height:auto;min-height:0;padding:2rem;display:flex;overflow:visible}.presentation-root:not(.js) .slide{width:min(100%, var(--slide-canvas-width));aspect-ratio:16/9;height:auto;position:relative;overflow:visible}.presentation-root:not(.js) .slide-content{height:auto;min-height:0}.presentation-root.js .slide-deck{flex-direction:column;align-items:center;gap:2rem;width:100%;height:auto;min-height:0;padding:2rem;display:flex;overflow:visible}.presentation-root.js .slide{width:min(100%, var(--slide-canvas-width));aspect-ratio:16/9;height:auto;position:relative;overflow:visible}.presentation-root.js .slide-content{height:auto;min-height:0}.slide-deck{isolation:isolate;width:100vw;height:100dvh;min-height:0;position:relative;container-type:size}.slide{width:var(--slide-canvas-width);height:var(--slide-canvas-height);aspect-ratio:16/9;color:var(--slide-fg);background:var(--slide-bg);position:relative;overflow:hidden}@supports (width:1cqw) and (height:1cqh) and (transform:scale(tan(atan2(1px, 1px)))){.presentation-root.js{width:100vw;height:100dvh;min-height:0;overflow:hidden}.presentation-root.js .slide-deck{place-items:center;gap:0;width:100%;height:100%;min-height:0;padding:0;display:grid;overflow:hidden;container-type:size}.presentation-root.js .slide{--slide-scale:min(tan(atan2(100cqw, 1920px)), tan(atan2(100cqh, 1080px)));width:var(--slide-canvas-width);height:var(--slide-canvas-height);transform:translate(-50%, -50%) scale(var(--slide-scale,1));transform-origin:50%;margin:0;position:absolute;inset:50% auto auto 50%;overflow:hidden}.presentation-root.js .slide-content{height:100%}.presentation-root.js:not(.is-overview) .slide:not(.is-active),.presentation-root.js[data-overview-active=false] .slide:not(.is-active){visibility:hidden;pointer-events:none}}@supports (transform:scale(abs(-1))){.presentation-root.js .slide{--slide-scale:min(abs(tan(atan2(100cqw, 1920px))), abs(tan(atan2(100cqh, 1080px))))}}.slide-content{z-index:1;flex-direction:column;width:100%;height:100%;padding:108px 132px 100px;display:flex;position:relative}:where(.prose,.layout-split-code .pane){max-width:100%;font-size:var(--slide-body-font-size);letter-spacing:0;line-height:1.4}:where(.prose,.layout-split-code .pane) :where(h1,h2,h3,h4){letter-spacing:-.012em;text-wrap:balance;max-width:16ch;margin:0 0 32px;line-height:1.12}:where(.prose,.layout-split-code .pane) :where(h1,h2){font-size:var(--slide-heading-font-size);font-weight:600}:where(.prose,.layout-split-code .pane) h3{font-size:56px;font-weight:600}:where(.prose,.layout-split-code .pane) h4{font-size:44px;font-weight:600}:where(.prose,.layout-split-code .pane) p{max-width:40ch;margin:0 0 28px}:where(.prose,.layout-split-code .pane) strong{color:var(--slide-accent-strong);font-weight:700}:where(.prose,.layout-split-code .pane) em{color:var(--slide-quote)}:where(.prose,.layout-split-code .pane) a{color:var(--slide-link);text-underline-offset:6px;text-decoration:underline;text-decoration-thickness:3px}:where(.prose,.layout-split-code .pane) :where(ul,ol){max-width:34ch;margin:0 0 28px;padding-inline-start:1.25em}:where(.prose,.layout-split-code .pane) ul{list-style-type:disc}:where(.prose,.layout-split-code .pane) ol{list-style-type:decimal}:where(.prose,.layout-split-code .pane) ul ul{list-style-type:circle}:where(.prose,.layout-split-code .pane) ol ol{list-style-type:lower-alpha}:where(.prose,.layout-split-code .pane) li{margin-block:.25em;padding-inline-start:.2em}:where(.prose,.layout-split-code .pane) li::marker{color:var(--slide-accent)}:where(.prose,.layout-split-code .pane) code:not(pre code){border:1px solid var(--slide-code-border);background:var(--slide-code-surface);color:var(--slide-accent-strong);font-family:var(--font-slide-mono);font-variant-ligatures:none;border-radius:8px;padding:.12em .28em;font-size:.95em}:where(.prose,.layout-split-code .pane) blockquote{border-inline-start:6px solid var(--slide-accent);max-width:34ch;color:var(--slide-quote);margin:0 0 28px;padding:12px 28px;font-style:italic}:where(.prose,.layout-split-code .pane) img{object-fit:contain;border-radius:20px;max-width:100%;max-height:520px;display:block}:where(.prose,.layout-split-code .pane) table{border-collapse:collapse;margin-block:16px 28px;font-size:1em}:where(.prose,.layout-split-code .pane) th,:where(.prose,.layout-split-code .pane) td{border-bottom:2px solid var(--slide-code-border);text-align:start;padding:12px 20px}:where(.prose,.layout-split-code .pane) th{color:var(--slide-accent-strong);font-weight:700}.visually-hidden{clip:rect(0 0 0 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.slide{isolation:isolate}.slide:before,.slide:after{content:none;pointer-events:none;position:absolute}.slide:before{z-index:0;background:var(--slide-bg);inset:0}.bg-plain:before{content:"";background:var(--slide-bg)}.bg-gradient:before{content:"";background:linear-gradient(135deg, var(--slide-gradient-start), var(--slide-gradient-end) 64%)}.bg-grid:before{content:"";background-color:var(--slide-bg);background-image:linear-gradient(var(--slide-grid-line) 1px, transparent 1px), linear-gradient(90deg, var(--slide-grid-line) 1px, transparent 1px);background-size:72px 72px}.bg-spotlight:before{content:"";background:radial-gradient(circle at 70% 18%, var(--slide-spotlight), transparent 42%), var(--slide-bg)}.bg-gradient:after,.bg-grid:after,.bg-spotlight:after{content:"";z-index:0;background:var(--slide-spotlight);filter:blur(90px);opacity:.5;border-radius:50%;width:70%;height:70%;top:-28%;right:-12%}.layout-title .slide-content{justify-content:center;padding-inline:180px}.layout-title .prose h1{max-width:12ch;font-size:var(--slide-title-font-size)}.layout-title .prose p{max-width:28ch;color:var(--slide-muted)}.layout-statement .slide-content{justify-content:center;padding-inline:180px}.layout-statement .prose{font-size:var(--slide-statement-font-size);letter-spacing:-.012em;line-height:1.12}.layout-statement .prose :where(h1,h2){font-size:var(--slide-statement-font-size);margin-block-end:36px;line-height:1.12}.layout-statement .prose p{font-size:var(--slide-body-font-size);letter-spacing:0;max-width:20ch;line-height:1.4}.layout-content .slide-content{justify-content:center}.layout-content .prose{max-width:920px}.layout-code .slide-content{justify-content:center;gap:50px}.layout-code .prose{flex:none}.visual,.stack{flex-direction:column;min-height:0;display:flex}.layout-code .visual{width:100%;max-width:none;min-height:0;margin-inline:auto}.layout-code-left .slide-content,.layout-code-right .slide-content,.layout-split-code .slide-content{justify-content:center}.panes{grid-template-rows:minmax(0,1fr);grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:center;gap:72px;width:100%;min-height:0;display:grid}.layout-code-left .panes{grid-template-columns:minmax(0,1.55fr) minmax(0,1fr)}.layout-code-right .panes{grid-template-columns:minmax(0,1fr) minmax(0,1.55fr)}.pane{min-width:0;min-height:0;max-height:100%}.pane.prose{max-width:640px}.layout-split-code .panes{align-items:stretch}.layout-split-code .pane{flex-direction:column;min-width:0;display:flex}.layout-split-code .pane>ul>li::marker{color:var(--slide-accent)}.layout-split-code .pane>ol>li::marker{color:var(--slide-accent)}.layout-code-result .slide-content{justify-content:center;gap:24px}.layout-code-result .prose{flex:none}.layout-code-result .prose :where(h1,h2){max-width:24ch}.layout-code-result .prose p{margin-bottom:16px}.layout-code-result .stack{flex-direction:column;gap:24px;min-height:0;display:flex}.stack{min-width:0}@media (max-width:900px){.presentation-root:not(.js) .slide-content{padding:clamp(24px,6vw,56px)}.presentation-root:not(.js) :is(.prose,.pane) :where(h1,h2){font-size:clamp(32px,7vw,64px)}.presentation-root:not(.js) :is(.prose,.pane) :where(h3,h4){font-size:clamp(26px,5vw,44px)}.presentation-root:not(.js) .prose{font-size:clamp(22px,4vw,40px)}.presentation-root:not(.js) .layout-code-left .panes,.presentation-root:not(.js) .layout-code-right .panes,.presentation-root:not(.js) .layout-split-code .panes{grid-template-columns:1fr;gap:40px}}@supports not ((width:1cqw) and (height:1cqh) and (transform:scale(tan(atan2(1px, 1px))))){@media (max-width:900px){.presentation-root.js .slide-content{padding:56px}.presentation-root.js .prose h1{font-size:clamp(48px,9vw,88px)}.presentation-root.js .prose{font-size:clamp(22px,4vw,40px)}.presentation-root.js .layout-code-left .panes,.presentation-root.js .layout-code-right .panes,.presentation-root.js .layout-split-code .panes{grid-template-columns:1fr;gap:40px}}}@supports (width:1cqw) and (height:1cqh) and (transform:scale(tan(atan2(1px, 1px)))){.presentation-root.js.is-overview .slide-deck,.presentation-root.js[data-overview-active=true] .slide-deck{grid-template-columns:repeat(auto-fit,minmax(min(360px,42vw),1fr));grid-auto-rows:max-content;align-content:start;align-items:start;gap:32px;padding:112px 48px 56px;display:grid;overflow:auto}.presentation-root.js.is-overview .slide,.presentation-root.js[data-overview-active=true] .slide{aspect-ratio:16/9;visibility:visible;border:2px solid var(--slide-code-border);width:100%;min-width:0;height:auto;box-shadow:0 12px 28px var(--slide-code-shadow);cursor:pointer;border-radius:16px;margin:0;position:relative;inset:auto;overflow:hidden;transform:none;container-type:inline-size}.presentation-root.js.is-overview .slide.is-active,.presentation-root.js[data-overview-active=true] .slide.is-active{border-color:var(--slide-accent);box-shadow:0 0 0 4px var(--slide-highlight), 0 12px 28px var(--slide-code-shadow)}.presentation-root.js.is-overview .slide-content,.presentation-root.js[data-overview-active=true] .slide-content{--overview-slide-scale:tan(atan2(100cqw, 1920px));width:1920px;height:1080px;transform:scale(var(--overview-slide-scale,1));transform-origin:0 0;padding:108px 132px 100px}.presentation-root.js.is-overview .slide:focus-visible,.presentation-root.js[data-overview-active=true] .slide:focus-visible{outline:5px solid var(--slide-focus);outline-offset:6px}}@supports (transform:scale(abs(-1))){.presentation-root.js.is-overview .slide-content,.presentation-root.js[data-overview-active=true] .slide-content{--overview-slide-scale:abs(tan(atan2(100cqw, 1920px)))}}.code-window,.terminal-window{border:2px solid var(--slide-code-border);min-width:0;min-height:0;max-height:100%;position:relative;overflow:hidden}@supports (color:color-mix(in lab, red, red)){.code-window,.terminal-window{border:2px solid color-mix(in srgb, var(--slide-code-border), transparent 15%)}}.code-window,.terminal-window{border-radius:var(--slide-radius);background:var(--slide-code-surface);box-shadow:0 24px 60px var(--slide-code-shadow), inset 0 1px 0 var(--slide-code-inset);font-family:var(--font-slide-mono);font-size:var(--slide-code-font-size);font-variant-ligatures:none;flex-direction:column;font-weight:450;line-height:1.45;display:flex}.code-window figcaption,.terminal-window figcaption{z-index:2;max-width:70%;color:var(--slide-muted);font-family:var(--font-slide-sans);letter-spacing:.015em;text-overflow:ellipsis;white-space:nowrap;font-size:28px;font-weight:500;position:absolute;top:16px;left:50%;overflow:hidden;transform:translate(-50%)}.code-window-header,.terminal-window:before{border-bottom:2px solid var(--slide-code-border);background:var(--slide-code-header);flex:0 0 72px;align-items:center;height:72px;padding:0 28px;display:flex}.code-window-controls{gap:10px;display:flex}.code-window-controls i{background:var(--slide-muted);opacity:.65;border-radius:50%;width:14px;height:14px;display:block}.code-window-controls i:first-child{background:var(--slide-dot-close)}.code-window-controls i:nth-child(2){background:var(--slide-dot-minimize)}.code-window-controls i:last-child{background:var(--slide-dot-maximize)}.code-window figcaption{max-width:min(50%,max(0px,100% - 224px))}.code-window-language{max-width:max(0px,25% - 40px);color:var(--slide-muted);letter-spacing:.04em;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap;margin-inline-start:auto;font-size:24px;overflow:hidden}.code-window pre,.terminal-window pre{tab-size:2;scrollbar-width:thin;scrollbar-color:var(--slide-muted) transparent;min-height:0;margin:0;padding:32px 34px 36px;font-family:inherit;overflow:auto}.code-window code,.terminal-window code{color:var(--slide-fg);font:inherit;display:block}.code-window .line{white-space:pre;border-inline-start:4px solid #0000;min-height:1.45em;padding-inline:16px 20px;display:block}.code-window .line:before{content:attr(data-line-number);width:2.2em;color:var(--slide-muted);text-align:end;-webkit-user-select:none;user-select:none;margin-inline-end:.8em;font-size:.8em;display:inline-block}.code-window .line:not([data-line-number]):before{content:none}.code-window .line.is-highlighted{border-inline-start-color:var(--slide-code-highlight-border);background:var(--slide-code-highlight-surface)}.code-window.has-focus .line.is-focused{border-inline-start-color:var(--slide-focus);background:var(--slide-code-focus-surface);opacity:1}.code-window .hll,.code-window .highlight{background:var(--slide-code-highlight-surface)}.code-window .c,.code-window .ch,.code-window .cm,.code-window .c1,.code-window .cs{color:var(--slide-syntax-comment)}.code-window .k,.code-window .kd,.code-window .kn,.code-window .kp,.code-window .kr,.code-window .kt{color:var(--slide-syntax-keyword)}.code-window .s,.code-window .sa,.code-window .sb,.code-window .sc,.code-window .dl,.code-window .sd,.code-window .s1,.code-window .s2{color:var(--slide-syntax-string)}.code-window .m,.code-window .mb,.code-window .mf,.code-window .mh,.code-window .mi,.code-window .mo{color:var(--slide-syntax-number)}.code-window .nf,.code-window .fm,.code-window .nd{color:var(--slide-syntax-function)}:is(.highlighter-rouge,figure.highlight) .c,:is(.highlighter-rouge,figure.highlight) .ch,:is(.highlighter-rouge,figure.highlight) .cm,:is(.highlighter-rouge,figure.highlight) .c1,:is(.highlighter-rouge,figure.highlight) .cs{color:var(--slide-syntax-comment)}:is(.highlighter-rouge,figure.highlight) .k,:is(.highlighter-rouge,figure.highlight) .kd,:is(.highlighter-rouge,figure.highlight) .kn,:is(.highlighter-rouge,figure.highlight) .kp,:is(.highlighter-rouge,figure.highlight) .kr,:is(.highlighter-rouge,figure.highlight) .kt{color:var(--slide-syntax-keyword)}:is(.highlighter-rouge,figure.highlight) .s,:is(.highlighter-rouge,figure.highlight) .sa,:is(.highlighter-rouge,figure.highlight) .sb,:is(.highlighter-rouge,figure.highlight) .sc,:is(.highlighter-rouge,figure.highlight) .dl,:is(.highlighter-rouge,figure.highlight) .sd,:is(.highlighter-rouge,figure.highlight) .s1,:is(.highlighter-rouge,figure.highlight) .s2{color:var(--slide-syntax-string)}:is(.highlighter-rouge,figure.highlight) .m,:is(.highlighter-rouge,figure.highlight) .mb,:is(.highlighter-rouge,figure.highlight) .mf,:is(.highlighter-rouge,figure.highlight) .mh,:is(.highlighter-rouge,figure.highlight) .mi,:is(.highlighter-rouge,figure.highlight) .mo{color:var(--slide-syntax-number)}:is(.highlighter-rouge,figure.highlight) .nf,:is(.highlighter-rouge,figure.highlight) .fm,:is(.highlighter-rouge,figure.highlight) .nd{color:var(--slide-syntax-function)}.code-window .o,.code-window .ow,:is(.highlighter-rouge,figure.highlight) .o,:is(.highlighter-rouge,figure.highlight) .ow{color:var(--slide-syntax-operator)}.code-window .p,:is(.highlighter-rouge,figure.highlight) .p{color:var(--slide-syntax-punctuation)}.code-window .n,.code-window .na,.code-window .nv,.code-window .vc,.code-window .vg,.code-window .vi,.code-window .py,:is(.highlighter-rouge,figure.highlight) .n,:is(.highlighter-rouge,figure.highlight) .na,:is(.highlighter-rouge,figure.highlight) .nv,:is(.highlighter-rouge,figure.highlight) .vc,:is(.highlighter-rouge,figure.highlight) .vg,:is(.highlighter-rouge,figure.highlight) .vi,:is(.highlighter-rouge,figure.highlight) .py{color:var(--slide-syntax-name)}.code-window .nv,.code-window .vc,.code-window .vg,.code-window .vi,:is(.highlighter-rouge,figure.highlight) .nv,:is(.highlighter-rouge,figure.highlight) .vc,:is(.highlighter-rouge,figure.highlight) .vg,:is(.highlighter-rouge,figure.highlight) .vi{color:var(--slide-syntax-variable)}.code-window .x,.code-window .sx,.code-window .ni,.code-window .nl,.code-window .nt,:is(.highlighter-rouge,figure.highlight) .x,:is(.highlighter-rouge,figure.highlight) .sx,:is(.highlighter-rouge,figure.highlight) .ni,:is(.highlighter-rouge,figure.highlight) .nl,:is(.highlighter-rouge,figure.highlight) .nt,.code-window .ss,.code-window .sh,.code-window .si,.code-window .sr,:is(.highlighter-rouge,figure.highlight) .ss,:is(.highlighter-rouge,figure.highlight) .sh,:is(.highlighter-rouge,figure.highlight) .si,:is(.highlighter-rouge,figure.highlight) .sr{color:var(--slide-syntax-symbol)}.code-window .kv,.code-window .kc,.code-window .cp,.code-window .cd,.code-window .pi,:is(.highlighter-rouge,figure.highlight) .kv,:is(.highlighter-rouge,figure.highlight) .kc,:is(.highlighter-rouge,figure.highlight) .cp,:is(.highlighter-rouge,figure.highlight) .cd,:is(.highlighter-rouge,figure.highlight) .pi{color:var(--slide-syntax-keyword)}.code-window .il,:is(.highlighter-rouge,figure.highlight) .il{color:var(--slide-syntax-number)}.code-window .nb,.code-window .bp,:is(.highlighter-rouge,figure.highlight) .nb,:is(.highlighter-rouge,figure.highlight) .bp{color:var(--slide-syntax-builtin)}.code-window .nc,.code-window .no,.code-window .ne,.code-window .nn,.code-window .nx,:is(.highlighter-rouge,figure.highlight) .nc,:is(.highlighter-rouge,figure.highlight) .no,:is(.highlighter-rouge,figure.highlight) .ne,:is(.highlighter-rouge,figure.highlight) .nn,:is(.highlighter-rouge,figure.highlight) .nx{color:var(--slide-syntax-constant)}.code-window .err,:is(.highlighter-rouge,figure.highlight) .err{color:var(--slide-syntax-error);-webkit-text-decoration:wavy underline var(--slide-syntax-error);-webkit-text-decoration:wavy underline var(--slide-syntax-error);text-decoration:wavy underline var(--slide-syntax-error);text-underline-offset:4px}.highlighter-rouge,figure.highlight{min-width:0;font-family:var(--font-slide-mono)}.highlighter-rouge .highlight,figure.highlight{border:1px solid var(--slide-code-border);background:var(--slide-code-surface);box-shadow:inset 0 1px 0 var(--slide-code-inset);font-size:var(--slide-code-font-size);font-variant-ligatures:none;scrollbar-width:thin;scrollbar-color:var(--slide-muted) transparent;border-radius:16px;font-weight:450;line-height:1.45;overflow:auto}.highlighter-rouge pre,figure.highlight pre{margin:0;padding:28px 32px}.highlighter-rouge code,figure.highlight code{color:var(--slide-fg);font:inherit}.code-window.size-sm,.terminal-window.size-sm{font-size:32px}.code-window.size-md,.terminal-window.size-md{font-size:38px}.code-window.size-lg,.terminal-window.size-lg{font-size:42px}.code-window.size-sm .code-window-header,.terminal-window.size-sm:before{flex-basis:62px;height:62px}.code-window.size-lg .code-window-header,.terminal-window.size-lg:before{flex-basis:82px;height:82px}.terminal-window{background:var(--slide-code-surface)}.terminal-window:before{content:"";background:var(--slide-code-header)}.terminal-window pre{padding-top:28px}.terminal-window .tline{white-space:pre-wrap;min-height:1.45em;display:block}.terminal-window .prompt{color:var(--slide-accent-strong);font-weight:700}.terminal-window .cmd{color:var(--slide-link)}.terminal-window .tline:not(:has(.prompt)):not(:has(.cmd)){color:var(--slide-fg)}.presentation-chrome{z-index:20;color:var(--slide-muted);pointer-events:none;position:fixed;inset:0}.presentation-root:not(.js) .presentation-chrome{visibility:hidden;pointer-events:none}.slide-controls{pointer-events:auto;background:0 0;border:1px solid #0000;border-radius:12px;align-items:center;gap:8px;padding:8px;transition:background .2s,border-color .2s;display:flex;position:absolute;bottom:16px;right:24px}.slide-controls:hover,.slide-controls:focus-within{border-color:var(--slide-code-border);background:var(--slide-bg)}@supports (color:color-mix(in lab, red, red)){.slide-controls:hover,.slide-controls:focus-within{background:color-mix(in srgb, var(--slide-bg), transparent 12%)}}.slide-controls:hover,.slide-controls:focus-within{-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.slide-control{border:1px solid var(--slide-code-border);width:46px;height:38px;color:var(--slide-fg);cursor:pointer;font:inherit;opacity:0;pointer-events:none;background:0 0;border-radius:9px;place-items:center;line-height:1;transition:background .2s,color .2s,border-color .2s,opacity .2s,transform .2s;display:inline-grid;transform:translateY(4px)}.slide-controls:hover .slide-control,.slide-controls:focus-within .slide-control{opacity:1;pointer-events:auto;transform:none}.slide-control:hover{border-color:var(--slide-accent);background:var(--slide-highlight);color:var(--slide-accent-strong)}.slide-controls:hover .slide-control:disabled,.slide-controls:focus-within .slide-control:disabled{opacity:.35;cursor:default}.slide-counter{font-family:var(--font-slide-mono);letter-spacing:.04em;margin:0;font-size:17px}.slide-progress{width:100%;height:4px;accent-color:var(--slide-accent);opacity:.58;pointer-events:auto;position:absolute;bottom:0;left:0;right:0}.slide-progress::-webkit-progress-bar{background:var(--slide-code-border);border-radius:99px}.slide-progress::-webkit-progress-value{background:var(--slide-accent);border-radius:99px}.overview-hint{z-index:25;border:1px solid var(--slide-code-border);background:var(--slide-code-surface);color:var(--slide-muted);font-family:var(--font-slide-mono);border-radius:999px;margin:0;padding:10px 18px;font-size:14px;position:fixed;top:82px;left:50%;transform:translate(-50%)}.overview-hint[hidden]{display:none}.presentation-root.js.is-fullscreen .presentation-chrome,.presentation-root.js[data-fullscreen-active=true] .presentation-chrome{opacity:0;transition:opacity .35s}.presentation-root.js.is-fullscreen .presentation-chrome:hover,.presentation-root.js.is-fullscreen .presentation-chrome:focus-within,.presentation-root.js[data-fullscreen-active=true] .presentation-chrome:hover,.presentation-root.js[data-fullscreen-active=true] .presentation-chrome:focus-within{opacity:1}.slide-control:focus-visible,.slide-progress:focus-visible{outline:4px solid var(--slide-focus);outline-offset:4px}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:0s!important;animation-duration:0s!important;animation-iteration-count:1!important}}.presentation-root.is-reduced-motion .presentation-chrome,.presentation-root[data-reduced-motion=true] .presentation-chrome{transition:none}@page{size:13.333in 7.5in;margin:0}@media print{*,:before,:after{transition:none!important;animation:none!important}html,body{width:13.333in;min-width:13.333in;background:var(--slide-bg)!important}body{-webkit-print-color-adjust:exact;print-color-adjust:exact}.presentation-root,.presentation-root.js{width:13.333in!important;height:auto!important;min-height:0!important;overflow:visible!important}.presentation-chrome,.slide-progress,.overview-hint{display:none!important}.slide-deck,.presentation-root.js .slide-deck,.presentation-root.js.is-overview .slide-deck{width:13.333in!important;height:auto!important;min-height:0!important;padding:0!important;display:block!important;position:static!important;overflow:visible!important}.slide,.presentation-root.js .slide,.presentation-root.js.is-overview .slide{break-after:page;page-break-after:always;min-height:0;visibility:visible!important;width:13.333in!important;height:7.5in!important;box-shadow:none!important;cursor:default!important;border:0!important;border-radius:0!important;margin:0!important;display:block!important;position:relative!important;inset:auto!important;overflow:hidden!important;transform:none!important}.slide:last-child{break-after:auto;page-break-after:auto}.slide-content,.presentation-root.js.is-overview .slide-content{transform-origin:0 0;width:1920px!important;height:1080px!important;transform:scale(.66665)!important}.code-window .line,.terminal-window .tline{opacity:1!important}}
|
|
2
|
+
@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--font-slide-sans:"Atkinson Hyperlegible Next", "Avenir Next", "Segoe UI Variable", "Segoe UI", system-ui, sans-serif;--font-slide-mono:"Atkinson Hyperlegible Mono", "JetBrains Mono", "SFMono-Regular", Consolas, monospace;--slide-canvas-width:1920px;--slide-canvas-height:1080px;--slide-pad-block:72px;--slide-pad-inline:80px;--slide-radius:28px}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.block{display:block}.grid{display:grid}.hidden{display:none}}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-weight:200 800;font-display:swap;src:url(../fonts/atkinson-hyperlegible-next.woff2)format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:italic;font-weight:200 800;font-display:swap;src:url(../fonts/atkinson-hyperlegible-next-italic.woff2)format("woff2")}@font-face{font-family:Atkinson Hyperlegible Mono;font-style:normal;font-weight:200 800;font-display:swap;src:url(../fonts/atkinson-hyperlegible-mono.woff2)format("woff2")}@font-face{font-family:Atkinson Hyperlegible Mono;font-style:italic;font-weight:200 800;font-display:swap;src:url(../fonts/atkinson-hyperlegible-mono-italic.woff2)format("woff2")}:root{--slide-dot-close:#ff5f57;--slide-dot-minimize:#febc2e;--slide-dot-maximize:#28c840;--slide-dot-rim:#00000029}:root,[data-theme=midnight],[data-code-theme=midnight]{--slide-fg:#f3f5f8;--slide-muted:#b4bdca;--slide-accent:#ff6b4a;--slide-accent-strong:#ff8a65;--slide-code-surface:#151b26;--slide-code-header:#1c2532;--slide-code-border:#364354;--slide-code-shadow:#0000006b;--slide-syntax-comment:#aab5c5;--slide-syntax-keyword:#ff9e7a;--slide-syntax-string:#b8d98e;--slide-syntax-number:#c6a9ff;--slide-syntax-function:#75c9db;--slide-syntax-operator:#f3f5f8;--slide-syntax-punctuation:#b9c4d2;--slide-syntax-name:#f3f5f8;--slide-syntax-variable:#f3f5f8;--slide-syntax-symbol:#75c9db;--slide-syntax-builtin:#75c9db;--slide-syntax-constant:#c6a9ff;--slide-syntax-error:#ff8675;--slide-highlight:#ff6b4a2b;--slide-focus:#ff9e7a;--slide-link:#9edbea;--slide-code-font-size:38px;--slide-code-highlight-surface:#ff6b4a1a;--slide-code-highlight-border:#ff6b4a;--slide-code-focus-surface:#ff9e7a1a}:root,[data-theme=midnight]{--slide-bg:#10141d;--slide-selection:#ff6b4a47;--slide-grid-line:#ffffff0e;--slide-spotlight:#ff6b4a26;--slide-gradient-start:#191d2c;--slide-gradient-end:#10141d;--slide-quote:#c8d1dc;--slide-heading-font-size:72px;--slide-title-font-size:108px;--slide-body-font-size:44px;--slide-statement-font-size:88px}[data-theme=minimal-light],[data-code-theme=minimal-light]{--slide-fg:#1c2027;--slide-muted:#4d5660;--slide-accent:#bc3e27;--slide-accent-strong:#8d2919;--slide-code-surface:#f0f0f0;--slide-code-header:#e6e6e6;--slide-code-border:#d2d2d2;--slide-code-shadow:#18181a29;--slide-syntax-comment:#50564f;--slide-syntax-keyword:#9d3e28;--slide-syntax-string:#325c35;--slide-syntax-number:#6b4ca0;--slide-syntax-function:#12586a;--slide-syntax-operator:#343b45;--slide-syntax-punctuation:#4d5863;--slide-syntax-name:#1c2027;--slide-syntax-variable:#1c2027;--slide-syntax-symbol:#12586a;--slide-syntax-builtin:#12586a;--slide-syntax-constant:#6b4ca0;--slide-syntax-error:#a52121;--slide-highlight:#bc3e2721;--slide-focus:#9d3e28;--slide-link:#176d82;--slide-code-font-size:38px;--slide-code-highlight-surface:#bc3e2712;--slide-code-highlight-border:#bc3e27;--slide-code-focus-surface:#9d3e2812}[data-theme=minimal-light]{--slide-bg:#fafafa;--slide-selection:#bc3e2733;--slide-grid-line:#1c202714;--slide-spotlight:#bc3e271f;--slide-gradient-start:#fff;--slide-gradient-end:#efefef;--slide-quote:#424a54;--slide-heading-font-size:72px;--slide-title-font-size:96px;--slide-body-font-size:44px;--slide-statement-font-size:88px}[data-theme=minimal-dark],[data-code-theme=minimal-dark]{--slide-fg:#f4f1ea;--slide-muted:#bcb8b0;--slide-accent:#e6b566;--slide-accent-strong:#f2c57a;--slide-code-surface:#202020;--slide-code-header:#2b2b2a;--slide-code-border:#454441;--slide-code-shadow:#00000080;--slide-syntax-comment:#b2afa9;--slide-syntax-keyword:#f0bd75;--slide-syntax-string:#b8d094;--slide-syntax-number:#d1a9e8;--slide-syntax-function:#83ced1;--slide-syntax-operator:#f4f1ea;--slide-syntax-punctuation:#c5c1b9;--slide-syntax-name:#f4f1ea;--slide-syntax-variable:#f4f1ea;--slide-syntax-symbol:#83ced1;--slide-syntax-builtin:#83ced1;--slide-syntax-constant:#d1a9e8;--slide-syntax-error:#f28272;--slide-highlight:#e6b56629;--slide-focus:#f0bd75;--slide-link:#83ced1;--slide-code-font-size:38px;--slide-code-highlight-surface:#e6b5661a;--slide-code-highlight-border:#e6b566;--slide-code-focus-surface:#f0bd751a}[data-theme=minimal-dark]{--slide-bg:#171717;--slide-selection:#e6b56640;--slide-grid-line:#ffffff0f;--slide-spotlight:#e6b56621;--slide-gradient-start:#25221e;--slide-gradient-end:#171717;--slide-quote:#d3cec4;--slide-heading-font-size:72px;--slide-title-font-size:108px;--slide-body-font-size:44px;--slide-statement-font-size:88px}[data-theme=ruby],[data-code-theme=ruby]{--slide-fg:#fff4ed;--slide-muted:#dfbcc3;--slide-accent:#ff7a68;--slide-accent-strong:#ffb09a;--slide-code-surface:#2a1520;--slide-code-header:#3a1c2a;--slide-code-border:#613348;--slide-code-shadow:#0a020780;--slide-syntax-comment:#cba8b0;--slide-syntax-keyword:#ff9f80;--slide-syntax-string:#c6e19c;--slide-syntax-number:#d9afff;--slide-syntax-function:#8ed9e0;--slide-syntax-operator:#fff4ed;--slide-syntax-punctuation:#e0bdc3;--slide-syntax-name:#fff4ed;--slide-syntax-variable:#fff4ed;--slide-syntax-symbol:#8ed9e0;--slide-syntax-builtin:#8ed9e0;--slide-syntax-constant:#d9afff;--slide-syntax-error:#ff8176;--slide-highlight:#ff7a682e;--slide-focus:#ffb09a;--slide-link:#8ed9e0;--slide-code-font-size:38px;--slide-code-highlight-surface:#ff7a681a;--slide-code-highlight-border:#ff7a68;--slide-code-focus-surface:#ffb09a1a}[data-theme=ruby]{--slide-bg:#210f18;--slide-selection:#ff7a6847;--slide-grid-line:#ffe5dc11;--slide-spotlight:#ff7a6829;--slide-gradient-start:#3a1828;--slide-gradient-end:#210f18;--slide-quote:#f1c7c9;--slide-heading-font-size:72px;--slide-title-font-size:108px;--slide-body-font-size:44px;--slide-statement-font-size:88px}[data-theme=catppuccin-latte],[data-code-theme=catppuccin-latte]{--slide-fg:#4c4f69;--slide-muted:#5b5e70;--slide-accent:#8839ef;--slide-accent-strong:#7d34dc;--slide-code-surface:#e6e9ef;--slide-code-header:#dce0e8;--slide-code-border:#bcc0cc;--slide-code-shadow:#4c4f6938;--slide-syntax-comment:#5b5e67;--slide-syntax-keyword:#7832d3;--slide-syntax-string:#2a6a1c;--slide-syntax-number:#a23f07;--slide-syntax-function:#1956d0;--slide-syntax-operator:#02658c;--slide-syntax-punctuation:#5b5e67;--slide-syntax-name:#4c4f69;--slide-syntax-variable:#4c4f69;--slide-syntax-symbol:#10696e;--slide-syntax-builtin:#b90d32;--slide-syntax-constant:#835311;--slide-syntax-error:#b90d32;--slide-highlight:#8839ef21;--slide-focus:#7d34dc;--slide-link:#1b5ee1;--slide-code-font-size:38px;--slide-code-highlight-surface:#8839ef12;--slide-code-highlight-border:#8839ef;--slide-code-focus-surface:#1e66f512}[data-theme=catppuccin-latte]{--slide-bg:#eff1f5;--slide-selection:#8839ef33;--slide-grid-line:#4c4f6914;--slide-spotlight:#8839ef1f;--slide-gradient-start:#fbfcfe;--slide-gradient-end:#eff1f5;--slide-quote:#5c5f77;--slide-heading-font-size:72px;--slide-title-font-size:108px;--slide-body-font-size:44px;--slide-statement-font-size:88px}[data-theme=catppuccin-frappe],[data-code-theme=catppuccin-frappe]{--slide-fg:#c6d0f5;--slide-muted:#acb3d1;--slide-accent:#ca9ee6;--slide-accent-strong:#babbf1;--slide-code-surface:#303446;--slide-code-header:#414559;--slide-code-border:#51576d;--slide-code-shadow:#2326348c;--slide-syntax-comment:#aeb4cb;--slide-syntax-keyword:#cea5e7;--slide-syntax-string:#a6d189;--slide-syntax-number:#efa27b;--slide-syntax-function:#99b3ef;--slide-syntax-operator:#99d1db;--slide-syntax-punctuation:#acb3d1;--slide-syntax-name:#c6d0f5;--slide-syntax-variable:#c6d0f5;--slide-syntax-symbol:#81c8be;--slide-syntax-builtin:#eba0a3;--slide-syntax-constant:#e5c890;--slide-syntax-error:#eca1a2;--slide-highlight:#ca9ee62b;--slide-focus:#babbf1;--slide-link:#99d1db;--slide-code-font-size:38px;--slide-code-highlight-surface:#ca9ee61f;--slide-code-highlight-border:#ca9ee6;--slide-code-focus-surface:#babbf11f}[data-theme=catppuccin-frappe]{--slide-bg:#292c3c;--slide-selection:#ca9ee647;--slide-grid-line:#c6d0f50f;--slide-spotlight:#ca9ee626;--slide-gradient-start:#414559;--slide-gradient-end:#292c3c;--slide-quote:#b5bfe2;--slide-heading-font-size:72px;--slide-title-font-size:108px;--slide-body-font-size:44px;--slide-statement-font-size:88px}[data-theme=catppuccin-macchiato],[data-code-theme=catppuccin-macchiato]{--slide-fg:#cad3f5;--slide-muted:#a5adcb;--slide-accent:#c6a0f6;--slide-accent-strong:#b7bdf8;--slide-code-surface:#24273a;--slide-code-header:#363a4f;--slide-code-border:#494d64;--slide-code-shadow:#1819268c;--slide-syntax-comment:#9fa5bf;--slide-syntax-keyword:#c6a0f6;--slide-syntax-string:#a6da95;--slide-syntax-number:#f5a97f;--slide-syntax-function:#8aadf4;--slide-syntax-operator:#91d7e3;--slide-syntax-punctuation:#a5adcb;--slide-syntax-name:#cad3f5;--slide-syntax-variable:#cad3f5;--slide-syntax-symbol:#8bd5ca;--slide-syntax-builtin:#ee99a0;--slide-syntax-constant:#eed49f;--slide-syntax-error:#ed8b9a;--slide-highlight:#c6a0f62b;--slide-focus:#b7bdf8;--slide-link:#91d7e3;--slide-code-font-size:38px;--slide-code-highlight-surface:#c6a0f61f;--slide-code-highlight-border:#c6a0f6;--slide-code-focus-surface:#b7bdf81f}[data-theme=catppuccin-macchiato]{--slide-bg:#1e2030;--slide-selection:#c6a0f647;--slide-grid-line:#cad3f50f;--slide-spotlight:#c6a0f626;--slide-gradient-start:#363a4f;--slide-gradient-end:#1e2030;--slide-quote:#b8c0e0;--slide-heading-font-size:72px;--slide-title-font-size:108px;--slide-body-font-size:44px;--slide-statement-font-size:88px}[data-theme=catppuccin-mocha],[data-code-theme=catppuccin-mocha]{--slide-fg:#cdd6f4;--slide-muted:#a6adc8;--slide-accent:#cba6f7;--slide-accent-strong:#b4befe;--slide-code-surface:#1e1e2e;--slide-code-header:#313244;--slide-code-border:#45475a;--slide-code-shadow:#11111b8c;--slide-syntax-comment:#979db5;--slide-syntax-keyword:#cba6f7;--slide-syntax-string:#a6e3a1;--slide-syntax-number:#fab387;--slide-syntax-function:#89b4fa;--slide-syntax-operator:#89dceb;--slide-syntax-punctuation:#a6adc8;--slide-syntax-name:#cdd6f4;--slide-syntax-variable:#cdd6f4;--slide-syntax-symbol:#94e2d5;--slide-syntax-builtin:#eba0ac;--slide-syntax-constant:#f9e2af;--slide-syntax-error:#f38ba8;--slide-highlight:#cba6f72b;--slide-focus:#b4befe;--slide-link:#89dceb;--slide-code-font-size:38px;--slide-code-highlight-surface:#cba6f71f;--slide-code-highlight-border:#cba6f7;--slide-code-focus-surface:#b4befe1f}[data-theme=catppuccin-mocha]{--slide-bg:#181825;--slide-selection:#cba6f747;--slide-grid-line:#cdd6f40f;--slide-spotlight:#cba6f726;--slide-gradient-start:#313244;--slide-gradient-end:#181825;--slide-quote:#bac2de;--slide-heading-font-size:72px;--slide-title-font-size:108px;--slide-body-font-size:44px;--slide-statement-font-size:88px}[data-code-theme=macos-light]{--slide-fg:#1d2025;--slide-muted:#565d66;--slide-accent:#2f6feb;--slide-accent-strong:#1f4fbf;--slide-link:#1f5fd0;--slide-code-surface:#fafafa;--slide-code-header:#eeeeef;--slide-code-border:#dcdcde;--slide-code-shadow:#14161a1f;--slide-syntax-comment:#5f6672;--slide-syntax-keyword:#7a3ec8;--slide-syntax-string:#216b32;--slide-syntax-number:#a5451c;--slide-syntax-function:#1f5fd0;--slide-syntax-operator:#2c3138;--slide-syntax-punctuation:#565d66;--slide-syntax-name:#1d2025;--slide-syntax-variable:#1d2025;--slide-syntax-symbol:#0a6a72;--slide-syntax-builtin:#0a6a72;--slide-syntax-constant:#8a4b12;--slide-syntax-error:#b3261e;--slide-highlight:#2f6feb1a;--slide-focus:#1f4fbf;--slide-code-font-size:38px;--slide-code-highlight-surface:#2f6feb12;--slide-code-highlight-border:#2f6feb;--slide-code-focus-surface:#1f4fbf1f}*{box-sizing:border-box}::selection{background:var(--slide-selection);color:var(--slide-fg)}html,body{min-height:100%;margin:0}body{background:var(--slide-bg);color:var(--slide-fg);font-family:var(--font-slide-sans);font-synthesis:none;text-rendering:optimizelegibility;font-weight:400}.presentation-root{background:var(--slide-bg);min-height:100dvh;color:var(--slide-fg)}.presentation-root:not(.js) .slide-deck{flex-direction:column;align-items:center;gap:2rem;width:100%;height:auto;min-height:0;padding:2rem;display:flex;overflow:visible}.presentation-root:not(.js) .slide{width:min(100%, var(--slide-canvas-width));aspect-ratio:16/9;height:auto;position:relative;overflow:visible}.presentation-root:not(.js) .slide-content{height:auto;min-height:0}.presentation-root.js .slide-deck{flex-direction:column;align-items:center;gap:2rem;width:100%;height:auto;min-height:0;padding:2rem;display:flex;overflow:visible}.presentation-root.js .slide{width:min(100%, var(--slide-canvas-width));aspect-ratio:16/9;height:auto;position:relative;overflow:visible}.presentation-root.js .slide-content{height:auto;min-height:0}.slide-deck{isolation:isolate;width:100vw;height:100dvh;min-height:0;position:relative;container-type:size}.slide{width:var(--slide-canvas-width);height:var(--slide-canvas-height);aspect-ratio:16/9;color:var(--slide-fg);background:var(--slide-bg);position:relative;overflow:hidden}@supports (width:1cqw) and (height:1cqh) and (transform:scale(tan(atan2(1px, 1px)))){.presentation-root.js{width:100vw;height:100dvh;min-height:0;overflow:hidden}.presentation-root.js .slide-deck{place-items:center;gap:0;width:100%;height:100%;min-height:0;padding:0;display:grid;overflow:hidden;container-type:size}.presentation-root.js .slide{--slide-scale:min(tan(atan2(100cqw, 1920px)), tan(atan2(100cqh, 1080px)));width:var(--slide-canvas-width);height:var(--slide-canvas-height);transform:translate(-50%, -50%) scale(var(--slide-scale,1));transform-origin:50%;margin:0;position:absolute;inset:50% auto auto 50%;overflow:hidden}.presentation-root.js .slide-content{height:100%}.presentation-root.js:not(.is-overview) .slide:not(.is-active),.presentation-root.js[data-overview-active=false] .slide:not(.is-active){visibility:hidden;pointer-events:none}}@supports (transform:scale(abs(-1))){.presentation-root.js .slide{--slide-scale:min(abs(tan(atan2(100cqw, 1920px))), abs(tan(atan2(100cqh, 1080px))))}}.slide-content{width:100%;height:100%;padding:var(--slide-pad-block) var(--slide-pad-inline);z-index:1;flex-direction:column;display:flex;position:relative}:where(.prose,.layout-split-code .pane){max-width:100%;font-size:var(--slide-body-font-size);letter-spacing:0;line-height:1.4}:where(.prose,.layout-split-code .pane) :where(h1,h2,h3,h4){letter-spacing:-.012em;text-wrap:balance;max-width:16ch;margin:0 0 32px;line-height:1.12}:where(.prose,.layout-split-code .pane) :where(h1,h2){font-size:var(--slide-heading-font-size);font-weight:600}:where(.prose,.layout-split-code .pane) h3{font-size:56px;font-weight:600}:where(.prose,.layout-split-code .pane) h4{font-size:44px;font-weight:600}:where(.prose,.layout-split-code .pane) p{max-width:40ch;margin:0 0 28px}:where(.prose,.layout-split-code .pane) strong{color:var(--slide-accent-strong);font-weight:700}:where(.prose,.layout-split-code .pane) em{color:var(--slide-quote)}:where(.prose,.layout-split-code .pane) a{color:var(--slide-link);text-underline-offset:6px;text-decoration:underline;text-decoration-thickness:3px}:where(.prose,.layout-split-code .pane) :where(ul,ol){max-width:34ch;margin:0 0 28px;padding-inline-start:1.25em}:where(.prose,.layout-split-code .pane) ul{list-style-type:disc}:where(.prose,.layout-split-code .pane) ol{list-style-type:decimal}:where(.prose,.layout-split-code .pane) ul ul{list-style-type:circle}:where(.prose,.layout-split-code .pane) ol ol{list-style-type:lower-alpha}:where(.prose,.layout-split-code .pane) li{margin-block:.25em;padding-inline-start:.2em}:where(.prose,.layout-split-code .pane) li::marker{color:var(--slide-accent)}:where(.prose,.layout-split-code .pane) code:not(pre code){border:1px solid var(--slide-code-border);background:var(--slide-code-surface);color:var(--slide-accent-strong);font-family:var(--font-slide-mono);font-variant-ligatures:none;border-radius:8px;padding:.12em .28em;font-size:.95em}:where(.prose,.layout-split-code .pane) blockquote{border-inline-start:6px solid var(--slide-accent);max-width:34ch;color:var(--slide-quote);margin:0 0 28px;padding:12px 28px;font-style:italic}:where(.prose,.layout-split-code .pane) img{object-fit:contain;border-radius:20px;max-width:100%;max-height:520px;display:block}:where(.prose,.layout-split-code .pane) table{border-collapse:collapse;margin-block:16px 28px;font-size:1em}:where(.prose,.layout-split-code .pane) th,:where(.prose,.layout-split-code .pane) td{border-bottom:2px solid var(--slide-code-border);text-align:start;padding:12px 20px}:where(.prose,.layout-split-code .pane) th{color:var(--slide-accent-strong);font-weight:700}:where(.prose,.layout-split-code .pane)>:is(pre,div.highlighter-rouge,figure)+*{margin-block-start:28px}.visually-hidden{clip:rect(0 0 0 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.slide{isolation:isolate}.slide:before,.slide:after{content:none;pointer-events:none;position:absolute}.slide:before{z-index:0;background:var(--slide-bg);inset:0}.bg-plain:before{content:"";background:var(--slide-bg)}.bg-gradient:before{content:"";background:linear-gradient(135deg, var(--slide-gradient-start), var(--slide-gradient-end) 64%)}.bg-grid:before{content:"";background-color:var(--slide-bg);background-image:linear-gradient(var(--slide-grid-line) 1px, transparent 1px), linear-gradient(90deg, var(--slide-grid-line) 1px, transparent 1px);background-size:72px 72px}.bg-spotlight:before{content:"";background:radial-gradient(circle at 70% 18%, var(--slide-spotlight), transparent 42%), var(--slide-bg)}.bg-gradient:after,.bg-grid:after,.bg-spotlight:after{content:"";z-index:0;background:var(--slide-spotlight);filter:blur(90px);opacity:.5;border-radius:50%;width:70%;height:70%;top:-28%;right:-12%}.layout-title .slide-content{justify-content:center}.layout-title .prose h1{max-width:12ch;font-size:var(--slide-title-font-size)}.layout-title .prose p{max-width:28ch;color:var(--slide-muted)}.layout-statement .slide-content{justify-content:center}.layout-statement .prose{font-size:var(--slide-statement-font-size);letter-spacing:-.012em;line-height:1.12}.layout-statement .prose :where(h1,h2){font-size:var(--slide-statement-font-size);margin-block-end:36px;line-height:1.12}.layout-statement .prose p{font-size:var(--slide-body-font-size);letter-spacing:0;max-width:20ch;line-height:1.4}.layout-content .slide-content{justify-content:center}.layout-content .prose{max-width:100%}.layout-code .slide-content{justify-content:center;gap:50px}.layout-code .prose{flex:none}.visual,.stack{flex-direction:column;min-height:0;display:flex}.layout-code .visual{width:100%;max-width:none;min-height:0;margin-inline:auto}.layout-code-left .slide-content,.layout-code-right .slide-content,.layout-split-code .slide-content{justify-content:center}.panes{grid-template-rows:minmax(0,1fr);grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:center;gap:72px;width:100%;min-height:0;display:grid}.layout-code-left .panes{grid-template-columns:minmax(0,1.55fr) minmax(0,1fr)}.layout-code-right .panes{grid-template-columns:minmax(0,1fr) minmax(0,1.55fr)}.pane{min-width:0;min-height:0;max-height:100%}.pane.prose{max-width:640px}.layout-split-code .panes{align-items:stretch}.layout-split-code .pane{flex-direction:column;min-width:0;display:flex}.layout-split-code .pane>ul>li::marker{color:var(--slide-accent)}.layout-split-code .pane>ol>li::marker{color:var(--slide-accent)}.layout-code-result .slide-content{justify-content:center;gap:24px}.layout-code-result .prose{flex:none}.layout-code-result .prose :where(h1,h2){max-width:24ch}.layout-code-result .prose p{margin-bottom:16px}.layout-code-result .stack{flex-direction:column;gap:24px;min-height:0;display:flex}.stack{min-width:0}@media (max-width:900px){.presentation-root:not(.js) .slide-content{padding:clamp(24px,6vw,56px)}.presentation-root:not(.js) :is(.prose,.pane) :where(h1,h2){font-size:clamp(32px,7vw,64px)}.presentation-root:not(.js) :is(.prose,.pane) :where(h3,h4){font-size:clamp(26px,5vw,44px)}.presentation-root:not(.js) .prose{font-size:clamp(22px,4vw,40px)}.presentation-root:not(.js) .layout-code-left .panes,.presentation-root:not(.js) .layout-code-right .panes,.presentation-root:not(.js) .layout-split-code .panes{grid-template-columns:1fr;gap:40px}}@supports not ((width:1cqw) and (height:1cqh) and (transform:scale(tan(atan2(1px, 1px))))){@media (max-width:900px){.presentation-root.js .slide-content{padding:56px}.presentation-root.js .prose h1{font-size:clamp(48px,9vw,88px)}.presentation-root.js .prose{font-size:clamp(22px,4vw,40px)}.presentation-root.js .layout-code-left .panes,.presentation-root.js .layout-code-right .panes,.presentation-root.js .layout-split-code .panes{grid-template-columns:1fr;gap:40px}}}@supports (width:1cqw) and (height:1cqh) and (transform:scale(tan(atan2(1px, 1px)))){.presentation-root.js.is-overview .slide-deck,.presentation-root.js[data-overview-active=true] .slide-deck{grid-template-columns:repeat(auto-fit,minmax(min(360px,42vw),1fr));grid-auto-rows:max-content;align-content:start;align-items:start;gap:32px;padding:112px 48px 56px;display:grid;overflow:auto}.presentation-root.js.is-overview .slide,.presentation-root.js[data-overview-active=true] .slide{aspect-ratio:16/9;visibility:visible;border:2px solid var(--slide-code-border);width:100%;min-width:0;height:auto;box-shadow:0 12px 28px var(--slide-code-shadow);cursor:pointer;border-radius:16px;margin:0;position:relative;inset:auto;overflow:hidden;transform:none;container-type:inline-size}.presentation-root.js.is-overview .slide.is-active,.presentation-root.js[data-overview-active=true] .slide.is-active{border-color:var(--slide-accent);box-shadow:0 0 0 4px var(--slide-highlight), 0 12px 28px var(--slide-code-shadow)}.presentation-root.js.is-overview .slide-content,.presentation-root.js[data-overview-active=true] .slide-content{--overview-slide-scale:tan(atan2(100cqw, 1920px));width:1920px;height:1080px;padding:var(--slide-pad-block) var(--slide-pad-inline);transform:scale(var(--overview-slide-scale,1));transform-origin:0 0}.presentation-root.js.is-overview .slide:focus-visible,.presentation-root.js[data-overview-active=true] .slide:focus-visible{outline:5px solid var(--slide-focus);outline-offset:6px}.presentation-root.js .fragment{transition:opacity .18s ease-out,transform .18s ease-out}.presentation-root.js .fragment:not(.is-revealed){visibility:hidden;opacity:0;transform:translateY(6px)}}@supports (transform:scale(abs(-1))){.presentation-root.js.is-overview .slide-content,.presentation-root.js[data-overview-active=true] .slide-content{--overview-slide-scale:abs(tan(atan2(100cqw, 1920px)))}}.code-window,.terminal-window{--slide-window-bar:72px;--slide-window-pad:28px;--slide-window-controls:calc(var(--slide-window-bar) * 1.28);border:1px solid var(--slide-code-border);border-radius:var(--slide-radius);background:var(--slide-code-surface);min-width:0;min-height:0;max-height:100%;box-shadow:0 12px 32px var(--slide-code-shadow);font-family:var(--font-slide-mono);font-size:var(--slide-code-font-size);font-variant-ligatures:none;flex-direction:column;font-weight:450;line-height:1.45;display:flex;position:relative;overflow:hidden}.code-window figcaption,.terminal-window figcaption{z-index:2;max-width:max(0px, calc(75% - var(--slide-window-pad) - var(--slide-window-controls) - 36px));height:var(--slide-window-bar);color:var(--slide-muted);font-family:var(--font-slide-sans);letter-spacing:.015em;font-size:28px;font-weight:500;line-height:var(--slide-window-bar);text-overflow:ellipsis;white-space:nowrap;top:0;position:absolute;inset-inline-start:calc(var(--slide-window-pad) + var(--slide-window-controls) + 24px);overflow:hidden}.code-window-header{height:var(--slide-window-bar);flex:0 0 var(--slide-window-bar);padding:0 var(--slide-window-pad);border-bottom:1px solid var(--slide-code-border);background:var(--slide-code-header);align-items:center;display:flex}.code-window-controls{gap:calc(var(--slide-window-bar) * .19);display:flex}.code-window-controls i{width:calc(var(--slide-window-bar) * .3);height:calc(var(--slide-window-bar) * .3);box-shadow:inset 0 0 0 1px var(--slide-dot-rim);border-radius:50%;display:block}.code-window-controls i:first-child{background:var(--slide-dot-close)}.code-window-controls i:nth-child(2){background:var(--slide-dot-minimize)}.code-window-controls i:last-child{background:var(--slide-dot-maximize)}.code-window-language{max-width:max(0px,25% - 40px);color:var(--slide-muted);letter-spacing:.04em;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap;margin-inline-start:auto;font-size:24px;overflow:hidden}.code-window pre,.terminal-window pre{tab-size:2;scrollbar-width:thin;scrollbar-color:var(--slide-muted) transparent;min-height:0;margin:0;padding:32px 34px 36px;font-family:inherit;overflow:auto}.code-window code,.terminal-window code{color:var(--slide-fg);font:inherit;display:block}.code-window .line{white-space:pre;border-inline-start:4px solid #0000;min-height:1.45em;padding-inline:16px 20px;display:block}.code-window .line:before{content:attr(data-line-number);width:2.2em;color:var(--slide-muted);text-align:end;-webkit-user-select:none;user-select:none;margin-inline-end:.8em;font-size:.8em;display:inline-block}.code-window .line:not([data-line-number]):before{content:none}.code-window .line.is-highlighted{border-inline-start-color:var(--slide-code-highlight-border);background:var(--slide-code-highlight-surface)}.code-window.has-focus .line.is-focused{border-inline-start-color:var(--slide-focus);background:var(--slide-code-focus-surface);opacity:1}.code-window .hll,.code-window .highlight{background:var(--slide-code-highlight-surface)}.code-window .c,.code-window .ch,.code-window .cm,.code-window .c1,.code-window .cs{color:var(--slide-syntax-comment)}.code-window .k,.code-window .kd,.code-window .kn,.code-window .kp,.code-window .kr,.code-window .kt{color:var(--slide-syntax-keyword)}.code-window .s,.code-window .sa,.code-window .sb,.code-window .sc,.code-window .dl,.code-window .sd,.code-window .s1,.code-window .s2{color:var(--slide-syntax-string)}.code-window .m,.code-window .mb,.code-window .mf,.code-window .mh,.code-window .mi,.code-window .mo{color:var(--slide-syntax-number)}.code-window .nf,.code-window .fm,.code-window .nd{color:var(--slide-syntax-function)}:is(.highlighter-rouge,figure.highlight) .c,:is(.highlighter-rouge,figure.highlight) .ch,:is(.highlighter-rouge,figure.highlight) .cm,:is(.highlighter-rouge,figure.highlight) .c1,:is(.highlighter-rouge,figure.highlight) .cs{color:var(--slide-syntax-comment)}:is(.highlighter-rouge,figure.highlight) .k,:is(.highlighter-rouge,figure.highlight) .kd,:is(.highlighter-rouge,figure.highlight) .kn,:is(.highlighter-rouge,figure.highlight) .kp,:is(.highlighter-rouge,figure.highlight) .kr,:is(.highlighter-rouge,figure.highlight) .kt{color:var(--slide-syntax-keyword)}:is(.highlighter-rouge,figure.highlight) .s,:is(.highlighter-rouge,figure.highlight) .sa,:is(.highlighter-rouge,figure.highlight) .sb,:is(.highlighter-rouge,figure.highlight) .sc,:is(.highlighter-rouge,figure.highlight) .dl,:is(.highlighter-rouge,figure.highlight) .sd,:is(.highlighter-rouge,figure.highlight) .s1,:is(.highlighter-rouge,figure.highlight) .s2{color:var(--slide-syntax-string)}:is(.highlighter-rouge,figure.highlight) .m,:is(.highlighter-rouge,figure.highlight) .mb,:is(.highlighter-rouge,figure.highlight) .mf,:is(.highlighter-rouge,figure.highlight) .mh,:is(.highlighter-rouge,figure.highlight) .mi,:is(.highlighter-rouge,figure.highlight) .mo{color:var(--slide-syntax-number)}:is(.highlighter-rouge,figure.highlight) .nf,:is(.highlighter-rouge,figure.highlight) .fm,:is(.highlighter-rouge,figure.highlight) .nd{color:var(--slide-syntax-function)}.code-window .o,.code-window .ow,:is(.highlighter-rouge,figure.highlight) .o,:is(.highlighter-rouge,figure.highlight) .ow{color:var(--slide-syntax-operator)}.code-window .p,:is(.highlighter-rouge,figure.highlight) .p{color:var(--slide-syntax-punctuation)}.code-window .n,.code-window .na,.code-window .nv,.code-window .vc,.code-window .vg,.code-window .vi,.code-window .py,:is(.highlighter-rouge,figure.highlight) .n,:is(.highlighter-rouge,figure.highlight) .na,:is(.highlighter-rouge,figure.highlight) .nv,:is(.highlighter-rouge,figure.highlight) .vc,:is(.highlighter-rouge,figure.highlight) .vg,:is(.highlighter-rouge,figure.highlight) .vi,:is(.highlighter-rouge,figure.highlight) .py{color:var(--slide-syntax-name)}.code-window .nv,.code-window .vc,.code-window .vg,.code-window .vi,:is(.highlighter-rouge,figure.highlight) .nv,:is(.highlighter-rouge,figure.highlight) .vc,:is(.highlighter-rouge,figure.highlight) .vg,:is(.highlighter-rouge,figure.highlight) .vi{color:var(--slide-syntax-variable)}.code-window .x,.code-window .sx,.code-window .ni,.code-window .nl,.code-window .nt,:is(.highlighter-rouge,figure.highlight) .x,:is(.highlighter-rouge,figure.highlight) .sx,:is(.highlighter-rouge,figure.highlight) .ni,:is(.highlighter-rouge,figure.highlight) .nl,:is(.highlighter-rouge,figure.highlight) .nt,.code-window .ss,.code-window .sh,.code-window .si,.code-window .sr,:is(.highlighter-rouge,figure.highlight) .ss,:is(.highlighter-rouge,figure.highlight) .sh,:is(.highlighter-rouge,figure.highlight) .si,:is(.highlighter-rouge,figure.highlight) .sr{color:var(--slide-syntax-symbol)}.code-window .kv,.code-window .kc,.code-window .cp,.code-window .cd,.code-window .pi,:is(.highlighter-rouge,figure.highlight) .kv,:is(.highlighter-rouge,figure.highlight) .kc,:is(.highlighter-rouge,figure.highlight) .cp,:is(.highlighter-rouge,figure.highlight) .cd,:is(.highlighter-rouge,figure.highlight) .pi{color:var(--slide-syntax-keyword)}.code-window .il,:is(.highlighter-rouge,figure.highlight) .il{color:var(--slide-syntax-number)}.code-window .nb,.code-window .bp,:is(.highlighter-rouge,figure.highlight) .nb,:is(.highlighter-rouge,figure.highlight) .bp{color:var(--slide-syntax-builtin)}.code-window .nc,.code-window .no,.code-window .ne,.code-window .nn,.code-window .nx,:is(.highlighter-rouge,figure.highlight) .nc,:is(.highlighter-rouge,figure.highlight) .no,:is(.highlighter-rouge,figure.highlight) .ne,:is(.highlighter-rouge,figure.highlight) .nn,:is(.highlighter-rouge,figure.highlight) .nx{color:var(--slide-syntax-constant)}.code-window .err,:is(.highlighter-rouge,figure.highlight) .err{color:var(--slide-syntax-error);-webkit-text-decoration:wavy underline var(--slide-syntax-error);-webkit-text-decoration:wavy underline var(--slide-syntax-error);text-decoration:wavy underline var(--slide-syntax-error);text-underline-offset:4px}.highlighter-rouge,figure.highlight{min-width:0;font-family:var(--font-slide-mono)}:where(.prose,.layout-split-code .pane)>pre{min-width:0;font-family:var(--font-slide-mono);font-variant-ligatures:none;scrollbar-width:thin;scrollbar-color:var(--slide-muted) transparent;overflow:auto}.highlighter-rouge .highlight,figure.highlight{border:1px solid var(--slide-code-border);background:var(--slide-code-surface);font-size:var(--slide-code-font-size);font-variant-ligatures:none;scrollbar-width:thin;scrollbar-color:var(--slide-muted) transparent;border-radius:16px;font-weight:450;line-height:1.45;overflow:auto}.highlighter-rouge pre,figure.highlight pre{margin:0;padding:28px 32px}.highlighter-rouge code,figure.highlight code{color:var(--slide-fg);font:inherit}.code-window.size-sm,.terminal-window.size-sm{--slide-window-bar:62px;font-size:32px}.code-window.size-md,.terminal-window.size-md{--slide-window-bar:72px;font-size:38px}.code-window.size-lg,.terminal-window.size-lg{--slide-window-bar:82px;font-size:42px}.terminal-window{background:var(--slide-code-surface)}.terminal-window pre{padding-top:28px}.terminal-window .tline{white-space:pre-wrap;min-height:1.45em;display:block}.terminal-window .prompt{color:var(--slide-accent-strong);font-weight:700}.terminal-window .cmd{color:var(--slide-link)}.terminal-window .tline:not(:has(.prompt)):not(:has(.cmd)){color:var(--slide-fg)}.presentation-chrome{z-index:20;color:var(--slide-muted);pointer-events:none;position:fixed;inset:0}.presentation-root:not(.js) .presentation-chrome{visibility:hidden;pointer-events:none}.slide-controls{pointer-events:auto;background:0 0;border:1px solid #0000;border-radius:12px;align-items:center;gap:8px;padding:8px;transition:background .2s,border-color .2s;display:flex;position:absolute;bottom:16px;right:24px}.slide-controls:hover,.slide-controls:focus-within{border-color:var(--slide-code-border);background:var(--slide-bg)}@supports (color:color-mix(in lab, red, red)){.slide-controls:hover,.slide-controls:focus-within{background:color-mix(in srgb, var(--slide-bg), transparent 12%)}}.slide-controls:hover,.slide-controls:focus-within{-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.slide-control{border:1px solid var(--slide-code-border);width:46px;height:38px;color:var(--slide-fg);cursor:pointer;font:inherit;opacity:0;pointer-events:none;background:0 0;border-radius:9px;place-items:center;line-height:1;transition:background .2s,color .2s,border-color .2s,opacity .2s,transform .2s;display:inline-grid;transform:translateY(4px)}.slide-controls:hover .slide-control,.slide-controls:focus-within .slide-control{opacity:1;pointer-events:auto;transform:none}.slide-control:hover{border-color:var(--slide-accent);background:var(--slide-highlight);color:var(--slide-accent-strong)}.slide-controls:hover .slide-control:disabled,.slide-controls:focus-within .slide-control:disabled{opacity:.35;cursor:default}.slide-counter{font-family:var(--font-slide-mono);letter-spacing:.04em;margin:0;font-size:17px}.slide-progress{width:100%;height:4px;accent-color:var(--slide-accent);opacity:.58;pointer-events:auto;position:absolute;bottom:0;left:0;right:0}.slide-progress::-webkit-progress-bar{background:var(--slide-code-border);border-radius:99px}.slide-progress::-webkit-progress-value{background:var(--slide-accent);border-radius:99px}.overview-hint{z-index:25;border:1px solid var(--slide-code-border);background:var(--slide-code-surface);color:var(--slide-muted);font-family:var(--font-slide-mono);border-radius:999px;margin:0;padding:10px 18px;font-size:14px;position:fixed;top:82px;left:50%;transform:translate(-50%)}.overview-hint[hidden]{display:none}.presentation-root.js.is-fullscreen .presentation-chrome,.presentation-root.js[data-fullscreen-active=true] .presentation-chrome{opacity:0;transition:opacity .35s}.presentation-root.js.is-fullscreen .presentation-chrome:hover,.presentation-root.js.is-fullscreen .presentation-chrome:focus-within,.presentation-root.js[data-fullscreen-active=true] .presentation-chrome:hover,.presentation-root.js[data-fullscreen-active=true] .presentation-chrome:focus-within{opacity:1}.slide-control:focus-visible,.slide-progress:focus-visible{outline:4px solid var(--slide-focus);outline-offset:4px}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:0s!important;animation-duration:0s!important;animation-iteration-count:1!important}}.presentation-root.is-reduced-motion .presentation-chrome,.presentation-root[data-reduced-motion=true] .presentation-chrome,.presentation-root.is-reduced-motion .fragment,.presentation-root[data-reduced-motion=true] .fragment{transition:none}@page{size:13.333in 7.5in;margin:0}@media print{*,:before,:after{transition:none!important;animation:none!important}html,body{width:13.333in;min-width:13.333in;background:var(--slide-bg)!important}body{-webkit-print-color-adjust:exact;print-color-adjust:exact}.presentation-root,.presentation-root.js{width:13.333in!important;height:auto!important;min-height:0!important;overflow:visible!important}.presentation-chrome,.slide-progress,.overview-hint{display:none!important}.slide-deck,.presentation-root.js .slide-deck,.presentation-root.js.is-overview .slide-deck{width:13.333in!important;height:auto!important;min-height:0!important;padding:0!important;display:block!important;position:static!important;overflow:visible!important}.slide,.presentation-root.js .slide,.presentation-root.js.is-overview .slide{break-after:page;page-break-after:always;min-height:0;visibility:visible!important;width:13.333in!important;height:7.5in!important;box-shadow:none!important;cursor:default!important;border:0!important;border-radius:0!important;margin:0!important;display:block!important;position:relative!important;inset:auto!important;overflow:hidden!important;transform:none!important}.slide:last-child{break-after:auto;page-break-after:auto}.slide-content,.presentation-root.js.is-overview .slide-content{transform-origin:0 0;width:1920px!important;height:1080px!important;transform:scale(.66665)!important}.code-window .line,.terminal-window .tline{opacity:1!important}.fragment{visibility:visible!important;opacity:1!important;transform:none!important}}
|
data/assets/js/presentation.js
CHANGED
|
@@ -106,6 +106,11 @@
|
|
|
106
106
|
tabindex: slide.getAttribute && slide.getAttribute("tabindex")
|
|
107
107
|
};
|
|
108
108
|
});
|
|
109
|
+
// Paragraphs only for now: a wider block vocabulary would need its own
|
|
110
|
+
// grouping rules, and one marked paragraph is the whole feature.
|
|
111
|
+
var slideFragments = slides.map(function (slide) {
|
|
112
|
+
return asArray(slide.querySelectorAll ? slide.querySelectorAll("p.fragment") : []);
|
|
113
|
+
});
|
|
109
114
|
var total = slides.length || Number(dataValue(root, "slide-count")) || 1;
|
|
110
115
|
var counter = root.querySelector("[data-slide-counter]");
|
|
111
116
|
var progress = root.querySelector("[data-slide-progress]");
|
|
@@ -116,7 +121,12 @@
|
|
|
116
121
|
var overviewHint = root.querySelector("[data-overview-hint]");
|
|
117
122
|
var overviewEnabled = enabled(root, "overview");
|
|
118
123
|
var fullscreenEnabled = enabled(root, "fullscreen");
|
|
119
|
-
|
|
124
|
+
// How many paragraphs of each slide the audience has already seen. Kept for
|
|
125
|
+
// the session, so leaving a slide and coming back does not replay it.
|
|
126
|
+
var state = {
|
|
127
|
+
current: 1, overview: false, printing: false,
|
|
128
|
+
revealed: slides.map(function () { return 0; })
|
|
129
|
+
};
|
|
120
130
|
var listeners = [];
|
|
121
131
|
|
|
122
132
|
function on(element, eventName, handler, options) {
|
|
@@ -198,6 +208,42 @@
|
|
|
198
208
|
if (slide.removeAttribute) slide.removeAttribute("hidden");
|
|
199
209
|
});
|
|
200
210
|
}
|
|
211
|
+
function fragmentsOf(number) { return slideFragments[number - 1] || []; }
|
|
212
|
+
function fragmentCount(number) { return fragmentsOf(number).length; }
|
|
213
|
+
function revealedCount(number) { return state.revealed[number - 1] || 0; }
|
|
214
|
+
function setRevealed(number, count) {
|
|
215
|
+
if (number < 1 || number > total) return;
|
|
216
|
+
state.revealed[number - 1] = clamp(count, 0, fragmentCount(number));
|
|
217
|
+
}
|
|
218
|
+
// Overview, print, and a torn-down runtime all show the whole slide: a
|
|
219
|
+
// paragraph nobody can reveal must never be a paragraph nobody can read.
|
|
220
|
+
function updateFragments() {
|
|
221
|
+
var showEverything = state.overview || state.printing || state.finished;
|
|
222
|
+
slideFragments.forEach(function (fragments, index) {
|
|
223
|
+
var visible = showEverything ? fragments.length : (state.revealed[index] || 0);
|
|
224
|
+
fragments.forEach(function (fragment, position) {
|
|
225
|
+
if (position < visible) {
|
|
226
|
+
addClass(fragment, "is-revealed");
|
|
227
|
+
if (fragment.removeAttribute) { fragment.removeAttribute("inert"); fragment.removeAttribute("aria-hidden"); }
|
|
228
|
+
} else {
|
|
229
|
+
removeClass(fragment, "is-revealed");
|
|
230
|
+
setAttribute(fragment, "inert", "");
|
|
231
|
+
setAttribute(fragment, "aria-hidden", "true");
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
// Reveals the paragraphs up to and including the one holding +element+, so
|
|
237
|
+
// an anchor into a slide lands on visible text.
|
|
238
|
+
function revealThrough(number, element) {
|
|
239
|
+
var fragments = fragmentsOf(number);
|
|
240
|
+
for (var index = fragments.length - 1; index >= 0; index -= 1) {
|
|
241
|
+
if (contains(fragments[index], element)) {
|
|
242
|
+
setRevealed(number, Math.max(revealedCount(number), index + 1));
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
201
247
|
function setPrinting(value) {
|
|
202
248
|
state.printing = Boolean(value);
|
|
203
249
|
if (state.printing) {
|
|
@@ -210,12 +256,14 @@
|
|
|
210
256
|
render();
|
|
211
257
|
}
|
|
212
258
|
function updateIndicators() {
|
|
259
|
+
// A reveal is a step too, so the deck ends only once the last slide has
|
|
260
|
+
// nothing left to show, and the first slide can still undo a reveal.
|
|
213
261
|
if (previousButton) {
|
|
214
|
-
previousButton.disabled = state.current === 1;
|
|
262
|
+
previousButton.disabled = state.current === 1 && revealedCount(1) === 0;
|
|
215
263
|
setAttribute(previousButton, "aria-disabled", previousButton.disabled ? "true" : "false");
|
|
216
264
|
}
|
|
217
265
|
if (nextButton) {
|
|
218
|
-
nextButton.disabled = state.current === total;
|
|
266
|
+
nextButton.disabled = state.current === total && revealedCount(total) === fragmentCount(total);
|
|
219
267
|
setAttribute(nextButton, "aria-disabled", nextButton.disabled ? "true" : "false");
|
|
220
268
|
}
|
|
221
269
|
if (counter) counter.textContent = state.current + " / " + total;
|
|
@@ -227,7 +275,30 @@
|
|
|
227
275
|
progress.style.setProperty("--progress-percent", (state.current / total * 100) + "%");
|
|
228
276
|
}
|
|
229
277
|
}
|
|
230
|
-
function render() { updateSlideVisibility(); updateIndicators(); updateOverviewButton(); updateOverviewHint(); updateOverviewDescription(); updateFullscreenButton(); }
|
|
278
|
+
function render() { updateSlideVisibility(); updateFragments(); updateIndicators(); updateOverviewButton(); updateOverviewHint(); updateOverviewDescription(); updateFullscreenButton(); }
|
|
279
|
+
// One step forward: reveal the next paragraph, or leave the slide once the
|
|
280
|
+
// slide has nothing left. A reveal is not a location, so it writes no
|
|
281
|
+
// history entry and does not move the slide counter.
|
|
282
|
+
function advance() {
|
|
283
|
+
if (revealedCount(state.current) < fragmentCount(state.current)) {
|
|
284
|
+
setRevealed(state.current, revealedCount(state.current) + 1);
|
|
285
|
+
render();
|
|
286
|
+
return state.current;
|
|
287
|
+
}
|
|
288
|
+
return goTo(state.current + 1);
|
|
289
|
+
}
|
|
290
|
+
// One step back, undoing the latest reveal first. Stepping onto an earlier
|
|
291
|
+
// slide arrives with it fully revealed, the way the audience left it.
|
|
292
|
+
function retreat() {
|
|
293
|
+
if (revealedCount(state.current) > 0) {
|
|
294
|
+
setRevealed(state.current, revealedCount(state.current) - 1);
|
|
295
|
+
render();
|
|
296
|
+
return state.current;
|
|
297
|
+
}
|
|
298
|
+
var destination = state.current - 1;
|
|
299
|
+
setRevealed(destination, fragmentCount(destination));
|
|
300
|
+
return goTo(destination);
|
|
301
|
+
}
|
|
231
302
|
function goTo(number, options) {
|
|
232
303
|
var previous = state.current;
|
|
233
304
|
var validNumber = typeof number === "number" && Number.isFinite(number) && Number.isInteger(number);
|
|
@@ -243,7 +314,10 @@
|
|
|
243
314
|
var target = fragmentTarget(hash);
|
|
244
315
|
if (target) {
|
|
245
316
|
var containingSlide = containingSlideNumber(target);
|
|
246
|
-
if (containingSlide !== null)
|
|
317
|
+
if (containingSlide !== null) {
|
|
318
|
+
state.current = containingSlide;
|
|
319
|
+
revealThrough(containingSlide, target);
|
|
320
|
+
}
|
|
247
321
|
render();
|
|
248
322
|
return state.current;
|
|
249
323
|
}
|
|
@@ -303,19 +377,40 @@
|
|
|
303
377
|
if (key === "Escape" && state.overview) { setOverview(false); if (event.preventDefault) event.preventDefault(); return; }
|
|
304
378
|
if ((key === "o" || key === "O") && overviewEnabled) { toggleOverview(); return; }
|
|
305
379
|
if ((key === "f" || key === "F") && fullscreenEnabled) { toggleFullscreen(); return; }
|
|
380
|
+
if (key === "ArrowRight" || key === " " || key === "PageDown") {
|
|
381
|
+
advance();
|
|
382
|
+
if (event.preventDefault) event.preventDefault();
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
if (key === "ArrowLeft" || key === "PageUp") {
|
|
386
|
+
retreat();
|
|
387
|
+
if (event.preventDefault) event.preventDefault();
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
306
390
|
var destination;
|
|
307
|
-
if (key === "
|
|
308
|
-
else if (key === "ArrowLeft" || key === "PageUp") destination = state.current - 1;
|
|
309
|
-
else if (key === "Home") destination = 1;
|
|
391
|
+
if (key === "Home") destination = 1;
|
|
310
392
|
else if (key === "End") destination = total;
|
|
311
393
|
if (destination === undefined) return;
|
|
312
394
|
goTo(destination);
|
|
313
395
|
if (event.preventDefault) event.preventDefault();
|
|
314
396
|
}
|
|
315
397
|
function selectOverviewSlide(number) { goTo(number); setOverview(false); }
|
|
398
|
+
// A primary click on the slide itself is the same step as ArrowRight. It
|
|
399
|
+
// must never steal a link, a selection, or a click something else handled.
|
|
400
|
+
function contentClickAdvances(event, slide, index) {
|
|
401
|
+
if (state.printing || index + 1 !== state.current) return false;
|
|
402
|
+
if (event.defaultPrevented || hasModifier(event)) return false;
|
|
403
|
+
if (typeof event.button === "number" && event.button !== 0) return false;
|
|
404
|
+
if (interactiveDescendant(event.target, slide)) return false;
|
|
405
|
+
return !hasNonCollapsedSelection(document);
|
|
406
|
+
}
|
|
316
407
|
function bindSlide(slide, index) {
|
|
317
408
|
on(slide, "click", function (event) {
|
|
318
|
-
if (state.overview
|
|
409
|
+
if (state.overview) {
|
|
410
|
+
if (!interactiveDescendant(event.target, slide)) selectOverviewSlide(index + 1);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
if (contentClickAdvances(event, slide, index)) advance();
|
|
319
414
|
});
|
|
320
415
|
on(slide, "keydown", function (event) {
|
|
321
416
|
if (!state.overview || event.target !== slide || (keyName(event) !== "Enter" && keyName(event) !== " ")) return;
|
|
@@ -335,15 +430,15 @@
|
|
|
335
430
|
on(window, "beforeprint", function () { setPrinting(true); });
|
|
336
431
|
on(window, "afterprint", function () { setPrinting(false); });
|
|
337
432
|
on(document, "fullscreenchange", updateFullscreenButton);
|
|
338
|
-
on(previousButton, "click",
|
|
339
|
-
on(nextButton, "click",
|
|
433
|
+
on(previousButton, "click", retreat);
|
|
434
|
+
on(nextButton, "click", advance);
|
|
340
435
|
on(overviewButton, "click", toggleOverview);
|
|
341
436
|
on(fullscreenButton, "click", toggleFullscreen);
|
|
342
437
|
syncFromLocation(true);
|
|
343
438
|
var controller = {
|
|
344
439
|
goTo: goTo,
|
|
345
|
-
next:
|
|
346
|
-
previous:
|
|
440
|
+
next: advance,
|
|
441
|
+
previous: retreat,
|
|
347
442
|
toggleOverview: toggleOverview,
|
|
348
443
|
toggleFullscreen: toggleFullscreen,
|
|
349
444
|
get current() { return state.current; },
|
|
@@ -351,6 +446,7 @@
|
|
|
351
446
|
destroy: function () {
|
|
352
447
|
state.overview = false;
|
|
353
448
|
state.printing = false;
|
|
449
|
+
state.finished = true;
|
|
354
450
|
removeClass(root, "is-overview");
|
|
355
451
|
removeClass(root, "is-printing");
|
|
356
452
|
if (root.removeAttribute) root.removeAttribute("data-overview-active");
|
data/doc/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Jekyll Slides are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.4.0 — 2026-09-10
|
|
6
|
+
|
|
7
|
+
- Add opt-in paragraph reveals: mark a paragraph `{: .fragment}` and it is held back until the next step. Forward steps (`ArrowRight`, `PageDown`, `Space`, the next button, or a click on the slide) reveal one paragraph before moving to the next slide; backward steps hide the most recent reveal first. Slide numbers, the progress bar, the URL hash, and browser history keep counting slides, not reveals. Hidden paragraphs keep their space, cannot be focused or reached by assistive technology, and fade in over 180ms unless the reader prefers reduced motion. The overview, print, no-JavaScript output, and browsers without the slide canvas show every paragraph.
|
|
8
|
+
- Add `macos-light`, a flat light code-window palette. It is component-only: a block selects it with `theme="macos-light"`, a deck cannot, and it repaints that window alone so it can sit inside a deck of any color.
|
|
9
|
+
- Give slides more usable space. Content insets drop from `108px 132px 100px`, and from the `180px` title and statement overrides, to one shared 72px/80px pair used by both the presented slide and the overview preview.
|
|
10
|
+
- Repaint `minimal-light` as a flat neutral near-white deck instead of a warm paper tint, including its plain, gradient, and code surfaces.
|
|
11
|
+
- Keep 28px between a block and the prose after it. Plain fenced code, Rouge output, and figures previously carried no bottom margin, so following prose sat flush against them. A plain fence also now uses the deck's monospace face rather than the browser default.
|
|
12
|
+
- Stop capping `content` slides at a 920px column. Headings, paragraphs, lists, and quotes each carry their own measure, so the column cap only ever clipped the code blocks and tables that have none.
|
|
13
|
+
- Flatten the window chrome to match macOS: a solid title-bar fill with no gradient, a 1px border, a restrained shadow, and traffic lights with a rim but no gloss.
|
|
14
|
+
- Move the editor and terminal title from the center of the title bar to just after the traffic lights, offset by a control run derived from the bar height so `sm`, `md`, and `lg` stay aligned. A long filename truncates before the language label.
|
|
15
|
+
- Remove `--slide-surface-shine`, `--slide-code-inset`, and `--slide-dot-gloss`. The flat chrome reads none of them. Sites that forked the stylesheet and set these tokens should drop them.
|
|
16
|
+
|
|
17
|
+
## 0.3.0 — 2026-09-10
|
|
18
|
+
|
|
19
|
+
- Add the four Catppuccin flavors as presentation themes: `catppuccin-latte`, `catppuccin-frappe`, `catppuccin-macchiato`, and `catppuccin-mocha`, ported from the palette shared by [catppuccin/ghostty](https://github.com/catppuccin/ghostty). Hues are the published values; lightness is adjusted only where a token cannot otherwise clear the 4.5:1 contrast checked on every code surface.
|
|
20
|
+
- Add a `theme` attribute to editor and terminal blocks, so one window can carry any theme while the deck around it keeps its own. The override repaints that window's surface, title bar, syntax colors, prompt, and body text. An unknown name warns and falls back to the deck theme.
|
|
21
|
+
- Give terminal windows a real title bar. It was previously an empty `::before` bar that could hold neither the window controls nor the title, which floated above it.
|
|
22
|
+
- Center editor and terminal titles inside the title bar, and size the controls and bar with the component `size`.
|
|
23
|
+
- Use the macOS traffic-light colors for the window controls in every theme, the way a real title bar does; only the window surface follows the theme. Themes no longer set `--slide-dot-close`, `--slide-dot-minimize`, or `--slide-dot-maximize`.
|
|
24
|
+
- Rename the generated LLM index from `llm.txt` to `llms.txt`, matching the llmstxt.org convention used across these plugins.
|
|
25
|
+
|
|
5
26
|
## 0.2.0 — 2026-09-06
|
|
6
27
|
|
|
7
28
|
- Add folder decks: author a presentation as one Markdown file per slide, ordered by a numeric filename prefix and alphabetically otherwise, opted into with `slides:` in the entry file's front matter.
|
|
@@ -14,9 +14,6 @@ Not documented.
|
|
|
14
14
|
### `OPTION_KEYS` <a id="constant-OPTION_KEYS"></a> <a id="OPTION_KEYS-constant"></a>
|
|
15
15
|
Not documented.
|
|
16
16
|
|
|
17
|
-
### `THEMES` <a id="constant-THEMES"></a> <a id="THEMES-constant"></a>
|
|
18
|
-
Not documented.
|
|
19
|
-
|
|
20
17
|
## Public Class Methods
|
|
21
18
|
### `install!()` <a id="method-c-install-21"></a> <a id="install!-class_method"></a>
|
|
22
19
|
Not documented.
|
data/doc/Jekyll/Slides.md
CHANGED
|
@@ -13,9 +13,8 @@ includes, styles, scripts, and offline fonts while preserving the site's theme
|
|
|
13
13
|
and local overrides.
|
|
14
14
|
|
|
15
15
|
Configure defaults under <code>slides:</code> in _config.yml, or use front
|
|
16
|
-
matter on individual decks.
|
|
17
|
-
|
|
18
|
-
quote this value in YAML.
|
|
16
|
+
matter on individual decks. The supported aspect ratio is 16:9; quote this
|
|
17
|
+
value in YAML.
|
|
19
18
|
|
|
20
19
|
Jekyll runs Liquid before rendering each slide as one Markdown document.
|
|
21
20
|
Jekyll::Slides::Presentation also renders slide HTML directly when Jekyll
|
|
@@ -23,12 +22,26 @@ integration is not needed; it does not evaluate Liquid or wrap the
|
|
|
23
22
|
presentation layout.
|
|
24
23
|
|
|
25
24
|
## Constants
|
|
25
|
+
### `COMPONENT_THEMES` <a id="constant-COMPONENT_THEMES"></a> <a id="COMPONENT_THEMES-constant"></a>
|
|
26
|
+
Every palette a single editor or terminal block may carry: the deck palettes
|
|
27
|
+
plus the ones that exist only at window scale. <code>macos-light</code> is a
|
|
28
|
+
flat light code window meant to sit inside a deck of any color, so it defines
|
|
29
|
+
no slide background or type scale and cannot be a deck theme.
|
|
30
|
+
|
|
31
|
+
### `DEFAULT_THEME` <a id="constant-DEFAULT_THEME"></a> <a id="DEFAULT_THEME-constant"></a>
|
|
32
|
+
Not documented.
|
|
33
|
+
|
|
26
34
|
### `LAYOUT_NAME` <a id="constant-LAYOUT_NAME"></a> <a id="LAYOUT_NAME-constant"></a>
|
|
27
35
|
Not documented.
|
|
28
36
|
|
|
29
37
|
### `ROOT` <a id="constant-ROOT"></a> <a id="ROOT-constant"></a>
|
|
30
38
|
Not documented.
|
|
31
39
|
|
|
40
|
+
### `THEMES` <a id="constant-THEMES"></a> <a id="THEMES-constant"></a>
|
|
41
|
+
Every deck palette the plugin ships. A theme sets the whole deck through front
|
|
42
|
+
matter, and any one of them also restyles a single editor or terminal block
|
|
43
|
+
through that block's `theme` attribute.
|
|
44
|
+
|
|
32
45
|
### `VERSION` <a id="constant-VERSION"></a> <a id="VERSION-constant"></a>
|
|
33
46
|
Not documented.
|
|
34
47
|
|
data/doc/README.md
CHANGED
|
@@ -33,7 +33,7 @@ title: A short talk
|
|
|
33
33
|
|
|
34
34
|
<!--
|
|
35
35
|
layout: title
|
|
36
|
-
background:
|
|
36
|
+
background: plain
|
|
37
37
|
-->
|
|
38
38
|
# A short talk
|
|
39
39
|
|
|
@@ -136,7 +136,7 @@ ruby 3.4.1
|
|
|
136
136
|
{: .terminal #ruby-version title="terminal" size="sm"}
|
|
137
137
|
````
|
|
138
138
|
|
|
139
|
-
Editor/terminal attributes are `title`, `id` (or `#id`), `size` (`sm`, `md`, `lg`), `line_numbers` (`true`/`false`), `focus`, and `highlight`. Ranges accept comma-separated lines and ranges such as `2,4-6,9`; invalid values fall back safely with a Jekyll warning. Terminal prompts beginning with `$ `, `> `, or `❯ ` are styled separately. Source remains server-rendered and copyable.
|
|
139
|
+
Editor/terminal attributes are `title`, `id` (or `#id`), `size` (`sm`, `md`, `lg`), `theme`, `line_numbers` (`true`/`false`), `focus`, and `highlight`. Ranges accept comma-separated lines and ranges such as `2,4-6,9`; invalid values fall back safely with a Jekyll warning. Terminal prompts beginning with `$ `, `> `, or `❯ ` are styled separately. Source remains server-rendered and copyable.
|
|
140
140
|
|
|
141
141
|
Long editor and terminal blocks scroll within the slide. Blocks over 20 lines produce an advisory build warning; the amount that fits depends on the layout and font size. Split long examples across slides for print, where scrolling is unavailable.
|
|
142
142
|
|
|
@@ -144,9 +144,29 @@ Liquid runs before slide rendering, just as it does on ordinary Jekyll pages. Wr
|
|
|
144
144
|
|
|
145
145
|
Code remains selectable and copyable with normal browser controls; version 0.1 does not add a copy button.
|
|
146
146
|
|
|
147
|
+
## Paragraph reveals
|
|
148
|
+
|
|
149
|
+
Mark a paragraph `.fragment` to hold it back until the next step. Everything else on the slide is visible from the start.
|
|
150
|
+
|
|
151
|
+
```markdown
|
|
152
|
+
This paragraph is visible immediately.
|
|
153
|
+
|
|
154
|
+
This explanation appears on the next click.
|
|
155
|
+
{: .fragment}
|
|
156
|
+
|
|
157
|
+
This conclusion appears on the following click.
|
|
158
|
+
{: .fragment}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Each forward step — `ArrowRight`, `PageDown`, `Space`, the next button, or a click on the slide — reveals one more marked paragraph. Once the slide has none left, the same step moves to the next slide. Backward steps hide the most recent reveal first, and stepping onto an earlier slide arrives with it fully revealed. Slide numbers, the progress bar, the URL hash, and browser history keep counting slides, not reveals.
|
|
162
|
+
|
|
163
|
+
A hidden paragraph keeps its space, so revealing one moves nothing else on the slide. It cannot be focused or read by assistive technology until it is revealed, and it fades in over 180ms unless the reader prefers reduced motion. The overview, print output, no-JavaScript output, and browsers without the slide canvas show every paragraph, because none of them can reveal one; leaving the overview or the print dialog restores the reveals for the session.
|
|
164
|
+
|
|
165
|
+
Reveals are opt-in per paragraph, and version 0.1 marks paragraphs only. The [presentation polish example](https://github.com/lucianghinda/jekyll-slides/blob/main/examples/presentation-polish.md) shows them on a flat light deck.
|
|
166
|
+
|
|
147
167
|
## Themes and configuration
|
|
148
168
|
|
|
149
|
-
Presentation themes are `minimal-light`, `minimal-dark`, `midnight` (the default), and `
|
|
169
|
+
Presentation themes are `minimal-light`, `minimal-dark`, `midnight` (the default), `ruby`, and the four Catppuccin flavors `catppuccin-latte`, `catppuccin-frappe`, `catppuccin-macchiato`, and `catppuccin-mocha`. These style the slides without replacing the site's Jekyll theme. Configure defaults under `slides:`:
|
|
150
170
|
|
|
151
171
|
```yaml
|
|
152
172
|
slides:
|
|
@@ -162,17 +182,52 @@ The same keys can be overridden per presentation in front matter (`theme`, `aspe
|
|
|
162
182
|
|
|
163
183
|
For a light presentation, set `slides: { theme: minimal-light }` in `_config.yml`, or `theme: minimal-light` in the deck's front matter. The [readability example](https://github.com/lucianghinda/jekyll-slides/blob/main/examples/readability.md) demonstrates the light theme with code, terminal output, tables, and prose.
|
|
164
184
|
|
|
185
|
+
### Terminal themes
|
|
186
|
+
|
|
187
|
+
The Catppuccin flavors are ported from the palette shared by [catppuccin/ghostty](https://github.com/catppuccin/ghostty). Hues are the published values; lightness is adjusted only where a token cannot otherwise clear the 4.5:1 contrast the project checks on every code surface. Latte, the light flavor, needed the most adjustment.
|
|
188
|
+
|
|
189
|
+
Any theme also works on a single editor or terminal block through a `theme` attribute, so one window can carry a different palette from the deck around it:
|
|
190
|
+
|
|
191
|
+
````markdown
|
|
192
|
+
```console
|
|
193
|
+
$ ghostty --version
|
|
194
|
+
ghostty 1.0.1
|
|
195
|
+
```
|
|
196
|
+
{: .terminal title="ghostty" theme="catppuccin-latte"}
|
|
197
|
+
````
|
|
198
|
+
|
|
199
|
+
The override repaints that window completely: surface, title bar, syntax colors, prompt, and body text. Everything outside it keeps the deck theme. An unknown name warns during the build and falls back to the deck theme. The [terminal themes example](https://github.com/lucianghinda/jekyll-slides/blob/main/examples/terminal-themes.md) shows a deck-wide flavor next to per-window overrides.
|
|
200
|
+
|
|
201
|
+
### The macOS light window
|
|
202
|
+
|
|
203
|
+
`macos-light` is a component-only palette: a flat near-white code window with a pale title bar, purple keywords, green strings, and blue functions. It is meant to sit inside a deck of any color, so it defines no slide background and no type scale, and a deck cannot select it.
|
|
204
|
+
|
|
205
|
+
````markdown
|
|
206
|
+
```ruby
|
|
207
|
+
class Invoice
|
|
208
|
+
def total = items.sum(&:price)
|
|
209
|
+
end
|
|
210
|
+
```
|
|
211
|
+
{: .editor title="app/models/invoice.rb" theme="macos-light" line_numbers="true"}
|
|
212
|
+
````
|
|
213
|
+
|
|
214
|
+
Because `theme` is one shared attribute, `macos-light` works on a terminal too. Omitting `theme` continues to inherit the deck palette, and naming it in front matter or `_config.yml` is not a deck theme — that warns and falls back like any other unknown deck name. The [editor themes example](https://github.com/lucianghinda/jekyll-slides/blob/main/examples/editor-themes.md) shows it on a dark deck across all three sizes.
|
|
215
|
+
|
|
216
|
+
### Window chrome
|
|
217
|
+
|
|
218
|
+
Editors and terminals render the same macOS-style title bar: traffic lights on the left, then the `title`, and for editors the language on the right. The bar is a single flat fill from the palette with a hairline under it; the window has a 1px border and a restrained shadow. The traffic lights keep the macOS red, amber, and green in every theme, the way a real title bar does; only the window surface follows the theme. Bar height, control size, and the title's offset all scale with the component `size`, so `sm`, `md`, and `lg` stay aligned. A long filename truncates before it reaches the language label.
|
|
219
|
+
|
|
165
220
|
## Typography and readability
|
|
166
221
|
|
|
167
222
|
The gem bundles Atkinson Hyperlegible Next for text and Atkinson Hyperlegible Mono for code, including variable upright and italic faces. Fonts load from the site's own assets and work offline. The font files retain their SIL Open Font License; source revisions, checksums, and notices are in [assets/fonts](https://github.com/lucianghinda/jekyll-slides/blob/main/assets/fonts/README.md).
|
|
168
223
|
|
|
169
|
-
On the 1920×1080 slide canvas, body text is 44px, section headings are 72px, and code sizes `sm`, `md`, and `lg` are 32px, 38px, and 42px. These sizes scale with the slide. Filenames and line numbers remain readable, and focused lines use borders and background color while keeping surrounding code fully visible. All
|
|
224
|
+
On the 1920×1080 slide canvas, body text is 44px, section headings are 72px, and code sizes `sm`, `md`, and `lg` are 32px, 38px, and 42px. These sizes scale with the slide. Filenames and line numbers remain readable, and focused lines use borders and background color while keeping surrounding code fully visible. All eight deck themes, plus the component-only `macos-light`, check syntax-token contrast against normal, highlighted, and focused code surfaces, both deck-wide and as a single-window override, and check the filename and language against the title bar.
|
|
170
225
|
|
|
171
226
|
Prefer medium or large code and short examples for projection. Long blocks can scroll, but an audience cannot reveal hidden lines independently; split examples when presenting or printing. Screen contrast tests do not replace checking the actual projector and viewing distance.
|
|
172
227
|
|
|
173
228
|
## Navigation and accessibility
|
|
174
229
|
|
|
175
|
-
Use `ArrowLeft`/`ArrowRight`, `PageUp`/`PageDown`, `Home`, and `End` to navigate. `Space` advances, `O` toggles overview, and `F` toggles fullscreen. The current slide is synchronized in the URL hash (`#3` for slide three), so links and browser history work. The controls include accessible labels and focus states; reduced-motion preferences are respected. Print the deck with the browser print dialog (slides are paginated and chrome is hidden). If JavaScript is disabled, all slides remain in document order as complete aspect-ratio frames with readable content.
|
|
230
|
+
Use `ArrowLeft`/`ArrowRight`, `PageUp`/`PageDown`, `Home`, and `End` to navigate. `Space` advances, `O` toggles overview, and `F` toggles fullscreen. A click on the slide advances too; links, buttons, modified clicks, and text selection keep their own behavior. On a slide with [paragraph reveals](#paragraph-reveals), a forward step reveals the next paragraph before it changes slide. `Home` and `End` always jump to a slide. The current slide is synchronized in the URL hash (`#3` for slide three), so links and browser history work. The controls include accessible labels and focus states; reduced-motion preferences are respected. Print the deck with the browser print dialog (slides are paginated and chrome is hidden). If JavaScript is disabled, all slides remain in document order as complete aspect-ratio frames with readable content.
|
|
176
231
|
|
|
177
232
|
## Demo and development
|
|
178
233
|
|
|
@@ -207,7 +262,7 @@ bundle exec rake docs
|
|
|
207
262
|
```
|
|
208
263
|
|
|
209
264
|
This replaces `doc/` with fresh YARD Markdown, updates the documentation index in
|
|
210
|
-
`doc/Jekyll/Slides.md`, and writes `
|
|
265
|
+
`doc/Jekyll/Slides.md`, and writes `llms.txt` with links relative to the gem root.
|
|
211
266
|
The generated files are checked in and shipped with the gem. Internal plans,
|
|
212
267
|
temporary files, and Node dependencies are excluded. YARD and `yard-markdown`
|
|
213
268
|
are development tools only.
|
|
@@ -229,7 +284,7 @@ Maintainers can follow the [release instructions](https://github.com/lucianghind
|
|
|
229
284
|
|
|
230
285
|
## 0.1 limitations and extension
|
|
231
286
|
|
|
232
|
-
Version 0.1 intentionally supports Markdown/Kramdown, a fixed 16:9 canvas, the curated layouts/themes above, and a small dependency-free browser runtime. It does not provide speaker notes, transitions, nested slide sections, a theme editor, or an authoring UI. JavaScript is enhancement-only; server-side HTML is the source of truth.
|
|
287
|
+
Version 0.1 intentionally supports Markdown/Kramdown, a fixed 16:9 canvas, the curated layouts/themes above, and a small dependency-free browser runtime. It does not provide speaker notes, slide transitions, nested slide sections, a theme editor, or an authoring UI. Reveals mark paragraphs only; other blocks and grouped sequences are not covered. JavaScript is enhancement-only; server-side HTML is the source of truth.
|
|
233
288
|
|
|
234
289
|
The plugin injects its `_layouts`, `_includes`, and `assets` into Jekyll without participating in theme resolution. A site can override the `presentation` layout, any `slides/*` include, or either compiled asset by placing a file with the same path in its own source tree. Copy the stylesheet only when you need a complete CSS fork; otherwise add a custom slide class and site CSS after the gem stylesheet. Keep `plugins: [jekyll-slides]` enabled even when overriding the layout so Markdown rendering and normalized slide settings remain active.
|
|
235
290
|
|
data/doc/index.csv
CHANGED
|
@@ -5,6 +5,9 @@ Jekyll,Module,Jekyll.md
|
|
|
5
5
|
Jekyll::Slides,Module,Jekyll/Slides.md
|
|
6
6
|
Jekyll::Slides.ROOT,Constant,Jekyll/Slides.md#constant-ROOT
|
|
7
7
|
Jekyll::Slides.LAYOUT_NAME,Constant,Jekyll/Slides.md#constant-LAYOUT_NAME
|
|
8
|
+
Jekyll::Slides.THEMES,Constant,Jekyll/Slides.md#constant-THEMES
|
|
9
|
+
Jekyll::Slides.COMPONENT_THEMES,Constant,Jekyll/Slides.md#constant-COMPONENT_THEMES
|
|
10
|
+
Jekyll::Slides.DEFAULT_THEME,Constant,Jekyll/Slides.md#constant-DEFAULT_THEME
|
|
8
11
|
Jekyll::Slides.VERSION,Constant,Jekyll/Slides.md#constant-VERSION
|
|
9
12
|
Jekyll::Slides::Assets,Module,Jekyll/Slides/Assets.md
|
|
10
13
|
Jekyll::Slides::Assets.asset_files,Method,Jekyll/Slides/Assets.md#method-c-asset_files
|
|
@@ -20,7 +23,6 @@ Jekyll::Slides::DeckAssembler,Module,Jekyll/Slides/DeckAssembler.md
|
|
|
20
23
|
Jekyll::Slides::DeckAssembler.assemble,Method,Jekyll/Slides/DeckAssembler.md#method-c-assemble
|
|
21
24
|
Jekyll::Slides::JekyllIntegration,Module,Jekyll/Slides/JekyllIntegration.md
|
|
22
25
|
Jekyll::Slides::JekyllIntegration.DEFAULTS,Constant,Jekyll/Slides/JekyllIntegration.md#constant-DEFAULTS
|
|
23
|
-
Jekyll::Slides::JekyllIntegration.THEMES,Constant,Jekyll/Slides/JekyllIntegration.md#constant-THEMES
|
|
24
26
|
Jekyll::Slides::JekyllIntegration.BOOLEAN_OPTIONS,Constant,Jekyll/Slides/JekyllIntegration.md#constant-BOOLEAN_OPTIONS
|
|
25
27
|
Jekyll::Slides::JekyllIntegration.OPTION_KEYS,Constant,Jekyll/Slides/JekyllIntegration.md#constant-OPTION_KEYS
|
|
26
28
|
Jekyll::Slides::JekyllIntegration.install!,Method,Jekyll/Slides/JekyllIntegration.md#method-c-install-21
|
|
@@ -165,9 +165,8 @@ module Jekyll
|
|
|
165
165
|
line_numbers = line_numbers?(attrs.fetch("line_numbers", "true"))
|
|
166
166
|
classes = ["code-window", "size-#{size}"] + attrs[:classes].reject { |name| name == "editor" }
|
|
167
167
|
classes << "has-focus" unless focus.empty?
|
|
168
|
-
attributes =
|
|
169
|
-
header =
|
|
170
|
-
header << %(<span class="code-window-language">#{Support.escape(language)}</span></header>)
|
|
168
|
+
attributes = window_attributes(classes, attrs)
|
|
169
|
+
header = window_header(language: language)
|
|
171
170
|
caption = attrs["title"] ? %(<figcaption>#{Support.escape(attrs['title'])}</figcaption>) : ""
|
|
172
171
|
source = lines.map { |line, newline| line + newline }.join
|
|
173
172
|
highlighted = @rouge_renderer.render_lines(source, language)
|
|
@@ -187,7 +186,7 @@ module Jekyll
|
|
|
187
186
|
def render_terminal(lines, attrs)
|
|
188
187
|
size = normalize_size(attrs["size"])
|
|
189
188
|
classes = ["terminal-window", "size-#{size}"] + attrs[:classes].reject { |name| name == "terminal" }
|
|
190
|
-
figure_attrs =
|
|
189
|
+
figure_attrs = window_attributes(classes, attrs)
|
|
191
190
|
caption = attrs["title"] ? %(<figcaption>#{Support.escape(attrs['title'])}</figcaption>) : ""
|
|
192
191
|
body = lines.map do |line, newline|
|
|
193
192
|
visible = Support.escape(line)
|
|
@@ -198,7 +197,38 @@ module Jekyll
|
|
|
198
197
|
end
|
|
199
198
|
%(<span class="tline">#{visible}#{Support.escape(newline)}</span>)
|
|
200
199
|
end.join
|
|
201
|
-
%(<figure#{figure_attrs}>#{caption}<pre><code>#{body}</code></pre></figure>)
|
|
200
|
+
%(<figure#{figure_attrs}>#{caption}#{window_header}<pre><code>#{body}</code></pre></figure>)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# The macOS-style title bar both window types share: traffic lights on
|
|
204
|
+
# the left, and for editors the language on the right. The centered title
|
|
205
|
+
# is the figure's own caption, which stays a direct child of the figure so
|
|
206
|
+
# the markup remains a valid figure/figcaption pair.
|
|
207
|
+
def window_header(language: nil)
|
|
208
|
+
header = +'<header class="code-window-header"><span class="code-window-controls" aria-hidden="true"><i></i><i></i><i></i></span>'
|
|
209
|
+
header << %(<span class="code-window-language">#{Support.escape(language)}</span>) if language
|
|
210
|
+
header << "</header>"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def window_attributes(classes, attrs)
|
|
214
|
+
html_attributes(
|
|
215
|
+
"class" => classes.join(" "),
|
|
216
|
+
"id" => attrs[:id],
|
|
217
|
+
"data-code-theme" => component_theme(attrs["theme"])
|
|
218
|
+
)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# A component may carry any deck theme, so one window can show a light
|
|
222
|
+
# terminal inside a dark deck, plus the palettes that exist only at window
|
|
223
|
+
# scale. Returns nil to inherit the deck theme.
|
|
224
|
+
def component_theme(value)
|
|
225
|
+
return nil if value.nil? || value.to_s.empty?
|
|
226
|
+
return value.to_s if COMPONENT_THEMES.include?(value.to_s)
|
|
227
|
+
|
|
228
|
+
Support.warn(@warning,
|
|
229
|
+
"Unsupported component theme #{value.inspect}; expected one of #{COMPONENT_THEMES.join(', ')}; " \
|
|
230
|
+
"using the deck theme")
|
|
231
|
+
nil
|
|
202
232
|
end
|
|
203
233
|
|
|
204
234
|
def line_range(value, max_line: nil)
|
|
@@ -6,14 +6,13 @@ module Jekyll
|
|
|
6
6
|
module Slides
|
|
7
7
|
module JekyllIntegration
|
|
8
8
|
DEFAULTS = {
|
|
9
|
-
"theme" =>
|
|
9
|
+
"theme" => DEFAULT_THEME,
|
|
10
10
|
"aspect_ratio" => "16:9",
|
|
11
11
|
"progress" => true,
|
|
12
12
|
"slide_numbers" => true,
|
|
13
13
|
"overview" => true,
|
|
14
14
|
"fullscreen" => true
|
|
15
15
|
}.freeze
|
|
16
|
-
THEMES = %w[minimal-light minimal-dark midnight ruby].freeze
|
|
17
16
|
BOOLEAN_OPTIONS = %w[progress slide_numbers overview fullscreen].freeze
|
|
18
17
|
OPTION_KEYS = DEFAULTS.keys.freeze
|
|
19
18
|
|
|
@@ -85,7 +84,7 @@ module Jekyll
|
|
|
85
84
|
theme = value.to_s
|
|
86
85
|
return theme if THEMES.include?(theme)
|
|
87
86
|
|
|
88
|
-
warning("Invalid theme #{value.inspect}; falling back to
|
|
87
|
+
warning("Invalid theme #{value.inspect}; expected one of #{THEMES.join(', ')}; falling back to #{DEFAULT_THEME}")
|
|
89
88
|
DEFAULTS[key]
|
|
90
89
|
when "aspect_ratio"
|
|
91
90
|
return value if value == DEFAULTS[key]
|
data/lib/jekyll/slides.rb
CHANGED
|
@@ -12,8 +12,7 @@ module Jekyll
|
|
|
12
12
|
# while preserving the site's theme and local overrides.
|
|
13
13
|
#
|
|
14
14
|
# Configure defaults under +slides:+ in _config.yml, or use front matter on
|
|
15
|
-
# individual decks.
|
|
16
|
-
# and +ruby+. The supported aspect ratio is 16:9; quote this value in YAML.
|
|
15
|
+
# individual decks. The supported aspect ratio is 16:9; quote this value in YAML.
|
|
17
16
|
#
|
|
18
17
|
# Jekyll runs Liquid before rendering each slide as one Markdown document.
|
|
19
18
|
# Jekyll::Slides::Presentation also renders slide HTML directly when Jekyll integration
|
|
@@ -21,6 +20,21 @@ module Jekyll
|
|
|
21
20
|
module Slides
|
|
22
21
|
ROOT = File.expand_path("../..", __dir__)
|
|
23
22
|
LAYOUT_NAME = "presentation"
|
|
23
|
+
|
|
24
|
+
# Every deck palette the plugin ships. A theme sets the whole deck through
|
|
25
|
+
# front matter, and any one of them also restyles a single editor or
|
|
26
|
+
# terminal block through that block's +theme+ attribute.
|
|
27
|
+
THEMES = %w[
|
|
28
|
+
minimal-light minimal-dark midnight ruby
|
|
29
|
+
catppuccin-latte catppuccin-frappe catppuccin-macchiato catppuccin-mocha
|
|
30
|
+
].freeze
|
|
31
|
+
|
|
32
|
+
# Every palette a single editor or terminal block may carry: the deck
|
|
33
|
+
# palettes plus the ones that exist only at window scale. +macos-light+ is
|
|
34
|
+
# a flat light code window meant to sit inside a deck of any color, so it
|
|
35
|
+
# defines no slide background or type scale and cannot be a deck theme.
|
|
36
|
+
COMPONENT_THEMES = (THEMES + %w[macos-light]).freeze
|
|
37
|
+
DEFAULT_THEME = "midnight"
|
|
24
38
|
end
|
|
25
39
|
end
|
|
26
40
|
|
data/{llm.txt → llms.txt}
RENAMED
|
@@ -13,9 +13,8 @@ includes, styles, scripts, and offline fonts while preserving the site's theme
|
|
|
13
13
|
and local overrides.
|
|
14
14
|
|
|
15
15
|
Configure defaults under <code>slides:</code> in _config.yml, or use front
|
|
16
|
-
matter on individual decks.
|
|
17
|
-
|
|
18
|
-
quote this value in YAML.
|
|
16
|
+
matter on individual decks. The supported aspect ratio is 16:9; quote this
|
|
17
|
+
value in YAML.
|
|
19
18
|
|
|
20
19
|
Jekyll runs Liquid before rendering each slide as one Markdown document.
|
|
21
20
|
Jekyll::Slides::Presentation also renders slide HTML directly when Jekyll
|
|
@@ -23,12 +22,26 @@ integration is not needed; it does not evaluate Liquid or wrap the
|
|
|
23
22
|
presentation layout.
|
|
24
23
|
|
|
25
24
|
## Constants
|
|
25
|
+
### `COMPONENT_THEMES` <a id="constant-COMPONENT_THEMES"></a> <a id="COMPONENT_THEMES-constant"></a>
|
|
26
|
+
Every palette a single editor or terminal block may carry: the deck palettes
|
|
27
|
+
plus the ones that exist only at window scale. <code>macos-light</code> is a
|
|
28
|
+
flat light code window meant to sit inside a deck of any color, so it defines
|
|
29
|
+
no slide background or type scale and cannot be a deck theme.
|
|
30
|
+
|
|
31
|
+
### `DEFAULT_THEME` <a id="constant-DEFAULT_THEME"></a> <a id="DEFAULT_THEME-constant"></a>
|
|
32
|
+
Not documented.
|
|
33
|
+
|
|
26
34
|
### `LAYOUT_NAME` <a id="constant-LAYOUT_NAME"></a> <a id="LAYOUT_NAME-constant"></a>
|
|
27
35
|
Not documented.
|
|
28
36
|
|
|
29
37
|
### `ROOT` <a id="constant-ROOT"></a> <a id="ROOT-constant"></a>
|
|
30
38
|
Not documented.
|
|
31
39
|
|
|
40
|
+
### `THEMES` <a id="constant-THEMES"></a> <a id="THEMES-constant"></a>
|
|
41
|
+
Every deck palette the plugin ships. A theme sets the whole deck through front
|
|
42
|
+
matter, and any one of them also restyles a single editor or terminal block
|
|
43
|
+
through that block's `theme` attribute.
|
|
44
|
+
|
|
32
45
|
### `VERSION` <a id="constant-VERSION"></a> <a id="VERSION-constant"></a>
|
|
33
46
|
Not documented.
|
|
34
47
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-slides
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lucian Ghinda
|
|
@@ -153,7 +153,7 @@ files:
|
|
|
153
153
|
- lib/jekyll/slides/slide_renderer.rb
|
|
154
154
|
- lib/jekyll/slides/support.rb
|
|
155
155
|
- lib/jekyll/slides/version.rb
|
|
156
|
-
-
|
|
156
|
+
- llms.txt
|
|
157
157
|
homepage: https://github.com/lucianghinda/jekyll-slides
|
|
158
158
|
licenses:
|
|
159
159
|
- Apache-2.0
|