main
   1/* ============================================================
   2   Flux Design Sandbox
   3   Combining ideas from: Beat Hagenlocher, Gwern, Daniel Miessler,
   4   Christian Tietze, Crafting Interpreters, Tufte CSS, David Larlet,
   5   Adactio, Butterick, Pawel Grzybek
   6   ============================================================ */
   7
   8/* --- Design Tokens --- */
   9:root {
  10  /* Typography */
  11  --font-body: "Iowan Old Style", "Palatino Linotype", "URW Palladio L",
  12    P052, Palatino, serif;
  13  --font-heading: Seravek, "Gill Sans Nova", Ubuntu, Calibri, "DejaVu Sans",
  14    source-sans-pro, sans-serif;
  15  --font-mono: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo,
  16    Consolas, "DejaVu Sans Mono", monospace;
  17
  18  /* Vertical rhythm — everything derives from this */
  19  --base-font-size: 18px;
  20  --base-line-height: 1.6;
  21  --lh: calc(var(--base-font-size) * var(--base-line-height));
  22
  23  /* Colors — warm parchment (Miessler-inspired) */
  24  --color-bg: #f4f1eb;
  25  --color-bg-alt: #eae7e0;
  26  --color-bg-card: #fff;
  27  --color-text: #2c2c2c;
  28  --color-text-muted: #6b6b6b;
  29  --color-text-faint: #999;
  30  --color-accent: #4a7c59;
  31  --color-accent-soft: rgba(74, 124, 89, 0.08);
  32  --color-link: #2a6496;
  33  --color-link-hover: #1a4060;
  34  --color-border: #ddd;
  35  --color-border-light: #eee;
  36  --color-code-bg: #f0ece4;
  37  --color-tag-bg: var(--color-accent-soft);
  38  --color-tag-text: var(--color-accent);
  39  --color-new: #2d8a56;
  40  --color-updated: #7a6c2a;
  41  --color-sidenote-bg: transparent;
  42  --color-theme-toggle-bg: var(--color-bg-alt);
  43  --color-theme-toggle-fg: var(--color-text-muted);
  44
  45  /* Syntax highlighting — Tonsky (light defaults) */
  46  --hl-string-bg: #e0f6e0;
  47  --hl-string-fg: #1a3a1a;
  48  --hl-comment-bg: #f8f0d0;
  49  --hl-comment-fg: #5a4a1a;
  50  --hl-def-bg: #ecedff;
  51  --hl-def-fg: #1a1a3a;
  52  --hl-constant: #531ab6;
  53  --hl-number: #531ab6;
  54  --hl-type: #595959;
  55
  56  /* Layout */
  57  --content-width: 640px;
  58  --content-padding: 1.5rem;
  59  --margin-note-width: 220px;
  60}
  61
  62/* Dark mode handled entirely by [data-theme="dark"] below.
  63   No @media query needed — JS sets data-theme on load. */
  64
  65/* --- Theme & Accent Controls --- */
  66
  67.site-controls {
  68  position: fixed;
  69  top: 1rem;
  70  right: 1rem;
  71  display: flex;
  72  align-items: center;
  73  gap: 0.3em;
  74  background: var(--color-bg-alt);
  75  border: 1px solid var(--color-border);
  76  border-radius: 99px;
  77  padding: 0.3em 0.5em;
  78  z-index: 100;
  79}
  80
  81.theme-toggle {
  82  background: none;
  83  border: none;
  84  cursor: pointer;
  85  font-size: 1rem;
  86  line-height: 1;
  87  padding: 0.15em;
  88  color: var(--color-text-muted);
  89  transition: color 0.2s;
  90}
  91
  92.theme-toggle:hover {
  93  color: var(--color-text);
  94}
  95
  96.accent-dot {
  97  width: 1em;
  98  height: 1em;
  99  border-radius: 50%;
 100  border: 2px solid transparent;
 101  cursor: pointer;
 102  transition: all 0.2s;
 103  padding: 0;
 104  background: none;
 105}
 106
 107.accent-dot:hover {
 108  transform: scale(1.25);
 109}
 110
 111.accent-dot.active {
 112  border-color: var(--color-text);
 113  box-shadow: 0 0 0 1px var(--color-bg);
 114}
 115
 116.accent-divider {
 117  width: 1px;
 118  height: 1.2em;
 119  background: var(--color-border);
 120  margin: 0 0.15em;
 121}
 122
 123/* Force light/dark via data attribute, overriding prefers-color-scheme */
 124[data-theme="light"] {
 125  --color-bg: #f4f1eb;
 126  --color-bg-alt: #eae7e0;
 127  --color-bg-card: #fff;
 128  --color-text: #2c2c2c;
 129  --color-text-muted: #6b6b6b;
 130  --color-text-faint: #999;
 131  --color-accent: #4a7c59;
 132  --color-accent-soft: rgba(74, 124, 89, 0.08);
 133  --color-link: #2a6496;
 134  --color-link-hover: #1a4060;
 135  --color-border: #ddd;
 136  --color-border-light: #eee;
 137  --color-code-bg: #f0ece4;
 138  --color-tag-bg: var(--color-accent-soft);
 139  --color-tag-text: var(--color-accent);
 140  --color-new: #2d8a56;
 141  --color-updated: #7a6c2a;
 142  --hl-string-bg: #e0f6e0;
 143  --hl-string-fg: #1a3a1a;
 144  --hl-comment-bg: #f8f0d0;
 145  --hl-comment-fg: #5a4a1a;
 146  --hl-def-bg: #ecedff;
 147  --hl-def-fg: #1a1a3a;
 148  --hl-constant: #531ab6;
 149  --hl-number: #531ab6;
 150  --hl-type: #595959;
 151}
 152
 153[data-theme="light"] a {
 154  text-decoration-color: rgba(42, 100, 150, 0.3);
 155}
 156
 157[data-theme="dark"] {
 158  --color-bg: #1a1a1f;
 159  --color-bg-alt: #222228;
 160  --color-bg-card: rgba(51, 51, 57, 1);
 161  --color-text: #d4d4d8;
 162  --color-text-muted: #9ca3af;
 163  --color-text-faint: #6b7280;
 164  --color-accent: #6aab7b;
 165  --color-accent-soft: rgba(106, 171, 123, 0.1);
 166  --color-link: #7daacd;
 167  --color-link-hover: #a3c4df;
 168  --color-border: #333;
 169  --color-border-light: #2a2a2f;
 170  --color-code-bg: #2a2a30;
 171  --color-tag-bg: var(--color-accent-soft);
 172  --color-tag-text: var(--color-accent);
 173  --color-new: #4ade80;
 174  --color-updated: #d4aa3c;
 175  --hl-string-bg: #1a2e1a;
 176  --hl-string-fg: #b0d8b0;
 177  --hl-comment-bg: #2a2518;
 178  --hl-comment-fg: #d4c89a;
 179  --hl-def-bg: #1a1a2e;
 180  --hl-def-fg: #a0a8d0;
 181  --hl-constant: #b6a0ff;
 182  --hl-number: #b6a0ff;
 183  --hl-type: #989898;
 184}
 185
 186[data-theme="dark"] a {
 187  text-decoration-color: rgba(125, 170, 205, 0.3);
 188}
 189
 190/* --- Reset & Base --- */
 191*,
 192*::before,
 193*::after {
 194  box-sizing: border-box;
 195  margin: 0;
 196  padding: 0;
 197}
 198
 199html {
 200  font-size: var(--base-font-size);
 201  line-height: var(--base-line-height);
 202  -webkit-text-size-adjust: 100%;
 203  scroll-behavior: smooth;
 204}
 205
 206body {
 207  font-family: var(--font-body);
 208  color: var(--color-text);
 209  background-color: var(--color-bg);
 210  max-width: calc(var(--content-width) + var(--margin-note-width) + 4rem);
 211  margin: 0 auto;
 212  padding: var(--content-padding);
 213  padding-top: 3rem;
 214}
 215
 216/* --- Vertical Rhythm ---
 217   Using lh units where supported, calc fallback otherwise.
 218   Butterick: 120-145% line spacing.
 219   Pawel Grzybek: lh/rlh units for rhythm.
 220   Christian Tietze: consistent custom property spacing. */
 221
 222p,
 223ul,
 224ol,
 225blockquote,
 226pre,
 227table,
 228figure,
 229.stream-card {
 230  margin-bottom: 1lh;
 231  margin-bottom: var(--lh);
 232}
 233
 234/* --- Typography --- */
 235
 236h1,
 237h2,
 238h3,
 239h4 {
 240  font-family: var(--font-heading);
 241  font-weight: 600;
 242  line-height: 1.25;
 243  color: var(--color-text);
 244}
 245
 246h1 {
 247  font-size: 2rem;
 248  margin-bottom: 0.5lh;
 249  margin-bottom: calc(var(--lh) * 0.5);
 250  letter-spacing: -0.02em;
 251}
 252
 253h2 {
 254  font-size: 1.4rem;
 255  margin-top: 2lh;
 256  margin-top: calc(var(--lh) * 2);
 257  margin-bottom: 0.5lh;
 258  margin-bottom: calc(var(--lh) * 0.5);
 259}
 260
 261/* Crafting Interpreters: § anchor on hover */
 262h2, h3, h4 {
 263  position: relative;
 264}
 265h2 a.anchor,
 266h3 a.anchor,
 267h4 a.anchor {
 268  position: absolute;
 269  left: -1.5em;
 270  color: transparent;
 271  text-decoration: none;
 272  font-weight: normal;
 273  transition: color 0.2s ease;
 274}
 275h2:hover a.anchor,
 276h3:hover a.anchor,
 277h4:hover a.anchor {
 278  color: var(--color-text-faint);
 279}
 280
 281h3 {
 282  font-size: 1.15rem;
 283  margin-top: 1.5lh;
 284  margin-top: calc(var(--lh) * 1.5);
 285  margin-bottom: 0.25lh;
 286  margin-bottom: calc(var(--lh) * 0.25);
 287  font-style: italic;
 288}
 289
 290.subtitle {
 291  font-family: var(--font-body);
 292  font-size: 1.1rem;
 293  font-weight: normal;
 294  font-style: italic;
 295  color: var(--color-text-muted);
 296  margin-top: -0.25lh;
 297  margin-top: calc(var(--lh) * -0.25);
 298  margin-bottom: 1.5lh;
 299  margin-bottom: calc(var(--lh) * 1.5);
 300}
 301
 302/* --- Links ---
 303   Adactio: styled underlines with text-decoration-* */
 304
 305a {
 306  color: var(--color-link);
 307  text-decoration-line: underline;
 308  text-decoration-color: rgba(42, 100, 150, 0.3);
 309  text-decoration-thickness: 1px;
 310  text-underline-offset: 0.15em;
 311  transition: color 0.2s ease, text-decoration-color 0.2s ease;
 312}
 313
 314a:hover {
 315  color: var(--color-link-hover);
 316  text-decoration-color: var(--color-link-hover);
 317}
 318
 319/* Dark link underline color handled by [data-theme="dark"] below. */
 320
 321/* --- Lists --- */
 322
 323ul {
 324  padding-left: 1.5em;
 325  list-style-type: "✧ ";  /* white star */
 326}
 327
 328ol {
 329  padding-left: 1.5em;
 330}
 331
 332li {
 333  margin-bottom: 0.25lh;
 334  margin-bottom: calc(var(--lh) * 0.25);
 335}
 336
 337/* --- Blockquotes ---
 338   Stylish, with subtle background, accent border, optional attribution */
 339
 340blockquote {
 341  border-left: 3px solid var(--color-accent);
 342  padding: 1em 1.2em;
 343  margin-left: 0;
 344  margin-right: 0;
 345  color: var(--color-text-muted);
 346  background: var(--color-accent-soft);
 347  border-radius: 0 6px 6px 0;
 348  position: relative;
 349}
 350
 351blockquote::before {
 352  content: "\201C";
 353  position: absolute;
 354  top: -0.15em;
 355  left: 0.15em;
 356  font-size: 3rem;
 357  line-height: 1;
 358  color: var(--color-accent);
 359  opacity: 0.2;
 360  font-family: Georgia, serif;
 361}
 362
 363blockquote p {
 364  margin-bottom: 0.5em;
 365}
 366
 367blockquote p:last-child {
 368  margin-bottom: 0;
 369}
 370
 371blockquote cite,
 372blockquote .attribution {
 373  display: block;
 374  margin-top: 0.5em;
 375  font-size: 0.85em;
 376  font-style: normal;
 377  color: var(--color-text-faint);
 378  font-family: var(--font-heading);
 379}
 380
 381blockquote cite::before,
 382blockquote .attribution::before {
 383  content: "— ";
 384}
 385
 386/* Epigraph style: centered, no border, more typographic */
 387blockquote.epigraph {
 388  border-left: none;
 389  background: transparent;
 390  text-align: center;
 391  max-width: 80%;
 392  margin-left: auto;
 393  margin-right: auto;
 394  padding: 1.5em 0;
 395  font-size: 1.1em;
 396}
 397
 398blockquote.epigraph::before {
 399  content: none;
 400}
 401
 402blockquote.epigraph cite {
 403  text-align: center;
 404}
 405
 406/* Pullquote: larger, accent-colored, editorial */
 407blockquote.pullquote {
 408  border-left: none;
 409  border-top: 2px solid var(--color-accent);
 410  border-bottom: 2px solid var(--color-accent);
 411  border-radius: 0;
 412  background: transparent;
 413  padding: 1em 0;
 414  font-size: 1.15em;
 415  font-style: italic;
 416  color: var(--color-accent);
 417  text-align: center;
 418}
 419
 420blockquote.pullquote::before {
 421  content: none;
 422}
 423
 424/* --- Code ---
 425   Monospace, subtle background, respects rhythm */
 426
 427code {
 428  font-family: var(--font-mono);
 429  font-size: 0.85em;
 430  background: var(--color-code-bg);
 431  padding: 0.1em 0.35em;
 432  border-radius: 3px;
 433}
 434
 435pre {
 436  background: var(--color-code-bg);
 437  padding: 1em 1.2em;
 438  border-radius: 6px;
 439  overflow-x: auto;
 440  font-size: 0.85rem;
 441  line-height: 1.5;
 442}
 443
 444pre code {
 445  background: none;
 446  padding: 0;
 447}
 448
 449/* --- Syntax Highlighting ---
 450   Tonsky-inspired: minimal colors, background-based for key elements.
 451   Only 4 semantic categories get color:
 452     1. Strings       → green bg
 453     2. Constants      → purple/magenta
 454     3. Definitions    → blue bg
 455     4. Comments       → warm/yellow bg
 456   Everything else: default foreground. No bold. */
 457
 458/* All --hl-* vars defined in :root, [data-theme="light"], and
 459   [data-theme="dark"] blocks above — no duplicate needed here. */
 460
 461/* Strings: green background, dark text */
 462pre .s, pre .s1, pre .s2, pre .string,
 463pre .str {
 464  background: var(--hl-string-bg);
 465  color: var(--hl-string-fg);
 466  border-radius: 2px;
 467  padding: 0 0.15em;
 468}
 469
 470/* Comments: warm yellow background */
 471pre .c, pre .c1, pre .cm, pre .comment,
 472pre .cmt {
 473  background: var(--hl-comment-bg);
 474  color: var(--hl-comment-fg);
 475  border-radius: 2px;
 476  padding: 0 0.15em;
 477  font-style: italic;
 478}
 479
 480/* Function/method definitions: blue background */
 481pre .nf, pre .fm, pre .def,
 482pre .fn-def {
 483  background: var(--hl-def-bg);
 484  color: var(--hl-def-fg);
 485  border-radius: 2px;
 486  padding: 0 0.15em;
 487}
 488
 489/* Constants, numbers, booleans: purple text (no bg — sparse enough) */
 490pre .mi, pre .mf, pre .mb, pre .mh, pre .mo,
 491pre .num, pre .const,
 492pre .kc {
 493  color: var(--hl-constant);
 494}
 495
 496/* Types: dimmed (they're everywhere in Go/Rust) */
 497pre .nc, pre .type, pre .typ {
 498  color: var(--hl-type);
 499}
 500
 501/* Everything else: default text color — keywords, variables, calls, 
 502   operators, punctuation. No color, no bold. This IS the code. */
 503pre .k, pre .kw, pre .kd, pre .kr,    /* keywords */
 504pre .nb, pre .bp,                       /* builtins */
 505pre .n, pre .na, pre .nx,               /* names/attrs */
 506pre .o, pre .p,                         /* operators/punctuation */
 507pre .nv, pre .vi, pre .var,             /* variables */
 508pre .nd                                  /* decorators */
 509{
 510  color: inherit;
 511  font-weight: normal;
 512  font-style: normal;
 513}
 514
 515/* --- Org-mode htmlize class mappings (org-html-htmlize-output-type 'css) ---
 516   Maps org-* face classes to Tonsky highlighting.
 517   These classes come from Emacs font-lock faces via htmlize. */
 518
 519/* Strings → green background */
 520pre .org-string,
 521pre .org-doc {
 522  background: var(--hl-string-bg);
 523  color: var(--hl-string-fg);
 524  border-radius: 2px;
 525  padding: 0 0.15em;
 526}
 527
 528/* Comments → warm background */
 529pre .org-comment,
 530pre .org-comment-delimiter {
 531  background: var(--hl-comment-bg);
 532  color: var(--hl-comment-fg);
 533  border-radius: 2px;
 534  padding: 0 0.15em;
 535  font-style: italic;
 536}
 537
 538/* Function/type definitions → blue background */
 539pre .org-function-name {
 540  background: var(--hl-def-bg);
 541  color: var(--hl-def-fg);
 542  border-radius: 2px;
 543  padding: 0 0.15em;
 544}
 545
 546/* Constants, numbers → purple text */
 547pre .org-constant,
 548pre .org-number {
 549  color: var(--hl-constant);
 550}
 551
 552/* Types → dimmed */
 553pre .org-type {
 554  color: var(--hl-type);
 555}
 556
 557/* Nix-mode classes → Tonsky mapping */
 558pre .org-nix-attribute { color: inherit; }
 559pre .org-nix-constant { color: var(--hl-constant); }
 560pre .org-nix-antiquote { color: inherit; }
 561
 562/* Everything else from org → default (Tonsky: de-emphasize) */
 563pre .org-keyword,
 564pre .org-builtin,
 565pre .org-nix-keyword,
 566pre .org-nix-builtin,
 567pre .org-variable-name,
 568pre .org-property-name,
 569pre .org-css-property,
 570pre .org-css-selector,
 571pre .org-preprocessor,
 572pre .org-negation-char {
 573  color: inherit;
 574  font-weight: normal;
 575  font-style: normal;
 576}
 577
 578/* --- Org export structure mappings --- */
 579
 580/* Main content wrapper */
 581article.content {
 582  counter-reset: sidenote-counter;
 583}
 584
 585/* Section structure */
 586.outline-2,
 587.outline-3,
 588.outline-4 {
 589  /* no special styling needed, headings handle it */
 590}
 591
 592/* Code blocks from org */
 593.org-src-container {
 594  margin-bottom: 1lh;
 595  margin-bottom: var(--lh);
 596}
 597
 598.org-src-container > pre.src {
 599  background: var(--color-code-bg);
 600  padding: 1em 1.2em;
 601  border-radius: 6px;
 602  overflow-x: auto;
 603  font-size: 0.85rem;
 604  line-height: 1.5;
 605  font-family: var(--font-mono);
 606}
 607
 608/* ox-tufte sidenote toggle (checkbox hack for mobile) */
 609.margin-toggle {
 610  display: none;
 611}
 612
 613label.margin-toggle.sidenote-number {
 614  display: inline;
 615}
 616
 617.margin-toggle:checked + .sidenote,
 618.margin-toggle:checked + .marginnote {
 619  display: block;
 620}
 621
 622/* ox-tufte epigraph (blockquote with caption/footer) */
 623blockquote footer {
 624  font-size: 0.85em;
 625  font-style: normal;
 626  color: var(--color-text-faint);
 627  font-family: var(--font-heading);
 628  margin-top: 0.5em;
 629}
 630
 631blockquote footer::before {
 632  content: "— ";
 633}
 634
 635/* Org figure numbering */
 636.figure-number {
 637  font-family: var(--font-heading);
 638  font-weight: 600;
 639  font-style: normal;
 640}
 641
 642/* Org tags on headings */
 643.tag {
 644  font-family: var(--font-mono);
 645  font-size: 0.7em;
 646  font-weight: normal;
 647  color: var(--color-text-faint);
 648}
 649
 650/* Org timestamps */
 651.timestamp-wrapper,
 652.timestamp {
 653  font-family: var(--font-mono);
 654  font-size: 0.82rem;
 655  color: var(--color-text-faint);
 656}
 657
 658a.timestamp-link {
 659  color: var(--color-text-faint);
 660  text-decoration: none;
 661  border-bottom: 1px dotted var(--color-border);
 662  transition: color 0.2s, border-color 0.2s;
 663}
 664
 665a.timestamp-link:hover {
 666  color: var(--color-accent);
 667  border-color: var(--color-accent);
 668}
 669
 670/* Org lists */
 671.org-ul {
 672  padding-left: 1.5em;
 673  list-style-type: "✧ ";
 674}
 675
 676.org-ol {
 677  padding-left: 1.5em;
 678}
 679
 680/* Subtitle from #+SUBTITLE */
 681.subtitle {
 682  font-family: var(--font-body);
 683  font-size: 1.1rem;
 684  font-weight: normal;
 685  font-style: italic;
 686  color: var(--color-text-muted);
 687  margin-top: calc(var(--lh) * -0.25);
 688  margin-bottom: calc(var(--lh) * 1.5);
 689}
 690
 691/* Postamble (footer) - hide validation link */
 692.status .validation {
 693  display: none;
 694}
 695
 696.status {
 697  margin-top: calc(var(--lh) * 3);
 698  padding-top: var(--lh);
 699  border-top: 1px solid var(--color-border);
 700  font-size: 0.8rem;
 701  color: var(--color-text-faint);
 702  font-family: var(--font-heading);
 703}
 704
 705/* --- Sidenotes / Margin Notes ---
 706   Tufte CSS + Gwern: margin notes for thinking */
 707
 708.sidenote,
 709.marginnote {
 710  float: right;
 711  clear: right;
 712  margin-right: calc(-1 * var(--margin-note-width) - 2rem);
 713  width: var(--margin-note-width);
 714  font-size: 0.8rem;
 715  line-height: 1.4;
 716  color: var(--color-text-muted);
 717  position: relative;
 718}
 719
 720.sidenote {
 721  border-left: 2px solid var(--color-border);
 722  padding-left: 0.75em;
 723}
 724
 725.sidenote-number {
 726  counter-increment: sidenote-counter;
 727}
 728
 729.sidenote-number::after {
 730  content: counter(sidenote-counter);
 731  font-size: 0.7em;
 732  position: relative;
 733  top: -0.5em;
 734  color: var(--color-accent);
 735  padding-left: 0.1em;
 736}
 737
 738.sidenote::before {
 739  content: counter(sidenote-counter);
 740  font-size: 0.7em;
 741  position: relative;
 742  top: -0.5em;
 743  color: var(--color-accent);
 744  padding-right: 0.3em;
 745}
 746
 747/* Collapse sidenotes on small screens */
 748@media (max-width: 900px) {
 749  body {
 750    max-width: var(--content-width);
 751  }
 752  .sidenote,
 753  .marginnote {
 754    float: none;
 755    display: block;
 756    margin: 0.5lh 0;
 757    margin: calc(var(--lh) * 0.5) 0;
 758    width: 100%;
 759    font-size: 0.85rem;
 760    background: var(--color-bg-alt);
 761    padding: 0.75em 1em;
 762    border-radius: 4px;
 763    border-left: 3px solid var(--color-border);
 764    margin-right: 0;
 765  }
 766}
 767
 768/* --- Callouts ---
 769   Crafting Interpreters design-note style, extended with types.
 770   Each type has: left border color, subtle bg, icon prefix. */
 771
 772:root {
 773  --callout-note-color: #2a6496;
 774  --callout-note-bg: rgba(42, 100, 150, 0.06);
 775  --callout-tip-color: #4a7c59;
 776  --callout-tip-bg: rgba(74, 124, 89, 0.06);
 777  --callout-info-color: #3a7ca5;
 778  --callout-info-bg: rgba(58, 124, 165, 0.06);
 779  --callout-warning-color: #9a7b2a;
 780  --callout-warning-bg: rgba(154, 123, 42, 0.06);
 781  --callout-danger-color: #b44;
 782  --callout-danger-bg: rgba(180, 68, 68, 0.06);
 783  --callout-design-color: var(--color-accent);
 784  --callout-design-bg: var(--color-accent-soft);
 785}
 786
 787/* Dark callout colors handled by [data-theme="dark"] below. */
 788
 789[data-theme="light"] {
 790  --callout-note-color: #2a6496;
 791  --callout-note-bg: rgba(42, 100, 150, 0.06);
 792  --callout-tip-color: #4a7c59;
 793  --callout-tip-bg: rgba(74, 124, 89, 0.06);
 794  --callout-info-color: #3a7ca5;
 795  --callout-info-bg: rgba(58, 124, 165, 0.06);
 796  --callout-warning-color: #9a7b2a;
 797  --callout-warning-bg: rgba(154, 123, 42, 0.06);
 798  --callout-danger-color: #b44;
 799  --callout-danger-bg: rgba(180, 68, 68, 0.06);
 800}
 801
 802[data-theme="dark"] {
 803  --callout-note-color: #7daacd;
 804  --callout-note-bg: rgba(125, 170, 205, 0.08);
 805  --callout-tip-color: #6aab7b;
 806  --callout-tip-bg: rgba(106, 171, 123, 0.08);
 807  --callout-info-color: #6aafcf;
 808  --callout-info-bg: rgba(106, 175, 207, 0.08);
 809  --callout-warning-color: #d4aa3c;
 810  --callout-warning-bg: rgba(212, 170, 60, 0.08);
 811  --callout-danger-color: #e07070;
 812  --callout-danger-bg: rgba(224, 112, 112, 0.08);
 813}
 814
 815.callout {
 816  border-left: 3px solid var(--callout-border, var(--color-accent));
 817  background: var(--callout-bg, var(--color-accent-soft));
 818  border-radius: 0 6px 6px 0;
 819  padding: 0.9em 1.2em;
 820  margin: 1lh 0;
 821  margin: var(--lh) 0;
 822  font-family: var(--font-heading);
 823  font-size: 0.9rem;
 824  color: var(--color-text-muted);
 825}
 826
 827.callout-title {
 828  font-weight: 600;
 829  text-transform: uppercase;
 830  letter-spacing: 0.05em;
 831  font-size: 0.72rem;
 832  color: var(--callout-border, var(--color-accent));
 833  margin-bottom: 0.4em;
 834  display: flex;
 835  align-items: center;
 836  gap: 0.4em;
 837}
 838
 839.callout-title::before {
 840  font-size: 1em;
 841  line-height: 1;
 842}
 843
 844.callout p:last-child {
 845  margin-bottom: 0;
 846}
 847
 848/* --- Callout Types --- */
 849
 850.callout-note {
 851  --callout-border: var(--callout-note-color);
 852  --callout-bg: var(--callout-note-bg);
 853}
 854.callout-note .callout-title::before { content: "✎"; }
 855
 856.callout-tip {
 857  --callout-border: var(--callout-tip-color);
 858  --callout-bg: var(--callout-tip-bg);
 859}
 860.callout-tip .callout-title::before { content: "✦"; }
 861
 862.callout-info {
 863  --callout-border: var(--callout-info-color);
 864  --callout-bg: var(--callout-info-bg);
 865}
 866.callout-info .callout-title::before { content: "ℹ"; }
 867
 868.callout-warning {
 869  --callout-border: var(--callout-warning-color);
 870  --callout-bg: var(--callout-warning-bg);
 871}
 872.callout-warning .callout-title::before { content: "⚠"; }
 873
 874.callout-danger {
 875  --callout-border: var(--callout-danger-color);
 876  --callout-bg: var(--callout-danger-bg);
 877}
 878.callout-danger .callout-title::before { content: "✖"; }
 879
 880.callout-design {
 881  --callout-border: var(--callout-design-color);
 882  --callout-bg: var(--callout-design-bg);
 883}
 884.callout-design .callout-title::before { content: "◆"; }
 885
 886/* --- Dropcap ---
 887   Gwern: classic typographic dropcap */
 888
 889.dropcap::first-letter {
 890  float: left;
 891  font-size: 3.2em;
 892  line-height: 0.8;
 893  padding-right: 0.08em;
 894  padding-top: 0.07em;
 895  font-weight: 600;
 896  color: var(--color-accent);
 897}
 898
 899/* --- Small Caps ---
 900   Gwern: small caps for emphasis/theming */
 901
 902.smallcaps {
 903  font-variant: small-caps;
 904  letter-spacing: 0.05em;
 905}
 906
 907/* --- Horizontal Rule --- */
 908
 909hr {
 910  border: none;
 911  border-top: 1px solid var(--color-border);
 912  margin: 2lh 0;
 913  margin: calc(var(--lh) * 2) 0;
 914}
 915
 916/* ============================================================
 917   STREAM / FLUX COMPONENTS
 918   Inspired by Beat Hagenlocher's /stream/
 919   ============================================================ */
 920
 921.flux {
 922  counter-reset: sidenote-counter;
 923}
 924
 925.flux-header {
 926  margin-bottom: 2lh;
 927  margin-bottom: calc(var(--lh) * 2);
 928}
 929
 930.flux-header h1 {
 931  font-size: 1.6rem;
 932}
 933
 934.flux-header .description {
 935  color: var(--color-text-muted);
 936  font-size: 0.95rem;
 937}
 938
 939.flux-feed-links {
 940  display: flex;
 941  gap: 1em;
 942  margin-top: 0.5lh;
 943  margin-top: calc(var(--lh) * 0.5);
 944  font-size: 0.8rem;
 945  font-family: var(--font-mono);
 946}
 947
 948.flux-feed-links a {
 949  color: var(--color-text-faint);
 950  text-decoration: none;
 951  border: 1px solid var(--color-border);
 952  padding: 0.2em 0.6em;
 953  border-radius: 4px;
 954  transition: all 0.2s;
 955}
 956
 957.flux-feed-links a:hover {
 958  color: var(--color-link);
 959  border-color: var(--color-link);
 960}
 961
 962/* --- Stream Card (streamlet) ---
 963   Beat-style: rounded card with date, title, body, tags */
 964
 965.stream-card {
 966  background: var(--color-bg-card);
 967  border-radius: 10px;
 968  padding: 1.2em 1.4em;
 969  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06),
 970    inset 0 1px 0 0 rgba(148, 163, 184, 0.06);
 971  position: relative;
 972}
 973
 974.stream-card .card-date {
 975  font-family: var(--font-mono);
 976  font-size: 0.72rem;
 977  color: var(--color-text-faint);
 978  margin-bottom: 0.3em;
 979}
 980
 981.stream-card .card-title {
 982  font-family: var(--font-heading);
 983  font-size: 1.05rem;
 984  font-weight: 600;
 985  margin-bottom: 0.5em;
 986  line-height: 1.3;
 987}
 988
 989.stream-card .card-body {
 990  font-size: 0.9rem;
 991  line-height: 1.55;
 992  color: var(--color-text-muted);
 993}
 994
 995.stream-card .card-body p:last-child {
 996  margin-bottom: 0;
 997}
 998
 999/* Section anchor on cards */
