-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
829 lines (723 loc) · 39 KB
/
index.html
File metadata and controls
829 lines (723 loc) · 39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
<!DOCTYPE html>
<html lang="en" data-mg-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Marginalia — Typographic Callout Library</title>
<link rel="stylesheet" href="marginalia.css">
<!-- PostHog + ClickSense: injected at deploy time, not checked into repo.
See CLAUDE.md for setup instructions. -->
<style>
/* Demo page chrome — not part of the library */
:root {
--demo-bg: var(--mg-bg);
--demo-text: var(--mg-text);
--demo-muted: var(--mg-text-muted);
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--demo-bg);
color: var(--demo-text);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
.demo-container {
max-width: 48rem;
margin: 0 auto;
padding: 3rem 1.5rem 6rem;
}
.demo-header {
text-align: center;
margin-bottom: 4rem;
padding-bottom: 2rem;
border-bottom: 1px solid var(--mg-border);
}
.demo-header h1 {
font-size: clamp(1.8rem, 5vw, 2.8rem);
font-weight: 800;
letter-spacing: -0.03em;
margin-bottom: 0.5rem;
}
.demo-header h1 span { color: var(--mg-accent); }
.demo-header p {
color: var(--demo-muted);
font-size: 1rem;
}
.demo-section {
margin-bottom: 4rem;
}
.demo-section h2 {
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--demo-muted);
margin-bottom: 1.5rem;
}
.demo-section h3 {
font-size: 1rem;
font-weight: 600;
color: var(--mg-accent-ink);
margin: 2rem 0 0.75rem;
}
.demo-prose {
margin-bottom: 1.25rem;
color: var(--demo-text);
line-height: 1.65;
}
/* Theme toggle */
.theme-toggle {
position: fixed;
top: 1rem;
right: 1rem;
background: var(--mg-bg2);
border: 1px solid var(--mg-border);
border-radius: var(--mg-radius);
color: var(--demo-muted);
font-size: 0.75rem;
font-weight: 600;
padding: 0.4em 0.8em;
cursor: pointer;
z-index: 100;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.theme-toggle:hover { color: var(--mg-accent); }
/* Badge row */
.badge-row { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; margin: 1rem 0; }
/* Clearfix for pull quotes */
.demo-flow::after { content: ''; display: table; clear: both; }
</style>
</head>
<body>
<button class="theme-toggle" id="themeToggle">Light</button>
<div class="demo-container">
<header class="demo-header">
<h1><span>Marginalia</span></h1>
<p>Typographic callout library. 15 components, CSS custom properties, zero dependencies.</p>
<p><a href="https://github.com/andyed/marginalia" style="color: var(--mg-text-muted); text-decoration: none; font-size: 0.82rem;">GitHub</a></p>
</header>
<!-- ── Showcase: All Components ────────────────────────────────── -->
<section class="demo-section">
<h2>Showcase</h2>
<div class="demo-flow">
<aside class="mg-pull">
The retina is not a camera. It is the first stage of a computational pipeline that begins filtering before signals leave the eye.
</aside>
<p class="mg-dropcap demo-prose">
Vision begins at the retina, where 130 million photoreceptors compress into
1.2 million ganglion cell axons — a <mark class="mg-mark">100:1 reduction</mark>
before information reaches the brain. This isn't a bottleneck. It's an
editorial decision, made in parallel across the visual field, about what
matters enough to transmit.
</p>
<div class="mg-callout" data-type="note">
<p><strong>Note:</strong> Ganglion cell density peaks at ~35,000 cells/mm² in the fovea and drops to ~5,000 cells/mm² at 10° eccentricity. The <code class="mg-inline-code">mg-dropcap</code> above mirrors this hierarchy — the initial letter demands foveal attention.</p>
</div>
<p class="demo-prose">
Center-surround receptive fields perform edge detection and contrast
normalization before any cortical processing occurs. Midget cells in the
fovea carry high-acuity color-opponent signals. Parasol cells across the
periphery prioritize motion and luminance transients. Two parallel channels,
tuned to different statistics, feeding <span class="mg-badge">V1</span>
<span class="mg-badge" data-type="tip">LGN</span>
<span class="mg-badge" data-type="warning">SC</span> simultaneously.
</p>
<pre class="mg-code" data-lang="glsl">// Retinal ganglion cell density falloff (Watson 2014)
float ganglionDensity(float eccentricity) {
float fovealPeak = 35000.0; // cells/mm²
float e2 = 1.72; // half-density eccentricity
return fovealPeak / pow(1.0 + eccentricity / e2, 2.0);
}</pre>
<details class="mg-collapse">
<summary>Why this matters for rendering</summary>
<div class="mg-collapse-body">
<p>
Foveated rendering exploits this density falloff. If you match your
shader's spatial frequency budget to the retina's sampling capacity at
each eccentricity, you can reduce fragment processing by 60-70% with
no perceptible quality loss. The <code class="mg-inline-code">ganglionDensity()</code>
function above is the biological ground truth that rendering LOD curves
approximate.
</p>
</div>
</details>
</div>
</section>
<!-- ── 1. Callouts ──────────────────────────────────────────────── -->
<section class="demo-section">
<h2>1. Callouts</h2>
<div class="mg-callout" data-type="note">
<p><strong>Note:</strong> The cortical magnification function falls off roughly as <code class="mg-inline-code">1 / (1 + e/e2)</code> where <code class="mg-inline-code">e2</code> varies by visual field meridian.</p>
</div>
<div class="mg-callout" data-type="tip">
<p><strong>Tip:</strong> Use <code class="mg-inline-code">shape-outside</code> with pull quotes to create text that wraps along the perspective tilt, not just a rectangular float.</p>
</div>
<div class="mg-callout" data-type="warning">
<p><strong>Warning:</strong> MIP level selection at extreme eccentricities can produce visible banding. Clamp to <code class="mg-inline-code">maxLod - 1</code> for smoother falloff.</p>
</div>
<div class="mg-callout" data-type="important">
<p><strong>Important:</strong> The 3D perspective transform uses <code class="mg-inline-code">transform: perspective(600px) rotateY(14deg)</code>. This is removed on viewports below 720px for readability.</p>
</div>
<h3>Without vertical bar</h3>
<div class="mg-callout" data-type="note" data-bar="none">
<p><strong>Note:</strong> Add <code class="mg-inline-code">data-bar="none"</code> to any callout, pull quote, or code block to remove the left border accent. The tinted background still provides visual separation.</p>
</div>
<div class="mg-callout" data-type="warning" data-bar="none">
<p><strong>Warning:</strong> Without the border, the background tint carries the semantic color. Works best with typed variants that have distinct tints.</p>
</div>
</section>
<!-- ── 2. Pull Quotes ───────────────────────────────────────────── -->
<section class="demo-section">
<h2>2. Pull Quotes</h2>
<div class="demo-flow">
<aside class="mg-pull">
The MIP chain wasn't designed to model the retina. They converged on the same structure because progressive spatial pooling solves the same problem.
</aside>
<p class="demo-prose">
Hardware texture MIP chains and biological retinal processing share a structural
parallel that runs deeper than analogy. Both systems face the same computational
problem: reducing high-resolution spatial information into progressively coarser
representations while preserving the features that matter for downstream processing.
</p>
<p class="demo-prose">
The GPU MIP chain builds power-of-two reductions through box filtering.
The retina builds a spatial frequency cascade through center-surround receptive
fields whose sizes increase with eccentricity from the fovea. Different mechanisms,
same computational strategy, same mathematical structure — a Laplacian pyramid.
</p>
<p class="demo-prose">
This convergence isn't mysterious. Progressive spatial pooling is simply an efficient
solution to the problem of representing visual information at multiple scales. Evolution
and engineering arrived at the same answer independently, which is exactly what you'd
expect for a well-constrained optimization problem.
</p>
</div>
<h3>Flat (no 3D transform)</h3>
<div class="demo-flow">
<aside class="mg-pull mg-flat">
Crowding — not blur — is the primary limit on peripheral object recognition. Flanking features merge into texture-like representations that preserve summary statistics but lose individual identity.
</aside>
<p class="demo-prose">
The <code class="mg-inline-code">mg-flat</code> modifier removes the perspective
tilt while keeping the sidebar float behavior. This works for content where the
3D effect would feel excessive — technical asides, definition boxes, or
supplementary notes that sit alongside body text without demanding attention
through visual skew.
</p>
<p class="demo-prose">
Flat pull quotes still float right by default and can be combined with
<code class="mg-inline-code">mg-flip</code> to float left. The left border
accent remains as the visual anchor.
</p>
</div>
<h3>Flipped (left float)</h3>
<div class="demo-flow">
<aside class="mg-pull mg-flip">
Every saccade is a decision. The visual system bets 200ms of processing time on a location, guided by a saliency map it built from the last fixation.
</aside>
<p class="demo-prose">
The oculomotor system makes roughly three saccadic eye movements per second during
active viewing. Each saccade commits the visual system to a new fixation point for
200-300 milliseconds. The choice of where to look next is informed by peripheral
vision — specifically, the low-spatial-frequency information available in the
parafoveal and peripheral visual field during the current fixation.
</p>
<p class="demo-prose">
Saliency models attempt to predict these fixation sequences from image statistics.
The best-performing models combine bottom-up feature contrast (color, orientation,
spatial frequency) with top-down task demands and scene grammar — the learned
statistical regularities of where objects tend to appear in natural scenes.
</p>
</div>
</section>
<!-- ── 3. Code Block ────────────────────────────────────────────── -->
<section class="demo-section">
<h2>3. Code Blocks</h2>
<pre class="mg-code" data-lang="glsl">// Lorenz attractor step — the heart of Psychodeli+'s fractal engine
vec3 lorenzStep(vec3 p, float sigma, float rho, float beta, float dt) {
return p + vec3(
sigma * (p.y - p.x),
p.x * (rho - p.z) - p.y,
p.x * p.y - beta * p.z
) * dt;
}</pre>
<pre class="mg-code" data-lang="js">// Cortical magnification — FOVI model (Blauch, Alvarez & Konkle 2026)
function corticalMagnification(eccentricity, e2 = 0.75) {
return 1 / (1 + eccentricity / e2);
}</pre>
<p class="demo-prose">
Inline code: The <code class="mg-inline-code">shape-outside</code> property creates
a polygon that text wraps around, matching the visual tilt of the
<code class="mg-inline-code">perspective()</code> transform.
</p>
</section>
<!-- ── 4. Badges ────────────────────────────────────────────────── -->
<section class="demo-section">
<h2>4. Badges</h2>
<div class="badge-row">
<span class="mg-badge">Default</span>
<span class="mg-badge" data-type="tip">Tip</span>
<span class="mg-badge" data-type="warning">Warning</span>
<span class="mg-badge" data-type="important">Important</span>
</div>
<p class="demo-prose">
Badges work inline: this feature is <span class="mg-badge">New</span> and requires
WebGL 2 <span class="mg-badge" data-type="warning">GPU</span> support.
</p>
</section>
<!-- ── 5. Collapse ──────────────────────────────────────────────── -->
<section class="demo-section">
<h2>5. Collapsible Sections</h2>
<details class="mg-collapse">
<summary>Mathematical derivation: Cortical magnification function</summary>
<div class="mg-collapse-body">
<p>
The cortical magnification factor M describes how many millimeters of cortical
surface represent one degree of visual angle at eccentricity e:
</p>
<p>
<code class="mg-inline-code">M(e) = M0 / (1 + e/e2)</code>
</p>
<p>
Where M0 is the foveal magnification (~15-20 mm/deg for V1) and e2 is the
eccentricity at which M drops to half its foveal value (~0.75 deg for V1,
varying by meridian). This hyperbolic falloff means roughly half of V1 is
devoted to the central 2-3 degrees of the visual field.
</p>
</div>
</details>
<details class="mg-collapse">
<summary>Implementation note: shape-outside polygon coordinates</summary>
<div class="mg-collapse-body">
<p>
The <code class="mg-inline-code">shape-outside: polygon(0% 0%, 100% 0%, 100% 100%, 14% 100%)</code>
creates a trapezoid that approximates the visual footprint of the perspective-tilted
pull quote. The 14% bottom-left inset roughly matches the apparent narrowing from
<code class="mg-inline-code">rotateY(14deg)</code> at the default perspective distance.
</p>
<p>
For the flipped variant, the polygon mirrors:
<code class="mg-inline-code">polygon(14% 0%, 100% 0%, 100% 100%, 0% 100%)</code>.
</p>
</div>
</details>
</section>
<!-- ── 6. Highlight ─────────────────────────────────────────────── -->
<section class="demo-section">
<h2>6. Inline Highlights</h2>
<p class="demo-prose">
The <mark class="mg-mark">foveal region</mark> covers roughly 2 degrees of visual angle —
about the width of your thumbnail at arm's length. Everything beyond that
<mark class="mg-mark">peripheral field</mark> is processed at progressively lower
spatial resolution, following the cortical magnification function described above.
</p>
</section>
<!-- ── 7. Drop Cap ──────────────────────────────────────────────── -->
<section class="demo-section">
<h2>7. Drop Caps</h2>
<p class="mg-dropcap demo-prose">
Peripheral vision is not blurry vision. The retina's ganglion cell density
drops with eccentricity, but peripheral processing excels at detecting motion,
flicker, and large-scale spatial structure. The visual system trades resolution
for temporal sensitivity as you move away from the fovea — a design tradeoff,
not a deficiency.
</p>
<h3>Ornate variant</h3>
<p class="mg-dropcap demo-prose" data-type="ornate">
Every typeface carries its own history. The drop cap, or lettrine, dates to
hand-illuminated manuscripts where monks painted the opening letter in gold
leaf and lapis lazuli. Modern typography inherited the convention stripped of
its gilding but not its function: signal the start, reward the eye, set the
pace for what follows.
</p>
</section>
<!-- ── 7b. Lead-in (Rubrication) ─────────────────────────────────── -->
<section class="demo-section">
<h2>7b. Lead-in (Rubrication)</h2>
<p class="demo-prose">
<span class="mg-lede">The ganglion cell layer</span> is where the retina's
editorial decisions become irreversible. Signals that survive center-surround
filtering are bundled into 1.2 million axons — the optic nerve — and there is
no going back to the raw photoreceptor mosaic after this point.
</p>
<h3>Small-caps variant</h3>
<p class="demo-prose">
<span class="mg-lede" data-type="caps">Cortical magnification</span> describes
how many millimeters of cortical surface represent one degree of visual angle.
The function falls off hyperbolically from the fovea, with roughly half of V1
devoted to the central 2–3 degrees.
</p>
<h3>Paired with drop cap</h3>
<p class="mg-dropcap demo-prose">
<span class="mg-lede">Rubrication</span> dates to medieval manuscripts where
scribes wrote opening words in red ink — Latin <em>ruber</em>. The convention
survived into modern editorial design as the colored lead-in, signaling the
start of a new section without the weight of a full subheading.
</p>
</section>
<!-- ── 8. Footnotes ─────────────────────────────────────────────── -->
<section class="demo-section">
<h2>8. Footnotes</h2>
<p class="demo-prose">
The fovea covers roughly 2 degrees of visual
angle<span class="mg-fn"><a class="mg-fn-ref" tabindex="0"></a><span class="mg-fn-body">About
the width of your thumbnail at arm's length, or roughly 1.5mm on the retina.
Ganglion cell density peaks here at ~35,000 cells/mm².</span></span>
but accounts for over half of the neural real estate in primary visual
cortex<span class="mg-fn"><a class="mg-fn-ref" tabindex="0"></a><span class="mg-fn-body">This
disproportionate allocation is described by the cortical magnification function:
M(e) = M₀ / (1 + e/e₂), where M₀ ≈ 15–20 mm/deg for V1.</span></span>.
This overrepresentation is not waste — it's the biological cost of high-acuity
central vision<span class="mg-fn"><a class="mg-fn-ref" tabindex="0"></a><span class="mg-fn-body">Peripheral
vision compensates with superior temporal resolution and motion sensitivity,
making it the dominant early-warning system for saccade targeting.</span></span>.
</p>
<p class="demo-prose">
Footnote markers auto-number via CSS counters. Content lives inline with its
reference — no bottom-of-page lists to maintain. Hover or tab to a marker to
reveal the note. Works without JavaScript; JS enhances popover positioning
near viewport edges.
</p>
<h3>Manual numbering</h3>
<p class="demo-prose">
You can also provide explicit marker text: some
claim<span class="mg-fn"><a class="mg-fn-ref" tabindex="0">*</a><span class="mg-fn-body">This
uses a manual marker instead of auto-numbering. Just put text inside the
<code class="mg-inline-code">mg-fn-ref</code> element.</span></span>
rather than a number.
</p>
</section>
<!-- ── 9. Gallery / Lightbox ────────────────────────────────────── -->
<section class="demo-section">
<h2>9. Gallery / Lightbox</h2>
<p class="demo-prose">
Click any image to expand in a lightbox overlay. Arrow keys navigate between
images, ESC or click outside to close. Side-by-side comparison grids stack
on mobile.
</p>
<h3>Single image</h3>
<figure class="mg-gallery">
<img src="https://picsum.photos/seed/marginalia-a/800/500" alt="Demo landscape">
<figcaption>Single expandable image with caption. Click to zoom.</figcaption>
</figure>
<h3>Side-by-side comparison</h3>
<div class="mg-gallery" data-type="compare">
<figure>
<img src="https://picsum.photos/seed/marginalia-b/800/500" alt="Mode A comparison">
<figcaption><strong style="color: var(--mg-accent);">Mode A.</strong> First comparison image with detailed caption text describing what the viewer should notice.</figcaption>
</figure>
<figure>
<img src="https://picsum.photos/seed/marginalia-c/800/500" alt="Mode B comparison">
<figcaption><strong style="color: var(--mg-accent);">Mode B.</strong> Second comparison image — differences from Mode A should be visible at full resolution in the lightbox.</figcaption>
</figure>
</div>
</section>
<!-- ── 10. Inline Skew ───────────────────────────────────────────── -->
<section class="demo-section">
<h2>10. Inline Skew Callout</h2>
<div class="mg-callout mg-skew" data-type="note">
<p><strong>Note:</strong> The V1 cortex tiles the visual field with orientation columns spaced at roughly 0.5mm intervals. Each hypercolumn contains a complete set of orientation preferences — a local Fourier basis for spatial frequency analysis.</p>
</div>
<div class="mg-callout mg-skew" data-type="tip">
<p><strong>Tip:</strong> Pair skewed callouts with pull quotes for a consistent 3D language across the page. The subtle 4° tilt here complements the stronger 14° on pull quotes.</p>
</div>
</section>
<!-- ── 11. Sidebar ─────────────────────────────────────────────── -->
<section class="demo-section">
<h2>11. Sidebar</h2>
<div class="demo-flow">
<aside class="mg-sidebar">
<strong>Implementation</strong>
<p>Scrutinizer uses Oklab for all perceptual color operations. sRGB conversions happen only at display output.</p>
</aside>
<p class="demo-prose">
Sidebars float alongside body text, providing tangential context without interrupting
the reading flow. They use body-copy sizing — small enough to be subordinate, large
enough to be legible. The subtle background and border distinguish them from the main
column without the visual weight of a full callout.
</p>
<p class="demo-prose">
Use sidebars for implementation notes, historical context, or definitions that
support the main argument but aren't essential to it. They work best when the reader
can skip them on a first pass and return on a closer read.
</p>
</div>
<h3>Wide variant</h3>
<div class="demo-flow">
<aside class="mg-sidebar mg-wide">
<strong>Parasol cells</strong>
<p>Large receptive fields, high temporal resolution, achromatic. Dominant in peripheral retina. Feed the magnocellular pathway → V1 layer 4Cα → MT for motion processing.</p>
</aside>
<p class="demo-prose">
The <code class="mg-inline-code">mg-wide</code> modifier increases sidebar width to
220px for longer content that needs breathing room. Both variants collapse to
full-width blocks on mobile viewports.
</p>
<p class="demo-prose">
Sidebars are the marginalia equivalent of a penciled annotation — they belong to
the document but live at a lower priority level than the prose they accompany.
</p>
</div>
</section>
<!-- ── 12. Margin Note ──────────────────────────────────────────── -->
<section class="demo-section">
<h2>12. Margin Note</h2>
<p class="demo-prose" style="margin-bottom: 1rem; color: var(--mg-text-muted); font-size: 0.85rem;">
On screens wider than 1200px, margin notes escape the content column and float
in the gutter with large peripheral-readable text. On narrower screens they
degrade to inline callouts. Resize your browser to see both modes.
</p>
<div class="mg-margin-scope demo-flow">
<div class="mg-margin" data-content="insert">
The tiles are still square
<small>That's the hardware. The retina compensates in the wiring.</small>
</div>
<p class="demo-prose">
The content column needs a parent with <code class="mg-inline-code">mg-margin-scope</code>
to allow the note to escape via absolute positioning. On desktop, the note appears
in the left gutter at 2.8rem / 800-weight with a 14° perspective tilt pointing
inward toward the body text.
</p>
<p class="demo-prose">
The 5px border sits on the inside edge — right border for left-gutter notes,
left border for right-gutter notes — creating a visual bridge between the
annotation and the text it refers to.
</p>
</div>
</section>
<!-- ── 12b. Margin Note — Right Gutter ────────────────────────── -->
<section class="demo-section">
<h2>12b. Margin Note — Right Gutter</h2>
<div class="mg-margin-scope demo-flow">
<div class="mg-margin mg-right" data-content="insert">
130M → 1.2M
<small>The retina's compression ratio. Not a bottleneck — an editorial decision.</small>
</div>
<p class="demo-prose">
Add <code class="mg-inline-code">mg-right</code> to position the note in the right
gutter instead. The border flips to the left (inside) edge and the perspective tilt
mirrors to point inward. On narrow screens both variants collapse identically to
inline callouts.
</p>
<p class="demo-prose">
Left and right gutter notes can alternate down a long article, creating the kind of
margin annotation rhythm you see in academic textbooks or magazine feature spreads.
</p>
</div>
</section>
<!-- ── 2b. Pull Quote — Flat + Flipped ─────────────────────────── -->
<section class="demo-section">
<h2>2b. Pull Quote — Flat + Flipped</h2>
<div class="demo-flow">
<aside class="mg-pull mg-flat mg-flip">
The saccade is the fastest movement the human body can make — up to 900°/sec. The visual system is effectively blind during the ballistic phase.
</aside>
<p class="demo-prose">
Combining <code class="mg-inline-code">mg-flat</code> and
<code class="mg-inline-code">mg-flip</code> gives a left-floated sidebar without the
3D perspective tilt. This is the quietest pull quote variant — no skew drawing the
eye, just a bordered float sitting in the left margin.
</p>
<p class="demo-prose">
The four pull quote configurations form a 2×2 matrix: skewed/flat × right/left.
Each serves a different editorial role, from the dramatic tilted hero quote to the
understated left-margin gloss.
</p>
</div>
</section>
<!-- ── 13. Content Mode ─────────────────────────────────────────── -->
<section class="demo-section">
<h2>13. Content Mode</h2>
<div class="demo-flow">
<aside class="mg-pull" data-content="repeat">
Progressive spatial pooling solves the same problem whether evolution or engineering builds it.
</aside>
<p class="demo-prose">
<strong>Repeat mode</strong> (<code class="mg-inline-code">data-content="repeat"</code>)
signals that the callout duplicates text from the surrounding body — the traditional
pull quote. It renders in italics at slightly reduced opacity, telling the reader
"you've seen this already; this is emphasis, not new information."
</p>
<p class="demo-prose">
Progressive spatial pooling solves the same problem whether evolution or engineering
builds it. Hardware MIP chains and retinal eccentricity gradients converge on the
same Laplacian pyramid structure because the optimization landscape has one global
minimum.
</p>
</div>
<div class="demo-flow" style="margin-top: 2rem;">
<aside class="mg-pull mg-flat" data-content="insert">
Crowding, not blur, is the primary limit on peripheral recognition. Flankers merge into texture.
</aside>
<p class="demo-prose">
<strong>Insert mode</strong> (<code class="mg-inline-code">data-content="insert"</code>)
signals new standalone content — a tangential observation, an aside, a definition.
Normal weight, full opacity. The reader knows this is additive information worth
reading even if they've read every word of the body text.
</p>
<p class="demo-prose">
The content mode attribute works on any callout variant: pull quotes, margin notes,
sidebars, and inline callouts. It's a semantic flag, not a layout modifier.
</p>
</div>
<h3>On a callout</h3>
<div class="mg-callout" data-type="note" data-content="insert">
<p><strong>Aside:</strong> The magnocellular pathway carries achromatic, high-temporal-frequency signals from parasol ganglion cells. It's faster than the parvocellular pathway by ~20ms — enough to prime spatial attention before fine detail arrives.</p>
</div>
<h3>On a sidebar</h3>
<div class="demo-flow">
<aside class="mg-sidebar" data-content="insert">
<strong>Terminology</strong>
<p><strong style="color: var(--mg-accent-ink);">Crowding</strong> — inability to recognize objects in clutter, despite adequate acuity. Distinct from blur.</p>
</aside>
<p class="demo-prose">
Content mode on a sidebar signals whether the tangential note paraphrases nearby
body text or introduces a new definition. Insert mode keeps normal weight; repeat
mode would italicize the sidebar body.
</p>
</div>
</section>
<!-- ── 14. Spread ─────────────────────────────────────────────── -->
<section class="demo-section">
<h2>14. Spread — Two-Column Magazine Layout</h2>
<p class="demo-prose" style="margin-bottom: 1rem; color: var(--mg-text-muted); font-size: 0.85rem;">
Two-column body text with callouts that bridge both columns. The classic
editorial spread — inspired by CSS Regions (Adobe's abandoned spec) but
built on <code class="mg-inline-code">column-count</code> +
<code class="mg-inline-code">column-span: all</code>, which actually ships
in every browser.
</p>
<div class="mg-spread">
<p class="mg-dropcap demo-prose">
The retina performs more computation than any other structure in the central
nervous system relative to its size. Six layers of neurons — photoreceptors,
horizontal cells, bipolar cells, amacrine cells, ganglion cells, and their
associated interneurons — implement a signal processing pipeline that would
require roughly 10 billion operations per second to simulate digitally.
</p>
<p class="demo-prose">
Center-surround receptive fields emerge at the ganglion cell layer through
lateral inhibition mediated by horizontal and amacrine cells. This
architecture performs simultaneous contrast normalization across the entire
visual field, adapting the neural code to local luminance statistics on a
millisecond timescale. The result is a representation that encodes edges,
gradients, and transients rather than absolute intensity — exactly the
features that matter for object recognition downstream.
</p>
<aside class="mg-pull" data-content="insert">
Six layers of neurons implement a signal processing pipeline that would
require 10 billion operations per second to simulate.
</aside>
<p class="demo-prose">
Midget ganglion cells in the central retina maintain a one-to-one connection
with individual cone photoreceptors, preserving the full spatial resolution
of the cone mosaic. This private-line architecture is unique to primates and
explains why human visual acuity exceeds that of all other mammals despite
having a similar optical system. The tradeoff: midget cells consume roughly
80% of ganglion cell bandwidth for the central 5 degrees alone.
</p>
<div class="mg-callout" data-type="note">
<p><strong>Note:</strong> The midget pathway's 80% bandwidth allocation for 5° of visual
field is the biological precedent for foveated rendering's aggressive LOD falloff.
If the retina can justify that resource distribution, so can your shader.</p>
</div>
<p class="demo-prose">
Parasol cells cover the remaining visual field with larger receptive fields
optimized for temporal contrast and motion detection. Their faster conduction
velocity and transient response profiles feed the magnocellular pathway,
which drives saccade targeting and the perception of optic flow. This is the
system that makes you flinch before you consciously see the baseball.
</p>
<p class="demo-prose">
The division of labor between midget and parasol pathways is not a compromise
— it's a Pareto-optimal allocation of neural bandwidth given the statistics
of natural scenes. High spatial frequency information is concentrated at
fixation. Motion energy dominates the periphery. The retina matches its
channel capacity to the signal structure at each eccentricity.
</p>
</div>
</section>
<!-- ── Usage ────────────────────────────────────────────────────── -->
<section class="demo-section" style="border-top: 1px solid var(--mg-border); padding-top: 3rem;">
<h2>Usage</h2>
<pre class="mg-code" data-lang="html"><!-- Include in your page -->
<link rel="stylesheet" href="marginalia.css">
<script src="marginalia.js" defer></script>
<!-- Callout -->
<div class="mg-callout" data-type="note">
<p><strong>Note:</strong> Your content here.</p>
</div>
<!-- Pull quote -->
<aside class="mg-pull">Your quote text.</aside>
<aside class="mg-pull mg-flat">Flat sidebar (no 3D tilt).</aside>
<!-- Code block -->
<pre class="mg-code" data-lang="js">const x = 42;</pre>
<!-- Badge -->
<span class="mg-badge">Label</span>
<!-- Collapse -->
<details class="mg-collapse">
<summary>Title</summary>
<div class="mg-collapse-body">Content</div>
</details>
<!-- Highlight -->
<mark class="mg-mark">highlighted text</mark>
<!-- Drop cap -->
<p class="mg-dropcap">Your opening paragraph.</p>
<p class="mg-dropcap" data-type="ornate">Ornate variant with border accent.</p>
<!-- Lead-in (rubrication) -->
<p><span class="mg-lede">Opening words</span> rest of text.</p>
<p><span class="mg-lede" data-type="caps">Small caps</span> variant.</p>
<!-- Footnote (auto-numbered) -->
Text<span class="mg-fn">
<a class="mg-fn-ref" tabindex="0"></a>
<span class="mg-fn-body">Footnote content shown on hover/focus.</span>
</span> continues.
<!-- Inline skew callout -->
<div class="mg-callout mg-skew" data-type="note">Tilted block callout.</div>
<!-- Sidebar — float-right body-copy tangential note -->
<aside class="mg-sidebar">
<strong>Title</strong>
<p>Tangential context at body-copy size.</p>
</aside>
<aside class="mg-sidebar mg-wide">Wider variant.</aside>
<!-- Margin note — escapes into the gutter on wide screens -->
<div class="mg-margin-scope">
<div class="mg-margin">
Big gutter text
<small>Explanatory subtext.</small>
</div>
<p>Body text continues normally.</p>
</div>
<!-- Content mode: repeat (duplicated body text) vs insert (new content) -->
<aside class="mg-pull" data-content="repeat">Emphasized body text.</aside>
<aside class="mg-pull" data-content="insert">New standalone aside.</aside>
<!-- Two-column magazine spread -->
<div class="mg-spread">
<p>Body text flows into two columns.</p>
<aside class="mg-pull">Bridges both columns.</aside>
<p>Text resumes in two columns.</p>
</div>
<!-- Remove vertical bar from any component -->
<div class="mg-callout" data-type="note" data-bar="none">No left border.</div></pre>
</section>
</div>
<script src="marginalia.js"></script>
<script>
// Theme toggle for demo
var toggle = document.getElementById('themeToggle');
var root = document.documentElement;
toggle.addEventListener('click', function () {
var current = root.getAttribute('data-mg-theme');
if (current === 'dark') {
root.setAttribute('data-mg-theme', 'light');
toggle.textContent = 'Dark';
} else {
root.setAttribute('data-mg-theme', 'dark');
toggle.textContent = 'Light';
}
});
</script>
</body>
</html>