1@use "sass:map";
2@use "sass:string";
3@use "colors" as c;
4
5// Emit CSS variables from a theme map
6@mixin emit-theme-vars($theme-map) {
7 @each $k, $v in $theme-map {
8 --#{$k}: #{$v};
9 }
10}
11
12// Convenience: read a CSS var in SCSS
13@function theme($key) {
14 @return string.unquote("var(--#{$key})");
15}
16
17// Shared frosted-glass blur (header, mobile menu, photo preview backdrop).
18// Emits the -webkit- prefix too, which Safari still requires.
19@mixin blur-surface($amount: 12px) {
20 -webkit-backdrop-filter: blur($amount);
21 backdrop-filter: blur($amount);
22}
23
24// Site-default underline: dashed, drawn as a background line so it never
25// affects box height (unlike border-bottom / padding).
26@mixin dashed-underline($color: theme(accent), $dash: 3px, $gap: 3px) {
27 background-image: repeating-linear-gradient(to right, $color 0, $color $dash, transparent $dash, transparent #{$dash + $gap});
28 background-position: 0 100%;
29 background-size: 100% 1px;
30 background-repeat: repeat-x;
31}
32
33// Shared "terminal window" look: code blocks, .copy-btn, .skip-link, the
34// home-page banner. 2px border, small radius, card bg.
35@mixin terminal-panel($radius: 2px) {
36 background: theme(card);
37 border: 2px solid theme(border);
38 border-radius: $radius;
39}
40
41// Default theme + prepare UA color-scheme hint
42:root {
43 @include emit-theme-vars(map.get(c.$themes, c.$default-theme));
44 --border-subtle: color-mix(in srgb, var(--border) 40%, transparent);
45 @if c.$default-theme == light {
46 color-scheme: light;
47 } @else {
48 color-scheme: dark;
49 }
50}
51
52// No-JS fallback: without JavaScript the inline head script never sets
53// [data-theme], so honour the OS preference here. JS visitors always have
54// [data-theme] set (higher specificity via :not), which keeps overriding.
55@media (prefers-color-scheme: light) {
56 :root:not([data-theme]) {
57 @include emit-theme-vars(map.get(c.$themes, light));
58 --border-subtle: color-mix(in srgb, var(--border) 40%, transparent);
59 color-scheme: light;
60 }
61}
62
63// Generate [data-theme="name"] blocks for each theme
64@each $name, $map in c.$themes {
65 :root[data-theme="#{$name}"] {
66 @include emit-theme-vars($map);
67 --border-subtle: color-mix(in srgb, var(--border) 40%, transparent);
68 @if $name == light {
69 color-scheme: light;
70 } @else {
71 color-scheme: dark;
72 }
73 }
74}
75
76// Optional: smoother switch
77.theme-transition * {
78 transition: background-color .2s ease, color .2s ease, border-color .2s ease;
79}