| @@ -6,7 +6,7 @@ |
| 6 | <meta name="viewport" content="width=device-width, initial-scale=1"> | 6 | <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 7 | <title>Glean</title> | 7 | <title>Glean</title> |
| 8 | <script> | 8 | <script> |
| 9 | - (function(){var t=localStorage.getItem('theme')||'dark';document.documentElement.setAttribute('data-theme',t)})(); | 9 | + (function(){var p=localStorage.getItem('theme')||'system';var r=p==='system'?(window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light'):p;document.documentElement.setAttribute('data-theme',r)})(); |
| 10 | </script> | 10 | </script> |
| 11 | <link rel="stylesheet" href="/static/output.css"> | 11 | <link rel="stylesheet" href="/static/output.css"> |
| 12 | <script src="https://unpkg.com/htmx.org@2"></script> | 12 | <script src="https://unpkg.com/htmx.org@2"></script> |
| @@ -37,14 +37,14 @@ |
| 37 | <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> | 37 | <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> |
| 38 | </head> | 38 | </head> |
| 39 | <body class="bg-spot-bg text-spot-text min-h-screen flex"> | 39 | <body class="bg-spot-bg text-spot-text min-h-screen flex"> |
| 40 | - <dialog id="confirm-dialog" class="bg-spot-surface rounded-xl p-6 max-w-sm shadow-lg border border-spot-divider backdrop:bg-black/50" style="color-scheme:dark" onclick="if(event.target===this)this.close()"> | 40 | + <dialog id="confirm-dialog" class="bg-spot-surface rounded-xl p-6 max-w-sm shadow-lg border border-spot-divider backdrop:bg-black/50" onclick="if(event.target===this)this.close()"> |
| 41 | <p id="confirm-dialog-msg" class="text-spot-text text-sm mb-6"></p> | 41 | <p id="confirm-dialog-msg" class="text-spot-text text-sm mb-6"></p> |
| 42 | <div class="flex justify-end gap-3"> | 42 | <div class="flex justify-end gap-3"> |
| 43 | <button onclick="document.getElementById('confirm-dialog').close(false)" class="text-sm text-spot-secondary hover:text-spot-text px-4 py-2 rounded-pill border border-spot-outline transition">Cancel</button> | 43 | <button onclick="document.getElementById('confirm-dialog').close(false)" class="text-sm text-spot-secondary hover:text-spot-text px-4 py-2 rounded-pill border border-spot-outline transition">Cancel</button> |
| 44 | <button id="confirm-dialog-ok" class="text-sm text-white bg-spot-red hover:brightness-110 px-4 py-2 rounded-pill font-bold uppercase tracking-button transition">Confirm</button> | 44 | <button id="confirm-dialog-ok" class="text-sm text-white bg-spot-red hover:brightness-110 px-4 py-2 rounded-pill font-bold uppercase tracking-button transition">Confirm</button> |
| 45 | </div> | 45 | </div> |
| 46 | </dialog> | 46 | </dialog> |
| 47 | - <dialog id="shortcuts-dialog" class="bg-spot-surface rounded-xl p-6 max-w-xs shadow-lg border border-spot-divider backdrop:bg-black/50" style="color-scheme:dark" onclick="if(event.target===this)this.close()"> | 47 | + <dialog id="shortcuts-dialog" class="bg-spot-surface rounded-xl p-6 max-w-xs shadow-lg border border-spot-divider backdrop:bg-black/50" onclick="if(event.target===this)this.close()"> |
| 48 | <h3 class="text-sm font-bold text-spot-text uppercase tracking-wide mb-4">Keyboard shortcuts</h3> | 48 | <h3 class="text-sm font-bold text-spot-text uppercase tracking-wide mb-4">Keyboard shortcuts</h3> |
| 49 | <div class="space-y-2 text-sm"> | 49 | <div class="space-y-2 text-sm"> |
| 50 | <div class="text-spot-secondary font-bold text-xs uppercase tracking-wide">Navigation</div> | 50 | <div class="text-spot-secondary font-bold text-xs uppercase tracking-wide">Navigation</div> |
| @@ -193,8 +193,10 @@ |
| 193 | <button onclick="toggleTheme()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left"> | 193 | <button onclick="toggleTheme()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left"> |
| 194 | <svg class="w-3.5 h-3.5 shrink-0 theme-icon-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg> | 194 | <svg class="w-3.5 h-3.5 shrink-0 theme-icon-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg> |
| 195 | <svg class="w-3.5 h-3.5 shrink-0 theme-icon-light hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg> | 195 | <svg class="w-3.5 h-3.5 shrink-0 theme-icon-light hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg> |
| 196 | - <span class="theme-text-dark">Light mode</span> | 196 | + <svg class="w-3.5 h-3.5 shrink-0 theme-icon-system hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25A2.25 2.25 0 0 1 5.25 3h13.5A2.25 2.25 0 0 1 21 5.25Z"/></svg> |
| 197 | - <span class="theme-text-light hidden">Dark mode</span> | 197 | + <span class="theme-text-dark">Dark</span> |
| | 198 | + <span class="theme-text-light hidden">Light</span> |
| | 199 | + <span class="theme-text-system hidden">System</span> |
| 198 | </button> | 200 | </button> |
| 199 | <button onclick="document.getElementById('shortcuts-dialog').showModal()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left"> | 201 | <button onclick="document.getElementById('shortcuts-dialog').showModal()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left"> |
| 200 | <svg class="w-3.5 h-3.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0 0 21 18V6a2.25 2.25 0 0 0-2.25-2.25H5.25A2.25 2.25 0 0 0 3 6v12a2.25 2.25 0 0 0 2.25 2.25Z"/></svg> | 202 | <svg class="w-3.5 h-3.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0 0 21 18V6a2.25 2.25 0 0 0-2.25-2.25H5.25A2.25 2.25 0 0 0 3 6v12a2.25 2.25 0 0 0 2.25 2.25Z"/></svg> |
| @@ -228,8 +230,10 @@ |
| 228 | <button onclick="toggleTheme()" class="text-xs text-spot-secondary hover:text-spot-text inline-flex gap-1.5 items-center transition"> | 230 | <button onclick="toggleTheme()" class="text-xs text-spot-secondary hover:text-spot-text inline-flex gap-1.5 items-center transition"> |
| 229 | <svg class="w-3.5 h-3.5 theme-icon-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg> | 231 | <svg class="w-3.5 h-3.5 theme-icon-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg> |
| 230 | <svg class="w-3.5 h-3.5 theme-icon-light hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg> | 232 | <svg class="w-3.5 h-3.5 theme-icon-light hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg> |
| 231 | - <span class="theme-text-dark">Light mode</span> | 233 | + <svg class="w-3.5 h-3.5 theme-icon-system hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25A2.25 2.25 0 0 1 5.25 3h13.5A2.25 2.25 0 0 1 21 5.25Z"/></svg> |
| 232 | - <span class="theme-text-light hidden">Dark mode</span> | 234 | + <span class="theme-text-dark">Dark</span> |
| | 235 | + <span class="theme-text-light hidden">Light</span> |
| | 236 | + <span class="theme-text-system hidden">System</span> |
| 233 | </button> | 237 | </button> |
| 234 | </div> | 238 | </div> |
| 235 | <span class="text-xs text-spot-secondary">© {{now.Format "2006"}} <a href="https://bsky.app/profile/julien.rbrt.fr">julien.rbrt.fr</a> · Made in Europe 🇪🇺</span> | 239 | <span class="text-xs text-spot-secondary">© {{now.Format "2006"}} <a href="https://bsky.app/profile/julien.rbrt.fr">julien.rbrt.fr</a> · Made in Europe 🇪🇺</span> |
| @@ -241,28 +245,35 @@ |
| 241 | </main> | 245 | </main> |
| 242 | | 246 | |
| 243 | <script> | 247 | <script> |
| 244 | - function toggleTheme() { | 248 | + var themePref = localStorage.getItem('theme') || 'system'; |
| 245 | - var current = document.documentElement.getAttribute('data-theme'); | 249 | + var modes = ['dark', 'light', 'system']; |
| 246 | - var next = current === 'dark' ? 'light' : 'dark'; | 250 | + |
| 247 | - document.documentElement.setAttribute('data-theme', next); | 251 | + function resolveTheme(pref) { |
| 248 | - localStorage.setItem('theme', next); | 252 | + return pref === 'system' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : pref; |
| 249 | - updateThemeIcons(next); | | |
| 250 | } | 253 | } |
| 251 | - function updateThemeIcons(theme) { | 254 | + |
| 252 | - document.querySelectorAll('.theme-icon-dark').forEach(function(el) { | 255 | + function applyTheme() { |
| 253 | - el.classList.toggle('hidden', theme === 'light'); | 256 | + document.documentElement.setAttribute('data-theme', resolveTheme(themePref)); |
| 254 | - }); | 257 | + var next = modes[(modes.indexOf(themePref) + 1) % 3]; |
| 255 | - document.querySelectorAll('.theme-icon-light').forEach(function(el) { | 258 | + modes.forEach(function(m) { |
| 256 | - el.classList.toggle('hidden', theme === 'dark'); | 259 | + var show = m === next; |
| 257 | - }); | 260 | + document.querySelectorAll('.theme-icon-' + m + ', .theme-text-' + m).forEach(function(el) { |
| 258 | - document.querySelectorAll('.theme-text-dark').forEach(function(el) { | 261 | + el.classList.toggle('hidden', !show); |
| 259 | - el.classList.toggle('hidden', theme === 'light'); | 262 | + }); |
| 260 | - }); | | |
| 261 | - document.querySelectorAll('.theme-text-light').forEach(function(el) { | | |
| 262 | - el.classList.toggle('hidden', theme === 'dark'); | | |
| 263 | }); | 263 | }); |
| 264 | } | 264 | } |
| 265 | - updateThemeIcons(document.documentElement.getAttribute('data-theme') || 'dark'); | 265 | + |
| | 266 | + function toggleTheme() { |
| | 267 | + themePref = modes[(modes.indexOf(themePref) + 1) % 3]; |
| | 268 | + localStorage.setItem('theme', themePref); |
| | 269 | + applyTheme(); |
| | 270 | + } |
| | 271 | + |
| | 272 | + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() { |
| | 273 | + if (themePref === 'system') applyTheme(); |
| | 274 | + }); |
| | 275 | + |
| | 276 | + applyTheme(); |
| 266 | | 277 | |
| 267 | function closeAnnotate(el) { | 278 | function closeAnnotate(el) { |
| 268 | var form = el.closest('.annotate-form'); | 279 | var form = el.closest('.annotate-form'); |