1000.stream-card .card-anchor {
1001  position: absolute;
1002  left: -1.5em;
1003  top: 1.2em;
1004  font-size: 1.1rem;
1005  color: transparent;
1006  text-decoration: none;
1007  transition: color 0.2s;
1008}
1009
1010.stream-card:hover .card-anchor {
1011  color: var(--color-text-faint);
1012}
1013
1014/* --- Tags --- */
1015
1016.tags {
1017  display: flex;
1018  flex-wrap: wrap;
1019  gap: 0.4em;
1020  margin-top: 0.7em;
1021}
1022
1023.tag {
1024  font-family: var(--font-heading);
1025  font-size: 0.68rem;
1026  font-weight: 500;
1027  background: var(--color-tag-bg);
1028  color: var(--color-tag-text);
1029  padding: 0.25em 0.7em;
1030  border-radius: 99px;
1031  white-space: nowrap;
1032  text-decoration: none;
1033  transition: background 0.2s, color 0.2s;
1034}
1035
1036a.tag:hover {
1037  background: var(--color-tag-text);
1038  color: var(--color-bg);
1039}
1040
1041/* Tags inline in headings (org export) */
1042h2 .tags,
1043h3 .tags,
1044h4 .tags {
1045  display: inline-flex;
1046  margin-top: 0;
1047  margin-left: 0.5em;
1048  vertical-align: middle;
1049}
1050
1051/* --- Page Update Entry ---
1052   Beat-style: compact one-liner for new (+) or updated (~) pages */
1053
1054.page-entry {
1055  display: flex;
1056  align-items: center;
1057  gap: 0.6em;
1058  padding: 0.5em 0.8em;
1059  border-radius: 8px;
1060  border: 1px solid var(--color-border-light);
1061  transition: background 0.2s;
1062  text-decoration: none;
1063  margin-bottom: 0.4lh;
1064  margin-bottom: calc(var(--lh) * 0.4);
1065}
1066
1067.page-entry:hover {
1068  background: var(--color-bg-alt);
1069  text-decoration: none;
1070}
1071
1072.page-entry .marker {
1073  font-size: 0.8rem;
1074  font-weight: 600;
1075  flex-shrink: 0;
1076}
1077
1078.page-entry .marker.new {
1079  color: var(--color-new);
1080}
1081
1082.page-entry .marker.updated {
1083  color: var(--color-updated);
1084}
1085
1086.page-entry .page-title {
1087  font-family: var(--font-heading);
1088  font-size: 0.85rem;
1089  font-weight: 500;
1090  color: var(--color-text);
1091  flex: 1;
1092}
1093
1094.page-entry .page-date {
1095  font-family: var(--font-mono);
1096  font-size: 0.68rem;
1097  color: var(--color-text-faint);
1098  margin-left: auto;
1099  white-space: nowrap;
1100}
1101
1102.page-entry .arrow {
1103  color: var(--color-accent);
1104  font-size: 0.75rem;
1105  transition: transform 0.2s;
1106}
1107
1108.page-entry:hover .arrow {
1109  transform: rotate(0deg) translateY(1px);
1110}
1111
1112/* --- GitHub Entry ---
1113   Compact PR/issue/release entries */
1114
1115.github-entry {
1116  display: flex;
1117  align-items: flex-start;
1118  gap: 0.6em;
1119  padding: 0.6em 0;
1120  border-bottom: 1px solid var(--color-border-light);
1121  font-size: 0.88rem;
1122}
1123
1124.github-entry:last-child {
1125  border-bottom: none;
1126}
1127
1128.github-entry .gh-icon {
1129  flex-shrink: 0;
1130  width: 1.3em;
1131  text-align: center;
1132  margin-top: 0.15em;
1133}
1134
1135.github-entry .gh-icon.pr {
1136  color: var(--color-new);
1137}
1138.github-entry .gh-icon.issue {
1139  color: var(--color-updated);
1140}
1141.github-entry .gh-icon.release {
1142  color: var(--color-accent);
1143}
1144
1145.github-entry .gh-content {
1146  flex: 1;
1147  min-width: 0;
1148}
1149
1150.github-entry .gh-title {
1151  color: var(--color-text);
1152}
1153
1154.github-entry .gh-title a {
1155  text-decoration: none;
1156}
1157
1158.github-entry .gh-title a:hover {
1159  text-decoration: underline;
1160  text-decoration-color: var(--color-link);
1161}
1162
1163.github-entry .gh-repo {
1164  font-family: var(--font-mono);
1165  font-size: 0.78rem;
1166  color: var(--color-text-faint);
1167}
1168
1169.github-entry .gh-date {
1170  font-family: var(--font-mono);
1171  font-size: 0.7rem;
1172  color: var(--color-text-faint);
1173  white-space: nowrap;
1174  margin-top: 0.15em;
1175}
1176
1177/* --- Bookmark Entry --- */
1178
1179.bookmark-entry {
1180  padding: 0.6em 0;
1181  border-bottom: 1px solid var(--color-border-light);
1182}
1183
1184.bookmark-entry:last-child {
1185  border-bottom: none;
1186}
1187
1188.bookmark-entry .bm-title {
1189  font-size: 0.9rem;
1190}
1191
1192.bookmark-entry .bm-note {
1193  font-size: 0.82rem;
1194  color: var(--color-text-muted);
1195  margin-top: 0.2em;
1196  font-style: italic;
1197}
1198
1199.bookmark-entry .bm-meta {
1200  font-family: var(--font-mono);
1201  font-size: 0.7rem;
1202  color: var(--color-text-faint);
1203  margin-top: 0.2em;
1204}
1205
1206/* --- Release highlight --- */
1207
1208.release-card {
1209  background: var(--color-accent-soft);
1210  border: 1px solid var(--color-accent);
1211  border-radius: 8px;
1212  padding: 0.8em 1em;
1213  margin-bottom: 1lh;
1214  margin-bottom: var(--lh);
1215}
1216
1217.release-card .release-version {
1218  font-family: var(--font-mono);
1219  font-weight: 600;
1220  color: var(--color-accent);
1221}
1222
1223.release-card .release-project {
1224  font-family: var(--font-heading);
1225  font-weight: 500;
1226}
1227
1228.release-card .release-date {
1229  font-family: var(--font-mono);
1230  font-size: 0.72rem;
1231  color: var(--color-text-faint);
1232}
1233
1234/* --- Flux navigation --- */
1235
1236.flux-years {
1237  font-family: var(--font-mono);
1238  font-size: 0.85rem;
1239  color: var(--color-text-faint);
1240  margin-bottom: 1.5lh;
1241  margin-bottom: calc(var(--lh) * 1.5);
1242}
1243
1244.flux-years a {
1245  color: var(--color-text-muted);
1246}
1247
1248.flux-years strong {
1249  color: var(--color-text);
1250  text-decoration: none;
1251}
1252
1253.flux-stats {
1254  font-family: var(--font-mono);
1255  font-size: 0.8rem;
1256  color: var(--color-text-faint);
1257  margin-bottom: 1.5lh;
1258  margin-bottom: calc(var(--lh) * 1.5);
1259}
1260
1261.flux-archive-link {
1262  font-family: var(--font-heading);
1263  font-size: 0.9rem;
1264  color: var(--color-text-muted);
1265  margin-top: 2lh;
1266  margin-top: calc(var(--lh) * 2);
1267}
1268
1269/* --- Year Separator --- */
1270
1271.year-separator {
1272  font-family: var(--font-heading);
1273  font-size: 0.75rem;
1274  font-weight: 600;
1275  text-transform: uppercase;
1276  letter-spacing: 0.1em;
1277  color: var(--color-text-faint);
1278  margin: 2lh 0 1lh 0;
1279  margin: calc(var(--lh) * 2) 0 calc(var(--lh) * 1) 0;
1280  padding-bottom: 0.3em;
1281  border-bottom: 1px solid var(--color-border);
1282}
1283
1284/* --- Table --- */
1285
1286table {
1287  width: 100%;
1288  border-collapse: collapse;
1289  font-size: 0.9rem;
1290  margin-bottom: 1lh;
1291  margin-bottom: var(--lh);
1292}
1293
1294th,
1295td {
1296  text-align: left;
1297  padding: 0.4em 0.8em;
1298  border-bottom: 1px solid var(--color-border-light);
1299}
1300
1301th {
1302  font-family: var(--font-heading);
1303  font-weight: 600;
1304  font-size: 0.8rem;
1305  text-transform: uppercase;
1306  letter-spacing: 0.04em;
1307  color: var(--color-text-muted);
1308}
1309
1310/* --- Footer --- */
1311
1312footer {
1313  margin-top: 3lh;
1314  margin-top: calc(var(--lh) * 3);
1315  padding-top: 1lh;
1316  padding-top: var(--lh);
1317  border-top: 1px solid var(--color-border);
1318  font-size: 0.8rem;
1319  color: var(--color-text-faint);
1320  font-family: var(--font-heading);
1321}
1322
1323/* --- Figures & Images --- */
1324
1325figure {
1326  margin: 1.5lh 0;
1327  margin: calc(var(--lh) * 1.5) 0;
1328}
1329
1330figure img {
1331  display: block;
1332  max-width: 100%;
1333  height: auto;
1334  border-radius: 4px;
1335}
1336
1337figcaption {
1338  font-family: var(--font-heading);
1339  font-size: 0.82rem;
1340  color: var(--color-text-muted);
1341  font-style: italic;
1342  margin-top: 0.5em;
1343  line-height: 1.4;
1344}
1345
1346figcaption strong {
1347  font-style: normal;
1348  color: var(--color-text);
1349}
1350
1351/* Full-width figure — breaks out of content column */
1352figure.fullwidth {
1353  max-width: calc(var(--content-width) + var(--margin-note-width) + 2rem);
1354  width: 100%;
1355}
1356
1357figure.fullwidth img {
1358  width: 100%;
1359}
1360
1361/* Margin figure — Tufte-style, floats in the right margin */
1362figure.margin {
1363  float: right;
1364  clear: right;
1365  margin-right: calc(-1 * var(--margin-note-width) - 2rem);
1366  width: var(--margin-note-width);
1367  margin-top: 0;
1368  margin-bottom: 1lh;
1369  margin-bottom: var(--lh);
1370}
1371
1372figure.margin img {
1373  width: 100%;
1374}
1375
1376figure.margin figcaption {
1377  font-size: 0.75rem;
1378}
1379
1380@media (max-width: 900px) {
1381  figure.margin {
1382    float: none;
1383    width: 100%;
1384    margin-right: 0;
1385    margin: 1lh 0;
1386    margin: var(--lh) 0;
1387  }
1388}
1389
1390/* Bordered figure — subtle frame */
1391figure.bordered img {
1392  border: 1px solid var(--color-border);
1393  padding: 0.5em;
1394  background: var(--color-bg-card);
1395  border-radius: 6px;
1396}
1397
1398/* Figure grid — side by side images */
1399.figure-grid {
1400  display: grid;
1401  gap: 1em;
1402  margin: 1.5lh 0;
1403  margin: calc(var(--lh) * 1.5) 0;
1404}
1405
1406.figure-grid.cols-2 {
1407  grid-template-columns: 1fr 1fr;
1408}
1409
1410.figure-grid.cols-3 {
1411  grid-template-columns: 1fr 1fr 1fr;
1412}
1413
1414@media (max-width: 600px) {
1415  .figure-grid.cols-2,
1416  .figure-grid.cols-3 {
1417    grid-template-columns: 1fr;
1418  }
1419}
1420
1421.figure-grid figure {
1422  margin: 0;
1423}
1424
1425/* Screenshot — drop shadow, slight rounding */
1426figure.screenshot img {
1427  border-radius: 8px;
1428  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12),
1429              0 1px 4px rgba(0, 0, 0, 0.08);
1430}
1431
1432[data-theme="dark"] figure.screenshot img {
1433  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4),
1434              0 1px 4px rgba(0, 0, 0, 0.2);
1435}
1436
1437/* Inline image in text — small, flows with text */
1438img.inline {
1439  display: inline;
1440  height: 1.2em;
1441  width: auto;
1442  vertical-align: text-bottom;
1443  margin: 0 0.1em;
1444}
1445
1446/* --- Color Palette Demo --- */
1447
1448.palette {
1449  display: flex;
1450  gap: 0.5em;
1451  flex-wrap: wrap;
1452  margin-bottom: 1lh;
1453  margin-bottom: var(--lh);
1454}
1455
1456.swatch {
1457  width: 3em;
1458  height: 3em;
1459  border-radius: 6px;
1460  border: 1px solid var(--color-border);
1461  display: flex;
1462  align-items: flex-end;
1463  padding: 0.2em;
1464  font-family: var(--font-mono);
1465  font-size: 0.5rem;
1466  color: #fff;
1467  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
1468}
1469
1470/* --- Accent Picker --- */
1471
1472.accent-picker {
1473  margin-bottom: 1lh;
1474  margin-bottom: var(--lh);
1475}
1476
1477.accent-group {
1478  margin-bottom: 0.8em;
1479}
1480
1481.accent-group-label {
1482  font-family: var(--font-heading);
1483  font-size: 0.72rem;
1484  font-weight: 600;
1485  text-transform: uppercase;
1486  letter-spacing: 0.06em;
1487  color: var(--color-text-faint);
1488  margin-bottom: 0.3em;
1489}
1490
1491.accent-group .palette {
1492  margin-bottom: 0.3em;
1493}
1494
1495.accent-swatch {
1496  width: 2.4em;
1497  height: 2.4em;
1498  border-radius: 8px;
1499  border: 2px solid transparent;
1500  cursor: pointer;
1501  transition: all 0.2s ease;
1502  position: relative;
1503  font-size: 0;
1504  /* color set via inline style, overridden by JS on theme change */
1505}
1506
1507.accent-swatch:hover {
1508  transform: scale(1.15);
1509  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
1510}
1511
1512.accent-swatch.active {
1513  border-color: var(--color-text);
1514  transform: scale(1.1);
1515  box-shadow: 0 0 0 2px var(--color-bg), 0 0 0 4px var(--color-text);
1516}
1517
1518.accent-current {
1519  font-family: var(--font-mono);
1520  font-size: 0.82rem;
1521  color: var(--color-text-muted);
1522  margin-top: 0.5em;
1523}
1524
1525.accent-current span {
1526  color: var(--color-accent);
1527  font-weight: 600;
1528}
1529
1530/* --- Utility classes (avoid inline styles for CSP) --- */
1531
1532.nav-toc {
1533  font-family: var(--font-heading);
1534  font-size: 0.85rem;
1535  margin-bottom: calc(var(--lh) * 2);
1536}
1537
1538.text-base { font-size: 1rem; }
1539.text-sm { font-size: 0.85rem; }
1540.text-italic { font-style: italic; }
1541.text-bold { font-weight: bold; }
1542.text-semibold { font-weight: 600; }
1543.mt-sm { margin-top: 0.3em; }
1544
1545.specimen-headings {
1546  background: transparent;
1547  padding: 0;
1548}
1549.specimen-headings h1,
1550.specimen-headings h2,
1551.specimen-headings h3 {
1552  margin: 0.3em 0;
1553}
1554.specimen-headings h1 { margin: 0; }
1555
1556/* Link style demos */
1557a.link-thick { text-decoration-thickness: 2px; }
1558a.link-offset { text-underline-offset: 0.3em; }
1559a.link-accent { text-decoration-color: var(--color-accent); }
1560a.link-dotted { text-decoration-style: dotted; }
1561
1562/* Tonsky inline highlight pills */
1563.hl-pill {
1564  padding: 0.1em 0.3em;
1565  border-radius: 2px;
1566}
1567.hl-pill-string { background: var(--hl-string-bg); }
1568.hl-pill-comment { background: var(--hl-comment-bg); font-style: italic; }
1569.hl-pill-def { background: var(--hl-def-bg); }
1570.hl-pill-constant { color: var(--hl-constant); }
1571
1572/* Stream card compact variant (for grouped entries) */
1573.stream-card-compact {
1574  padding: 0.8em 1.2em;
1575}
1576.stream-card-compact .card-date {
1577  margin-bottom: 0.6em;
1578}
1579
1580/* Color palette demo swatches — colors set by JS */
1581.swatch {
1582  /* background set via data-bg attribute + JS */
1583}
1584
1585/* --- Typography Specimen --- */
1586
1587.specimen {
1588  padding: 1.2em;
1589  background: var(--color-bg-alt);
1590  border-radius: 8px;
1591  margin-bottom: 1lh;
1592  margin-bottom: var(--lh);
1593}
1594
1595.specimen .label {
1596  font-family: var(--font-mono);
1597  font-size: 0.7rem;
1598  color: var(--color-text-faint);
1599  margin-bottom: 0.3em;
1600}
1601
1602.specimen-serif {
1603  font-family: var(--font-body);
1604}
1605.specimen-sans {
1606  font-family: var(--font-heading);
1607}
1608.specimen-mono {
1609  font-family: var(--font-mono);
1610}
1611
1612/* Marker candidates for comparison (sandbox only) */
1613ul.marker-endash      { list-style-type: "– "; }
1614ul.marker-hyphen      { list-style-type: "⁃ "; }
1615ul.marker-hedera      { list-style-type: "❧ "; }
1616ul.marker-reference   { list-style-type: "※ "; }