this repo has no description
1(** Theme CSS files for the scrollycode extension.
2
3 Each theme sets the CSS custom property values defined in
4 {!Scrollycode_css.structural_css} and imports its Google Fonts. *)
5
6(** Warm Workshop theme.
7 Cream background, burnt sienna accents, Fraunces + Source Serif 4. *)
8let warm_css =
9 {|@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300..900;1,9..144,300..900&family=Source+Code+Pro:ital,wght@0,300..900;1,300..900&family=Source+Serif+4:ital,opsz,wght@0,8..60,300..900;1,8..60,300..900&display=swap');
10
11.sc-container {
12 /* Typography */
13 --sc-font-display: 'Fraunces', serif;
14 --sc-font-body: 'Source Serif 4', Georgia, serif;
15 --sc-font-code: 'Source Code Pro', monospace;
16
17 /* Colors */
18 --sc-bg: #f5f0e6;
19 --sc-text: #2c2416;
20 --sc-text-dim: #8a7c6a;
21 --sc-accent: #c25832;
22 --sc-accent-soft: rgba(194, 88, 50, 0.08);
23 --sc-code-bg: #1a1a2e;
24 --sc-code-text: #d4d0c8;
25 --sc-code-gutter: #3a3a52;
26 --sc-border: rgba(44, 36, 22, 0.1);
27 --sc-focus-bg: rgba(194, 88, 50, 0.06);
28 --sc-panel-radius: 12px;
29
30 /* Syntax highlighting */
31 --sc-hl-keyword: #f0a6a0;
32 --sc-hl-type: #8ec8e8;
33 --sc-hl-string: #b8d89a;
34 --sc-hl-comment: #6a6a82;
35 --sc-hl-number: #ddb97a;
36 --sc-hl-module: #e8c87a;
37 --sc-hl-operator: #c8a8d8;
38 --sc-hl-punct: #7a7a92;
39
40 /* Mobile */
41 --sc-mobile-step-bg: rgba(255,255,255,0.5);
42}
43
44/* Warm hero: centered */
45.sc-container .sc-hero {
46 text-align: center;
47 border-bottom: 1px solid var(--sc-border);
48}
49
50.sc-container .sc-hero h1 {
51 font-style: italic;
52}
53
54.sc-container .sc-hero p {
55 margin: 0 auto;
56}
57
58/* Warm code panel: navy shadow */
59.sc-container .sc-code-panel {
60 box-shadow: 0 20px 60px rgba(26, 26, 46, 0.3), 0 0 0 1px rgba(255,255,255,0.03) inset;
61}
62
63/* Warm dots: traffic light colors */
64.sc-container .sc-dots span:nth-child(1) { background: #ff5f57; }
65.sc-container .sc-dots span:nth-child(2) { background: #ffbd2e; }
66.sc-container .sc-dots span:nth-child(3) { background: #28c840; }
67
68/* Warm diff */
69.sc-container .sc-diff-block {
70 background: #1e1b2e;
71}
72.sc-container .sc-diff-added { background: rgba(80, 200, 80, 0.15); border-left: 3px solid #4caf50; }
73.sc-container .sc-diff-removed { background: rgba(255, 80, 80, 0.12); border-left: 3px solid #ef5350; text-decoration: line-through; opacity: 0.7; }
74.sc-container .sc-diff-same { opacity: 0.5; }
75|}
76
77(** Dark Terminal theme.
78 Near-black background, phosphor green and amber, JetBrains Mono + Outfit. *)
79let dark_css =
80 {|@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300..800&family=Outfit:wght@300..900&display=swap');
81
82.sc-container {
83 /* Typography */
84 --sc-font-display: 'Outfit', sans-serif;
85 --sc-font-body: 'Outfit', sans-serif;
86 --sc-font-code: 'JetBrains Mono', monospace;
87
88 /* Colors */
89 --sc-bg: #0a0a0f;
90 --sc-text: #e8e6f0;
91 --sc-text-dim: #6e6b80;
92 --sc-accent: #4ade80;
93 --sc-accent-soft: rgba(74, 222, 128, 0.06);
94 --sc-code-bg: #0f0f18;
95 --sc-code-text: #c8c5d8;
96 --sc-code-gutter: #2a2a3e;
97 --sc-border: rgba(255, 255, 255, 0.06);
98 --sc-focus-bg: rgba(74, 222, 128, 0.04);
99 --sc-panel-radius: 0;
100
101 /* Syntax highlighting — neon palette */
102 --sc-hl-keyword: #ff7eb3;
103 --sc-hl-type: #7dd3fc;
104 --sc-hl-string: #4ade80;
105 --sc-hl-comment: #4a4a62;
106 --sc-hl-number: #fbbf24;
107 --sc-hl-module: #c4b5fd;
108 --sc-hl-operator: #67e8f9;
109 --sc-hl-punct: #4a4a62;
110
111 /* Mobile */
112 --sc-mobile-step-bg: rgba(255,255,255,0.04);
113}
114
115/* Dark hero: left-aligned, larger */
116.sc-container .sc-hero {
117 text-align: left;
118 padding: 8rem 4rem 4rem;
119 max-width: 800px;
120 position: relative;
121}
122
123.sc-container .sc-hero::before {
124 content: '';
125 position: absolute;
126 top: 0; left: 0; right: 0; bottom: 0;
127 background: radial-gradient(ellipse at 20% 50%, rgba(74, 222, 128, 0.04) 0%, transparent 60%);
128 pointer-events: none;
129}
130
131.sc-container .sc-hero h1 {
132 font-size: clamp(2.8rem, 6vw, 4.5rem);
133 font-weight: 800;
134 letter-spacing: -0.04em;
135 line-height: 1.0;
136 margin-bottom: 1.25rem;
137}
138
139.sc-container .sc-hero h1 em {
140 font-style: normal;
141 color: var(--sc-accent);
142}
143
144.sc-container .sc-hero p {
145 max-width: 50ch;
146 font-weight: 300;
147}
148
149/* Dark layout: narrow prose, wide code */
150.sc-container .sc-steps-col {
151 width: 38%;
152 flex: none;
153 padding: 2rem 2.5rem 50vh 4rem;
154 border-right: 1px solid var(--sc-border);
155}
156
157.sc-container .sc-code-col {
158 flex: 1;
159 width: auto;
160}
161
162/* Dark step number: with line */
163.sc-container .sc-step-number {
164 font-weight: 700;
165 letter-spacing: 0.15em;
166 display: flex;
167 align-items: center;
168 gap: 0.75rem;
169}
170
171.sc-container .sc-step-number::after {
172 content: '';
173 flex: 1;
174 height: 1px;
175 background: var(--sc-border);
176}
177
178.sc-container .sc-step h2 {
179 font-size: 1.4rem;
180 line-height: 1.2;
181}
182
183.sc-container .sc-step p {
184 font-size: 0.9rem;
185 max-width: 40ch;
186 font-weight: 300;
187}
188
189/* Dark code panel: full viewport height */
190.sc-container .sc-code-panel {
191 top: 0;
192 height: 100vh;
193 margin: 0;
194 border-radius: 0;
195 border-left: 1px solid var(--sc-border);
196 box-shadow: none;
197}
198
199.sc-container .sc-code-header {
200 padding: 1rem 1.5rem;
201 border-bottom: 1px solid var(--sc-border);
202 gap: 1rem;
203}
204
205.sc-container .sc-dots span {
206 width: 8px;
207 height: 8px;
208 background: var(--sc-code-gutter);
209}
210
211.sc-container .sc-filename {
212 color: var(--sc-text-dim);
213 text-align: left;
214}
215
216.sc-container .sc-step-badge {
217 color: var(--sc-accent);
218 background: rgba(74, 222, 128, 0.08);
219 padding: 0.25em 0.75em;
220 border-radius: 3px;
221}
222
223.sc-container .sc-code-body {
224 padding: 1.5rem 0;
225 line-height: 1.75;
226}
227
228.sc-container .sc-line {
229 padding: 0 1.5rem;
230 transition: opacity 0.3s ease, background 0.3s ease;
231 opacity: 0.25;
232}
233
234.sc-container .sc-line.sc-focused {
235 border-left: 2px solid var(--sc-accent);
236 padding-left: calc(1.5rem - 2px);
237}
238
239.sc-container .sc-line-number {
240 margin-right: 2ch;
241}
242
243/* Dark progress: right side, bar style */
244.sc-container .sc-progress {
245 left: auto;
246 right: 1.5rem;
247 gap: 10px;
248}
249
250.sc-container .sc-pip {
251 width: 3px;
252 height: 20px;
253 border-radius: 2px;
254}
255
256.sc-container .sc-pip.sc-active {
257 box-shadow: 0 0 12px rgba(74, 222, 128, 0.5);
258 height: 30px;
259 transform: none;
260}
261
262/* Dark mobile */
263.sc-container .sc-mobile-step {
264 border-radius: 10px;
265 border: 1px solid rgba(255,255,255,0.08);
266}
267
268.sc-container .sc-mobile-step-num {
269 font-family: var(--sc-font-body);
270 letter-spacing: 0.2em;
271 color: #00d4aa;
272}
273
274.sc-container .sc-mobile-step h2 {
275 color: #e8e6e3;
276}
277
278.sc-container .sc-mobile-step p {
279 color: rgba(232,230,227,0.7);
280}
281
282.sc-container .sc-diff-block {
283 background: #0d1117;
284 border: 1px solid rgba(0,212,170,0.15);
285}
286.sc-container .sc-diff-added { background: rgba(0, 212, 170, 0.12); border-left: 3px solid #00d4aa; }
287.sc-container .sc-diff-removed { background: rgba(255, 80, 80, 0.1); border-left: 3px solid #ff6b6b; text-decoration: line-through; opacity: 0.6; }
288.sc-container .sc-diff-same { opacity: 0.4; }
289
290.sc-container .sc-playground-btn {
291 border-color: rgba(0,212,170,0.3);
292 color: #00d4aa;
293}
294.sc-container .sc-playground-btn:hover {
295 background: rgba(0,212,170,0.1);
296 border-color: #00d4aa;
297}
298|}
299
300(** Notebook theme.
301 Soft white, blue-violet accent, Newsreader + DM Sans. *)
302let notebook_css =
303 {|@import url('https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=DM+Sans:ital,opsz,wght@0,9..40,300..900;1,9..40,300..900&family=Newsreader:ital,opsz,wght@0,6..72,300..800;1,6..72,300..800&display=swap');
304
305.sc-container {
306 /* Typography */
307 --sc-font-display: 'Newsreader', serif;
308 --sc-font-body: 'DM Sans', sans-serif;
309 --sc-font-code: 'DM Mono', 'Source Code Pro', monospace;
310
311 /* Colors */
312 --sc-bg: #fafbfe;
313 --sc-text: #1a1a2e;
314 --sc-text-dim: #64648a;
315 --sc-accent: #6366f1;
316 --sc-accent-soft: rgba(99, 102, 241, 0.06);
317 --sc-code-bg: #1e1e32;
318 --sc-code-text: #d1d0e0;
319 --sc-code-gutter: #3a3a52;
320 --sc-border: rgba(99, 102, 241, 0.08);
321 --sc-focus-bg: rgba(99, 102, 241, 0.05);
322 --sc-panel-radius: 16px;
323
324 /* Syntax highlighting — cool tones */
325 --sc-hl-keyword: #a78bfa;
326 --sc-hl-type: #67e8f9;
327 --sc-hl-string: #86efac;
328 --sc-hl-comment: #4a4a62;
329 --sc-hl-number: #fde68a;
330 --sc-hl-module: #f9a8d4;
331 --sc-hl-operator: #93c5fd;
332 --sc-hl-punct: #4a4a62;
333
334 /* Mobile */
335 --sc-mobile-step-bg: #ffffff;
336}
337
338/* Notebook hero: left-aligned, accent underline */
339.sc-container .sc-hero {
340 text-align: left;
341 padding: 6rem 0 3rem;
342 max-width: 640px;
343 margin: 0 auto;
344 border-bottom: 2px solid var(--sc-accent);
345 position: relative;
346}
347
348.sc-container .sc-hero::after {
349 content: '';
350 position: absolute;
351 bottom: -2px; left: 0;
352 width: 120px;
353 height: 2px;
354 background: var(--sc-accent);
355 box-shadow: 0 0 16px rgba(99, 102, 241, 0.4);
356}
357
358.sc-container .sc-hero h1 {
359 font-size: clamp(2rem, 4vw, 2.8rem);
360 font-weight: 600;
361 letter-spacing: -0.02em;
362 line-height: 1.15;
363}
364
365.sc-container .sc-hero p {
366 font-size: 1rem;
367 max-width: 52ch;
368 font-weight: 400;
369}
370
371/* Notebook layout: constrained width */
372.sc-container .sc-tutorial {
373 max-width: 1200px;
374 margin: 0 auto;
375}
376
377.sc-container .sc-steps-col {
378 padding: 2rem 3rem 50vh 0;
379 max-width: 420px;
380}
381
382.sc-container .sc-code-col {
383 flex: 1;
384 width: auto;
385}
386
387/* Notebook step: accent line indicator */
388.sc-container .sc-step {
389 min-height: 60vh;
390 padding: 1.5rem 0;
391 position: relative;
392}
393
394.sc-container .sc-step::before {
395 content: '';
396 position: absolute;
397 left: -1.5rem;
398 top: 50%;
399 transform: translateY(-50%);
400 width: 3px;
401 height: 0;
402 background: var(--sc-accent);
403 border-radius: 2px;
404 transition: height 0.4s cubic-bezier(0.22, 1, 0.36, 1);
405}
406
407.sc-container .sc-step-number {
408 font-family: var(--sc-font-body);
409 font-weight: 700;
410 letter-spacing: 0.12em;
411 display: flex;
412 align-items: center;
413 gap: 0.5rem;
414}
415
416.sc-container .sc-step h2 {
417 font-size: 1.3rem;
418 font-weight: 600;
419 letter-spacing: -0.01em;
420 margin-bottom: 0.6rem;
421 line-height: 1.3;
422}
423
424.sc-container .sc-step p {
425 font-size: 0.88rem;
426 max-width: 42ch;
427}
428
429/* Notebook code panel */
430.sc-container .sc-code-panel {
431 top: 8vh;
432 height: 84vh;
433 margin: 0 0 0 2rem;
434 box-shadow:
435 0 24px 80px rgba(30, 30, 50, 0.15),
436 0 0 0 1px rgba(99, 102, 241, 0.08);
437}
438
439.sc-container .sc-code-header {
440 background: rgba(99, 102, 241, 0.04);
441 border-bottom: 1px solid rgba(255,255,255,0.04);
442 gap: 0.75rem;
443}
444
445.sc-container .sc-dots span {
446 width: 9px;
447 height: 9px;
448 background: rgba(255,255,255,0.08);
449}
450
451.sc-container .sc-code-body {
452 font-size: 0.78rem;
453 line-height: 1.75;
454}
455
456.sc-container .sc-line {
457 opacity: 0.3;
458}
459
460/* Notebook progress: left side, square pips */
461.sc-container .sc-progress {
462 left: 2rem;
463 gap: 6px;
464}
465
466.sc-container .sc-pip {
467 width: 8px;
468 height: 8px;
469 border-radius: 3px;
470}
471
472.sc-container .sc-pip.sc-active {
473 box-shadow: 0 0 10px rgba(99, 102, 241, 0.4);
474 border-radius: 2px;
475 width: 8px;
476 height: 16px;
477 transform: none;
478}
479
480/* Notebook mobile */
481.sc-container .sc-mobile-step {
482 border-radius: 6px;
483 border: 1px solid #e0ddd8;
484}
485
486.sc-container .sc-mobile-step-num {
487 font-family: var(--sc-font-body);
488 font-weight: 600;
489 color: #0066cc;
490}
491
492.sc-container .sc-mobile-step h2 {
493 color: #1a1a1a;
494}
495
496.sc-container .sc-mobile-step p {
497 color: #4a4a4a;
498}
499
500.sc-container .sc-diff-block {
501 background: #282c34;
502 border: 1px solid #e0ddd8;
503 font-family: 'IBM Plex Mono', monospace;
504}
505.sc-container .sc-diff-added { background: rgba(0, 102, 204, 0.12); border-left: 3px solid #0066cc; }
506.sc-container .sc-diff-removed { background: rgba(220, 50, 50, 0.1); border-left: 3px solid #dc3232; text-decoration: line-through; opacity: 0.6; }
507.sc-container .sc-diff-same { opacity: 0.4; }
508
509.sc-container .sc-playground-btn {
510 border-color: rgba(0,102,204,0.3);
511 color: #0066cc;
512}
513.sc-container .sc-playground-btn:hover {
514 background: rgba(0,102,204,0.1);
515 border-color: #0066cc;
516}
517|}
518
519(** Register all theme CSS files as support files *)
520let () =
521 let register name content =
522 Odoc_extension_api.Registry.register_support_file ~prefix:"scrolly" {
523 filename = "extensions/scrollycode-" ^ name ^ ".css";
524 content = Inline content;
525 }
526 in
527 register "warm" warm_css;
528 register "dark" dark_css;
529 register "notebook" notebook_css