| 1 | /* ============================================================ |
| 2 | Alchemy Design System — Colors & Type |
| 3 | Sunny-forest palette: warm cream parchment, muted moss green, |
| 4 | terracotta accents, walnut browns. Light mode, earthy, calm. |
| 5 | ============================================================ */ |
| 6 | |
| 7 | @import "@fontsource-variable/inter"; |
| 8 | @import "@fontsource-variable/source-serif-4/opsz.css"; |
| 9 | @import "@fontsource-variable/source-serif-4/opsz-italic.css"; |
| 10 | @import "@fontsource-variable/jetbrains-mono"; |
| 11 | @import "@fontsource-variable/caveat"; |
| 12 | |
| 13 | :root { |
| 14 | /* ---------- Brand: muted forest greens ---------- */ |
| 15 | --alc-accent: #5c7a3e; /* moss — primary brand */ |
| 16 | --alc-accent-deep: #38511f; /* deep forest — pressed/emphasis (AAA ≥7:1 on parchment) */ |
| 17 | --alc-accent-warm: #7a9a5e; /* sage — lighter, sunny */ |
| 18 | --alc-accent-bright: #8fb15e; /* lit leaves — accents on cream */ |
| 19 | /* Translucent so surfaces using `accent-soft` (hero CTA cards, asides, |
| 20 | selection) let the underlying texture show through — same approach |
| 21 | as the dark-mode token below. */ |
| 22 | --alc-accent-soft: color-mix(in srgb, #5c7a3e 18%, transparent); |
| 23 | --alc-accent-60: color-mix(in srgb, #5c7a3e 60%, transparent); |
| 24 | --alc-accent-40: color-mix(in srgb, #5c7a3e 40%, transparent); |
| 25 | --alc-accent-12: color-mix(in srgb, #5c7a3e 12%, transparent); |
| 26 | |
| 27 | /* Bindu (yantra centroid dot). Kept in sync with YANTRA_THEMES in |
| 28 | src/brand/yantra.ts, which paints the generated favicons and app icons. */ |
| 29 | --alc-yantra-dot: #9a4f27; |
| 30 | |
| 31 | /* ---------- Secondary: warm terracotta ---------- */ |
| 32 | --alc-terracotta: #c56e3c; |
| 33 | --alc-terracotta-deep: #9a4f27; |
| 34 | --alc-terracotta-soft: color-mix(in srgb, #c56e3c 18%, transparent); |
| 35 | |
| 36 | /* ---------- Surfaces (warm cream / parchment) ---------- */ |
| 37 | --alc-bg: #f5efe3; /* page — parchment */ |
| 38 | --alc-bg-nav: #efe7d6; /* nav, sidebar — a touch deeper */ |
| 39 | --alc-bg-elev-1: #fbf6ea; /* cards, panels — lifted, paper */ |
| 40 | --alc-bg-elev-2: #fffaf0; /* hover / nested */ |
| 41 | --alc-bg-code: #2a2620; /* terminal / code blocks — walnut */ |
| 42 | --alc-bg-sunk: #ebe3d0; /* insets */ |
| 43 | |
| 44 | /* ---------- Neutrals (warm walnut scale) ---------- */ |
| 45 | --alc-walnut-50: #faf6ec; |
| 46 | --alc-walnut-100: #f1ead8; |
| 47 | --alc-walnut-200: #e2d7bc; |
| 48 | --alc-walnut-300: #c7b795; |
| 49 | --alc-walnut-400: #a89572; |
| 50 | --alc-walnut-500: #85714f; |
| 51 | --alc-walnut-600: #68573c; |
| 52 | --alc-walnut-700: #4e402c; |
| 53 | --alc-walnut-800: #363022; |
| 54 | --alc-walnut-900: #2a2620; |
| 55 | --alc-walnut-950: #1a1813; |
| 56 | |
| 57 | /* ---------- Text ---------- */ |
| 58 | --alc-fg-1: #2a2620; /* primary — walnut */ |
| 59 | --alc-fg-2: #4e402c; /* body — deep tan */ |
| 60 | --alc-fg-3: #52442e; /* muted — dark mushroom (AAA ≥7:1 incl. footer bg) */ |
| 61 | --alc-fg-4: #564733; /* tertiary / captions (AAA ≥7:1 incl. footer bg) */ |
| 62 | --alc-fg-invert: #fbf6ea; /* on dark (code/term) */ |
| 63 | --alc-fg-on-accent: #fbf6ea; /* on moss */ |
| 64 | |
| 65 | /* ---------- Hairlines / borders ---------- */ |
| 66 | --alc-hairline: rgba(42, 38, 32, 0.08); |
| 67 | --alc-hairline-2: rgba(42, 38, 32, 0.14); |
| 68 | --alc-hairline-3: rgba(42, 38, 32, 0.22); |
| 69 | |
| 70 | /* ---------- Semantic (status) — earthy ---------- */ |
| 71 | --alc-success: #5c7a3e; /* plan: create — moss */ |
| 72 | --alc-warn: #d49a2a; /* plan: update — honey */ |
| 73 | --alc-danger: #b3462e; /* plan: replace / destroy — brick */ |
| 74 | --alc-info: #4a7a8a; /* info — slate teal */ |
| 75 | --alc-muted: #a89572; /* dim text */ |
| 76 | |
| 77 | /* ---------- Syntax (on walnut bg, SUNRISE — bright & distinct) ---------- */ |
| 78 | --alc-code-keyword: #d4f26a; /* electric spring green — keywords, export, const */ |
| 79 | --alc-code-string: #ffe38a; /* bright honey — strings */ |
| 80 | --alc-code-fn: #ffb968; /* sunrise amber — function calls */ |
| 81 | --alc-code-type: #7ddfff; /* sky cyan — types */ |
| 82 | --alc-code-comment: #b3a27a; /* bright readable tan */ |
| 83 | --alc-code-var: #faf5e3; /* near-white parchment — identifiers */ |
| 84 | --alc-code-literal: #ff9a6b; /* coral sunrise — numbers/literals */ |
| 85 | |
| 86 | /* ---------- Type ---------- */ |
| 87 | --alc-font-sans: |
| 88 | "Inter Variable", ui-sans-serif, system-ui, -apple-system, "Segoe UI", |
| 89 | sans-serif; |
| 90 | --alc-font-serif: |
| 91 | "Source Serif 4 Variable", "Source Serif Pro", Georgia, "Times New Roman", |
| 92 | serif; |
| 93 | --alc-font-mono: |
| 94 | "JetBrains Mono Variable", ui-monospace, SFMono-Regular, Menlo, monospace; |
| 95 | --alc-font-hand: |
| 96 | "Caveat Variable", "Comic Sans MS", cursive; /* hand-drawn diagram labels */ |
| 97 | |
| 98 | /* ---------- Radius ---------- */ |
| 99 | --alc-radius-xs: 2px; |
| 100 | --alc-radius-sm: 4px; |
| 101 | --alc-radius: 8px; |
| 102 | --alc-radius-md: 10px; |
| 103 | --alc-radius-lg: 12px; |
| 104 | --alc-radius-xl: 16px; |
| 105 | |
| 106 | /* ---------- Spacing (4px grid) ---------- */ |
| 107 | --alc-space-1: 4px; |
| 108 | --alc-space-2: 8px; |
| 109 | --alc-space-3: 12px; |
| 110 | --alc-space-4: 16px; |
| 111 | --alc-space-5: 24px; |
| 112 | --alc-space-6: 32px; |
| 113 | --alc-space-7: 48px; |
| 114 | --alc-space-8: 64px; |
| 115 | --alc-space-9: 96px; |
| 116 | |
| 117 | /* ---------- Shadows (warm, soft) ---------- */ |
| 118 | --alc-shadow-sm: 0 1px 2px rgba(78, 64, 44, 0.08); |
| 119 | --alc-shadow: 0 4px 14px rgba(78, 64, 44, 0.1); |
| 120 | --alc-shadow-lg: 0 20px 40px rgba(78, 64, 44, 0.14); |
| 121 | --alc-glow: |
| 122 | 0 0 0 1px var(--alc-accent-40), 0 0 24px -4px var(--alc-accent-40); |
| 123 | |
| 124 | /* ---------- Motion ---------- */ |
| 125 | --alc-ease: cubic-bezier(0.2, 0, 0, 1); |
| 126 | --alc-dur-fast: 120ms; |
| 127 | --alc-dur: 180ms; |
| 128 | --alc-dur-slow: 320ms; |
| 129 | } |
| 130 | |
| 131 | /* ============================================================ |
| 132 | Dark mode — "night forest, walnut interior". |
| 133 | Same warm/earthy logic as light, inverted around the walnut |
| 134 | scale. The page joins the dark code-block surface; cream |
| 135 | becomes the text scale; moss & terracotta lift one step so |
| 136 | they read on dark. |
| 137 | ============================================================ */ |
| 138 | |
| 139 | [data-theme="dark"] { |
| 140 | /* Brand: lifted moss for emphasis on dark walnut */ |
| 141 | --alc-accent: #7a9a5e; |
| 142 | --alc-accent-deep: #a3c473; /* emphasis / text-accent — lifted, not darkened */ |
| 143 | --alc-accent-warm: #8fb15e; |
| 144 | --alc-accent-bright: #b3d188; |
| 145 | --alc-accent-soft: color-mix(in srgb, #7a9a5e 22%, transparent); |
| 146 | --alc-accent-60: color-mix(in srgb, #a3c473 60%, transparent); |
| 147 | --alc-accent-40: color-mix(in srgb, #a3c473 40%, transparent); |
| 148 | --alc-accent-12: color-mix(in srgb, #a3c473 18%, transparent); |
| 149 | |
| 150 | /* Bindu, lifted for the dark page. */ |
| 151 | --alc-yantra-dot: #d8835a; |
| 152 | |
| 153 | /* Secondary: warm terracotta — lifted */ |
| 154 | --alc-terracotta: #d8835a; |
| 155 | --alc-terracotta-deep: #e89a72; |
| 156 | --alc-terracotta-soft: color-mix(in srgb, #d8835a 20%, transparent); |
| 157 | |
| 158 | /* Surfaces — page joins the code-block aesthetic. In dark mode the |
| 159 | code surface LIFTS above the page (vs. light mode where it sinks), |
| 160 | so terminal/code chrome still reads as a distinct card on the page. */ |
| 161 | --alc-bg: #14110d; |
| 162 | --alc-bg-nav: #1a1613; |
| 163 | --alc-bg-elev-1: #221e18; |
| 164 | --alc-bg-elev-2: #2a2620; |
| 165 | --alc-bg-code: #2a2620; /* same as light-mode code surface — chrome/syntax tuning carries over */ |
| 166 | --alc-bg-sunk: #100c08; |
| 167 | |
| 168 | /* Text — cream scale */ |
| 169 | --alc-fg-1: #faf6ec; /* primary — parchment */ |
| 170 | --alc-fg-2: #e2d7bc; /* body — washed parchment */ |
| 171 | --alc-fg-3: #c0af89; /* muted — lifted walnut (AAA ≥7:1 on elevated cards) */ |
| 172 | --alc-fg-4: #b9a881; /* tertiary / captions (AAA ≥7:1 on elevated cards) */ |
| 173 | /* `--alc-fg-invert` is text on the dark code surface, which stays dark in |
| 174 | both modes — so this token is the same in light and dark. */ |
| 175 | --alc-fg-invert: #fbf6ea; |
| 176 | --alc-fg-on-accent: #fbf6ea; |
| 177 | |
| 178 | /* Hairlines — cream over walnut */ |
| 179 | --alc-hairline: rgba(250, 246, 236, 0.08); |
| 180 | --alc-hairline-2: rgba(250, 246, 236, 0.14); |
| 181 | --alc-hairline-3: rgba(250, 246, 236, 0.22); |
| 182 | |
| 183 | /* Semantic — lifted on dark for AA contrast */ |
| 184 | --alc-success: #8fb15e; |
| 185 | --alc-warn: #e8b04a; |
| 186 | --alc-danger: #d76a4e; |
| 187 | --alc-info: #6da4b4; |
| 188 | --alc-muted: #85714f; |
| 189 | |
| 190 | /* Shadows — heavier black, less warmth shows through */ |
| 191 | --alc-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4); |
| 192 | --alc-shadow: 0 4px 14px rgba(0, 0, 0, 0.5); |
| 193 | --alc-shadow-lg: 0 20px 40px rgba(0, 0, 0, 0.6); |
| 194 | --alc-glow: |
| 195 | 0 0 0 1px var(--alc-accent-40), 0 0 24px -4px var(--alc-accent-40); |
| 196 | } |
| 197 | |
| 198 | /* ============================================================ |
| 199 | Semantic text styles |
| 200 | ============================================================ */ |
| 201 | |
| 202 | .alc-display { |
| 203 | font-family: var(--alc-font-serif); |
| 204 | font-size: 76px; |
| 205 | line-height: 1.02; |
| 206 | letter-spacing: -0.02em; |
| 207 | font-weight: 500; |
| 208 | color: var(--alc-fg-1); |
| 209 | } |
| 210 | |
| 211 | .alc-h1 { |
| 212 | font-family: var(--alc-font-serif); |
| 213 | font-size: 52px; |
| 214 | line-height: 1.06; |
| 215 | letter-spacing: -0.015em; |
| 216 | font-weight: 500; |
| 217 | color: var(--alc-fg-1); |
| 218 | } |
| 219 | |
| 220 | .alc-h2 { |
| 221 | font-family: var(--alc-font-serif); |
| 222 | font-size: 34px; |
| 223 | line-height: 1.15; |
| 224 | letter-spacing: -0.01em; |
| 225 | font-weight: 500; |
| 226 | color: var(--alc-fg-1); |
| 227 | } |
| 228 | |
| 229 | .alc-h3 { |
| 230 | font-family: var(--alc-font-sans); |
| 231 | font-size: 22px; |
| 232 | line-height: 1.25; |
| 233 | letter-spacing: -0.01em; |
| 234 | font-weight: 600; |
| 235 | color: var(--alc-fg-1); |
| 236 | } |
| 237 | |
| 238 | .alc-h4 { |
| 239 | font-family: var(--alc-font-sans); |
| 240 | font-size: 17px; |
| 241 | line-height: 1.35; |
| 242 | font-weight: 600; |
| 243 | color: var(--alc-fg-1); |
| 244 | } |
| 245 | |
| 246 | .alc-eyebrow { |
| 247 | font-family: var(--alc-font-mono); |
| 248 | font-size: 12px; |
| 249 | line-height: 1; |
| 250 | letter-spacing: 0.12em; |
| 251 | text-transform: uppercase; |
| 252 | font-weight: 500; |
| 253 | color: var(--alc-accent-deep); |
| 254 | } |
| 255 | |
| 256 | .alc-body-lg { |
| 257 | font-family: var(--alc-font-sans); |
| 258 | font-size: 18px; |
| 259 | line-height: 1.6; |
| 260 | font-weight: 400; |
| 261 | color: var(--alc-fg-2); |
| 262 | } |
| 263 | |
| 264 | .alc-body { |
| 265 | font-family: var(--alc-font-sans); |
| 266 | font-size: 15px; |
| 267 | line-height: 1.6; |
| 268 | font-weight: 400; |
| 269 | color: var(--alc-fg-2); |
| 270 | } |
| 271 | |
| 272 | .alc-small { |
| 273 | font-family: var(--alc-font-sans); |
| 274 | font-size: 13px; |
| 275 | line-height: 1.5; |
| 276 | color: var(--alc-fg-3); |
| 277 | } |
| 278 | |
| 279 | .alc-caption { |
| 280 | font-family: var(--alc-font-sans); |
| 281 | font-size: 12px; |
| 282 | line-height: 1.4; |
| 283 | color: var(--alc-fg-4); |
| 284 | } |
| 285 | |
| 286 | .alc-code { |
| 287 | font-family: var(--alc-font-mono); |
| 288 | font-size: 14px; |
| 289 | line-height: 1.55; |
| 290 | font-variant-ligatures: none; |
| 291 | color: var(--alc-fg-invert); |
| 292 | } |
| 293 | |
| 294 | .alc-code-inline { |
| 295 | font-family: var(--alc-font-mono); |
| 296 | font-size: 0.9em; |
| 297 | padding: 0.12em 0.38em; |
| 298 | border-radius: var(--alc-radius-sm); |
| 299 | background: var(--alc-bg-sunk); |
| 300 | border: 1px solid var(--alc-hairline); |
| 301 | color: var(--alc-fg-1); |
| 302 | white-space: nowrap; |
| 303 | vertical-align: baseline; |
| 304 | } |
| 305 | |
| 306 | /* In large headings the inline-code pill's padding + border makes the box |
| 307 | taller than the heading's line-height, so it visually clips into adjacent |
| 308 | lines. Shrink it slightly and align to baseline so it sits cleanly. */ |
| 309 | h1 .alc-code-inline, |
| 310 | h2 .alc-code-inline, |
| 311 | h3 .alc-code-inline { |
| 312 | font-size: 0.78em; |
| 313 | padding: 0.08em 0.34em; |
| 314 | vertical-align: 0.04em; |
| 315 | line-height: 1; |
| 316 | } |
| 317 | |
| 318 | .alc-hand { |
| 319 | font-family: var(--alc-font-hand); |
| 320 | font-size: 40px; |
| 321 | line-height: 1; |
| 322 | font-weight: 600; |
| 323 | color: var(--alc-accent-deep); |
| 324 | } |
| 325 | |
| 326 | .alc-text-accent { |
| 327 | color: var(--alc-accent-deep); |
| 328 | font-style: italic; |
| 329 | font-family: var(--alc-font-serif); |
| 330 | font-weight: 500; |
| 331 | } |
| 332 | |
| 333 | /* ============================================================ |
| 334 | Body defaults |
| 335 | ============================================================ */ |
| 336 | |
| 337 | body.alc-root, |
| 338 | .alc-root { |
| 339 | background: var(--alc-bg); |
| 340 | color: var(--alc-fg-2); |
| 341 | font-family: var(--alc-font-sans); |
| 342 | font-size: 15px; |
| 343 | line-height: 1.6; |
| 344 | -webkit-font-smoothing: antialiased; |
| 345 | -moz-osx-font-smoothing: grayscale; |
| 346 | } |
| 347 | |
| 348 | ::selection { |
| 349 | background: var(--alc-accent-soft); |
| 350 | color: var(--alc-fg-1); |
| 351 | } |
| 352 | |
| 353 | /* Code surfaces stay dark walnut in BOTH themes, but the global selection |
| 354 | foreground follows the page (--alc-fg-1 is dark walnut in light mode) — |
| 355 | selecting code text would paint dark-on-dark. Pin selection inside code |
| 356 | surfaces to the dark-surface palette instead. */ |
| 357 | .expressive-code ::selection, |
| 358 | .alc-term ::selection, |
| 359 | .alc-code::selection, |
| 360 | .alc-code ::selection { |
| 361 | background: #5c7a3e66; /* editor.selectionBackground from the walnut EC theme */ |
| 362 | color: var(--alc-code-var); |
| 363 | } |
| 364 | |
| 365 | /* ---------- Reduced motion (site-wide) ---------- |
| 366 | Visitors who ask for less motion get every CSS animation and transition |
| 367 | jumped to its end state (entrance animations land on their final frame, |
| 368 | looping pulses and spinners stop) and instant scrolling. Canvas and |
| 369 | scripted demos check the same media query in JS. */ |
| 370 | @media (prefers-reduced-motion: reduce) { |
| 371 | *, |
| 372 | *::before, |
| 373 | *::after { |
| 374 | animation-duration: 0.01ms !important; |
| 375 | animation-delay: 0s !important; |
| 376 | animation-iteration-count: 1 !important; |
| 377 | transition-duration: 0.01ms !important; |
| 378 | transition-delay: 0s !important; |
| 379 | } |
| 380 | html, |
| 381 | * { |
| 382 | scroll-behavior: auto !important; |
| 383 | } |
| 384 | } |