79 lines (70 loc) · 2.40 KB
 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}