blob: e833b8f8a624be729925d641b7a9041452f5456b [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
369.reveal .slides section.level1:not(.title-frame) > h1:first-child {
370 text-align: center !important;
371 margin: 0 !important;
372 padding: 0 !important;
373}
374
375.reveal .slides section.level1:not(.title-frame) > h1:first-child::before {
376 content: none !important;
377}
378
Marc Kupietza737b1b2023-10-07 09:32:20 +0200379// Define additional color effects based on Dracula spec
380// https://spec.draculatheme.com/
381:root {
382 --r-bold-color: #{$idsOrange};
383 --r-list-bullet-color: #{$listBulletColor};
384}
385
386.reveal {
Marc Kupietz9b795bd2026-08-19 06:58:44 +0200387 // Bold ("highlighted") text gets the orange colour AND the condensed Fira
388 // Sans face, as in the IDS reference decks -- the lighter weight and 90%
389 // size keep it from dominating the serif body text.
Marc Kupietza737b1b2023-10-07 09:32:20 +0200390 strong, b {
Marc Kupietz9b795bd2026-08-19 06:58:44 +0200391 font-family: "Fira Sans Condensed", sans-serif;
392 font-weight: 600;
393 font-size: 90%;
Marc Kupietza737b1b2023-10-07 09:32:20 +0200394 color: var(--r-bold-color);
395 }
396
397 // Dracula colored list bullets and numbers
398 ul, ol {
399 li::marker {
400 color: var(--r-list-bullet-color) !important;
401 }
402 }
403}
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200404
Marc Kupietz281ba9c2026-08-11 15:37:48 +0200405// Nested list items are set progressively smaller, both to emphasise the
406// hierarchy and to keep deeply nested lists from visually competing with the
407// first level. The em size compounds down the nesting levels, so each deeper
408// level is 80% of its parent (level 2: 80%, level 3: 64%, level 4: 51%).
409// Markers and the hanging indentation (padding-left: 0.7em above) scale with
410// the text automatically.
411.reveal li li {
412 font-size: 0.8em;
413}
414
Marc Kupietzf4945eb2026-08-19 17:48:41 +0200415// Description lists: dt in orange Fira Sans Condensed, dd indented.
416.reveal dl {
417 font-size: 0.62em;
418 line-height: 1.25;
419}
420.reveal dt {
421 font-weight: 700;
422 margin-top: 0.35em;
423 font-family: "Fira Sans Condensed", sans-serif;
424 color: $idsOrange;
425}
426.reveal dd {
427 margin: 0 0 0 1.2em;
428 color: #444;
429}
430
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200431
432/*********************************************
433 * FOOTER
434 *********************************************/
Marc Kupietzc0b272d2023-10-08 14:24:18 +0200435 #ids-footer:not(title-slide) {
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200436 opacity: 1;
437 background: white;
438 color: #444444;
439 border-top: dotted orange 2px;
440 transition: opacity 800ms ease-in-out;
441 position: fixed;
442 height: 6%;
443 line-height: 6%;
444 z-index: -20;
445 width: 100%;
446 letter-spacing: 0em;
447 text-align: center;
448 display: table;
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200449}
450
451#ids-footer span {
452 height: 100%;
453 line-height: 100%;
454 z-index: -20;
Marc Kupietz61ad0262024-05-14 22:07:50 +0200455 font-size: 1.8vh;
Marc Kupietzc0b272d2023-10-08 14:24:18 +0200456 font-family: "Fira Sans Condensed", "Fira Sans", "Roboto Condensed", "League Gothic", Impact, sans-serif;
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200457 display: inline-block;
458 display: table-cell;
459 vertical-align: middle;
460}
461
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200462/* Bottom position for the IDS-Footer footer when both progress bar and TOC-Progress are visible */
Marc Kupietzc0b272d2023-10-08 14:24:18 +0200463div.progress[style="display: block;"] ~ #ids-footer {
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200464 bottom: calc(3px + 0vh);
465}
466
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200467/* Bottom position for the IDS-Footer footer when TOC-Progress is visible */
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200468#ids-footer {
469 bottom: 3px;
470}
471
472#ids-footer a {
473 color: #555555;
474}
475
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200476/* Bottom position for the IDS-Footer footer when progress bar is visible */
Marc Kupietzc0b272d2023-10-08 14:24:18 +0200477div.progress[style="display: block;"] ~ footer:last-of-type#ids-footer {
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200478 bottom: 3px;
479}
480
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200481/* Bottom position for the IDS-Footer footer when neither progress bar nor TOC-Progress are visible */
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200482footer:last-of-type#ids-footer {
483 bottom: 0px;
484}
485
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200486/* Make IDS-Footer invisible if explicitly indicated */
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200487.no-ids-footer #ids-footer {
488 opacity: 0;
489 transition: opacity 800ms ease-in-out;
490}
491
492.title-frame #ids-footer {
493 opacity: 0;
494 transition: opacity 800ms ease-in-out;
495}
496
497.no-toc-progress #ids-footer {
498 opacity: 0;
499 transition: opacity 800ms ease-in-out;
500}
501
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200502/* Make IDS-Footer invisible in overview mode */
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200503.overview #ids-footer {
504 opacity: 0;
505 transition: opacity 800ms ease-in-out;
506}
507
Marc Kupietz61c8ec72026-08-20 20:47:45 +0200508/* In print, the footer's negative stacking drops it behind the .pdf-page
509 * backgrounds (z-index 1); lift it above them. position: fixed repeats it at
510 * the bottom of every printed page. */
511html.reveal-print #ids-footer {
512 z-index: 100 !important;
513}
514
515// reveal's print CSS gives every .pdf-page z-index:1, which forms a separate
516// stacking context per page. The slide-number-pdf lives INSIDE such a page, so
517// its own z-index only competes within the page: the footer (z-index 100 at
518// root level) always paints over it, and raising the number's z-index alone
519// cannot help. Remove the per-page stacking context in print (the pages are
520// separated by page-break-after:always anyway, so nothing needs stacking), and
521// the number's z-index 200 wins against the footer globally. Position stays
522// the theme's screen rule (right:29px / bottom:22px), which puts the number
523// inside the footer band with its white background cutting the dotted line --
524// the same look as on screen.
525html.reveal-print .reveal .slides .pdf-page {
526 z-index: auto !important;
527}
528
529// On screen the number is flanked by the arrow buttons, so its slightly raised
530// baseline reads as deliberate; in print it shares the footer band with the
531// author/title/date line, whose vertically centered text has its baseline
532// ~19px above the page bottom. The number's screen offset (bottom:22px, 14px
533// font from reveal's print rule) puts its baseline ~25px up. 15px aligns the
534// two baselines. Print-only: the screen rule keeps its 22px.
535html.reveal-print div.slide-number-pdf {
536 z-index: 200 !important;
537 bottom: 15px !important;
538}
539
540// On screen the bar segments shift left by --ids-band-left so the bar reaches
541// the window's physical edge when the slide is pillarboxed. In print there are
542// no bands (.pdf-page == slide box), and if the band values are ever stale
543// (e.g. an outdated template script), a nonzero band-left would push the
544// segments outside the pdf-page, whose overflow:hidden then clips them.
545// Pin the geometry explicitly for print instead of trusting the custom
546// property: title segments start at the heading's (== pdf-page's) left edge,
547// the subtitle segment (which lives in the text column, inset by
548// $idsContentInset) reaches back out by exactly the inset, and the level1
549// divider bar starts at the section's left edge. Widths stay the normal bar
550// width, so the visible result is pixel-identical to the on-screen bar.
551html.reveal-print .reveal .slides section:not(.title-frame) > h1:first-child::before,
552html.reveal-print .reveal .slides section:not(.title-frame) > h2:first-child::before {
553 left: 0 !important;
554}
555
556html.reveal-print .reveal .slides section:not(.title-frame) > h2:first-child + h3::before {
557 left: calc(-1 * #{$idsContentInset}) !important;
558}
559
560html.reveal-print .reveal .slides section.level1:not(.title-frame)::before {
561 left: 0 !important;
562}
563
564// The WGL membership logo sits at bottom:10px of the title frame -- inside
565// the footer's ~46px band on print pages (the footer is force-shown on every
566// page in print view and cannot be hidden per page, position:fixed). Lift the
567// logo above the footer in print only; the screen layout stays put.
568html.reveal-print .reveal .slides section.title-frame {
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300569 background-position: right #{$idsLogoInset} bottom 55px;
Marc Kupietz61c8ec72026-08-20 20:47:45 +0200570}
571
Marc Kupietza0f8f682026-08-08 14:13:11 +0200572// Like the orange bar/IDS logo above, this is painted on the slide itself
573// (rather than on .slide-background-content, which spans the raw,
574// unscaled viewport) so it stays pinned to the title slide's true
Marc Kupietz67715592026-08-15 14:55:18 +0200575// bottom-right corner instead of the browser window's. Its margin mirrors
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300576// the IDS logo's, so the two sit on one shared inset.
Marc Kupietza0f8f682026-08-08 14:13:11 +0200577.reveal .slides section.title-frame {
578 background-image: url("https://corpora.ids-mannheim.de/slides/reveal.js.ids/images/Mitglied_WGL_transparent.svg");
Marc Kupietzf0ce0322023-10-07 15:33:47 +0200579 background-repeat: no-repeat;
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300580 background-position: right #{$idsLogoInset} bottom #{$idsLogoInset};
Marc Kupietz67715592026-08-15 14:55:18 +0200581 background-size: calc(var(--slide-height) * 0.1) auto;
582 /* full slide height, so "bottom" really is the slide's bottom edge */
583 height: 100%;
Marc Kupietze9ace292024-05-14 22:11:15 +0200584}
585
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300586// qrlink() codes placed anywhere else in a deck: qr_svg_fit() crops the svg
587// to the dark modules, so the quiet zone the code needs to stay scannable is
588// this padding (which also keeps a code readable on a dark background).
589.reveal a.qrcode {
590 display: inline-block;
591 padding: 0.5em;
592 background: #fff;
593}
594
Marc Kupietz59e95a62026-08-29 10:19:05 +0300595// Website QR code and funder logo on the title slide (document options
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300596// `website` and `funder_logo`): top-left and bottom-left corners. Like the
597// two logos on the right, they keep $idsLogoInset to both slide edges --
598// measured to the visible ink, so that all four corners look alike. Both are
599// DOM elements injected into the title frame by the pandoc template (the QR
600// itself is generated in R by qrlink()); absolute positioning sticks to the
601// slide, because reveal.js positions the sections themselves.
602//
603// qrlink() crops the svg to the dark modules, so the quiet zone the code
604// needs to stay scannable is this white plate's padding -- which is also
605// what puts the modules themselves at $idsLogoInset from the slide's edges,
606// the plate sitting flush in the corner (invisible on the white slide).
Marc Kupietz59e95a62026-08-29 10:19:05 +0300607.reveal .slides section.title-frame .title-qr {
608 position: absolute;
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300609 top: 0;
610 left: 0;
Marc Kupietz59e95a62026-08-29 10:19:05 +0300611 box-sizing: border-box;
612 width: calc(var(--slide-height) * 0.28);
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300613 padding: #{$idsLogoInset};
Marc Kupietz59e95a62026-08-29 10:19:05 +0300614 background: #fff;
615}
616
617.reveal .slides section.title-frame .title-qr a.qrcode,
618.reveal .slides section.title-frame .title-qr svg {
619 display: block;
620 width: 100%;
621 height: auto;
622 margin: 0;
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300623 // the quiet zone comes from the plate around it here
624 padding: 0;
Marc Kupietz59e95a62026-08-29 10:19:05 +0300625}
626
627.reveal .slides section.title-frame img.funder-logo {
628 position: absolute;
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300629 left: #{$idsLogoInset};
630 bottom: #{$idsLogoInset};
Marc Kupietz59e95a62026-08-29 10:19:05 +0300631 height: calc(var(--slide-height) * 0.07);
Marc Kupietzb2cc5232026-08-29 16:21:52 +0300632 // reveal.js gives images a vertical margin, which for an absolutely
633 // positioned one would add itself to the inset above.
634 margin: 0;
Marc Kupietz59e95a62026-08-29 10:19:05 +0300635 width: auto;
636}
637
638// Lift the funder logo above the print footer band, like the WGL logo above
639html.reveal-print .reveal .slides section.title-frame img.funder-logo {
640 bottom: 55px;
641}
642
643// The navigation chrome is hidden on the title slide (the template toggles
644// the ids-title-plain class when the title frame is the current slide). Use
645// opacity/visibility rather than display:none so the transition out of the
646// title slide fades the chrome in instead of popping it up, and so reveal.js'
647// own controls bookkeeping keeps working underneath.
648html.ids-title-plain .reveal .controls,
649html.ids-title-plain .reveal .slide-number,
650html.ids-title-plain .reveal .slide-menu-button {
651 opacity: 0 !important;
652 visibility: hidden !important;
653 pointer-events: none !important;
654}
655
656.reveal .controls,
657.reveal .slide-number,
658.reveal .slide-menu-button {
659 transition: opacity 0.4s;
660}
661
Marc Kupietze9ace292024-05-14 22:11:15 +0200662
Marc Kupietz903104a2026-08-20 10:10:41 +0200663/*********************************************
664 * SLIDES MENU
665 *********************************************/
666
667// The menu plugin copies .reveal's computed font-family onto .slide-menu as an
668// inline style (and its own CSS is loaded after the theme), so without
669// !important here the menu would come out in the Libertinus serif body face.
670// Fira Sans Condensed is the IDS sans for navigation/UI text, and its narrow
671// glyphs keep long (German) slide titles on one line.
672.slide-menu-wrapper .slide-menu {
673 font-family: "Fira Sans Condensed", sans-serif !important;
674}
675
676// Widen the menu a little over the plugin's 300px default -- but only the
677// default: a width the user picked via the menu-width option maps to one of
678// the plugin's width classes (or an inline style), which must keep winning.
679.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 +0200680 width: 372px !important;
Marc Kupietz903104a2026-08-20 10:10:41 +0200681}
682
683// Tighter, less wasteful rows than the plugin's 10px 18px padding with a 12px
684// icon gap: the icon column and generous side padding eat exactly the width
685// the titles need.
686.slide-menu-wrapper .slide-menu-item,
687.slide-menu-wrapper .slide-menu-item-vertical {
688 padding: 6px 12px !important;
689 line-height: 1.3 !important;
690}
691
692.slide-menu-wrapper .slide-menu-item-vertical {
693 padding-left: 26px !important;
694}
695
696// Wrapped titles: make the row a flex line so the second line aligns with the
697// first instead of sliding under the bullet/circle icon. The icon sits on the
698// first line's text baseline; the title column takes the remaining width and
699// wraps within itself.
700.slide-menu-wrapper .slide-menu-item,
701.slide-menu-wrapper .slide-menu-item-vertical {
702 display: flex !important;
703 align-items: baseline !important;
704}
705
706.slide-menu-wrapper .slide-menu-item-title {
707 flex: 1 !important;
708 min-width: 0 !important;
709}
710
711.slide-menu-wrapper .slide-menu-item i.far,
712.slide-menu-wrapper .slide-menu-item i.fas,
713.slide-menu-wrapper .slide-menu-item-vertical i.far,
714.slide-menu-wrapper .slide-menu-item-vertical i.fas,
715.slide-menu-wrapper .slide-menu-item svg.svg-inline--fa,
716.slide-menu-wrapper .slide-menu-item-vertical svg.svg-inline--fa {
717 padding-right: 8px !important;
718}
719
Marc Kupietz7427cca2026-08-20 10:53:03 +0200720// Top-level (section) entries in bold, marking the hierarchy as the indented
721// sub-slides alone do now. Note the Google Fonts import only ships Fira Sans
722// Condensed in 300/400/700/800 -- there is no 600.
723.slide-menu-wrapper .slide-menu-item {
724 font-weight: 700 !important;
725}
726
Marc Kupietz903104a2026-08-20 10:10:41 +0200727// Current slide in the IDS accent colour, matching the slide-number and the
728// orange bar.
729.slide-menu-wrapper .active-menu-panel li.active {
730 color: #{$idsOrange} !important;
Marc Kupietzf0ce0322023-10-07 15:33:47 +0200731}
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200732
733/*
734 * Menu controls
735 */
Marc Kupietzc0b272d2023-10-08 14:24:18 +0200736body .reveal .slide-menu-button {
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200737 color: #aaaaaa !important;
738 position: fixed;
739 left: 30px;
740 bottom: 2%;
741 vertical-align: middle;
742 z-index: 30;
743 font-size: 2vh;
744}
745
746#customcontrols > ul {
747 color: #aaaaaa !important;
748 position: fixed;
Marc Kupietzf51e9152023-10-07 15:32:33 +0200749 left: 50px;
Marc Kupietz7c8f7de2023-10-07 11:42:29 +0200750 bottom: 2% !important;
751 vertical-align: middle;
752 z-index: 30;
753 font-size: 2vh;
754}
755
756@media only screen and (min-width: 500px) {
757 #customcontrols > ul {
758 bottom: 2% !important;
759 }
760}
Marc Kupietz3fdee732023-10-07 18:52:20 +0200761
Marc Kupietzc7249f92023-10-10 07:16:50 +0200762.reveal .controls .controls-arrow {
763 position: relative;
764 width: 3.6em;
765 height: 3.6em;
766 bottom: -12px;
767 right: -4px;
768}
769
Marc Kupietz3fdee732023-10-07 18:52:20 +0200770.reveal h3, h4, h5, h6 {
771 text-transform: none !important;
772}
773
774.reveal h3, h4, h5, h6 {
775 text-transform: none !important;
776}
777
778.reveal h2 + h3 {
779 margin-top: -0.5em !important;
780}
Marc Kupietzdf0eda92023-10-07 20:50:00 +0200781
782.title-frame h1,
783.title-frame h2 {
784 margin: 0 0 0 0;
785 background: rgb(246, 168, 0);
786 color: white;
787 font-family: "Fira Sans Condensed", "Roboto Condensed", Impact, sans-serif;
788 font-weight: 600;
789 line-height: 1.2;
790 letter-spacing: 0.05ex;
791 text-transform: uppercase;
792 width: 100%;
793 margin-top: .5em;
794 padding-top: .5em;
795 font-size: 1.75em;
796 margin-left: 0;
797 text-align: center;
798 text-shadow: none;
799 word-wrap: break-word;
800}
801
802
803.title-frame .author {
804 font-family: "Fira Sans Condensed", sans-serif;
805 font-weight: 400;
806 color: #657b83;
807 margin-top: 10vh;
808}
809
810.title-frame .place {
811 font-family: "Fira Sans Condensed", sans-serif;
812 margin-top: 40px;
813 font-weight: 400;
814 color: #657b83;
815}
816
817.title-frame h2 {
818 margin-top: -3px;
819 margin-bottom: 1em;
820 padding-bottom: .5em;
821 font-size: 1em;
822}
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200823
824/*********************************************
825 * TABLES
826 *********************************************/
827
828 th {
829 color: rgb(246, 168, 0);
830}
831
832table {
833 font-family: 'Fira Sans Condensed', sans-serif;
834 font-weight: 400;
835 font-size: 16px;
Marc Kupietz25570ef2026-08-28 14:03:21 +0300836 // Fira Sans Condensed ships proportional figures by default, so the digits
837 // in neighbouring rows do not line up; tabular numbers (tnum) fix the digit
838 // widths and align numeric table columns vertically.
839 font-variant-numeric: tabular-nums;
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200840}
841
842.reveal table.dataTable {
843 border: #aaaaaa 1px solid;
844 border-collapse: collapse;
845}
846
847.reveal table.dataTable td {
848 border: #aaaaaa 1px solid;
849 border-collapse: collapse;
850}
851
852.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 {
853 display: none;
854}
855
856.caption {
857 font-family: 'Fira Sans Condensed', sans-serif;
858 font-weight: 400;
859 font-size: 16px;
860 text-align: center;
861}
862
863/*
864table.display td { white-space: nowrap; }
865*/
866
867.dt-buttons, .dataTables_filter {
868 margin-top: 10pt;
869}
870
Marc Kupietz069f1e42023-10-11 10:26:16 +0200871/* Sort Arrows in DataTables */
872table.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 {
873 right: 0 !important;
874 line-height: 80% !important;
875}
876
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200877/*********************************************
878 * BIBLIOGRAPHY
879 *********************************************/
880
881.reveal .references {
882 font-family: "Fira Sans Condensed", sans-serif;
883 font-size: 16px;
884 text-align: left;
Marc Kupietzbfab8a12026-08-19 14:42:42 +0200885 margin-top: 10px;
886 max-height: 510px;
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200887 font-weight: 400;
888 color: #253b43;
889 overflow-y: auto;
890}
891
892.hanging-indent > .csl-entry {
893 padding-left: 22px ;
894 text-indent: -22px ;
895}
896
Marc Kupietz21f526c2026-08-14 12:32:56 +0200897// .references scopes these above pandoc's CSL defaults (div.csl-entry), which
898// otherwise win on specificity and pin margin-bottom to 0em.
899.references .csl-entry {
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200900 color: #888888;
Marc Kupietz21f526c2026-08-14 12:32:56 +0200901 margin-bottom: 0.5em;
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200902}
903
Marc Kupietz21f526c2026-08-14 12:32:56 +0200904// "Authors (Year):" as a bold dark first line; the theme template's JS wraps
905// the leading text of each entry in .csl-authors-year (see default.html) --
906// which part of an entry citeproc wraps in spans depends on the entry type, so
907// a CSS-only break cannot place it reliably.
908.csl-entry .csl-authors-year {
909 display: block;
910 font-weight: bold;
911 color: #4d616b;
Marc Kupietz0a3c2e52023-10-08 20:20:43 +0200912}
Marc Kupietz11797162023-10-09 23:17:36 +0200913
914.reveal code.sourceCode:last-child + pre {
915 height: 800px !important;
Marc Kupietzc7249f92023-10-10 07:16:50 +0200916}
917
Marc Kupietz589d1b82023-10-10 12:31:33 +0200918
919/*********************************************
Marc Kupietz54d9ce02026-08-21 11:38:45 +0200920 * FULLSCREEN TOGGLE
Marc Kupietz589d1b82023-10-10 12:31:33 +0200921 *********************************************/
922
Marc Kupietz54d9ce02026-08-21 11:38:45 +0200923// Small fixed toggle for touch devices (script injected by default.html):
924// phones have no F11 and the browser chrome eats slide pixels. Hidden on
925// pointer devices (F11 exists there) and whenever the Fullscreen API is
926// unavailable -- the script also removes it then. Same muted look and column
927// as the slide menu button, one slot above it.
928#ids-fullscreen {
929 display: none;
930 position: fixed;
931 left: 30px;
932 bottom: 6%;
933 z-index: 30;
934 width: 28px;
935 height: 28px;
936 border: 0;
937 padding: 0;
938 cursor: pointer;
939 opacity: 0.55;
940 // Feather-style corner brackets; gray idle, IDS orange while fullscreen
941 // (the two data URIs differ only in the stroke colour).
942 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;
943
944 &:active,
945 &:focus-visible {
946 opacity: 0.9;
947 }
948
949 &.is-fullscreen {
950 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");
951 }
952}
953
954// Only touch devices get the button; desktops keep their F11.
955@media (hover: none) and (pointer: coarse) {
956 #ids-fullscreen {
957 display: block;
958 }
959}
960
961// position:fixed elements repeat on every printed page -- never print it.
962html.reveal-print #ids-fullscreen {
963 display: none !important;
964}
965
966
967
Marc Kupietz589d1b82023-10-10 12:31:33 +0200968 .reveal .controls .controls-arrow:after, .reveal .controls .controls-arrow:before {
969 width: 13px !important; /* size */
970 height: 4px; /* line width */
971}
972
973.reveal .controls {
974 display: none;
975 position: absolute;
976 top: auto;
977 bottom: -8px;
978 right: 16px;
979 left: auto;
980 z-index: 11;
981 /* color: #000;*/
982 pointer-events: none;
983 font-size: 8px;
984}
985
986.reveal .controls .controls-arrow {
987 position: relative;
988 height: 3.6em;
989 width: 1.2em; /* distance betwee arrows */
990 bottom: 0;
991 right: 0;
992}
993
994.reveal div.slide-number {
995 text-align: center;
996 width: 2em;
997 position: absolute;
998 display: block;
999 right: 29px;
1000 bottom: 22px;
1001 z-index: 31;
1002 font-family: "Fira Sans Condensed", sans-serif;
1003 font-size: 18px;
1004 line-height: 1;
1005 background-color: white;
1006 color: #666;
1007 padding: 0;
1008}
1009
Marc Kupietzddd9ba52026-08-29 16:22:29 +03001010
1011/*********************************************
Marc Kupietzf8e92bb2026-08-29 16:32:01 +03001012 * SPEAKER NOTES OVERLAY (touch devices)
1013 *********************************************/
1014#ids-notes {
1015 display: none;
1016 position: fixed;
1017 left: 70px;
1018 bottom: 6%;
1019 z-index: 30;
1020 width: 28px;
1021 height: 28px;
1022 border: 0;
1023 padding: 0;
1024 cursor: pointer;
1025 opacity: 0.55;
1026 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;
1027}
1028
1029#ids-notes:active, #ids-notes:focus-visible {
1030 opacity: 0.9;
1031}
1032
1033#ids-notes.is-open {
1034 opacity: 0.9;
1035 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");
1036}
1037
1038#ids-transcript-btn {
1039 display: none;
1040 position: fixed;
1041 left: 110px;
1042 bottom: 6%;
1043 z-index: 30;
1044 width: 28px;
1045 height: 28px;
1046 border: 0;
1047 padding: 0;
1048 cursor: pointer;
1049 opacity: 0.55;
1050 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;
1051}
1052
1053#ids-transcript-btn:active, #ids-transcript-btn:focus-visible, #ids-transcript-btn.is-open {
1054 opacity: 0.9;
1055}
1056
1057#ids-transcript-btn.is-open {
1058 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");
1059}
1060
1061@media (hover: none) and (pointer: coarse) {
1062 #ids-notes, #ids-transcript-btn {
1063 display: block;
1064 }
1065}
1066
1067html.reveal-print #ids-notes, html.reveal-print #ids-transcript-btn {
1068 display: none !important;
1069}
1070
1071#ids-notes-overlay {
1072 position: fixed;
1073 inset: 0;
1074 z-index: 100;
1075 background: #fff;
1076 color: #444444;
1077 font-family: "Fira Sans", "Fira Sans Condensed", sans-serif;
1078 overflow-y: auto;
1079 -webkit-overflow-scrolling: touch;
1080 padding: max(24px, env(safe-area-inset-top)) max(24px, env(safe-area-inset-right))
1081 max(24px, env(safe-area-inset-bottom)) max(24px, env(safe-area-inset-left));
1082}
1083
1084#ids-notes-overlay[hidden] {
1085 display: none;
1086}
1087
1088#ids-notes-header {
1089 display: flex;
1090 align-items: baseline;
1091 gap: 12px;
1092 border-bottom: 1px solid #e0e0e0;
1093 margin-bottom: 16px;
1094 padding-bottom: 8px;
1095}
1096
1097#ids-notes-timing {
1098 flex-shrink: 0;
1099 color: #f6a800;
1100 font-weight: bold;
1101 white-space: nowrap;
1102}
1103
1104#ids-notes-title {
1105 flex-grow: 1;
1106 margin: 0;
1107 font-size: 1.1em;
1108}
1109
1110#ids-notes-close {
1111 flex-shrink: 0;
1112 border: 0;
1113 background: none;
1114 color: #888888;
1115 font-size: 1.2em;
1116 cursor: pointer;
1117 padding: 8px;
1118 margin: -8px;
1119}
1120
1121#ids-notes-content {
1122 font-size: 20px;
1123 line-height: 1.5;
1124}
1125
1126#ids-notes-content em {
1127 color: #888888;
1128}
1129
1130/*********************************************
Marc Kupietzddd9ba52026-08-29 16:22:29 +03001131 * OVERVIEW / TOC SLIDES
1132 *********************************************/
Marc Kupietzde3ffa42026-08-30 13:47:57 +03001133/* The auto-generated TOC lists the chapters with their numbers as
1134 .ids-toc-number spans in the marker colour, prepended to the entry
1135 titles: the enumeration therefore starts flush with the slide heading
1136 (the drawn ol/ul markers are suppressed for the top-level entries;
1137 sub-headings below their chapters keep their bullets). Entries stay at
1138 the normal slide body size and keep the theme's link colour, so they
1139 read as the navigation links they are. Only the denser two-column
1140 variant with sub-headings is scaled down. */
1141.reveal .slides section:not(.title-frame) .ids-overview-toc {
1142 padding-left: 0 !important;
1143}
1144.reveal .slides section:not(.title-frame) .ids-overview-toc > li::before {
1145 content: none !important;
1146}
1147.reveal .ids-overview-toc .ids-toc-number {
1148 color: var(--r-list-bullet-color);
1149}
Marc Kupietzddd9ba52026-08-29 16:22:29 +03001150.reveal .ids-overview-toc {
1151 list-style: none;
1152 margin: 0.2em 0 0 0;
1153 padding: 0;
1154 line-height: 1.35;
1155}
1156.reveal .ids-overview-toc > li {
1157 margin: 0.45em 0;
1158 font-weight: bold;
1159}
1160.reveal .ids-overview-toc ul {
1161 list-style: none;
1162 margin: 0.1em 0 0.2em 0;
1163 padding: 0 0 0 1.1em;
1164 font-weight: normal;
1165}
1166.reveal .ids-overview-toc.with-subheadings {
1167 columns: 2;
1168 column-gap: 2.5em;
1169 font-size: 0.8em;
1170}
1171.reveal .ids-overview-toc.with-subheadings > li {
1172 break-inside: avoid;
1173}
1174.reveal .ids-overview-toc ul li {
1175 margin: 0.18em 0;
1176}
Marc Kupietzf8e92bb2026-08-29 16:32:01 +03001177
1178/*********************************************
1179 * TRANSCRIPT / READ-ALOUD VIEW ('r')
1180 *********************************************/
1181#ids-transcript {
1182 position: fixed;
1183 inset: 0;
1184 z-index: 90;
1185 background: #fff;
1186 color: #444444;
1187 font-family: "Fira Sans", "Fira Sans Condensed", sans-serif;
1188 font-size: 18px;
1189 line-height: 1.5;
1190 overflow-y: auto;
1191 -webkit-overflow-scrolling: touch;
1192 padding: max(32px, env(safe-area-inset-top)) max(40px, env(safe-area-inset-right))
1193 max(32px, env(safe-area-inset-bottom)) max(40px, env(safe-area-inset-left));
1194}
1195
1196#ids-transcript[hidden] {
1197 display: none;
1198}
1199
1200#ids-transcript .ids-transcript-slide {
1201 max-width: 900px;
1202 margin: 0 auto 2.5em auto;
1203}
1204
1205#ids-transcript h1, #ids-transcript h2 {
1206 color: var(--r-heading-color);
1207 margin: 0 0 0.4em 0;
1208}
1209
1210#ids-transcript h1 { font-size: 1.4em; }
1211
1212#ids-transcript h2 { font-size: 1.2em; }
1213
1214#ids-transcript .fragment {
1215 opacity: 1;
1216 visibility: visible;
1217}
1218
1219#ids-transcript .ids-transcript-notes {
1220 border-left: 3px solid #f6a800;
1221 padding: 0.2em 0 0.2em 0.8em;
1222 margin-top: 0.8em;
1223 color: #666;
1224}
1225
1226#ids-transcript .ids-transcript-notes:empty {
1227 display: none;
1228}
1229
1230#ids-transcript img, #ids-transcript video, #ids-transcript iframe {
1231 max-width: 100%;
1232}
Marc Kupietz75327972026-08-29 18:25:28 +03001233
1234// The title slide's branding is cloned into the transcript along with the
1235// rest of the slide, but outside .reveal, where neither the title frame's
1236// sizing rules nor the svg's own (absent) intrinsic dimensions constrain it
1237// -- both would fill the transcript's whole width. Give them a size that
1238// suits a page one reads rather than presents: the QR stays tappable and
1239// scannable, the funder logo shrinks to a line of text.
1240#ids-transcript .title-qr {
1241 box-sizing: border-box;
1242 width: 140px;
1243 max-width: 40%;
1244 padding: #{$idsLogoInset};
1245 background: #fff;
1246}
1247
1248#ids-transcript .title-qr a.qrcode,
1249#ids-transcript .title-qr svg {
1250 display: block;
1251 width: 100%;
1252 height: auto;
1253 padding: 0;
1254}
1255
1256#ids-transcript img.funder-logo {
1257 height: 2.5em;
1258 width: auto;
1259 margin: 0.6em 0;
1260}