fix ios toolbar tint not following theme changes; round pantry corners on mobile too
Hunter
Sunday, August 2nd, 2026 at 8:14 PM
-/* Registered so theme swaps can be transitioned — plain custom properties don't animate.
- Everything downstream (borders, color-mix, scrollbars) follows for free. */
-@property --desk {
- syntax: '<color>';
- inherits: true;
- initial-value: #7a8520;
-}
-
1 @property --page {
2 syntax: '<color>';
3 inherits: true;
92 --marquee-fade: 75ms;
93 --page-radius: 0px;
94 transition:
- --desk var(--theme-transition),
95 --page var(--theme-transition),
96 --grid-line var(--theme-transition),
97 --accent var(--theme-transition);
98 }
99
-@media (prefers-reduced-motion: reduce) {
- :root,
- .page.theming {
- transition: none;
- }
100 +:root.no-theme-transition,
101 +:root.no-theme-transition body {
102 + transition: none;
103 }
104
105 /* Theme definitions */
168 }
169
170 body {
- background: var(--desk);
171 + background-color: var(--desk);
172 display: flex;
173 justify-content: center;
174 align-items: flex-start;
175 align-items: safe center;
176 min-height: 100vh;
177 padding: 20px;
178 + transition: background-color var(--theme-transition);
179 }
180
181 .page {
194 transition: border-radius var(--theme-transition);
195 }
196
197 +@media (prefers-reduced-motion: reduce) {
198 + :root,
199 + :root body,
200 + .page.theming {
201 + transition: none;
202 + }
203 +}
204 +
205 .grid {
206 /* Grid dimensions as percentage of page to scale responsively */
207 width: var(--grid-width-percent);
264
265 .page {
266 box-shadow: none;
- border-radius: 0;
267 }
268
269 .grid-cell {
509 overscroll-behavior: none;
510 }
511
- /* Only fix position in portrait mode to prevent scroll issues in landscape */
512 @media (orientation: portrait) {
513 html, body {
514 height: 100%;
- position: fixed;
515 width: 100%;
516 + overflow: hidden;
517 }
518 }
519
5 const DEFAULT_THEME = 'guac';
6 const DEFAULT_DARK_THEME = 'pantry';
7 const THEME_TRANSITION_MS = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--theme-transition'));
-let pageTransitionTimer = null;
8 +let themeTransitionTimer = null;
9
10 function syncThemeColorMeta() {
11 const backgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--desk').trim();
17 syncThemeColorMeta();
18 }
19
-document.documentElement.addEventListener('transitionend', (e) => {
- if (e.propertyName === '--desk') {
- syncThemeColorMeta();
- }
-});
-
-// Only do border-radius transition on page when changing themes
-function withPageTransition() {
20 +function armPageRadiusTransition() {
21 const page = document.querySelector('.page');
22 if (!page) return;
23
24 page.classList.add('theming');
- clearTimeout(pageTransitionTimer);
- pageTransitionTimer = setTimeout(() => page.classList.remove('theming'), THEME_TRANSITION_MS + 50);
25 + clearTimeout(themeTransitionTimer);
26 + themeTransitionTimer = setTimeout(() => page.classList.remove('theming'), THEME_TRANSITION_MS + 50);
27 }
28
29 function cycleTheme(step = 1) {
30 currentThemeIndex = (currentThemeIndex + step + themes.length) % themes.length;
31 const newTheme = themes[currentThemeIndex];
- withPageTransition();
32 + armPageRadiusTransition();
33 setTheme(newTheme);
34 saveThemeToLocalStorage(newTheme);
35 }
40
41 function loadThemeFromLocalStorage() {
42 const savedTheme = localStorage.getItem('memori-theme');
- if (savedTheme && themes.includes(savedTheme)) {
- currentThemeIndex = themes.indexOf(savedTheme);
- setTheme(savedTheme);
- } else {
- const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
- const theme = prefersDark ? DEFAULT_DARK_THEME : DEFAULT_THEME;
- currentThemeIndex = themes.indexOf(theme);
- setTheme(theme);
- }
43 + const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
44 + const theme = (savedTheme && themes.includes(savedTheme))
45 + ? savedTheme
46 + : (prefersDark ? DEFAULT_DARK_THEME : DEFAULT_THEME);
47 +
48 + currentThemeIndex = themes.indexOf(theme);
49 +
50 + // the document opens on the default theme, so the first swap needs to land unanimated
51 + document.documentElement.classList.add('no-theme-transition');
52 + setTheme(theme);
53 + document.documentElement.offsetWidth; // flush the change before transitions come back
54 + document.documentElement.classList.remove('no-theme-transition');
55 }
56
57 // F2 cycles themes, shift+F2 cycles backwards