blob: f431662f0c4acc5bf1c493865af21b4c0d17e85e [file] [log] [blame]
Marc Kupietza737b1b2023-10-07 09:32:20 +02001/**
2 * IDS theme for reveal.js
3 *
4 * By Marc Kupietz
5 */
6
7
8// Default mixins and settings -----------------
9@import "../template/mixins";
10@import "../template/settings";
11// ---------------------------------------------
12
13
14// Include theme-specific fonts
Marc Kupietza0f8f682026-08-08 14:13:11 +020015// NB: https://korap.ids-mannheim.de/font/{fira-condensed,libertinus}.css both
16// return 404, so the condensed and bold faces never loaded and headings fell
17// back to a regular-width, regular-weight face. Google Fonts serves the real
18// Fira Sans Condensed incl. weights 700/800 (this is where the IDS reference
19// decks get it from too); the others are kept for locally installed copies.
20@import url('https://fonts.googleapis.com/css2?family=Fira+Sans+Condensed:wght@300;400;700;800&family=Fira+Sans:wght@200;300;400;700&family=Fira+Sans+Extra+Condensed:wght@300;700&display=swap');
Marc Kupietza737b1b2023-10-07 09:32:20 +020021@import url('https://code.cdn.mozilla.net/fonts/fira.css');
Marc Kupietzc22be152026-08-18 15:54:55 +020022// Fira Code: the monospaced Fira Sans variant for highlighted/code text (as
23// in the IDS reference decks; falls back to Fira Mono from the Mozilla CSS
24// above, then DejaVu Sans Mono)
25@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&display=swap');
Marc Kupietza737b1b2023-10-07 09:32:20 +020026@import url('https://korap.ids-mannheim.de/font/libertinus.css');
27
28$idsOrange: #f6a800;
29
30// Override theme settings (see ../template/settings.scss)
31$backgroundColor: #fff;
32
33$mainColor: #222;
34$headingColor: $idsOrange;
35
36$mainFontSize: 42px;
37$mainFont: 'Libertinus Serif', Helvetica, sans-serif;
Marc Kupietza0f8f682026-08-08 14:13:11 +020038$headingFont: 'Fira Sans Extra Condensed', 'Fira Sans Condensed', 'Fira Sans', Helvetica, sans-serif;
Marc Kupietza737b1b2023-10-07 09:32:20 +020039$headingTextShadow: none;
40$headingLetterSpacing: 0.05ex;
41$headingTextTransform: uppercase;
Marc Kupietza0f8f682026-08-08 14:13:11 +020042$headingFontWeight: 700;
Marc Kupietza737b1b2023-10-07 09:32:20 +020043$linkColor: #2a76dd;
44$linkColorHover: lighten( $linkColor, 15% );
45$selectionBackgroundColor: lighten( $linkColor, 25% );
46
47$heading1Size: 2em;
48$heading2Size: 1.35em;
Marc Kupietz3fdee732023-10-07 18:52:20 +020049$heading3Size: 0.9em;
50$heading4Size: 0.7em;
Marc Kupietza737b1b2023-10-07 09:32:20 +020051
52$listBulletColor: $idsOrange;
53
Marc Kupietzc22be152026-08-18 15:54:55 +020054// --r-code-font (template emits #{$codeFont} as-is)
55$codeFont: "Fira Code", "Fira Mono", "DejaVu Sans Mono", "Source Code Pro", monospace;
56
Marc Kupietza737b1b2023-10-07 09:32:20 +020057// Change text colors against dark slide backgrounds
58@include dark-bg-text-color(#fff);
59
60
61// Theme template ------------------------------
62@import "../template/theme";
63// ---------------------------------------------
64
Marc Kupietza0f8f682026-08-08 14:13:11 +020065// Bar/logo sizes, expressed as fractions of the slide's own height (reveal.js
66// exposes the configured slide size as --slide-width / --slide-height custom
67// properties). Sizing relative to the slide rather than the raw viewport (vh
68// units) keeps things pinned to the true slide edges instead of drifting
69// into the letter-/pillarboxed margins when the window's aspect ratio
70// doesn't exactly match the configured one.
71$idsBarWidthRatio: 0.05;
72$idsLogoWidthRatio: 0.25;
Marc Kupietz59e95a62026-08-29 10:19:05 +030073// Partner (second institution) logo: shown next to the IDS logo on every
74// slide when the document sets the `partner_logo` yaml entry (the template
75// then publishes the URL as the --partner-logo custom property).
76$idsPartnerGap: 16px;
77$idsPartnerHeightRatio: 0.085;
Marc Kupietza0f8f682026-08-08 14:13:11 +020078$idsBarWidth: calc(var(--slide-height) * #{$idsBarWidthRatio});
79$idsHeadingGap: 24px;
80
81// Vertical gap between the title and the subtitle. The subtitle's bar segment
82// reaches up by this much to bridge it, so the two segments read as one bar.
83$idsHeadingSpacing: 8px;
84
85// Rendered height of one subtitle line. Slides without a subtitle reserve
86// exactly this much, so the bar and the start of the body content stay put
87// from slide to slide instead of jumping. Must stay in sync with
88// $heading3Size (0.9em) and $headingLineHeight (1.2, from template/settings).
89$idsSubtitleHeight: 0.9 * $mainFontSize * 1.2;
90
91// The two bar segments abut at a fractional pixel, which browsers round into a
92// visible hairline. Overlapping them slightly makes the join seamless.
93$idsBarOverlap: 2px;
94
95// reveal.js centres the scaled slide in the viewport, so whenever the window's
96// aspect ratio does not match the deck's, an empty band is left beside (or
97// above) the slide and the bar would not reach the window's physical edge.
98// Working out how wide that band is needs viewport / scale, and CSS cannot
99// divide a length by a length -- which is why the hand-written IDS decks solve
100// this in JavaScript. revealjs_presentation()'s template therefore publishes
101// the band widths, in slide coordinates, as --ids-band-left / --ids-band-top,
102// and the bar simply shifts out by that much. Falling back to 0px keeps this
103// correct whenever the aspect ratios do match, and if the script never runs.
104$idsBandLeft: var(--ids-band-left, 0px);
105
106// revealjs_presentation() sets reveal.js' own `margin` option to 0, so that the
107// slide box is the whole viewport and the orange bar can sit flush in its top
108// left corner. That would otherwise leave the body content running edge to
109// edge, so the breathing room reveal.js' margin used to provide is added back
110// here as slide padding; the bar and the headings reach back out to the edge
111// with matching negative margins below. The inset is the bar plus its gap, so
112// body content lines up with the heading text rather than with the bar.
113$idsContentInset: calc(#{$idsBarWidth} + #{$idsHeadingGap});
114
Marc Kupietz61c8ec72026-08-20 20:47:45 +0200115// The html prefix is solely about specificity: reveal's print styles
116// (html.reveal-print .reveal .slides section { padding: 0 !important }) would
117// otherwise beat this rule and flatten the inset on ?print-pdf pages. An html
118// prefix ties that specificity, and since the theme is loaded after
119// reveal.css, this rule wins both on screen and in print.
120html .reveal .slides section:not(.stack) {
Marc Kupietza0f8f682026-08-08 14:13:11 +0200121 box-sizing: border-box !important;
122 padding-left: #{$idsContentInset} !important;
123 padding-right: #{$idsContentInset} !important;
124}
125
126// Body content is left aligned with the headings; the title frame keeps its
127// own centered layout.
128.reveal .slides section:not(.stack):not(.title-frame) {
129 text-align: left !important;
130}
131
132// reveal.js centers lists by making them inline-block; make them ordinary
Marc Kupietze0826862026-08-11 16:34:54 +0200133// blocks so they line up with the headings.
134//
135// The markers are NOT native ::marker glyphs: browsers anchor outside-position
136// markers at slightly different offsets per engine (and per scale), and even
137// ::before font glyphs carry font-specific side bearings, so a padding(text)-
138// based alignment of the bullet column with the heading text can never be
139// pixel-exact everywhere. Instead we DRAW the markers as CSS boxes in
140// absolutely positioned li::before rules. Geometry (all values in the item's
141// own font size, so the hierarchy scales with the 0.8em per-level sizing from
142// the NESTED LISTS section below):
143//
144// - item text starts at (list left edge) + 0.65em
145// - the marker box starts exactly at the list's left edge; on content
146// slides that edge coincides with the heading text's left edge, i.e. the
147// bullet column is flush with the slide title, deterministically in every
148// browser and at every window size
149//
150// For nested lists the ::before offset has to be divided by the 0.8 font-size
151// factor, because the list's padding is computed in the PARENT item's font
152// size while the ::before offset is computed in the (smaller) child size.
153$idsListIndent: 0.65em;
154$idsListShrink: 0.8;
155$idsMarkerSize: 0.22em;
156$idsMarkerTop: calc((1.3em - #{$idsMarkerSize}) / 2);
157
Marc Kupietza0f8f682026-08-08 14:13:11 +0200158.reveal .slides section:not(.title-frame) ul,
159.reveal .slides section:not(.title-frame) ol {
160 display: block !important;
161 text-align: left !important;
162 margin-left: 0 !important;
Marc Kupietze0826862026-08-11 16:34:54 +0200163 padding-left: $idsListIndent !important;
164 list-style: none !important;
165}
166
167.reveal .slides section:not(.title-frame) li {
168 position: relative !important;
169}
170
171.reveal .slides section:not(.title-frame) li::before {
172 position: absolute !important;
173 left: calc(-1 * #{$idsListIndent}) !important;
174 color: var(--r-list-bullet-color) !important;
175}
176
177.reveal .slides section:not(.title-frame) li li::before {
178 left: calc(-1 * #{$idsListIndent} / #{$idsListShrink}) !important;
179}
180
181// Unordered-list markers: drawn boxes (round dot, square, ring for deeper
182// levels), vertically centered on the item's first line.
183.reveal .slides section:not(.title-frame) ul > li::before {
184 content: "" !important;
185 top: $idsMarkerTop !important;
186 width: $idsMarkerSize !important;
187 height: $idsMarkerSize !important;
188 box-sizing: border-box !important;
189 border-radius: 50% !important;
190 background: var(--r-list-bullet-color) !important;
191}
192
193.reveal .slides section:not(.title-frame) ul ul > li::before {
194 border-radius: 0 !important; // square
195}
196
197.reveal .slides section:not(.title-frame) ul ul ul > li::before {
198 background: transparent !important; // ring
199 border: 0.055em solid var(--r-list-bullet-color) !important;
200 border-radius: 50% !important;
201}
202
203// Ordered lists: the CSS list-item counter honours the HTML start/value
204// attributes, so pandoc's `start`/`value` lists keep their numbers. Numbers
Marc Kupietzde3ffa42026-08-30 13:47:57 +0300205// are anchored with their right edge $idsNumberGap away from the item text
206// (a shrink-to-fit box; anchoring from the right instead of a fixed-width,
207// right-aligned box, because over-wide numbers would otherwise overflow
208// INTO the text). Longer numbers like "10." grow to the left.
209$idsNumberGap: 0.3em;
210
Marc Kupietze0826862026-08-11 16:34:54 +0200211.reveal .slides section:not(.title-frame) ol > li::before {
212 content: counter(list-item, decimal) "." !important;
Marc Kupietzde3ffa42026-08-30 13:47:57 +0300213 left: auto !important;
214 right: 100% !important;
215 margin-right: $idsNumberGap !important;
Marc Kupietze0826862026-08-11 16:34:54 +0200216}
217
218// Checkbox (pandoc task) lists keep their checkboxes, no markers on top.
219.reveal .slides section:not(.title-frame) ul.task-list li::before {
220 content: none !important;
Marc Kupietza0f8f682026-08-08 14:13:11 +0200221}
222
223// reveal.js centres code blocks (width: 90%; margin: auto); make them fill the
224// slide's text column so they start on the same left edge as the headings.
225.reveal .slides section:not(.title-frame) pre {
226 width: auto !important;
227 margin-left: 0 !important;
228 margin-right: 0 !important;
229}
230
231// The IDS logo stays a slide-wide watermark (top right of every slide,
Marc Kupietz28822cd2026-08-20 14:10:18 +0200232// including the title page). The SVG carries no internal padding of its own,
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300233// so it needs an explicit inset from the slide's edges. That inset is shared
234// by everything that sits in a corner of the slide -- IDS (+ partner) logo
235// top right, website QR top left, funder logo bottom left, WGL membership
236// logo bottom right -- and is used for both edges of each corner, so all
237// four keep exactly the same distance to the slide's borders.
238$idsLogoInset: 8px;
Marc Kupietza0f8f682026-08-08 14:13:11 +0200239
240.reveal .slides {
Marc Kupietz59e95a62026-08-29 10:19:05 +0300241 // Second layer: the optional partner institution logo (--partner-logo is
242 // supplied by the template from the document's `partner_logo` yaml entry);
243 // paints as "none" without it, leaving a harmless empty layer.
244 background-image: url('https://corpora.ids-mannheim.de/slides/reveal.js.ids/images/IDS-Logo-2019.svg'),
245 var(--partner-logo, none);
Marc Kupietza0f8f682026-08-08 14:13:11 +0200246 background-repeat: no-repeat;
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300247 background-position: top #{$idsLogoInset} right #{$idsLogoInset},
248 top #{$idsLogoInset} right calc(#{$idsLogoInset} + var(--slide-height) * #{$idsLogoWidthRatio} + #{$idsPartnerGap});
Marc Kupietz59e95a62026-08-29 10:19:05 +0300249 background-size: calc(var(--slide-height) * #{$idsLogoWidthRatio}) auto,
250 auto calc(var(--slide-height) * #{$idsPartnerHeightRatio});
Marc Kupietza0f8f682026-08-08 14:13:11 +0200251}
252
253// The orange bar is drawn as a ::before on the headings rather than on the
254// slide, in two segments: one behind the title and one behind the subtitle.
255// Because each segment is sized as a percentage of its own heading's box, the
256// bar always ends exactly at the bottom of the last heading -- it follows a
257// subtitle when there is one, stops at the title when there isn't, and grows
258// by itself when a heading wraps onto a second line. No fixed heights, and no
259// JavaScript. Headings carry no vertical padding, so they sit as high on the
260// slide as the bar does. Every rule is !important because this theme has to
261// win against plugin- and document-level CSS loaded after it.
262.reveal .slides section:not(.title-frame) > h1:first-child,
263.reveal .slides section:not(.title-frame) > h2:first-child {
264 position: relative !important;
265 display: block !important;
266 text-align: left !important;
267 margin: 0 calc(-1 * #{$idsContentInset}) #{$idsHeadingSpacing} calc(-1 * #{$idsContentInset}) !important;
268 padding: 0 0 0 #{$idsContentInset} !important;
269 font-weight: var(--r-heading-font-weight) !important;
270}
271
272.reveal .slides section:not(.title-frame) > h1:first-child::before,
273.reveal .slides section:not(.title-frame) > h2:first-child::before,
274.reveal .slides section:not(.title-frame) > h2:first-child + h3::before {
275 content: "" !important;
276 position: absolute !important;
277 width: #{$idsBarWidth} !important;
278 // A flat fill rather than orange_bar.png: that image is two-toned (a lighter
279 // band across its top), so stretching it over each segment separately left a
280 // pale seam where the two met. The IDS reference decks draw a flat #f6a800.
281 background: #{$idsOrange} !important;
282}
283
284// Title segment: pulled out to the window's physical left edge.
285.reveal .slides section:not(.title-frame) > h1:first-child::before,
286.reveal .slides section:not(.title-frame) > h2:first-child::before {
287 top: 0 !important;
288 left: calc(-1 * #{$idsBandLeft}) !important;
289 height: 100% !important;
290}
291
292// A slide without a subtitle reserves the room one would have taken, so the
293// bar keeps the same height and the body content starts at the same place on
294// every slide. :has() is what lets us ask "is a subtitle coming?" in CSS; where
295// it is unsupported such slides simply keep a title-height bar.
Marc Kupietz6acbd662026-08-20 14:41:00 +0200296//
297// The lone title is vertically CENTRED in its reserved bar: half of the
298// reservation goes above the text as top padding (the bar segment, anchored
299// to the heading box, moves up with it), and the bottom half stays in the bar
300// extension plus margin. The space consumed below the bar is reduced by the
301// same half, so body content starts where it always did.
Marc Kupietza0f8f682026-08-08 14:13:11 +0200302.reveal .slides section:not(.title-frame) > h1:first-child:not(:has(+ h3)),
303.reveal .slides section:not(.title-frame) > h2:first-child:not(:has(+ h3)) {
Marc Kupietz6acbd662026-08-20 14:41:00 +0200304 padding-top: calc((#{$idsHeadingSpacing} + #{$idsSubtitleHeight}) / 2) !important;
305 margin-bottom: calc((#{$idsHeadingSpacing} + #{$idsSubtitleHeight}) / 2 + #{$blockMargin}) !important;
Marc Kupietza0f8f682026-08-08 14:13:11 +0200306}
307
308.reveal .slides section:not(.title-frame) > h1:first-child:not(:has(+ h3))::before,
309.reveal .slides section:not(.title-frame) > h2:first-child:not(:has(+ h3))::before {
Marc Kupietz6acbd662026-08-20 14:41:00 +0200310 height: calc(100% + (#{$idsHeadingSpacing} + #{$idsSubtitleHeight}) / 2) !important;
Marc Kupietza0f8f682026-08-08 14:13:11 +0200311}
312
Marc Kupietzd023f072026-08-20 15:27:37 +0200313// Vertical balance when a subtitle follows: the orange strip between the
314// title's baseline and the subtitle's cap height used to be title descent (16)
315// + segment spacing (8) + subtitle leading (3) ≈ 27px, against only ≈ 11px of
316// orange above the title's cap height. Moving the title 8px DOWN inside its
317// box while REMOVING the 8px segment spacing makes the two margins equal
318// (19px each) AND keeps the bar's total height and the body content's start
319// position pixel-identical: box grows by 8, spacing drops by 8. The subtitle
320// segment still rises (#{$idsHeadingSpacing} + #{$idsBarOverlap}) above its
321// own box, so the bar stays seamless.
322.reveal .slides section:not(.title-frame) > h1:first-child:has(+ h3),
323.reveal .slides section:not(.title-frame) > h2:first-child:has(+ h3) {
324 padding-top: #{$idsHeadingSpacing} !important;
325 margin-bottom: 0 !important;
326}
327
Marc Kupietza0f8f682026-08-08 14:13:11 +0200328// The subtitle sits in the slide's normal text column, so its segment has to
329// reach back out to the slide edge, and up over the gap to the title.
330.reveal .slides section:not(.title-frame) > h2:first-child + h3 {
331 position: relative !important;
332 text-align: left !important;
333 margin-top: 0 !important;
334 margin-left: 0 !important;
335 margin-bottom: $blockMargin !important;
336}
337
338.reveal .slides section:not(.title-frame) > h2:first-child + h3::before {
339 top: calc(-1 * (#{$idsHeadingSpacing} + #{$idsBarOverlap})) !important;
340 left: calc(-1 * (#{$idsContentInset} + #{$idsBandLeft})) !important;
341 height: calc(100% + #{$idsHeadingSpacing} + #{$idsBarOverlap}) !important;
Marc Kupietza737b1b2023-10-07 09:32:20 +0200342}
343
Marc Kupietz55c9cef2026-08-08 16:03:06 +0200344// Section-divider slides: a level 1 heading alone on a slide (pandoc marks
345// these .level1). The IDS reference decks centre that title on the slide while
346// the bar stays in its usual top left corner, so here the bar cannot hang off
347// the heading -- it is painted on the slide itself, at the height it has on
348// every other slide, and the heading gets none of the top-left treatment.
349$idsTitleHeight: 1.35 * $mainFontSize * 1.2;
350$idsBarBlockHeight: $idsTitleHeight + $idsHeadingSpacing + $idsSubtitleHeight;
351
352.reveal .slides section.level1:not(.title-frame) {
353 height: 100% !important;
354 display: flex !important;
355 flex-direction: column !important;
356 justify-content: center !important;
357}
358
359.reveal .slides section.level1:not(.title-frame)::before {
360 content: "" !important;
361 position: absolute !important;
362 top: 0 !important;
363 left: calc(-1 * #{$idsBandLeft}) !important;
364 width: #{$idsBarWidth} !important;
365 height: #{$idsBarBlockHeight} !important;
366 background: #{$idsOrange} !important;
367}
368
Marc Kupietzde3c6c12026-08-30 14:40:33 +0300369// Adaptive vertical centering of slide content: the template groups each
370// slide's body content (everything after the heading block except speaker
371// notes) into a div.ids-slide-content. Slides carrying such a wrapper become
372// flex columns of full slide height: the heading block stays pinned to the
373// top and the wrapper's auto margins center the content in the remaining
374// space. Auto margins collapse to zero when there is no free space, so
375// packed slides still start directly below the heading and overflow
376// downwards as before -- the drawback that makes reveal.js' own `center`
377// option unusable here (it would also center the headings). The wrapper
378// keeps the footer band free (--ids-footer-reserve, published by the
379// template from the actual footer height), so centered content never
380// covers the footer; slides too packed to fit above it may, as they always
381// could. Display only ever changes for slides reveal.js is actually
382// showing, mirroring the section-divider rule above, which works the same
383// way; screen-only, so the pdf export keeps laying out slides itself.
384@media screen {
385 html .reveal .slides section:not(.stack):not(.title-frame) {
386 height: 100% !important;
387 display: flex !important;
388 flex-direction: column !important;
389 }
390
391 .reveal .slides section:not(.stack):not(.title-frame) > .ids-slide-content {
392 flex: none;
393 margin-top: auto !important;
394 margin-bottom: auto !important;
395 padding-bottom: var(--ids-footer-reserve, 48px);
396
397 // under block layout the first content element's margin-top collapsed
398 // with the heading's margin-bottom; as flex items the two would add up
399 // instead, so drop it and let the heading spacing rule alone define
400 // the gap, as before
401 > :first-child {
402 margin-top: 0 !important;
403 }
404 }
405}
406
Marc Kupietz55c9cef2026-08-08 16:03:06 +0200407.reveal .slides section.level1:not(.title-frame) > h1:first-child {
408 text-align: center !important;
409 margin: 0 !important;
410 padding: 0 !important;
411}
412
413.reveal .slides section.level1:not(.title-frame) > h1:first-child::before {
414 content: none !important;
415}
416
Marc Kupietza737b1b2023-10-07 09:32:20 +0200417// Define additional color effects based on Dracula spec
418// https://spec.draculatheme.com/
419:root {
420 --r-bold-color: #{$idsOrange};
421 --r-list-bullet-color: #{$listBulletColor};
422}
423
424.reveal {
Marc Kupietz9b795bd2026-08-19 06:58:44 +0200425 // Bold ("highlighted") text gets the orange colour AND the condensed Fira
426 // Sans face, as in the IDS reference decks -- the lighter weight and 90%
427 // size keep it from dominating the serif body text.
Marc Kupietza737b1b2023-10-07 09:32:20 +0200428 strong, b {
Marc Kupietz9b795bd2026-08-19 06:58:44 +0200429 font-family: "Fira Sans Condensed", sans-serif;
430 font-weight: 600;
431 font-size: 90%;
Marc Kupietza737b1b2023-10-07 09:32:20 +0200432 color: var(--r-bold-color);
433 }
434
435 // Dracula colored list bullets and numbers
436 ul, ol {
437 li::marker {
438 color: var(--r-list-bullet-color) !important;
439 }
440 }
441}
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200442
Marc Kupietz281ba9c2026-08-11 15:37:48 +0200443// Nested list items are set progressively smaller, both to emphasise the
444// hierarchy and to keep deeply nested lists from visually competing with the
445// first level. The em size compounds down the nesting levels, so each deeper
446// level is 80% of its parent (level 2: 80%, level 3: 64%, level 4: 51%).
447// Markers and the hanging indentation (padding-left: 0.7em above) scale with
448// the text automatically.
449.reveal li li {
450 font-size: 0.8em;
451}
452
Marc Kupietzf4945eb2026-08-19 17:48:41 +0200453// Description lists: dt in orange Fira Sans Condensed, dd indented.
454.reveal dl {
455 font-size: 0.62em;
456 line-height: 1.25;
457}
458.reveal dt {
459 font-weight: 700;
460 margin-top: 0.35em;
461 font-family: "Fira Sans Condensed", sans-serif;
462 color: $idsOrange;
463}
464.reveal dd {
465 margin: 0 0 0 1.2em;
466 color: #444;
467}
468
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200469
470/*********************************************
471 * FOOTER
472 *********************************************/
Marc Kupietzc0b272d2023-10-08 14:24:18 +0200473 #ids-footer:not(title-slide) {
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200474 opacity: 1;
475 background: white;
476 color: #444444;
477 border-top: dotted orange 2px;
478 transition: opacity 800ms ease-in-out;
479 position: fixed;
480 height: 6%;
481 line-height: 6%;
482 z-index: -20;
483 width: 100%;
484 letter-spacing: 0em;
485 text-align: center;
486 display: table;
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200487}
488
489#ids-footer span {
490 height: 100%;
491 line-height: 100%;
492 z-index: -20;
Marc Kupietz61ad0262024-05-14 22:07:50 +0200493 font-size: 1.8vh;
Marc Kupietzc0b272d2023-10-08 14:24:18 +0200494 font-family: "Fira Sans Condensed", "Fira Sans", "Roboto Condensed", "League Gothic", Impact, sans-serif;
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200495 display: inline-block;
496 display: table-cell;
497 vertical-align: middle;
498}
499
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200500/* Bottom position for the IDS-Footer footer when both progress bar and TOC-Progress are visible */
Marc Kupietzc0b272d2023-10-08 14:24:18 +0200501div.progress[style="display: block;"] ~ #ids-footer {
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200502 bottom: calc(3px + 0vh);
503}
504
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200505/* Bottom position for the IDS-Footer footer when TOC-Progress is visible */
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200506#ids-footer {
507 bottom: 3px;
508}
509
510#ids-footer a {
511 color: #555555;
512}
513
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200514/* Bottom position for the IDS-Footer footer when progress bar is visible */
Marc Kupietzc0b272d2023-10-08 14:24:18 +0200515div.progress[style="display: block;"] ~ footer:last-of-type#ids-footer {
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200516 bottom: 3px;
517}
518
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200519/* Bottom position for the IDS-Footer footer when neither progress bar nor TOC-Progress are visible */
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200520footer:last-of-type#ids-footer {
521 bottom: 0px;
522}
523
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200524/* Make IDS-Footer invisible if explicitly indicated */
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200525.no-ids-footer #ids-footer {
526 opacity: 0;
527 transition: opacity 800ms ease-in-out;
528}
529
530.title-frame #ids-footer {
531 opacity: 0;
532 transition: opacity 800ms ease-in-out;
533}
534
535.no-toc-progress #ids-footer {
536 opacity: 0;
537 transition: opacity 800ms ease-in-out;
538}
539
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200540/* Make IDS-Footer invisible in overview mode */
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200541.overview #ids-footer {
542 opacity: 0;
543 transition: opacity 800ms ease-in-out;
544}
545
Marc Kupietz61c8ec72026-08-20 20:47:45 +0200546/* In print, the footer's negative stacking drops it behind the .pdf-page
547 * backgrounds (z-index 1); lift it above them. position: fixed repeats it at
548 * the bottom of every printed page. */
549html.reveal-print #ids-footer {
550 z-index: 100 !important;
551}
552
553// reveal's print CSS gives every .pdf-page z-index:1, which forms a separate
554// stacking context per page. The slide-number-pdf lives INSIDE such a page, so
555// its own z-index only competes within the page: the footer (z-index 100 at
556// root level) always paints over it, and raising the number's z-index alone
557// cannot help. Remove the per-page stacking context in print (the pages are
558// separated by page-break-after:always anyway, so nothing needs stacking), and
559// the number's z-index 200 wins against the footer globally. Position stays
560// the theme's screen rule (right:29px / bottom:22px), which puts the number
561// inside the footer band with its white background cutting the dotted line --
562// the same look as on screen.
563html.reveal-print .reveal .slides .pdf-page {
564 z-index: auto !important;
565}
566
567// On screen the number is flanked by the arrow buttons, so its slightly raised
568// baseline reads as deliberate; in print it shares the footer band with the
569// author/title/date line, whose vertically centered text has its baseline
570// ~19px above the page bottom. The number's screen offset (bottom:22px, 14px
571// font from reveal's print rule) puts its baseline ~25px up. 15px aligns the
572// two baselines. Print-only: the screen rule keeps its 22px.
573html.reveal-print div.slide-number-pdf {
574 z-index: 200 !important;
575 bottom: 15px !important;
576}
577
578// On screen the bar segments shift left by --ids-band-left so the bar reaches
579// the window's physical edge when the slide is pillarboxed. In print there are
580// no bands (.pdf-page == slide box), and if the band values are ever stale
581// (e.g. an outdated template script), a nonzero band-left would push the
582// segments outside the pdf-page, whose overflow:hidden then clips them.
583// Pin the geometry explicitly for print instead of trusting the custom
584// property: title segments start at the heading's (== pdf-page's) left edge,
585// the subtitle segment (which lives in the text column, inset by
586// $idsContentInset) reaches back out by exactly the inset, and the level1
587// divider bar starts at the section's left edge. Widths stay the normal bar
588// width, so the visible result is pixel-identical to the on-screen bar.
589html.reveal-print .reveal .slides section:not(.title-frame) > h1:first-child::before,
590html.reveal-print .reveal .slides section:not(.title-frame) > h2:first-child::before {
591 left: 0 !important;
592}
593
594html.reveal-print .reveal .slides section:not(.title-frame) > h2:first-child + h3::before {
595 left: calc(-1 * #{$idsContentInset}) !important;
596}
597
598html.reveal-print .reveal .slides section.level1:not(.title-frame)::before {
599 left: 0 !important;
600}
601
602// The WGL membership logo sits at bottom:10px of the title frame -- inside
603// the footer's ~46px band on print pages (the footer is force-shown on every
604// page in print view and cannot be hidden per page, position:fixed). Lift the
605// logo above the footer in print only; the screen layout stays put.
606html.reveal-print .reveal .slides section.title-frame {
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300607 background-position: right #{$idsLogoInset} bottom 55px;
Marc Kupietz61c8ec72026-08-20 20:47:45 +0200608}
609
Marc Kupietza0f8f682026-08-08 14:13:11 +0200610// Like the orange bar/IDS logo above, this is painted on the slide itself
611// (rather than on .slide-background-content, which spans the raw,
612// unscaled viewport) so it stays pinned to the title slide's true
Marc Kupietz67715592026-08-15 14:55:18 +0200613// bottom-right corner instead of the browser window's. Its margin mirrors
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300614// the IDS logo's, so the two sit on one shared inset.
Marc Kupietza0f8f682026-08-08 14:13:11 +0200615.reveal .slides section.title-frame {
616 background-image: url("https://corpora.ids-mannheim.de/slides/reveal.js.ids/images/Mitglied_WGL_transparent.svg");
Marc Kupietzf0ce0322023-10-07 15:33:47 +0200617 background-repeat: no-repeat;
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300618 background-position: right #{$idsLogoInset} bottom #{$idsLogoInset};
Marc Kupietz67715592026-08-15 14:55:18 +0200619 background-size: calc(var(--slide-height) * 0.1) auto;
620 /* full slide height, so "bottom" really is the slide's bottom edge */
621 height: 100%;
Marc Kupietze9ace292024-05-14 22:11:15 +0200622}
623
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300624// qrlink() codes placed anywhere else in a deck: qr_svg_fit() crops the svg
625// to the dark modules, so the quiet zone the code needs to stay scannable is
626// this padding (which also keeps a code readable on a dark background).
627.reveal a.qrcode {
628 display: inline-block;
629 padding: 0.5em;
630 background: #fff;
631}
632
Marc Kupietz59e95a62026-08-29 10:19:05 +0300633// Website QR code and funder logo on the title slide (document options
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300634// `website` and `funder_logo`): top-left and bottom-left corners. Like the
635// two logos on the right, they keep $idsLogoInset to both slide edges --
636// measured to the visible ink, so that all four corners look alike. Both are
637// DOM elements injected into the title frame by the pandoc template (the QR
638// itself is generated in R by qrlink()); absolute positioning sticks to the
639// slide, because reveal.js positions the sections themselves.
640//
641// qrlink() crops the svg to the dark modules, so the quiet zone the code
642// needs to stay scannable is this white plate's padding -- which is also
643// what puts the modules themselves at $idsLogoInset from the slide's edges,
644// the plate sitting flush in the corner (invisible on the white slide).
Marc Kupietz59e95a62026-08-29 10:19:05 +0300645.reveal .slides section.title-frame .title-qr {
646 position: absolute;
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300647 top: 0;
648 left: 0;
Marc Kupietz59e95a62026-08-29 10:19:05 +0300649 box-sizing: border-box;
650 width: calc(var(--slide-height) * 0.28);
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300651 padding: #{$idsLogoInset};
Marc Kupietz59e95a62026-08-29 10:19:05 +0300652 background: #fff;
653}
654
655.reveal .slides section.title-frame .title-qr a.qrcode,
656.reveal .slides section.title-frame .title-qr svg {
657 display: block;
658 width: 100%;
659 height: auto;
660 margin: 0;
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300661 // the quiet zone comes from the plate around it here
662 padding: 0;
Marc Kupietz59e95a62026-08-29 10:19:05 +0300663}
664
665.reveal .slides section.title-frame img.funder-logo {
666 position: absolute;
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300667 left: #{$idsLogoInset};
668 bottom: #{$idsLogoInset};
Marc Kupietz59e95a62026-08-29 10:19:05 +0300669 height: calc(var(--slide-height) * 0.07);
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300670 // reveal.js gives images a vertical margin, which for an absolutely
671 // positioned one would add itself to the inset above.
672 margin: 0;
Marc Kupietz59e95a62026-08-29 10:19:05 +0300673 width: auto;
674}
675
676// Lift the funder logo above the print footer band, like the WGL logo above
677html.reveal-print .reveal .slides section.title-frame img.funder-logo {
678 bottom: 55px;
679}
680
681// The navigation chrome is hidden on the title slide (the template toggles
682// the ids-title-plain class when the title frame is the current slide). Use
683// opacity/visibility rather than display:none so the transition out of the
684// title slide fades the chrome in instead of popping it up, and so reveal.js'
685// own controls bookkeeping keeps working underneath.
686html.ids-title-plain .reveal .controls,
687html.ids-title-plain .reveal .slide-number,
688html.ids-title-plain .reveal .slide-menu-button {
689 opacity: 0 !important;
690 visibility: hidden !important;
691 pointer-events: none !important;
692}
693
694.reveal .controls,
695.reveal .slide-number,
696.reveal .slide-menu-button {
697 transition: opacity 0.4s;
698}
699
Marc Kupietze9ace292024-05-14 22:11:15 +0200700
Marc Kupietz903104a2026-08-20 10:10:41 +0200701/*********************************************
702 * SLIDES MENU
703 *********************************************/
704
705// The menu plugin copies .reveal's computed font-family onto .slide-menu as an
706// inline style (and its own CSS is loaded after the theme), so without
707// !important here the menu would come out in the Libertinus serif body face.
708// Fira Sans Condensed is the IDS sans for navigation/UI text, and its narrow
709// glyphs keep long (German) slide titles on one line.
710.slide-menu-wrapper .slide-menu {
711 font-family: "Fira Sans Condensed", sans-serif !important;
712}
713
714// Widen the menu a little over the plugin's 300px default -- but only the
715// default: a width the user picked via the menu-width option maps to one of
716// the plugin's width classes (or an inline style), which must keep winning.
717.slide-menu-wrapper .slide-menu:not(.slide-menu--wide):not(.slide-menu--half):not(.slide-menu--third):not(.slide-menu--full):not(.slide-menu--custom) {
Marc Kupietz7427cca2026-08-20 10:53:03 +0200718 width: 372px !important;
Marc Kupietz903104a2026-08-20 10:10:41 +0200719}
720
721// Tighter, less wasteful rows than the plugin's 10px 18px padding with a 12px
722// icon gap: the icon column and generous side padding eat exactly the width
723// the titles need.
724.slide-menu-wrapper .slide-menu-item,
725.slide-menu-wrapper .slide-menu-item-vertical {
726 padding: 6px 12px !important;
727 line-height: 1.3 !important;
728}
729
730.slide-menu-wrapper .slide-menu-item-vertical {
731 padding-left: 26px !important;
732}
733
734// Wrapped titles: make the row a flex line so the second line aligns with the
735// first instead of sliding under the bullet/circle icon. The icon sits on the
736// first line's text baseline; the title column takes the remaining width and
737// wraps within itself.
738.slide-menu-wrapper .slide-menu-item,
739.slide-menu-wrapper .slide-menu-item-vertical {
740 display: flex !important;
741 align-items: baseline !important;
742}
743
744.slide-menu-wrapper .slide-menu-item-title {
745 flex: 1 !important;
746 min-width: 0 !important;
747}
748
749.slide-menu-wrapper .slide-menu-item i.far,
750.slide-menu-wrapper .slide-menu-item i.fas,
751.slide-menu-wrapper .slide-menu-item-vertical i.far,
752.slide-menu-wrapper .slide-menu-item-vertical i.fas,
753.slide-menu-wrapper .slide-menu-item svg.svg-inline--fa,
754.slide-menu-wrapper .slide-menu-item-vertical svg.svg-inline--fa {
755 padding-right: 8px !important;
756}
757
Marc Kupietz7427cca2026-08-20 10:53:03 +0200758// Top-level (section) entries in bold, marking the hierarchy as the indented
759// sub-slides alone do now. Note the Google Fonts import only ships Fira Sans
760// Condensed in 300/400/700/800 -- there is no 600.
761.slide-menu-wrapper .slide-menu-item {
762 font-weight: 700 !important;
763}
764
Marc Kupietz903104a2026-08-20 10:10:41 +0200765// Current slide in the IDS accent colour, matching the slide-number and the
766// orange bar.
767.slide-menu-wrapper .active-menu-panel li.active {
768 color: #{$idsOrange} !important;
Marc Kupietzf0ce0322023-10-07 15:33:47 +0200769}
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200770
771/*
772 * Menu controls
773 */
Marc Kupietzc0b272d2023-10-08 14:24:18 +0200774body .reveal .slide-menu-button {
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200775 color: #aaaaaa !important;
776 position: fixed;
777 left: 30px;
778 bottom: 2%;
779 vertical-align: middle;
780 z-index: 30;
781 font-size: 2vh;
782}
783
784#customcontrols > ul {
785 color: #aaaaaa !important;
786 position: fixed;
Marc Kupietzf51e9152023-10-07 15:32:33 +0200787 left: 50px;
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200788 bottom: 2% !important;
789 vertical-align: middle;
790 z-index: 30;
791 font-size: 2vh;
792}
793
794@media only screen and (min-width: 500px) {
795 #customcontrols > ul {
796 bottom: 2% !important;
797 }
798}
Marc Kupietz3fdee732023-10-07 18:52:20 +0200799
Marc Kupietzc7249f92023-10-10 07:16:50 +0200800.reveal .controls .controls-arrow {
801 position: relative;
802 width: 3.6em;
803 height: 3.6em;
804 bottom: -12px;
805 right: -4px;
806}
807
Marc Kupietz3fdee732023-10-07 18:52:20 +0200808.reveal h3, h4, h5, h6 {
809 text-transform: none !important;
810}
811
812.reveal h3, h4, h5, h6 {
813 text-transform: none !important;
814}
815
816.reveal h2 + h3 {
817 margin-top: -0.5em !important;
818}
Marc Kupietzdf0eda92023-10-07 20:50:00 +0200819
820.title-frame h1,
821.title-frame h2 {
822 margin: 0 0 0 0;
823 background: rgb(246, 168, 0);
824 color: white;
825 font-family: "Fira Sans Condensed", "Roboto Condensed", Impact, sans-serif;
826 font-weight: 600;
827 line-height: 1.2;
828 letter-spacing: 0.05ex;
829 text-transform: uppercase;
830 width: 100%;
831 margin-top: .5em;
832 padding-top: .5em;
833 font-size: 1.75em;
834 margin-left: 0;
835 text-align: center;
836 text-shadow: none;
837 word-wrap: break-word;
838}
839
840
841.title-frame .author {
842 font-family: "Fira Sans Condensed", sans-serif;
843 font-weight: 400;
844 color: #657b83;
845 margin-top: 10vh;
846}
847
848.title-frame .place {
849 font-family: "Fira Sans Condensed", sans-serif;
850 margin-top: 40px;
851 font-weight: 400;
852 color: #657b83;
853}
854
855.title-frame h2 {
856 margin-top: -3px;
857 margin-bottom: 1em;
858 padding-bottom: .5em;
859 font-size: 1em;
860}
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200861
862/*********************************************
863 * TABLES
864 *********************************************/
865
866 th {
867 color: rgb(246, 168, 0);
868}
869
870table {
871 font-family: 'Fira Sans Condensed', sans-serif;
872 font-weight: 400;
873 font-size: 16px;
Marc Kupietz25570ef2026-08-28 14:03:21 +0300874 // Fira Sans Condensed ships proportional figures by default, so the digits
875 // in neighbouring rows do not line up; tabular numbers (tnum) fix the digit
876 // widths and align numeric table columns vertically.
877 font-variant-numeric: tabular-nums;
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200878}
879
880.reveal table.dataTable {
881 border: #aaaaaa 1px solid;
882 border-collapse: collapse;
883}
884
885.reveal table.dataTable td {
886 border: #aaaaaa 1px solid;
887 border-collapse: collapse;
888}
889
890.dataTables_wrapper .dataTables_length, .dataTables_wrapper .dataTables_filter, .dataTables_wrapper .dataTables_info, .dataTables_wrapper .dataTables_processing, .dataTables_wrapper .dataTables_paginate, table.dataTable thead > tr > th.sorting::before, table.dataTable thead > tr > th.sorting::after, table.dataTable thead > tr > th.sorting_asc::before, table.dataTable thead > tr > th.sorting_asc::after, table.dataTable thead > tr > th.sorting_desc::before, table.dataTable thead > tr > th.sorting_desc::after, table.dataTable thead > tr > th.sorting_asc_disabled::before, table.dataTable thead > tr > th.sorting_asc_disabled::after, table.dataTable thead > tr > th.sorting_desc_disabled::before, table.dataTable thead > tr > th.sorting_desc_disabled::after, table.dataTable thead > tr > td.sorting::before, table.dataTable thead > tr > td.sorting::after, table.dataTable thead > tr > td.sorting_asc::before, table.dataTable thead > tr > td.sorting_asc::after, table.dataTable thead > tr > td.sorting_desc::before, table.dataTable thead > tr > td.sorting_desc::after, table.dataTable thead > tr > td.sorting_asc_disabled::before, table.dataTable thead > tr > td.sorting_asc_disabled::after, table.dataTable thead > tr > td.sorting_desc_disabled::before, table.dataTable thead > tr > td.sorting_desc_disabled::after {
891 display: none;
892}
893
894.caption {
895 font-family: 'Fira Sans Condensed', sans-serif;
896 font-weight: 400;
897 font-size: 16px;
898 text-align: center;
899}
900
901/*
902table.display td { white-space: nowrap; }
903*/
904
905.dt-buttons, .dataTables_filter {
906 margin-top: 10pt;
907}
908
Marc Kupietz069f1e42023-10-11 10:26:16 +0200909/* Sort Arrows in DataTables */
910table.dataTable thead>tr>th.sorting:before, table.dataTable thead>tr>th.sorting:after, table.dataTable thead>tr>th.sorting_asc:before, table.dataTable thead>tr>th.sorting_asc:after, table.dataTable thead>tr>th.sorting_desc:before, table.dataTable thead>tr>th.sorting_desc:after, table.dataTable thead>tr>th.sorting_asc_disabled:before, table.dataTable thead>tr>th.sorting_asc_disabled:after, table.dataTable thead>tr>th.sorting_desc_disabled:before, table.dataTable thead>tr>th.sorting_desc_disabled:after, table.dataTable thead>tr>td.sorting:before, table.dataTable thead>tr>td.sorting:after, table.dataTable thead>tr>td.sorting_asc:before, table.dataTable thead>tr>td.sorting_asc:after, table.dataTable thead>tr>td.sorting_desc:before, table.dataTable thead>tr>td.sorting_desc:after, table.dataTable thead>tr>td.sorting_asc_disabled:before, table.dataTable thead>tr>td.sorting_asc_disabled:after, table.dataTable thead>tr>td.sorting_desc_disabled:before, table.dataTable thead>tr>td.sorting_desc_disabled:after {
911 right: 0 !important;
912 line-height: 80% !important;
913}
914
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200915/*********************************************
916 * BIBLIOGRAPHY
917 *********************************************/
918
919.reveal .references {
920 font-family: "Fira Sans Condensed", sans-serif;
921 font-size: 16px;
922 text-align: left;
Marc Kupietzbfab8a12026-08-19 14:42:42 +0200923 margin-top: 10px;
924 max-height: 510px;
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200925 font-weight: 400;
926 color: #253b43;
927 overflow-y: auto;
928}
929
930.hanging-indent > .csl-entry {
931 padding-left: 22px ;
932 text-indent: -22px ;
933}
934
Marc Kupietz21f526c2026-08-14 12:32:56 +0200935// .references scopes these above pandoc's CSL defaults (div.csl-entry), which
936// otherwise win on specificity and pin margin-bottom to 0em.
937.references .csl-entry {
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200938 color: #888888;
Marc Kupietz21f526c2026-08-14 12:32:56 +0200939 margin-bottom: 0.5em;
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200940}
941
Marc Kupietz21f526c2026-08-14 12:32:56 +0200942// "Authors (Year):" as a bold dark first line; the theme template's JS wraps
943// the leading text of each entry in .csl-authors-year (see default.html) --
944// which part of an entry citeproc wraps in spans depends on the entry type, so
945// a CSS-only break cannot place it reliably.
946.csl-entry .csl-authors-year {
947 display: block;
948 font-weight: bold;
949 color: #4d616b;
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200950}
Marc Kupietz11797162023-10-09 23:17:36 +0200951
952.reveal code.sourceCode:last-child + pre {
953 height: 800px !important;
Marc Kupietzc7249f92023-10-10 07:16:50 +0200954}
955
Marc Kupietz589d1b82023-10-10 12:31:33 +0200956
957/*********************************************
Marc Kupietz54d9ce02026-08-21 11:38:45 +0200958 * FULLSCREEN TOGGLE
Marc Kupietz589d1b82023-10-10 12:31:33 +0200959 *********************************************/
960
Marc Kupietz54d9ce02026-08-21 11:38:45 +0200961// Small fixed toggle for touch devices (script injected by default.html):
962// phones have no F11 and the browser chrome eats slide pixels. Hidden on
963// pointer devices (F11 exists there) and whenever the Fullscreen API is
964// unavailable -- the script also removes it then. Same muted look and column
965// as the slide menu button, one slot above it.
966#ids-fullscreen {
967 display: none;
968 position: fixed;
969 left: 30px;
970 bottom: 6%;
971 z-index: 30;
972 width: 28px;
973 height: 28px;
974 border: 0;
975 padding: 0;
976 cursor: pointer;
977 opacity: 0.55;
978 // Feather-style corner brackets; gray idle, IDS orange while fullscreen
979 // (the two data URIs differ only in the stroke colour).
980 background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23aaaaaa' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 3H5a2 2 0 0 0-2 2v3'/%3E%3Cpath d='M16 3h3a2 2 0 0 1 2 2v3'/%3E%3Cpath d='M8 21H5a2 2 0 0 1-2-2v-3'/%3E%3Cpath d='M16 21h3a2 2 0 0 0 2-2v-3'/%3E%3C/svg%3E") center / contain no-repeat;
981
982 &:active,
983 &:focus-visible {
984 opacity: 0.9;
985 }
986
987 &.is-fullscreen {
988 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f6a800' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 3H5a2 2 0 0 0-2 2v3'/%3E%3Cpath d='M16 3h3a2 2 0 0 1 2 2v3'/%3E%3Cpath d='M8 21H5a2 2 0 0 1-2-2v-3'/%3E%3Cpath d='M16 21h3a2 2 0 0 0 2-2v-3'/%3E%3C/svg%3E");
989 }
990}
991
992// Only touch devices get the button; desktops keep their F11.
993@media (hover: none) and (pointer: coarse) {
994 #ids-fullscreen {
995 display: block;
996 }
997}
998
999// position:fixed elements repeat on every printed page -- never print it.
1000html.reveal-print #ids-fullscreen {
1001 display: none !important;
1002}
1003
1004
1005
Marc Kupietz589d1b82023-10-10 12:31:33 +02001006 .reveal .controls .controls-arrow:after, .reveal .controls .controls-arrow:before {
1007 width: 13px !important; /* size */
1008 height: 4px; /* line width */
1009}
1010
1011.reveal .controls {
1012 display: none;
1013 position: absolute;
1014 top: auto;
1015 bottom: -8px;
1016 right: 16px;
1017 left: auto;
1018 z-index: 11;
1019 /* color: #000;*/
1020 pointer-events: none;
1021 font-size: 8px;
1022}
1023
1024.reveal .controls .controls-arrow {
1025 position: relative;
1026 height: 3.6em;
1027 width: 1.2em; /* distance betwee arrows */
1028 bottom: 0;
1029 right: 0;
1030}
1031
1032.reveal div.slide-number {
1033 text-align: center;
1034 width: 2em;
1035 position: absolute;
1036 display: block;
1037 right: 29px;
1038 bottom: 22px;
1039 z-index: 31;
1040 font-family: "Fira Sans Condensed", sans-serif;
1041 font-size: 18px;
1042 line-height: 1;
1043 background-color: white;
1044 color: #666;
1045 padding: 0;
1046}
1047
Marc Kupietzddd9ba52026-08-29 16:22:29 +03001048
1049/*********************************************
Marc Kupietzf8e92bb2026-08-29 16:32:01 +03001050 * SPEAKER NOTES OVERLAY (touch devices)
1051 *********************************************/
1052#ids-notes {
1053 display: none;
1054 position: fixed;
1055 left: 70px;
1056 bottom: 6%;
1057 z-index: 30;
1058 width: 28px;
1059 height: 28px;
1060 border: 0;
1061 padding: 0;
1062 cursor: pointer;
1063 opacity: 0.55;
1064 background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23aaaaaa' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z'/%3E%3C/svg%3E") center/contain no-repeat;
1065}
1066
1067#ids-notes:active, #ids-notes:focus-visible {
1068 opacity: 0.9;
1069}
1070
1071#ids-notes.is-open {
1072 opacity: 0.9;
1073 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f6a800' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z'/%3E%3C/svg%3E");
1074}
1075
1076#ids-transcript-btn {
1077 display: none;
1078 position: fixed;
1079 left: 110px;
1080 bottom: 6%;
1081 z-index: 30;
1082 width: 28px;
1083 height: 28px;
1084 border: 0;
1085 padding: 0;
1086 cursor: pointer;
1087 opacity: 0.55;
1088 background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23aaaaaa' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='8' y1='6' x2='21' y2='6'/%3E%3Cline x1='8' y1='12' x2='21' y2='12'/%3E%3Cline x1='8' y1='18' x2='21' y2='18'/%3E%3Cline x1='3' y1='6' x2='3.01' y2='6'/%3E%3Cline x1='3' y1='12' x2='3.01' y2='12'/%3E%3Cline x1='3' y1='18' x2='3.01' y2='18'/%3E%3C/svg%3E") center/contain no-repeat;
1089}
1090
1091#ids-transcript-btn:active, #ids-transcript-btn:focus-visible, #ids-transcript-btn.is-open {
1092 opacity: 0.9;
1093}
1094
1095#ids-transcript-btn.is-open {
1096 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f6a800' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='8' y1='6' x2='21' y2='6'/%3E%3Cline x1='8' y1='12' x2='21' y2='12'/%3E%3Cline x1='8' y1='18' x2='21' y2='18'/%3E%3Cline x1='3' y1='6' x2='3.01' y2='6'/%3E%3Cline x1='3' y1='12' x2='3.01' y2='12'/%3E%3Cline x1='3' y1='18' x2='3.01' y2='18'/%3E%3C/svg%3E");
1097}
1098
1099@media (hover: none) and (pointer: coarse) {
1100 #ids-notes, #ids-transcript-btn {
1101 display: block;
1102 }
1103}
1104
1105html.reveal-print #ids-notes, html.reveal-print #ids-transcript-btn {
1106 display: none !important;
1107}
1108
1109#ids-notes-overlay {
1110 position: fixed;
1111 inset: 0;
1112 z-index: 100;
1113 background: #fff;
1114 color: #444444;
1115 font-family: "Fira Sans", "Fira Sans Condensed", sans-serif;
1116 overflow-y: auto;
1117 -webkit-overflow-scrolling: touch;
1118 padding: max(24px, env(safe-area-inset-top)) max(24px, env(safe-area-inset-right))
1119 max(24px, env(safe-area-inset-bottom)) max(24px, env(safe-area-inset-left));
1120}
1121
1122#ids-notes-overlay[hidden] {
1123 display: none;
1124}
1125
1126#ids-notes-header {
1127 display: flex;
1128 align-items: baseline;
1129 gap: 12px;
1130 border-bottom: 1px solid #e0e0e0;
1131 margin-bottom: 16px;
1132 padding-bottom: 8px;
1133}
1134
1135#ids-notes-timing {
1136 flex-shrink: 0;
1137 color: #f6a800;
1138 font-weight: bold;
1139 white-space: nowrap;
1140}
1141
1142#ids-notes-title {
1143 flex-grow: 1;
1144 margin: 0;
1145 font-size: 1.1em;
1146}
1147
1148#ids-notes-close {
1149 flex-shrink: 0;
1150 border: 0;
1151 background: none;
1152 color: #888888;
1153 font-size: 1.2em;
1154 cursor: pointer;
1155 padding: 8px;
1156 margin: -8px;
1157}
1158
1159#ids-notes-content {
1160 font-size: 20px;
1161 line-height: 1.5;
1162}
1163
1164#ids-notes-content em {
1165 color: #888888;
1166}
1167
1168/*********************************************
Marc Kupietzddd9ba52026-08-29 16:22:29 +03001169 * OVERVIEW / TOC SLIDES
1170 *********************************************/
Marc Kupietzde3ffa42026-08-30 13:47:57 +03001171/* The auto-generated TOC lists the chapters with their numbers as
1172 .ids-toc-number spans in the marker colour, prepended to the entry
1173 titles: the enumeration therefore starts flush with the slide heading
1174 (the drawn ol/ul markers are suppressed for the top-level entries;
1175 sub-headings below their chapters keep their bullets). Entries stay at
1176 the normal slide body size and keep the theme's link colour, so they
1177 read as the navigation links they are. Only the denser two-column
1178 variant with sub-headings is scaled down. */
1179.reveal .slides section:not(.title-frame) .ids-overview-toc {
1180 padding-left: 0 !important;
1181}
1182.reveal .slides section:not(.title-frame) .ids-overview-toc > li::before {
1183 content: none !important;
1184}
1185.reveal .ids-overview-toc .ids-toc-number {
1186 color: var(--r-list-bullet-color);
1187}
Marc Kupietzddd9ba52026-08-29 16:22:29 +03001188.reveal .ids-overview-toc {
1189 list-style: none;
1190 margin: 0.2em 0 0 0;
1191 padding: 0;
1192 line-height: 1.35;
1193}
1194.reveal .ids-overview-toc > li {
1195 margin: 0.45em 0;
1196 font-weight: bold;
1197}
1198.reveal .ids-overview-toc ul {
1199 list-style: none;
1200 margin: 0.1em 0 0.2em 0;
1201 padding: 0 0 0 1.1em;
1202 font-weight: normal;
1203}
1204.reveal .ids-overview-toc.with-subheadings {
1205 columns: 2;
1206 column-gap: 2.5em;
1207 font-size: 0.8em;
1208}
1209.reveal .ids-overview-toc.with-subheadings > li {
1210 break-inside: avoid;
1211}
1212.reveal .ids-overview-toc ul li {
1213 margin: 0.18em 0;
1214}
Marc Kupietzf8e92bb2026-08-29 16:32:01 +03001215
1216/*********************************************
1217 * TRANSCRIPT / READ-ALOUD VIEW ('r')
1218 *********************************************/
1219#ids-transcript {
1220 position: fixed;
1221 inset: 0;
1222 z-index: 90;
1223 background: #fff;
1224 color: #444444;
1225 font-family: "Fira Sans", "Fira Sans Condensed", sans-serif;
1226 font-size: 18px;
1227 line-height: 1.5;
1228 overflow-y: auto;
1229 -webkit-overflow-scrolling: touch;
1230 padding: max(32px, env(safe-area-inset-top)) max(40px, env(safe-area-inset-right))
1231 max(32px, env(safe-area-inset-bottom)) max(40px, env(safe-area-inset-left));
1232}
1233
1234#ids-transcript[hidden] {
1235 display: none;
1236}
1237
1238#ids-transcript .ids-transcript-slide {
1239 max-width: 900px;
1240 margin: 0 auto 2.5em auto;
1241}
1242
1243#ids-transcript h1, #ids-transcript h2 {
1244 color: var(--r-heading-color);
1245 margin: 0 0 0.4em 0;
1246}
1247
1248#ids-transcript h1 { font-size: 1.4em; }
1249
1250#ids-transcript h2 { font-size: 1.2em; }
1251
1252#ids-transcript .fragment {
1253 opacity: 1;
1254 visibility: visible;
1255}
1256
1257#ids-transcript .ids-transcript-notes {
1258 border-left: 3px solid #f6a800;
1259 padding: 0.2em 0 0.2em 0.8em;
1260 margin-top: 0.8em;
1261 color: #666;
1262}
1263
1264#ids-transcript .ids-transcript-notes:empty {
1265 display: none;
1266}
1267
1268#ids-transcript img, #ids-transcript video, #ids-transcript iframe {
1269 max-width: 100%;
1270}
Marc Kupietz75327972026-08-29 18:25:28 +03001271
1272// The title slide's branding is cloned into the transcript along with the
1273// rest of the slide, but outside .reveal, where neither the title frame's
1274// sizing rules nor the svg's own (absent) intrinsic dimensions constrain it
1275// -- both would fill the transcript's whole width. Give them a size that
1276// suits a page one reads rather than presents: the QR stays tappable and
1277// scannable, the funder logo shrinks to a line of text.
1278#ids-transcript .title-qr {
1279 box-sizing: border-box;
1280 width: 140px;
1281 max-width: 40%;
1282 padding: #{$idsLogoInset};
1283 background: #fff;
1284}
1285
1286#ids-transcript .title-qr a.qrcode,
1287#ids-transcript .title-qr svg {
1288 display: block;
1289 width: 100%;
1290 height: auto;
1291 padding: 0;
1292}
1293
1294#ids-transcript img.funder-logo {
1295 height: 2.5em;
1296 width: auto;
1297 margin: 0.6em 0;
1298}