From 106edd1df0e44beecbdde88f57bc7d80282acabc Mon Sep 17 00:00:00 2001 From: Rayhaan Jaufeerally Date: Sun, 20 Sep 2026 21:30:41 +0200 Subject: [PATCH] slides: reveal.js deck template for the BGP lecture Structured like Matt Godbolt's newer talks (hrt-theme.css in what-happens-beneath-accu-2026): reveal.js with no stock theme but a custom dark one, every slide on a rounded panel, IBM Plex Sans and Mono, monokai code with glowing stepped lines, 16:9 with fade transitions, and the content in one Markdown file per section. Made our own: the palette is a handful of variables (with ?accent= presets for comparing), and his ring-and-thread corner motif became a chain of nodes and links, an AS path, which also opens the title slide. A wordmark sits where his decks carry the employer logo. Also: a small `bird` syntax highlighter for router config on slides, a bytes component in the four groups of the /statusz bytes view, columns, boxes, and a `bare` slide class. reveal.js 6 loads from a vendored copy when slides/vendor-reveal.sh has been run (works offline, ignored by git) and from the CDN otherwise. Section files carry a starter outline for the lab that doubles as a tour of the slide types. Co-Authored-By: Claude Fable 5.1 --- .gitignore | 1 + slides/README.md | 81 ++++++ slides/images/favicon.svg | 8 + slides/images/placeholder.svg | 5 + slides/index.html | 143 ++++++++++ slides/sections/01-intro.md | 31 +++ slides/sections/02-bgp.md | 53 ++++ slides/sections/03-lab.md | 61 +++++ slides/sections/04-communities.md | 25 ++ slides/sections/05-wrap-up.md | 21 ++ slides/style.css | 177 ++++++++++++ slides/theme.css | 429 ++++++++++++++++++++++++++++++ slides/vendor-reveal.sh | 16 ++ 13 files changed, 1051 insertions(+) create mode 100644 slides/README.md create mode 100644 slides/images/favicon.svg create mode 100644 slides/images/placeholder.svg create mode 100644 slides/index.html create mode 100644 slides/sections/01-intro.md create mode 100644 slides/sections/02-bgp.md create mode 100644 slides/sections/03-lab.md create mode 100644 slides/sections/04-communities.md create mode 100644 slides/sections/05-wrap-up.md create mode 100644 slides/style.css create mode 100644 slides/theme.css create mode 100755 slides/vendor-reveal.sh diff --git a/.gitignore b/.gitignore index df611ec..58cbbf1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target __pycache__/ +slides/reveal.js/ diff --git a/slides/README.md b/slides/README.md new file mode 100644 index 0000000..58f859b --- /dev/null +++ b/slides/README.md @@ -0,0 +1,81 @@ +# Slides + +A reveal.js deck structured like Matt Godbolt's newer talks +([what-happens-beneath-accu-2026](https://github.com/mattgodbolt/what-happens-beneath-accu-2026)): +no stock theme but a custom dark one, every slide on a rounded panel, IBM Plex +Sans and Mono, monokai code with glowing stepped lines, 16:9 with fade +transitions, and the content in one Markdown file per section. + +What is ours: the palette, and the corner motif. His ring-and-thread became a +chain of nodes and links, an AS path, which also opens the title slide. + +| File | Holds | +|---|---| +| `theme.css` | the look: palette, type, panels, motif, title slide | +| `style.css` | components used by slides: columns, boxes, bytes, notes | +| `index.html` | section list, reveal.js loader and options, `bird` highlighter | +| `sections/*.md` | the slides | + +## Make it yours + +Everything brand-like is a variable at the top of `theme.css`. To compare +accents without editing, open `?accent=green`, `?accent=amber` or +`?accent=magenta` (blue is the default); copy the one you like into `:root`. +The wordmark bottom-left is the `
` in `index.html`. +For a full-bleed title image, empty the title `
` and give it +`data-background="images/title.png"`. + +## Show it + +The sections are loaded over HTTP, so open the deck through a server, not as a +file: + + python3 -m http.server 8000 --directory slides + +Then . Keys: arrows to move, `S` speaker view with +notes and a timer, `O` overview, `F` fullscreen, `B` blank the screen. + +## Offline + + slides/vendor-reveal.sh + +copies reveal.js into `slides/reveal.js/` (ignored by git). The deck uses that +copy when present and the CDN otherwise. Do this before presenting anywhere +with uncertain Wi-Fi. IBM Plex still comes from Google Fonts; without a +network the deck falls back to Helvetica/Arial and the system monospace, so +install IBM Plex on the presenting machine if that matters. + +## Write slides + +Edit the files in `sections/`; add a section by adding a file and a +`
` line in `index.html`. + + ----- next slide + --- next vertical slide (detail you can skip) + Notes: speaker notes from here to the end of the slide + +Apply a class to the element above with ``. + +| Class | Effect | +|---|---| +| `fragment` | appears on the next click | +| `fragment pop` | appears, grows and takes the accent colour | +| `big` | one large statement on the slide | +| `note` | quiet italic aside | +| `attribution` | small credit under an image or quote | +| `borders` | table with visible borders | +| `r-stretch` | image or iframe fills the remaining height | +| `blur-edges` | soft edge for photos | + +Blocks: `
` two columns, `
` labelled cards +(`us`, `ok`, `bad`), `
` BGP bytes in the colours of the lab
+page. Code fences take a language and optional line steps, e.g.
+` ```bird [1-3|5-9] `; `bird` is a small highlighter defined in `index.html`.
+
+`` drops the panel, the motif and the wordmark
+for one slide, e.g. a full-bleed image. The title slide does so by itself.
+
+## PDF
+
+Open  in Chrome and print to PDF with
+background graphics on.
diff --git a/slides/images/favicon.svg b/slides/images/favicon.svg
new file mode 100644
index 0000000..a112e20
--- /dev/null
+++ b/slides/images/favicon.svg
@@ -0,0 +1,8 @@
+
+  
+  
+    
+    
+    
+  
+
diff --git a/slides/images/placeholder.svg b/slides/images/placeholder.svg
new file mode 100644
index 0000000..176616d
--- /dev/null
+++ b/slides/images/placeholder.svg
@@ -0,0 +1,5 @@
+
+  
+  your picture here
+  slides/images/
+
diff --git a/slides/index.html b/slides/index.html
new file mode 100644
index 0000000..5c9dbd9
--- /dev/null
+++ b/slides/index.html
@@ -0,0 +1,143 @@
+
+
+  
+    
+    
+    BGP hands-on: announce your own prefix
+    
+    
+    
+    
+    
+  
+  
+    
+
+ +
+ +

Announce your own prefix

+

A hands-on introduction to BGP

+ +
+ + +
+
+
+
+
+
+
+ +
ferrix_bgp · netsec 2026
+ + + + diff --git a/slides/sections/01-intro.md b/slides/sections/01-intro.md new file mode 100644 index 0000000..c84b356 --- /dev/null +++ b/slides/sections/01-intro.md @@ -0,0 +1,31 @@ +## Today + +* What BGP is, in ten minutes +* You announce a real prefix to the real Internet +* You steer where it goes with communities +* We look at what could go wrong + +Notes: +Speaker notes go after a line that starts with "Notes:". Press S to open the +speaker view; it shows these, a timer, and the next slide. + +----- + +The Internet is about +75,000 +networks that agreed to talk to each other. + + + +Notes: +One idea per slide, large. The class="big" comment applies to the paragraph +above it. "pop" is a fragment that grows when it appears. +A slide with class "bare" drops the panel and the path motif: + +----- + +Replace with a picture + +Replace `images/placeholder.svg`. `r-stretch` makes an image fill the slide. + + diff --git a/slides/sections/02-bgp.md b/slides/sections/02-bgp.md new file mode 100644 index 0000000..9ca0309 --- /dev/null +++ b/slides/sections/02-bgp.md @@ -0,0 +1,53 @@ +## An autonomous system + +
+
AS210036
our upstream
+
AS559
SWITCH
+
AS6939
Hurricane Electric
+
AS13335
Cloudflare
+
+ +A network under one administration, with a number. + +Notes: +"boxes" lays out small labelled cards. Classes: us, ok, bad. + +----- + +## A route is a prefix plus a promise + +```text +2a0d:d741:1::/48 via AS210036 AS4200000001 + ^ nearest ^ origin +``` + +"Send me traffic for this prefix. It crossed these networks to reach you." + + + +----- + +## What actually goes on the wire + +
headerlengthspath attributesNLRI
+ +
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 50 02 00 00 00 35 40 01 01 00 40 02 0a 02 02 00 00 fd e8 00 00 fd e8 40 03 04 7f 00 00 01 80 04 04 00 00 00 32 c0 08 04 fd e8 00 64 18 0a 64 01
+ +Same colours as the bytes view on the lab page, so you can point from one to the other. + + + +--- + +## Going deeper (a vertical slide) + +Press ↓. Put detail here that you can skip when short of time. + +| Attribute | Type | Meaning | +|---|---|---| +| ORIGIN | 1 | how the route entered BGP | +| AS_PATH | 2 | networks it crossed | +| COMMUNITIES | 8 | 32-bit tags, meaning by agreement | +| LARGE_COMMUNITIES | 32 | three 32-bit numbers | + + diff --git a/slides/sections/03-lab.md b/slides/sections/03-lab.md new file mode 100644 index 0000000..5fa40f0 --- /dev/null +++ b/slides/sections/03-lab.md @@ -0,0 +1,61 @@ +## The lab + +
+
+ +* Open the status page +* Your prefix is `2a0d:d741:::/48` +* `n` is your number, **in hex** +* Use your name as owner + +
+
+ +```text + you ─▶ ferrix ─▶ AS210036 ─▶ SwissIX ─▶ … + AS42000… (BIRD) +``` + +
+
+ +Notes: +"cols" gives two equal columns. Leave a blank line after the opening div and +before the closing one, or the Markdown inside is not parsed. + +----- + +## The router's side + +```bird [1-3|5-9|11] +filter ferrix_import { + if !(net ~ [ 2a0d:d741::/40{48,48} ]) then reject; + if bgp_path.first != 4200000001 then reject; + + bgp_community.filter([ (65535, 65281), (65535, 65282) ]); + bgp_large_community.filter([ (42476, *, *), (210036, 0..3, *) ]); + bgp_ext_community.empty; + + dest = RTD_UNREACHABLE; + accept; +} +``` + +`[1-3|5-9|11]` steps through the highlighted lines on each click. + + + +----- + +## Live + + + +Point `data-src` at the status page to have it live on the slide. + + + +Notes: +A live page on the slide is very much the Godbolt move. It needs the network, +and a page behind a password will prompt inside the frame. Have a screenshot +on a vertical slide below as the fallback. diff --git a/slides/sections/04-communities.md b/slides/sections/04-communities.md new file mode 100644 index 0000000..796cb10 --- /dev/null +++ b/slides/sections/04-communities.md @@ -0,0 +1,25 @@ +## Communities + +Tags on a route. They mean whatever the receiving network says they mean. + +
+
NO_EXPORT
65535:65281
+
BLACKHOLE
65535:666
+
210036:0:0
announce nowhere
+
42476:1:559
SwissIX: only SWITCH
+
+ +----- + +## Two hops, one idea + +| You set | Who acts | Effect | +|---|---|---| +| `210036:0:0` `210036:1:42476` | our router | only the SwissIX route servers | +| `42476:0:0` `42476:1:559` | SwissIX | only SWITCH | + + + +Now find your prefix on a looking glass. Who can see it? + + diff --git a/slides/sections/05-wrap-up.md b/slides/sections/05-wrap-up.md new file mode 100644 index 0000000..a0aaedc --- /dev/null +++ b/slides/sections/05-wrap-up.md @@ -0,0 +1,21 @@ +## What could go wrong? + +* Anyone can announce anything +* Filters are the only thing between a typo and an outage +* IRR objects and RPKI say who *may* announce a prefix + +----- + +> "The Internet works because a lot of people are careful, most of the time." + +Quotes use a plain Markdown blockquote. + + + +----- + +## Thank you + +Questions? + +

Slides: slides/ in the ferrix_bgp repository

diff --git a/slides/style.css b/slides/style.css new file mode 100644 index 0000000..8a85c51 --- /dev/null +++ b/slides/style.css @@ -0,0 +1,177 @@ +/* + * Components and helpers used by the slides. The look (palette, type, panels, + * motif) is in theme.css; nothing here sets a brand colour directly. + */ + +.hidden { + display: none; +} + +/* ---- text -------------------------------------------------------------------- */ + +/* A quiet aside under the main point. */ +.reveal .note { + font-style: italic; + font-size: 75%; + color: var(--muted); +} + +/* Image and quote credits: */ +.reveal .attribution { + font-size: 45%; + font-style: italic; + color: var(--muted); +} + +/* One big statement on an otherwise empty slide. */ +.reveal .big { + font-size: 1.9em; + font-weight: 300; + line-height: 1.25; + color: var(--ink-strong); +} + +/* A fragment that grows when it appears, for the one thing to look at. It + grows by font size, not transform, so the text around it makes room. */ +.reveal .pop { + transition: font-size 0.4s ease, color 0.4s ease; +} + +.reveal .pop.visible { + font-size: 1.5em; + font-weight: 700; + color: var(--accent); +} + +/* ---- layout ------------------------------------------------------------------ */ + +.container { + display: flex; + justify-content: center; + align-items: center; + gap: 1em; +} + +.flex-around { + display: flex; + justify-content: space-around; + align-items: flex-start; + gap: 1em; +} + +/* Two equal columns:
…
…
*/ +.cols { + display: flex; + gap: 1.2em; + align-items: center; + text-align: left; +} + +.cols > * { + flex: 1 1 0; + min-width: 0; +} + +.float-left { + float: left; +} + +.float-right { + float: right; +} + +.no-border { + background: none !important; + border: none !important; + box-shadow: none !important; +} + +.reveal img.blur-edges { + border-radius: 12px; + box-shadow: 0 0 25px 8px rgba(0, 0, 0, 0.5); +} + +.reveal table.borders td, +.reveal table.borders th { + border: 1px solid var(--rule); +} + +/* ---- boxes: small labelled cards, e.g. one per AS or per community ----------- */ + +.boxes { + display: flex; + flex-wrap: wrap; + justify-content: center; + font-size: 70%; + margin: 0.6em 0; +} + +.boxes > div { + padding: 0.35em 0.8em; + margin: 0.3em 0.5em; + border: 1px solid var(--rule); + border-radius: 10px; + background: var(--ground); + line-height: 1.35; +} + +.boxes > div.us { + border-color: var(--accent); + box-shadow: 0 0 18px rgba(var(--accent-rgb), 0.35); + color: var(--ink-strong); +} + +.boxes > div.ok { + border-color: #4fd98a; +} + +.boxes > div.bad { + border-color: #ff6b6b; +} + +/* ---- BGP bytes, matching the four groups of the /statusz bytes view ---------- */ + +.reveal pre.bytes { + font-size: 0.5em; + line-height: 1.9; + white-space: pre-wrap; + word-break: break-all; + background: rgba(8, 9, 20, 0.65); + border-radius: 6px; + padding: 15px 20px; + box-sizing: border-box; + color: var(--ink); +} + +.bytes span, +.legend span { + border-radius: 3px; + padding: 1px 3px; +} + +.bytes .hh, +.legend .hh { background: #34406e; } +.bytes .hl, +.legend .hl { background: #6e3440; } +.bytes .ha, +.legend .ha { background: #245c3a; } +.bytes .ha2 { background: #2f7a4b; } +.bytes .hn, +.legend .hn { background: #6b5a1f; } + +.legend { + font-size: 50%; + font-family: var(--r-code-font); +} + +.legend span { + padding: 1px 0.6em; + margin: 0 0.2em; +} + +/* A framed live page on a slide. */ +.reveal iframe.live { + border: 1px solid var(--rule); + border-radius: 8px; + background: #fff; +} diff --git a/slides/theme.css b/slides/theme.css new file mode 100644 index 0000000..9889be9 --- /dev/null +++ b/slides/theme.css @@ -0,0 +1,429 @@ +/* + * The look of the deck. Structure borrowed from Matt Godbolt's newer talks + * (hrt-theme.css in github.com/mattgodbolt/what-happens-beneath-accu-2026): + * near-black navy ground, every slide on a rounded panel, IBM Plex Sans with + * thin white h1 and bold accent h2, IBM Plex Mono code, accent-coloured list + * markers, links and progress bar, glowing highlighted code lines. + * + * Made our own: the palette is ours (change it in :root below), and his + * "thread" motif becomes a chain of nodes and links, an AS path. + * + * Try accents without editing: index.html?accent=green (blue, green, + * amber, magenta). Make one permanent by copying its values into :root. + */ +@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&family=IBM+Plex+Mono:ital,wght@0,400;0,500;1,400&display=swap"); + +:root { + --ground: #11131f; /* behind the panels */ + --panel: #1b1e33; /* the slide itself */ + --panel-edge: rgba(94, 177, 255, 0.14); + --ink: #eceff9; /* body text */ + --ink-strong: #ffffff; /* h1, h3 */ + --muted: #7d7f99; /* h4, captions */ + --rule: #4f526b; /* table rules, borders */ + --accent: #5eb1ff; /* h2, markers, links, motif */ + --accent-soft: #b7dcff; /* inline code, emphasis */ + --accent-rgb: 94, 177, 255; + --r-code-font: "IBM Plex Mono", "SF Mono", Menlo, Consolas, monospace; + --r-heading-text-shadow: none; +} + +:root[data-accent="green"] { + --accent: #4fd98a; + --accent-soft: #b5f0cf; + --accent-rgb: 79, 217, 138; + --panel-edge: rgba(79, 217, 138, 0.14); +} + +:root[data-accent="amber"] { + --accent: #ffb020; + --accent-soft: #ffdc99; + --accent-rgb: 255, 176, 32; + --panel-edge: rgba(255, 176, 32, 0.14); +} + +:root[data-accent="magenta"] { + --accent: #ff6ac1; + --accent-soft: #ffc2e6; + --accent-rgb: 255, 106, 193; + --panel-edge: rgba(255, 106, 193, 0.14); +} + +/* ---- ground and panels ---------------------------------------------------- */ + +.reveal-viewport { + background: var(--ground); +} + +.reveal { + font-family: "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif; + font-size: 40px; + font-weight: 400; + color: var(--ink); +} + +.reveal .slides section:not(.stack):not(.title-slide):not(.bare) { + background-color: var(--panel); + border-radius: 12px; + box-shadow: 0 4px 30px rgba(0, 0, 0, 0.3); + border: 1px solid var(--panel-edge); + padding: 1em 0.8em; + box-sizing: border-box; +} + +/* ---- type ------------------------------------------------------------------ */ + +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4 { + font-family: inherit; + text-transform: none; + text-shadow: none; + margin: 0 0 20px 0; + line-height: 1.25; +} + +.reveal h1 { + font-weight: 300; + color: var(--ink-strong); + font-size: 2.2em; + line-height: 1.15; +} + +.reveal h2 { + font-weight: 700; + color: var(--accent); + font-size: 1.5em; +} + +.reveal h3 { + font-weight: 500; + color: var(--ink-strong); + font-size: 1.2em; +} + +.reveal h4 { + font-weight: 500; + color: var(--muted); + font-size: 1em; +} + +.reveal p { + margin: 20px 0; + line-height: 1.5; +} + +.reveal strong, +.reveal b { + font-weight: 700; + color: var(--ink-strong); +} + +.reveal em { + font-style: italic; + color: var(--accent-soft); +} + +.reveal a { + color: var(--accent); + text-decoration: none; + transition: color 0.15s ease; +} + +.reveal a:hover { + color: var(--accent-soft); +} + +.reveal ul, +.reveal ol { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; +} + +.reveal ul { + list-style-type: square; +} + +.reveal ul li, +.reveal ol li { + margin-bottom: 0.4em; +} + +.reveal li::marker { + color: var(--accent); +} + +.reveal blockquote { + background: var(--ground); + border-left: 4px solid var(--accent); + padding: 20px 30px; + font-style: italic; + width: 85%; + margin: 20px auto; + text-align: left; +} + +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; +} + +.reveal kbd { + font-family: var(--r-code-font); + font-size: 80%; + border: 1px solid var(--rule); + border-bottom-width: 3px; + border-radius: 5px; + padding: 0 0.35em; +} + +/* ---- code ------------------------------------------------------------------ */ + +.reveal pre { + width: 100%; + margin: 20px auto; + box-shadow: none; + text-align: left; + position: relative; + font-size: 0.55em; + line-height: 1.4; +} + +.reveal code { + font-family: var(--r-code-font); + color: var(--accent-soft); +} + +.reveal :not(pre) > code { + white-space: nowrap; + font-size: 92%; +} + +.reveal pre code { + display: block; + color: var(--ink); + background: rgba(8, 9, 20, 0.65); + border-radius: 6px; + padding: 15px 20px; + max-height: 560px; + overflow: auto; +} + +/* The lines being talked about glow; the rest dim (reveal handles the dim). */ +.reveal .hljs.has-highlights tr.highlight-line { + text-shadow: + 0 0 6px currentColor, + 0 0 12px currentColor; + transition: text-shadow 0.4s ease; +} + +/* ---- tables ---------------------------------------------------------------- */ + +.reveal table { + border-collapse: collapse; + border-spacing: 0; + margin: 20px auto; + font-size: 75%; +} + +.reveal table th { + font-weight: 700; + color: var(--ink-strong); +} + +.reveal table th, +.reveal table td { + text-align: left; + border-bottom: 1px solid var(--rule); + padding: 0.25em 0.6em; +} + +.reveal table tr:last-child td { + border-bottom: none; +} + +/* ---- reveal chrome ---------------------------------------------------------- */ + +.reveal .controls { + color: var(--accent); + bottom: 40px; +} + +.reveal .progress { + background: var(--panel); + height: 4px; +} + +.reveal .progress span { + background: var(--accent); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); +} + +.reveal .slide-number { + color: var(--ground); + font-family: var(--r-code-font); + font-size: 18px; + font-weight: 500; + background: rgba(var(--accent-rgb), 0.9); + padding: 3px 9px; + border-radius: 4px; + right: 16px; + bottom: 16px; +} + +::selection { + color: var(--ground); + background: var(--accent); +} + +/* ---- the path motif --------------------------------------------------------- + * Matt's decks carry a ring with a line running off the edge. Ours is a short + * AS path: nodes joined by links, heading off the top-right corner, mirrored + * running up from the bottom-left. Drawn in the accent colour via a mask, so + * it follows --accent. Hidden on the title slide and on "bare" slides. + */ +.reveal::before, +.reveal-viewport::before { + content: ""; + position: fixed; + background: var(--accent); + z-index: 0; + pointer-events: none; + opacity: 0.9; +} + +.reveal::before { + top: 26px; + right: 0; + width: 38vw; + height: 22px; + -webkit-mask: + url("data:image/svg+xml;utf8,") + left center / 190px 22px no-repeat, + linear-gradient(black, black) 189px center / calc(100% - 189px) 3px no-repeat; + mask: + url("data:image/svg+xml;utf8,") + left center / 190px 22px no-repeat, + linear-gradient(black, black) 189px center / calc(100% - 189px) 3px no-repeat; +} + +.reveal-viewport::before { + bottom: 64px; + left: 40px; + width: 22px; + height: 36vh; + -webkit-mask: + url("data:image/svg+xml;utf8,") + center bottom / 22px 126px no-repeat, + linear-gradient(black, black) center top / 3px calc(100% - 125px) no-repeat; + mask: + url("data:image/svg+xml;utf8,") + center bottom / 22px 126px no-repeat, + linear-gradient(black, black) center top / 3px calc(100% - 125px) no-repeat; +} + +.reveal:has(> .slides > section.title-slide.present)::before, +.reveal:has(> .slides section.bare.present)::before { + display: none; +} + +.reveal-viewport:has(.reveal > .slides > section.title-slide.present)::before, +.reveal-viewport:has(.reveal > .slides section.bare.present)::before { + display: none; +} + +.reveal:has(section.title-slide.present) .controls { + display: none !important; +} + +/* ---- wordmark, where his logo sits ------------------------------------------ */ + +.wordmark { + position: fixed; + left: 22px; + bottom: 18px; + z-index: 10; + font-family: var(--r-code-font); + font-size: 15px; + letter-spacing: 0.04em; + color: var(--muted); + pointer-events: none; +} + +.wordmark b { + color: var(--accent); + font-weight: 500; +} + +.reveal:has(section.title-slide.present) ~ .wordmark, +.reveal:has(section.bare.present) ~ .wordmark { + display: none; +} + +/* ---- title slide -------------------------------------------------------------- */ + +.reveal section.title-slide { + text-align: left; + padding: 0 1.5em; +} + +.reveal section.title-slide h1 { + font-size: 2.6em; + margin-bottom: 0.15em; +} + +.reveal section.title-slide h3 { + font-weight: 400; + color: var(--accent); + margin-bottom: 1.6em; +} + +.reveal section.title-slide .byline { + font-size: 60%; + color: var(--muted); + margin: 0; +} + +.reveal section.title-slide .as-path { + display: block; + width: 100%; + max-width: none; + height: 90px; + margin: 0 0 1em; +} + +.as-path circle { + fill: var(--ground); + stroke: var(--accent); + stroke-width: 3; +} + +.as-path line { + stroke: var(--accent); + stroke-width: 3; +} + +.as-path text { + font-family: "IBM Plex Mono", monospace; + font-size: 15px; + fill: var(--muted); +} + +.as-path .you circle { + fill: var(--accent); +} + +.as-path .you text { + fill: var(--ink-strong); +} + +/* ---- print ------------------------------------------------------------------ */ + +html.print-pdf .wordmark, +html.reveal-print .wordmark { + display: none; +} diff --git a/slides/vendor-reveal.sh b/slides/vendor-reveal.sh new file mode 100755 index 0000000..c746ea9 --- /dev/null +++ b/slides/vendor-reveal.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# Copies reveal.js into ./reveal.js so the deck works with no network. +# index.html uses this copy when it exists and the CDN otherwise. Keep VERSION +# in step with the one in index.html. +set -eu +VERSION=6.0.2 +cd "$(dirname "$0")" +tmp=$(mktemp -d) +trap 'rm -rf "$tmp"' EXIT +npm pack "reveal.js@$VERSION" --pack-destination "$tmp" --silent >/dev/null 2>&1 +tar -xzf "$tmp/reveal.js-$VERSION.tgz" -C "$tmp" +rm -rf reveal.js +mkdir -p reveal.js +cp -R "$tmp/package/dist" reveal.js/dist +cp "$tmp/package/LICENSE" reveal.js/LICENSE +echo "reveal.js $VERSION vendored into $(pwd)/reveal.js ($(du -sh reveal.js | cut -f1))"