forked from
anil.recoil.org/monopam-myspace
My aggregated monorepo of OCaml code, automaintained
1(** Structural CSS for the scrollycode extension.
2
3 This CSS defines layout, animations, and structure using CSS custom
4 properties for all theming. Theme files set the custom property values.
5
6 Custom property contract:
7 - Typography: --sc-font-display, --sc-font-body, --sc-font-code
8 - Colors: --sc-bg, --sc-text, --sc-text-dim, --sc-accent, --sc-accent-soft,
9 --sc-code-bg, --sc-code-text, --sc-code-gutter, --sc-border,
10 --sc-focus-bg, --sc-panel-radius
11 - Syntax: --sc-hl-keyword, --sc-hl-type, --sc-hl-string, --sc-hl-comment,
12 --sc-hl-number, --sc-hl-module, --sc-hl-operator, --sc-hl-punct *)
13
14let structural_css =
15 {|
16/* === Container === */
17
18/* odoc wraps tag extension output in <ul class="at-tags"><li class="scrolly">
19 — remove the bullet and list padding. */
20ul.at-tags:has(> li.scrolly) {
21 list-style: none;
22 padding: 0;
23 margin: 0;
24}
25li.scrolly {
26 list-style: none;
27 padding: 0;
28 margin: 0;
29}
30
31.sc-container {
32 font-family: var(--sc-font-body);
33 background: var(--sc-bg);
34 color: var(--sc-text);
35}
36
37/* === Hero === */
38.sc-container .sc-hero {
39 background: var(--sc-bg);
40 padding: 5rem 2rem 3rem;
41}
42
43.sc-container .sc-hero h1 {
44 font-family: var(--sc-font-display);
45 font-size: clamp(2.2rem, 5vw, 3.4rem);
46 font-weight: 800;
47 color: var(--sc-text);
48 letter-spacing: -0.03em;
49 line-height: 1.1;
50 margin-bottom: 0.75rem;
51}
52
53.sc-container .sc-hero p {
54 color: var(--sc-text-dim);
55 font-size: 1.05rem;
56 max-width: 48ch;
57 line-height: 1.6;
58}
59
60/* === Tutorial layout === */
61.sc-container .sc-tutorial {
62 display: flex;
63 gap: 0;
64 background: var(--sc-bg);
65 position: relative;
66}
67
68.sc-container .sc-steps-col {
69 flex: 1;
70 min-width: 0;
71 padding: 2rem 2.5rem 50vh 2.5rem;
72}
73
74.sc-container .sc-code-col {
75 width: 52%;
76 flex-shrink: 0;
77}
78
79/* === Step === */
80.sc-container .sc-step {
81 min-height: 70vh;
82 display: flex;
83 flex-direction: column;
84 justify-content: center;
85 padding: 2rem 0;
86}
87
88.sc-container .sc-step-number {
89 font-family: var(--sc-font-code);
90 font-size: 0.7rem;
91 font-weight: 600;
92 letter-spacing: 0.1em;
93 color: var(--sc-accent);
94 text-transform: uppercase;
95 margin-bottom: 0.5rem;
96}
97
98.sc-container .sc-step h2 {
99 font-family: var(--sc-font-display);
100 font-size: 1.5rem;
101 font-weight: 700;
102 color: var(--sc-text);
103 letter-spacing: -0.02em;
104 margin-bottom: 0.75rem;
105 line-height: 1.25;
106}
107
108.sc-container .sc-step p {
109 color: var(--sc-text-dim);
110 font-size: 0.95rem;
111 line-height: 1.7;
112 max-width: 44ch;
113}
114
115/* === Code panel === */
116.sc-container .sc-code-panel {
117 position: sticky;
118 top: 10vh;
119 height: 80vh;
120 margin: 0 2rem 0 0;
121 background: var(--sc-code-bg);
122 border-radius: var(--sc-panel-radius);
123 overflow: hidden;
124 display: flex;
125 flex-direction: column;
126 box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(255,255,255,0.03) inset;
127}
128
129.sc-container .sc-code-header {
130 display: flex;
131 align-items: center;
132 padding: 0.85rem 1.25rem;
133 background: rgba(255,255,255,0.03);
134 border-bottom: 1px solid rgba(255,255,255,0.06);
135 gap: 0.6rem;
136}
137
138.sc-container .sc-dots {
139 display: flex;
140 gap: 6px;
141}
142
143.sc-container .sc-dots span {
144 width: 10px;
145 height: 10px;
146 border-radius: 50%;
147}
148
149.sc-container .sc-dots span:nth-child(1) { background: #ff5f57; }
150.sc-container .sc-dots span:nth-child(2) { background: #ffbd2e; }
151.sc-container .sc-dots span:nth-child(3) { background: #28c840; }
152
153.sc-container .sc-filename {
154 font-family: var(--sc-font-code);
155 font-size: 0.72rem;
156 color: rgba(255,255,255,0.35);
157 letter-spacing: 0.04em;
158 flex: 1;
159 text-align: center;
160}
161
162.sc-container .sc-step-badge {
163 font-family: var(--sc-font-code);
164 font-size: 0.65rem;
165 color: rgba(255,255,255,0.25);
166 letter-spacing: 0.06em;
167}
168
169.sc-container .sc-code-body {
170 flex: 1;
171 overflow-y: auto;
172 padding: 1.25rem 0;
173 font-family: var(--sc-font-code);
174 font-size: 0.82rem;
175 line-height: 1.7;
176 color: var(--sc-code-text);
177}
178
179/* === Lines === */
180.sc-container .sc-line {
181 padding: 0 1.25rem;
182 white-space: pre;
183 transition: opacity 0.3s ease;
184 opacity: 0.35;
185}
186
187.sc-container .sc-line.sc-focused {
188 opacity: 1;
189 background: var(--sc-focus-bg, rgba(255,255,255,0.04));
190}
191
192.sc-container .sc-line-number {
193 display: inline-block;
194 width: 3ch;
195 text-align: right;
196 margin-right: 1.5ch;
197 color: var(--sc-code-gutter);
198 user-select: none;
199}
200
201/* === Syntax highlighting === */
202.sc-container .hl-keyword { color: var(--sc-hl-keyword); font-weight: 500; }
203.sc-container .hl-type { color: var(--sc-hl-type); }
204.sc-container .hl-string { color: var(--sc-hl-string); }
205.sc-container .hl-comment { color: var(--sc-hl-comment); font-style: italic; }
206.sc-container .hl-number { color: var(--sc-hl-number); }
207.sc-container .hl-module { color: var(--sc-hl-module); }
208.sc-container .hl-operator { color: var(--sc-hl-operator); }
209.sc-container .hl-punct { color: var(--sc-hl-punct); }
210
211/* === Progress pips === */
212.sc-container .sc-progress {
213 position: fixed;
214 left: 1.5rem;
215 top: 50%;
216 transform: translateY(-50%);
217 display: flex;
218 flex-direction: column;
219 gap: 8px;
220 z-index: 100;
221}
222
223.sc-container .sc-pip {
224 width: 6px;
225 height: 6px;
226 border-radius: 50%;
227 background: var(--sc-border);
228 transition: all 0.3s ease;
229}
230
231.sc-container .sc-pip.sc-active {
232 background: var(--sc-accent);
233 box-shadow: 0 0 8px color-mix(in srgb, var(--sc-accent) 40%, transparent);
234 transform: scale(1.4);
235}
236
237/* === Animations === */
238@keyframes sc-line-exit {
239 0% { opacity: 1; transform: translateX(0); }
240 100% { opacity: 0; transform: translateX(-30px); }
241}
242
243@keyframes sc-line-enter {
244 0% { opacity: 0; transform: translateX(30px); }
245 100% { opacity: 1; transform: translateX(0); }
246}
247
248.sc-container .sc-line.sc-exiting {
249 animation: sc-line-exit 0.2s cubic-bezier(0.22, 1, 0.36, 1) forwards;
250}
251
252.sc-container .sc-line.sc-entering {
253 animation: sc-line-enter 0.25s cubic-bezier(0.22, 1, 0.36, 1) both;
254}
255
256/* Hidden code slot */
257.sc-code-slot { display: none; }
258
259/* === Mobile responsive === */
260@media (max-width: 700px) {
261 .sc-container { padding: 0 1rem; }
262 .sc-container .sc-desktop { display: none !important; }
263 .sc-container .sc-mobile { display: block !important; }
264 .sc-container .sc-progress { display: none; }
265 .sc-container .sc-hero h1 { font-size: 2rem; }
266}
267@media (min-width: 701px) {
268 .sc-container .sc-mobile { display: none !important; }
269}
270
271.sc-container .sc-mobile-step {
272 margin: 1.5rem 0;
273 padding: 1.5rem;
274 border-radius: 12px;
275 background: var(--sc-mobile-step-bg, rgba(255,255,255,0.5));
276}
277
278.sc-container .sc-mobile-step-num {
279 font-family: var(--sc-font-display);
280 font-size: 0.75rem;
281 text-transform: uppercase;
282 letter-spacing: 0.15em;
283 color: var(--sc-accent);
284 margin-bottom: 0.5rem;
285}
286
287.sc-container .sc-mobile-step h2 {
288 font-family: var(--sc-font-display);
289 font-size: 1.3rem;
290 color: var(--sc-text);
291 margin: 0 0 0.75rem;
292}
293
294.sc-container .sc-mobile-step p {
295 font-family: var(--sc-font-body);
296 font-size: 1rem;
297 color: var(--sc-text-dim);
298 line-height: 1.6;
299 margin: 0 0 1rem;
300}
301
302.sc-container .sc-diff-block {
303 background: var(--sc-code-bg);
304 border-radius: 8px;
305 padding: 0.75rem;
306 overflow-x: auto;
307 font-family: var(--sc-font-code);
308 font-size: 0.8rem;
309 line-height: 1.5;
310}
311
312.sc-container .sc-diff-line { padding: 1px 0.5rem; white-space: pre; }
313.sc-container .sc-diff-added { background: rgba(80, 200, 80, 0.15); border-left: 3px solid #4caf50; }
314.sc-container .sc-diff-removed { background: rgba(255, 80, 80, 0.12); border-left: 3px solid #ef5350; text-decoration: line-through; opacity: 0.7; }
315.sc-container .sc-diff-same { opacity: 0.5; }
316
317/* === Playground overlay === */
318.sc-playground-overlay {
319 display: none;
320 position: fixed;
321 inset: 0;
322 z-index: 10000;
323 background: rgba(0,0,0,0.6);
324 backdrop-filter: blur(4px);
325 align-items: center;
326 justify-content: center;
327}
328.sc-playground-overlay.sc-open {
329 display: flex;
330}
331.sc-playground-container {
332 width: 90vw;
333 max-width: 900px;
334 height: 80vh;
335 background: var(--sc-code-bg, #1e1b2e);
336 border-radius: 12px;
337 display: flex;
338 flex-direction: column;
339 overflow: hidden;
340 box-shadow: 0 25px 80px rgba(0,0,0,0.5);
341}
342.sc-playground-header {
343 display: flex;
344 align-items: center;
345 justify-content: space-between;
346 padding: 0.85rem 1.5rem;
347 background: rgba(255,255,255,0.05);
348 border-bottom: 1px solid rgba(255,255,255,0.1);
349 flex-shrink: 0;
350}
351.sc-playground-title {
352 font-family: var(--sc-font-code, monospace);
353 font-size: 0.8rem;
354 font-weight: 500;
355 letter-spacing: 0.04em;
356 color: rgba(255,255,255,0.6);
357 text-transform: uppercase;
358}
359.sc-playground-close {
360 background: none;
361 border: none;
362 color: rgba(255,255,255,0.4);
363 font-size: 1.25rem;
364 cursor: pointer;
365 padding: 0 0.25rem;
366 line-height: 1;
367}
368.sc-playground-close:hover { color: #fff; }
369.sc-playground-editor {
370 flex: 1;
371 overflow: auto;
372 min-height: 0;
373}
374.sc-playground-editor x-ocaml {
375 display: block;
376 height: 100%;
377 font-size: 0.85rem;
378
379 /* Map scrollycode theme properties to x-ocaml custom properties */
380 --xo-font: var(--sc-font-code, monospace);
381 --xo-font-size: inherit;
382 --xo-bg: var(--sc-code-bg, #1a1a2e);
383 --xo-text: var(--sc-code-text, #d4d0c8);
384 --xo-gutter-bg: var(--sc-code-bg, #1a1a2e);
385 --xo-gutter-text: var(--sc-code-gutter, #3a3a52);
386 --xo-gutter-border: rgba(255,255,255,0.06);
387 --xo-focus-outline: rgba(255,255,255,0.2);
388 --xo-active-line: rgba(255,255,255,0.04);
389 --xo-active-line-focused: rgba(255,255,255,0.06);
390 --xo-selection: rgba(255,255,255,0.12);
391 --xo-selection-focused: rgba(255,255,255,0.15);
392 --xo-content-padding-left: 16px;
393 --xo-gutter-element-padding: 0 12px 0 8px;
394 --xo-line-numbers-min-width: 40px;
395
396 /* Run button */
397 --xo-btn-bg: var(--sc-code-bg, #1a1a2e);
398 --xo-btn-border: var(--sc-code-gutter, #3a3a52);
399 --xo-btn-text: var(--sc-code-text, #d4d0c8);
400 --xo-btn-hover-bg: var(--sc-accent, #c25832);
401 --xo-btn-hover-text: #fff;
402
403 /* Tooltips */
404 --xo-tooltip-bg: var(--sc-code-bg, #1a1a2e);
405 --xo-tooltip-text: var(--sc-code-text, #d4d0c8);
406 --xo-tooltip-border: rgba(255,255,255,0.15);
407
408 /* Output areas */
409 --xo-stdout-bg: rgba(255,255,255,0.05);
410 --xo-stdout-text: var(--sc-code-text, #d4d0c8);
411 --xo-stderr-bg: rgba(235,86,86,0.1);
412 --xo-stderr-text: #f08080;
413 --xo-meta-bg: rgba(255,255,255,0.03);
414 --xo-meta-text: var(--sc-code-gutter, #3a3a52);
415}
416
417/* === Playground button === */
418.sc-container .sc-playground-btn {
419 display: inline-block;
420 margin-top: 0.75rem;
421 padding: 0.4rem 1rem;
422 border: 1px solid color-mix(in srgb, var(--sc-accent) 30%, transparent);
423 border-radius: 6px;
424 background: transparent;
425 color: var(--sc-accent);
426 font-family: var(--sc-font-body);
427 font-size: 0.85rem;
428 cursor: pointer;
429 transition: all 0.2s;
430}
431.sc-container .sc-playground-btn:hover {
432 background: color-mix(in srgb, var(--sc-accent) 10%, transparent);
433 border-color: var(--sc-accent);
434}
435|}