@kadal/theme-crisp 0.0.0-stage → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Slidev.js Team (the original theme, @slidev/theme-apple-basic)
4
+ Copyright (c) 2026 Mithunish Prabhakaran (the Kadal Deck port, @kadal/theme-crisp)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,49 @@
1
- # Temporary Holding Version
1
+ # @kadal/theme-crisp
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **Crisp**, a theme for [Kadal Deck](https://deck.kadal.cc): plain black on white. Helvetica
4
+ Neue, bold titles over a bold subtitle, pictures set inside a margin, and layouts for title
5
+ pictures and photo grids. Light and dark. A port of a Slidev theme (see the attribution below),
6
+ with its layout names and frontmatter, so a Slidev deck moves over unchanged.
7
+
8
+ ```bash
9
+ npm install @kadal/theme-crisp
10
+ ```
11
+
12
+ ```yaml
13
+ ---
14
+ theme: crisp
15
+ layout: intro-image
16
+ image: /title.jpg
17
+ ---
18
+ ```
19
+
20
+ ## Layouts
21
+
22
+ Every engine layout is styled. The theme's own:
23
+
24
+ | layout | frontmatter | what |
25
+ |---|---|---|
26
+ | `intro-image` | `image` | the picture fills the slide; the words, white, sit on it |
27
+ | `intro-image-right` | `image` | a title block centred on the left, the picture in a margin on the right |
28
+ | `image-right` | `image` | the words from the top on the left, the picture in a margin on the right (replaces the engine's) |
29
+ | `3-images` | `imageLeft`, `imageTopRight`, `imageBottomRight` | one tall picture and two stacked |
30
+ | `bullets` | | a list without a title, hung below the top |
31
+
32
+ An `image` that starts with `#`, `rgb` or `hsl` paints a colour instead, as in Slidev. `intro`,
33
+ `section`, `statement`, `fact` and `quote` keep their Slidev look.
34
+
35
+ ## Develop
36
+
37
+ The preview deck (`preview/deck.mdx`) is the original theme's own example deck, slide for slide:
38
+
39
+ ```bash
40
+ npm run dev # the preview deck, live
41
+ npm run check # lint it
42
+ ```
43
+
44
+ ## Licence and attribution
45
+
46
+ MIT. This package is a port of [`@slidev/theme-apple-basic`](https://github.com/slidevjs/themes), MIT License,
47
+ Copyright (c) 2021 Slidev.js Team (the theme by Jeremy Meissner). The look, the layouts and their frontmatter are
48
+ theirs; the React layouts and the stylesheet were rewritten for Kadal Deck. The full notice is in
49
+ [LICENSE](./LICENSE).
package/index.tsx ADDED
@@ -0,0 +1,80 @@
1
+ import type { CSSProperties } from "react";
2
+
3
+ import type { LayoutProps } from "@kadal/deck";
4
+
5
+ /**
6
+ * Crisp: the Slidev theme @slidev/theme-apple-basic (MIT, © 2021 Slidev.js Team) for Kadal Deck.
7
+ *
8
+ * Its layouts, with the same names and frontmatter as Slidev's:
9
+ *
10
+ * intro-image `image:` fills the slide, the words white on it
11
+ * intro-image-right a title block centred on the left, `image:` inside a margin on the right
12
+ * image-right the same with the words from the top (replaces the engine's image-right)
13
+ * 3-images `imageLeft:`, `imageTopRight:`, `imageBottomRight:` in a margin
14
+ * bullets a list with no title, hung below the top
15
+ *
16
+ * The theme's intro, section, statement, fact and quote are the engine's layouts of those names,
17
+ * restyled in style.css (Slidev's are the same centred box). Pictures follow Slidev's
18
+ * handleBackground: a colour (`#…`, `rgb…`, `hsl…`) paints the box, anything else is a picture.
19
+ */
20
+
21
+ function str(v: unknown): string | null {
22
+ return typeof v === "string" && v.trim() ? v.trim() : null;
23
+ }
24
+
25
+ /** Slidev's handleBackground, without the dim: a colour, or a picture set to cover. */
26
+ function picture(value: unknown): CSSProperties {
27
+ const v = str(value);
28
+ if (!v) return {};
29
+ if (/^(#|rgb|hsl)/.test(v)) return { background: v };
30
+ return { backgroundImage: `url("${v}")` };
31
+ }
32
+
33
+ function IntroImage({ frontmatter, children }: LayoutProps) {
34
+ return (
35
+ <div className="deck-layout deck-layout-intro-image" style={picture(frontmatter.image)}>
36
+ {children}
37
+ </div>
38
+ );
39
+ }
40
+
41
+ function makeImageRight(name: "image-right" | "intro-image-right") {
42
+ return function ImageRight({ frontmatter, children }: LayoutProps) {
43
+ return (
44
+ <div className={`deck-layout deck-layout-${name}`}>
45
+ <div className="crisp-image-content">{children}</div>
46
+ <div className="crisp-picture" style={picture(frontmatter.image)} role="presentation" />
47
+ </div>
48
+ );
49
+ };
50
+ }
51
+
52
+ function ThreeImages({ frontmatter, children }: LayoutProps) {
53
+ return (
54
+ <div className="deck-layout deck-layout-3-images">
55
+ <div className="crisp-picture crisp-3-left" style={picture(frontmatter.imageLeft)} />
56
+ <div className="crisp-3-right">
57
+ <div className="crisp-picture crisp-3-top" style={picture(frontmatter.imageTopRight)} />
58
+ <div
59
+ className="crisp-picture crisp-3-bottom"
60
+ style={picture(frontmatter.imageBottomRight)}
61
+ />
62
+ </div>
63
+ <div className="crisp-3-content">{children}</div>
64
+ </div>
65
+ );
66
+ }
67
+
68
+ function Bullets({ children }: LayoutProps) {
69
+ return <div className="deck-layout deck-layout-bullets">{children}</div>;
70
+ }
71
+
72
+ export default {
73
+ layouts: {
74
+ "intro-image": IntroImage,
75
+ "intro-image-right": makeImageRight("intro-image-right"),
76
+ "image-right": makeImageRight("image-right"),
77
+ "3-images": ThreeImages,
78
+ bullets: Bullets,
79
+ },
80
+ };
package/package.json CHANGED
@@ -1,6 +1,91 @@
1
1
  {
2
2
  "name": "@kadal/theme-crisp",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.4.0",
4
+ "description": "Crisp: plain black on white for Kadal Deck, ported from a Slidev theme. Helvetica Neue, bold titles, pictures set in a margin; light and dark.",
5
+ "keywords": [
6
+ "kadal-theme",
7
+ "kadal-deck",
8
+ "presentation",
9
+ "slides",
10
+ "theme",
11
+ "slidev-port"
12
+ ],
13
+ "homepage": "https://deck.kadal.cc/docs/",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/kadalcc/deck.git",
17
+ "directory": "packages/theme-crisp"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/kadalcc/deck/issues"
21
+ },
22
+ "license": "MIT",
23
+ "author": "Mithunish Prabhakaran <pmithunish@gmail.com>",
24
+ "type": "module",
25
+ "files": [
26
+ "style.css",
27
+ "index.tsx",
28
+ "README.md",
29
+ "LICENSE"
30
+ ],
31
+ "exports": {
32
+ ".": "./index.tsx",
33
+ "./style.css": "./style.css",
34
+ "./package.json": "./package.json"
35
+ },
36
+ "kadal": {
37
+ "theme": {
38
+ "name": "crisp",
39
+ "title": "Crisp",
40
+ "description": "Plain black on white: Helvetica Neue, bold titles, pictures in a margin, intro-image and 3-images layouts.",
41
+ "colorScheme": "both",
42
+ "themeConfig": {
43
+ "primary": "#3ab9d5"
44
+ },
45
+ "config": {
46
+ "fonts": {
47
+ "sans": "Helvetica Neue",
48
+ "local": "Helvetica Neue",
49
+ "weights": "300,400,500,600,700"
50
+ }
51
+ },
52
+ "shiki": {
53
+ "light": "vitesse-light",
54
+ "dark": "vitesse-dark"
55
+ },
56
+ "defaults": {},
57
+ "layouts": [
58
+ "intro-image",
59
+ "intro-image-right",
60
+ "image-right",
61
+ "3-images",
62
+ "bullets"
63
+ ],
64
+ "components": []
65
+ }
66
+ },
67
+ "publishConfig": {
68
+ "access": "public",
69
+ "provenance": true
70
+ },
71
+ "scripts": {
72
+ "dev": "kadal-deck dev -C preview",
73
+ "build": "kadal-deck build -C preview",
74
+ "check": "kadal-deck check -C preview",
75
+ "typecheck": "tsc --noEmit"
76
+ },
77
+ "peerDependencies": {
78
+ "@kadal/deck": "^0.4.0",
79
+ "react": "^19.2.0"
80
+ },
81
+ "devDependencies": {
82
+ "@kadal/deck": "workspace:*",
83
+ "@types/react": "^19.2.0",
84
+ "@types/react-dom": "^19.2.0",
85
+ "@vitejs/plugin-react": "^6.0.2",
86
+ "react": "^19.2.7",
87
+ "react-dom": "^19.2.7",
88
+ "typescript": "^6.0.3",
89
+ "vite": "^8.0.16"
90
+ }
91
+ }
package/style.css ADDED
@@ -0,0 +1,410 @@
1
+ /* Crisp — a port to Kadal Deck of the Slidev theme @slidev/theme-apple-basic (MIT, © 2021
2
+ Slidev.js Team; the theme by Jeremy Meissner): plain black on white. Helvetica Neue, bold
3
+ headings, a bold subtitle under a big title, pictures set inside a margin, and the layouts that
4
+ go with them (intro-image, intro-image-right, image-right, 3-images, bullets). White on
5
+ #121212 in the dark.
6
+
7
+ Units. Slidev draws on a 980px-wide canvas with a 16px rem and a 1.1rem body; Kadal draws on a
8
+ 1920px one. Everything here is in `--crisp-rem`, one Slidev rem at Kadal's scale, worked out
9
+ from the slide's base size the way Slidev's body is (1.1rem), so the proportions are Slidev's
10
+ exactly and a deck that changes --deck-base-size scales the whole theme with it.
11
+
12
+ Unlike Slidev's other themes this one does not build on Slidev's shared layout stylesheet: the
13
+ rules below are its own, so h4–h6 are body-sized and ordered lists are its (numbered) own.
14
+
15
+ themeConfig: `primary` → --theme-primary (the quote's rule, links on hover, the progress bar). */
16
+
17
+ .theme-crisp {
18
+ --crisp-rem: calc(var(--deck-base-size) / 1.1);
19
+ /* colour */
20
+ --deck-bg: #ffffff;
21
+ --deck-fg: #181818;
22
+ --deck-muted: #6b6b6b;
23
+ --deck-accent: var(--theme-primary, #3ab9d5);
24
+ --deck-accent-2: #2993a3;
25
+ --deck-surface: #f5f5f5;
26
+ --deck-border: rgba(156, 163, 175, 0.2);
27
+ --deck-live: var(--theme-primary, #3ab9d5);
28
+ /* type: the fonts mechanism (config.fonts in package.json) points these at Helvetica Neue */
29
+ --deck-heading-font: "Helvetica Neue", Helvetica, Arial, ui-sans-serif, system-ui, sans-serif;
30
+ --deck-body-font: "Helvetica Neue", Helvetica, Arial, ui-sans-serif, system-ui, sans-serif;
31
+ --deck-mono-font: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
32
+ --deck-serif-font: ui-serif, Georgia, Cambria, "Times New Roman", serif;
33
+ --deck-base-size: 34.5px;
34
+ /* code */
35
+ --deck-code-bg: #f5f5f5;
36
+ --deck-code-fg: #1b1b1b;
37
+ --deck-code-active: rgba(24, 24, 24, 0.06);
38
+ /* shape: Slidev's 2.5rem × 3.5rem page padding; --deck-pad is the wider of the two */
39
+ --deck-radius: calc(var(--crisp-rem) * 0.25);
40
+ --deck-pad: calc(var(--crisp-rem) * 3.5);
41
+ --deck-transition: 500ms;
42
+ --deck-controls-color: var(--deck-fg);
43
+ }
44
+ .theme-crisp[data-color-scheme="dark"] {
45
+ --deck-bg: #121212;
46
+ --deck-fg: #dddddd;
47
+ --deck-muted: #9a9a9a;
48
+ --deck-accent-2: #54b1bf;
49
+ --deck-surface: #1b1b1b;
50
+ --deck-border: rgba(156, 163, 175, 0.2);
51
+ --deck-code-bg: #1b1b1b;
52
+ --deck-code-fg: #eeeeee;
53
+ --deck-code-active: rgba(221, 221, 221, 0.08);
54
+ }
55
+
56
+ /* ── the page ─────────────────────────────────────────────────────────── */
57
+ .theme-crisp .deck-slide {
58
+ padding: calc(var(--crisp-rem) * 2.5) calc(var(--crisp-rem) * 3.5);
59
+ line-height: 1.5;
60
+ }
61
+ .theme-crisp .deck-slide-background {
62
+ inset: calc(var(--crisp-rem) * -2.5) calc(var(--crisp-rem) * -3.5);
63
+ }
64
+
65
+ /* ── type (the theme's styles/layout.css) ─────────────────────────────── */
66
+ .theme-crisp .deck-slide :is(h1, h2, h3, h4, h5, h6) {
67
+ font-family: var(--deck-heading-font);
68
+ font-size: 1em;
69
+ font-weight: 400;
70
+ line-height: inherit;
71
+ letter-spacing: normal;
72
+ margin: 0;
73
+ text-wrap: wrap;
74
+ }
75
+ .theme-crisp .deck-slide h1 {
76
+ font-size: calc(var(--crisp-rem) * 2.25);
77
+ line-height: calc(var(--crisp-rem) * 2.5);
78
+ font-weight: 700;
79
+ margin-bottom: var(--crisp-rem);
80
+ margin-inline-start: -0.05em;
81
+ }
82
+ .theme-crisp .deck-slide h1 + h2 {
83
+ margin-top: calc(var(--crisp-rem) * -1);
84
+ }
85
+ .theme-crisp .deck-slide h2 {
86
+ font-size: calc(var(--crisp-rem) * 1.5);
87
+ line-height: calc(var(--crisp-rem) * 2);
88
+ font-weight: 700;
89
+ }
90
+ .theme-crisp .deck-slide h3 {
91
+ font-size: calc(var(--crisp-rem) * 0.875);
92
+ line-height: calc(var(--crisp-rem) * 1.25);
93
+ padding-top: calc(var(--crisp-rem) * 0.5);
94
+ text-transform: uppercase;
95
+ letter-spacing: 0.1em;
96
+ font-weight: 500;
97
+ margin-inline-start: -0.05em;
98
+ }
99
+ .theme-crisp .deck-slide h3:not(.opacity-100) {
100
+ opacity: 0.4;
101
+ }
102
+ .theme-crisp .deck-slide p {
103
+ margin: var(--crisp-rem) 0;
104
+ line-height: calc(var(--crisp-rem) * 1.5);
105
+ }
106
+ .theme-crisp .deck-slide h1 + p {
107
+ margin-top: calc(var(--crisp-rem) * -0.5);
108
+ margin-bottom: var(--crisp-rem);
109
+ }
110
+ .theme-crisp .deck-slide :is(p, ul, table) + h2 {
111
+ margin-top: calc(var(--crisp-rem) * 2.5);
112
+ }
113
+ .theme-crisp .deck-slide :is(ul, ol) {
114
+ margin: 0 0 var(--crisp-rem);
115
+ padding: 0;
116
+ }
117
+ .theme-crisp .deck-slide ul {
118
+ list-style: disc;
119
+ }
120
+ .theme-crisp .deck-slide ol {
121
+ list-style: decimal;
122
+ }
123
+ .theme-crisp .deck-slide li {
124
+ margin: 0 0 0 1.1em;
125
+ padding-inline-start: 0.2em;
126
+ line-height: 1.8em;
127
+ }
128
+ .theme-crisp .deck-slide li > :is(ul, ol) {
129
+ margin-bottom: 0;
130
+ }
131
+ .theme-crisp .deck-slide blockquote {
132
+ margin: 0;
133
+ padding: calc(var(--crisp-rem) * 0.25) calc(var(--crisp-rem) * 0.5);
134
+ font-size: calc(var(--crisp-rem) * 0.875);
135
+ line-height: calc(var(--crisp-rem) * 1.25);
136
+ font-style: normal;
137
+ color: inherit;
138
+ background: var(--deck-code-bg);
139
+ border: 0;
140
+ border-inline-start: 1px solid var(--deck-accent);
141
+ border-radius: calc(var(--crisp-rem) * 0.25);
142
+ }
143
+ .theme-crisp .deck-slide blockquote > * {
144
+ margin-block: 0;
145
+ }
146
+ .theme-crisp .deck-slide table {
147
+ width: 100%;
148
+ font-size: 1em;
149
+ line-height: calc(var(--crisp-rem) * 1.5);
150
+ }
151
+ .theme-crisp .deck-slide :is(th, td) {
152
+ padding: calc(var(--crisp-rem) * 0.75) calc(var(--crisp-rem) * 0.5);
153
+ border-bottom: 1px solid var(--deck-border);
154
+ }
155
+ .theme-crisp .deck-slide th {
156
+ text-align: left;
157
+ font-size: 1em;
158
+ font-weight: 400;
159
+ text-transform: none;
160
+ letter-spacing: normal;
161
+ color: inherit;
162
+ }
163
+ .theme-crisp .deck-slide a {
164
+ color: inherit;
165
+ text-decoration: none;
166
+ border-bottom: 1px dashed currentColor;
167
+ }
168
+ .theme-crisp .deck-slide a:hover {
169
+ color: var(--deck-accent);
170
+ border-bottom-style: solid;
171
+ }
172
+ .theme-crisp .deck-slide :is(b, strong) {
173
+ font-weight: 600;
174
+ }
175
+ .theme-crisp .deck-slide :not(pre) > code {
176
+ font-family: var(--deck-mono-font);
177
+ font-size: 0.9em;
178
+ font-weight: 300;
179
+ padding: calc(var(--crisp-rem) * 0.125) calc(var(--crisp-rem) * 0.375);
180
+ background: var(--deck-code-bg);
181
+ border-radius: calc(var(--crisp-rem) * 0.25);
182
+ }
183
+ .theme-crisp .deck-slide :is(kbd, .deck-kbd) {
184
+ font-family: var(--deck-mono-font);
185
+ font-size: calc(var(--crisp-rem) * 0.875);
186
+ padding: calc(var(--crisp-rem) * 0.125) calc(var(--crisp-rem) * 0.25);
187
+ border: 1px solid var(--deck-border);
188
+ border-bottom-width: 2px;
189
+ border-radius: calc(var(--crisp-rem) * 0.25);
190
+ background: rgba(156, 163, 175, 0.05);
191
+ box-shadow: none;
192
+ }
193
+
194
+ /* ── code ─────────────────────────────────────────────────────────────── */
195
+ .theme-crisp .deck-code-block {
196
+ margin: calc(var(--crisp-rem) * 0.25) 0;
197
+ border: 0;
198
+ border-radius: calc(var(--crisp-rem) * 0.25);
199
+ }
200
+ .theme-crisp pre.deck-code,
201
+ .theme-crisp .shiki-magic-move-wrap {
202
+ font-size: calc(var(--crisp-rem) * 0.75);
203
+ line-height: calc(var(--crisp-rem) * 1.125);
204
+ padding: calc(var(--crisp-rem) * 0.5) 0;
205
+ }
206
+ .theme-crisp .shiki-magic-move-wrap {
207
+ padding-inline: calc(var(--crisp-rem) * 0.5);
208
+ }
209
+ .theme-crisp pre.deck-code .line {
210
+ padding: 0 calc(var(--crisp-rem) * 0.5);
211
+ }
212
+ .theme-crisp pre.deck-code .line.is-dim {
213
+ opacity: 0.3;
214
+ }
215
+ .theme-crisp .deck-code-title {
216
+ font-size: calc(var(--crisp-rem) * 0.75);
217
+ padding: calc(var(--crisp-rem) * 0.5);
218
+ }
219
+
220
+ /* ── the layouts ──────────────────────────────────────────────────────── */
221
+ .theme-crisp .deck-layout-default {
222
+ justify-content: flex-start;
223
+ }
224
+ /* Slidev's center does not centre the text by itself (its examples add `text-center`); Kadal's
225
+ does, which reads the same for a title and better for a line or two. */
226
+ .theme-crisp .deck-layout-center {
227
+ justify-content: center;
228
+ }
229
+ /* intro and section: the words vertically centred, on the left */
230
+ .theme-crisp :is(.deck-layout-cover, .deck-layout-intro, .deck-layout-section, .deck-layout-quote) {
231
+ align-items: stretch;
232
+ text-align: start;
233
+ }
234
+ .theme-crisp :is(.deck-layout-cover, .deck-layout-intro, .deck-layout-intro-image) h1 {
235
+ font-size: calc(var(--crisp-rem) * 3.75);
236
+ line-height: calc(var(--crisp-rem) * 5);
237
+ font-weight: 700;
238
+ }
239
+ .theme-crisp :is(.deck-layout-cover, .deck-layout-intro, .deck-layout-intro-image) h1 + p {
240
+ font-size: calc(var(--crisp-rem) * 1.5);
241
+ line-height: calc(var(--crisp-rem) * 2);
242
+ font-weight: 700;
243
+ margin-top: calc(var(--crisp-rem) * -1);
244
+ }
245
+ .theme-crisp .deck-layout-section h1 {
246
+ font-size: calc(var(--crisp-rem) * 3.75);
247
+ line-height: calc(var(--crisp-rem) * 5);
248
+ font-weight: 500;
249
+ }
250
+ .theme-crisp :is(.deck-layout-fact, .deck-layout-statement) {
251
+ text-align: center;
252
+ }
253
+ .theme-crisp .deck-layout-fact > :is(h1, h2, p, .deck-counter) {
254
+ letter-spacing: normal;
255
+ }
256
+ .theme-crisp .deck-layout-fact h1 {
257
+ font-size: calc(var(--crisp-rem) * 6);
258
+ line-height: 1;
259
+ font-weight: 700;
260
+ }
261
+ .theme-crisp .deck-layout-fact h1 + p {
262
+ font-size: calc(var(--crisp-rem) * 1.5);
263
+ line-height: calc(var(--crisp-rem) * 2);
264
+ font-weight: 700;
265
+ }
266
+ .theme-crisp .deck-layout-statement h1 {
267
+ font-size: calc(var(--crisp-rem) * 3.75);
268
+ line-height: 1;
269
+ font-weight: 700;
270
+ }
271
+ .theme-crisp .deck-layout-quote {
272
+ padding-inline: 0;
273
+ font-size: 1em;
274
+ font-style: normal;
275
+ }
276
+ .theme-crisp .deck-layout-quote h1 + p {
277
+ margin-top: calc(var(--crisp-rem) * 1.5);
278
+ margin-inline-start: calc(var(--crisp-rem) * 1.5);
279
+ }
280
+ /* bullets: a title-less list, hung 4.5rem below the top */
281
+ .theme-crisp .deck-layout-bullets {
282
+ justify-content: flex-start;
283
+ padding-top: calc(var(--crisp-rem) * 4.5);
284
+ }
285
+ .theme-crisp .deck-slide.layout-end {
286
+ background: #000;
287
+ }
288
+ .theme-crisp .deck-layout-end {
289
+ color: rgba(255, 255, 255, 0.85);
290
+ font-size: calc(var(--crisp-rem) * 1.25);
291
+ letter-spacing: 0.1em;
292
+ user-select: none;
293
+ }
294
+ .theme-crisp .deck-layout-end:empty::before {
295
+ content: "END";
296
+ }
297
+ .theme-crisp .deck-layout-full {
298
+ padding: 0;
299
+ }
300
+ .theme-crisp :is(.deck-layout-two-cols, .deck-layout-two-cols-header) {
301
+ column-gap: var(--crisp-rem);
302
+ }
303
+ .theme-crisp .deck-layout-two-cols-header > .deck-slot-bottom {
304
+ align-self: end;
305
+ }
306
+
307
+ /* The picture layouts are full-bleed: they cover the slide's padding and set their own. */
308
+ .theme-crisp :is(.deck-layout-intro-image, .deck-layout-3-images, .deck-layout-image-right, .deck-layout-intro-image-right) {
309
+ position: absolute;
310
+ inset: 0;
311
+ width: auto;
312
+ height: auto;
313
+ box-sizing: border-box;
314
+ }
315
+ .theme-crisp .crisp-picture {
316
+ background-repeat: no-repeat;
317
+ background-position: center;
318
+ background-size: cover;
319
+ min-width: 0;
320
+ min-height: 0;
321
+ }
322
+ /* intro-image: the picture is the slide, the words white on it (no dim) */
323
+ .theme-crisp .deck-layout-intro-image {
324
+ padding: calc(var(--crisp-rem) * 2.5) calc(var(--crisp-rem) * 3.5);
325
+ background-repeat: no-repeat;
326
+ background-position: center;
327
+ background-size: cover;
328
+ color: #fff;
329
+ justify-content: flex-start;
330
+ }
331
+ /* image-right and intro-image-right: the words in the left half, the picture in the right half
332
+ inside a 3.5rem margin (top, right and bottom) */
333
+ .theme-crisp :is(.deck-layout-image-right, .deck-layout-intro-image-right) {
334
+ display: grid;
335
+ grid-template-columns: 1fr 1fr;
336
+ gap: 0;
337
+ }
338
+ .theme-crisp .crisp-image-content {
339
+ padding: calc(var(--crisp-rem) * 2.5) calc(var(--crisp-rem) * 3.5);
340
+ min-width: 0;
341
+ display: flex;
342
+ flex-direction: column;
343
+ justify-content: flex-start;
344
+ }
345
+ .theme-crisp .deck-layout-intro-image-right .crisp-image-content {
346
+ justify-content: center;
347
+ }
348
+ .theme-crisp :is(.deck-layout-image-right, .deck-layout-intro-image-right) .crisp-picture {
349
+ margin: calc(var(--crisp-rem) * 3.5) calc(var(--crisp-rem) * 3.5) calc(var(--crisp-rem) * 3.5) 0;
350
+ }
351
+ /* 3-images: one tall picture on the left, two stacked on the right, 1.75rem between them */
352
+ .theme-crisp .deck-layout-3-images {
353
+ display: grid;
354
+ grid-template-columns: 1fr 1fr;
355
+ column-gap: calc(var(--crisp-rem) * 1.75);
356
+ }
357
+ .theme-crisp .crisp-3-left {
358
+ margin: calc(var(--crisp-rem) * 3.5) 0 calc(var(--crisp-rem) * 3.5) calc(var(--crisp-rem) * 3.5);
359
+ }
360
+ .theme-crisp .crisp-3-right {
361
+ display: grid;
362
+ grid-template-rows: 1fr 1fr;
363
+ row-gap: calc(var(--crisp-rem) * 1.75);
364
+ min-height: 0;
365
+ }
366
+ .theme-crisp .crisp-3-top {
367
+ margin: calc(var(--crisp-rem) * 3.5) calc(var(--crisp-rem) * 3.5) 0 0;
368
+ }
369
+ .theme-crisp .crisp-3-bottom {
370
+ margin: 0 calc(var(--crisp-rem) * 3.5) calc(var(--crisp-rem) * 3.5) 0;
371
+ }
372
+ /* Words written on a 3-images slide (Slidev drops them) sit over the pictures. */
373
+ .theme-crisp .crisp-3-content {
374
+ position: absolute;
375
+ inset: 0;
376
+ padding: calc(var(--crisp-rem) * 2.5) calc(var(--crisp-rem) * 3.5);
377
+ pointer-events: none;
378
+ }
379
+ .theme-crisp .crisp-3-content:empty {
380
+ display: none;
381
+ }
382
+ /* the engine's image-left and image (Slidev's own): flush picture, words from the top */
383
+ .theme-crisp .deck-layout-image-left .deck-layout-image-content,
384
+ .theme-crisp :is(.deck-layout-iframe-left, .deck-layout-iframe-right) .deck-layout-iframe-content {
385
+ justify-content: flex-start;
386
+ padding: calc(var(--crisp-rem) * 2.5) calc(var(--crisp-rem) * 3.5);
387
+ }
388
+ .theme-crisp .deck-layout-image .deck-layout-image-content {
389
+ inset: 0;
390
+ justify-content: flex-start;
391
+ padding: calc(var(--crisp-rem) * 2.5) calc(var(--crisp-rem) * 3.5);
392
+ background: none;
393
+ }
394
+ .theme-crisp .deck-layout-image .deck-layout-image-content:empty {
395
+ display: none;
396
+ }
397
+ .theme-crisp :is(.deck-layout-iframe, .deck-layout-iframe-left, .deck-layout-iframe-right) {
398
+ padding: 0;
399
+ gap: 0;
400
+ }
401
+ .theme-crisp .deck-frame.deck-layout-iframe-pane {
402
+ border: 0;
403
+ border-radius: 0;
404
+ box-shadow: none;
405
+ }
406
+
407
+ /* ── chrome ───────────────────────────────────────────────────────────── */
408
+ .theme-crisp .deck-progress span {
409
+ background: var(--deck-fg);
410
+ }