nandi/gleanpublic⑂ Fork 0
⑂ 92bdf78
Commits
⬇ Clone ▾
git clone https://git.rickub.com/nandi/glean.git
git clone ssh://git@rickub.com/nandi/glean.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Add squared design support and improve shadowsUnverified

Julien Robert committed 2026-04-28T16:31:33+02:00 Browse files
92bdf78 parent: 2140c8a
modified docs/design.md +7 -4
@@ -10,6 +10,8 @@ Typography uses **Inter** (Google Fonts) as the universal typeface, with tight `
1010
1111 Surfaces breathe through rounded geometry: pill buttons (`9999px`), `12px` card corners, and `50%` circular avatars. Shadows are whisper-soft dual-layers, never heavy. The system feels like a well-lit reading room.
1212
13+All radii are driven by CSS custom properties (`--radius-sm`, `--radius-md`, `--radius-lg`, `--radius-pill`, `--radius-full`) wired through `tailwind.config.js`. A **squared** shape mode is available via `data-shape="squared"` on the root element, which sets all radius variables to `0`. The toggle lives in the footer alongside the theme switcher and persists via `localStorage('shape')`.
14+
1315 **Color-block rhythm (landing page):** Cream/forest hero → white card sections → House Green (`#1E3932`) feature band with white text → cream utility zone → House Green footer.
1416
1517 Logo is a stylized bee: body with horizontal stripes (like text lines on a page), semi-transparent wings that evoke open book pages, round eyes, curved antennae, and a small smile. The bee represents gleaning (collecting nectar/knowledge), social behavior (hives/communities), and reading (the striped body reads like lines of text, wings like turning pages).
@@ -105,10 +107,11 @@ bg-spot-surface rounded-xl p-4 shadow-spot hover:bg-spot-hover-50 transition
105107
106108 ### Shadows
107109
108-| Token | Value | Use |
109-| ------------------- | -------------------------------------------------------- | ------------ |
110-| `shadow-spot` | `0 0 0.5px rgba(0,0,0,0.14), 0 1px 1px rgba(0,0,0,0.24)` | Cards |
111-| `shadow-spot-heavy` | `0 0 6px rgba(0,0,0,0.24), 0 8px 12px rgba(0,0,0,0.14)` | Modals, hero |
110+| Token | Use |
111+| ---------------------- | ------------ |
112+| `shadow-spot` | Cards |
113+| `shadow-spot-heavy` | Modals, hero |
114+| `shadow-spot-elevated` | Dialogs, floating elements |
112115
113116 ### Navigation
114117
@@ -10,6 +10,8 @@ Typography uses **Inter** (Google Fonts) as the universal typeface, with tight `
10 10
11 Surfaces breathe through rounded geometry: pill buttons (`9999px`), `12px` card corners, and `50%` circular avatars. Shadows are whisper-soft dual-layers, never heavy. The system feels like a well-lit reading room.11 Surfaces breathe through rounded geometry: pill buttons (`9999px`), `12px` card corners, and `50%` circular avatars. Shadows are whisper-soft dual-layers, never heavy. The system feels like a well-lit reading room.
12 12
13+All radii are driven by CSS custom properties (`--radius-sm`, `--radius-md`, `--radius-lg`, `--radius-pill`, `--radius-full`) wired through `tailwind.config.js`. A **squared** shape mode is available via `data-shape="squared"` on the root element, which sets all radius variables to `0`. The toggle lives in the footer alongside the theme switcher and persists via `localStorage('shape')`.
14+
13 **Color-block rhythm (landing page):** Cream/forest hero → white card sections → House Green (`#1E3932`) feature band with white text → cream utility zone → House Green footer.15 **Color-block rhythm (landing page):** Cream/forest hero → white card sections → House Green (`#1E3932`) feature band with white text → cream utility zone → House Green footer.
14 16
15 Logo is a stylized bee: body with horizontal stripes (like text lines on a page), semi-transparent wings that evoke open book pages, round eyes, curved antennae, and a small smile. The bee represents gleaning (collecting nectar/knowledge), social behavior (hives/communities), and reading (the striped body reads like lines of text, wings like turning pages).17 Logo is a stylized bee: body with horizontal stripes (like text lines on a page), semi-transparent wings that evoke open book pages, round eyes, curved antennae, and a small smile. The bee represents gleaning (collecting nectar/knowledge), social behavior (hives/communities), and reading (the striped body reads like lines of text, wings like turning pages).
@@ -105,10 +107,11 @@ bg-spot-surface rounded-xl p-4 shadow-spot hover:bg-spot-hover-50 transition
105 107
106 ### Shadows108 ### Shadows
107 109
108-| Token | Value | Use |110+| Token | Use |
109-| ------------------- | -------------------------------------------------------- | ------------ |111+| ---------------------- | ------------ |
110-| `shadow-spot` | `0 0 0.5px rgba(0,0,0,0.14), 0 1px 1px rgba(0,0,0,0.24)` | Cards |112+| `shadow-spot` | Cards |
111-| `shadow-spot-heavy` | `0 0 6px rgba(0,0,0,0.24), 0 8px 12px rgba(0,0,0,0.14)` | Modals, hero |113+| `shadow-spot-heavy` | Modals, hero |
114+| `shadow-spot-elevated` | Dialogs, floating elements |
112 115
113 ### Navigation116 ### Navigation
114 117
modified internal/tmpl/articles.html +3 -3
@@ -56,17 +56,17 @@
5656 </form>
5757 <div class="flex items-center gap-2 shrink-0">
5858 <a href="/articles?status=all{{if .FeedURL}}&feed={{.FeedURL}}{{end}}"
59- class="px-4 py-1.5 rounded-full text-xs font-bold uppercase tracking-button transition
59+ class="px-4 py-1.5 rounded-pill text-xs font-bold uppercase tracking-button transition
6060 {{if eq .Status "all"}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}}">
6161 All
6262 </a>
6363 <a href="/articles?status=unread{{if .FeedURL}}&feed={{.FeedURL}}{{end}}"
64- class="px-4 py-1.5 rounded-full text-xs font-bold uppercase tracking-button transition
64+ class="px-4 py-1.5 rounded-pill text-xs font-bold uppercase tracking-button transition
6565 {{if or (eq .Status "unread") (eq .Status "")}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}}">
6666 Unread
6767 </a>
6868 <a href="/articles?status=read{{if .FeedURL}}&feed={{.FeedURL}}{{end}}"
69- class="px-4 py-1.5 rounded-full text-xs font-bold uppercase tracking-button transition
69+ class="px-4 py-1.5 rounded-pill text-xs font-bold uppercase tracking-button transition
7070 {{if eq .Status "read"}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}}">
7171 Read
7272 </a>
@@ -56,17 +56,17 @@
56 </form>56 </form>
57 <div class="flex items-center gap-2 shrink-0">57 <div class="flex items-center gap-2 shrink-0">
58 <a href="/articles?status=all{{if .FeedURL}}&feed={{.FeedURL}}{{end}}"58 <a href="/articles?status=all{{if .FeedURL}}&feed={{.FeedURL}}{{end}}"
59- class="px-4 py-1.5 rounded-full text-xs font-bold uppercase tracking-button transition59+ class="px-4 py-1.5 rounded-pill text-xs font-bold uppercase tracking-button transition
60 {{if eq .Status "all"}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}}">60 {{if eq .Status "all"}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}}">
61 All61 All
62 </a>62 </a>
63 <a href="/articles?status=unread{{if .FeedURL}}&feed={{.FeedURL}}{{end}}"63 <a href="/articles?status=unread{{if .FeedURL}}&feed={{.FeedURL}}{{end}}"
64- class="px-4 py-1.5 rounded-full text-xs font-bold uppercase tracking-button transition64+ class="px-4 py-1.5 rounded-pill text-xs font-bold uppercase tracking-button transition
65 {{if or (eq .Status "unread") (eq .Status "")}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}}">65 {{if or (eq .Status "unread") (eq .Status "")}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}}">
66 Unread66 Unread
67 </a>67 </a>
68 <a href="/articles?status=read{{if .FeedURL}}&feed={{.FeedURL}}{{end}}"68 <a href="/articles?status=read{{if .FeedURL}}&feed={{.FeedURL}}{{end}}"
69- class="px-4 py-1.5 rounded-full text-xs font-bold uppercase tracking-button transition69+ class="px-4 py-1.5 rounded-pill text-xs font-bold uppercase tracking-button transition
70 {{if eq .Status "read"}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}}">70 {{if eq .Status "read"}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}}">
71 Read71 Read
72 </a>72 </a>
modified internal/tmpl/base.html +35 -3
@@ -6,7 +6,7 @@
66 <meta name="viewport" content="width=device-width, initial-scale=1">
77 <title>Glean</title>
88 <script>
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)})();
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);var s=localStorage.getItem('shape');if(s)document.documentElement.setAttribute('data-shape',s)})();
1010 </script>
1111 <link rel="stylesheet" href="/static/output.css">
1212 <script src="https://unpkg.com/htmx.org@2"></script>
@@ -37,14 +37,14 @@
3737 <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
3838 </head>
3939 <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" onclick="if(event.target===this)this.close()">
40+ <dialog id="confirm-dialog" class="bg-spot-surface rounded-xl p-6 max-w-sm shadow-spot-elevated border border-spot-divider backdrop:bg-black/50" onclick="if(event.target===this)this.close()">
4141 <p id="confirm-dialog-msg" class="text-spot-text text-sm mb-6"></p>
4242 <div class="flex justify-end gap-3">
4343 <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>
4444 <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>
4545 </div>
4646 </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" onclick="if(event.target===this)this.close()">
47+ <dialog id="shortcuts-dialog" class="bg-spot-surface rounded-xl p-6 max-w-xs shadow-spot-elevated border border-spot-divider backdrop:bg-black/50" onclick="if(event.target===this)this.close()">
4848 <h3 class="text-sm font-bold text-spot-text uppercase tracking-wide mb-4">Keyboard shortcuts</h3>
4949 <div class="space-y-2 text-sm">
5050 <div class="text-spot-secondary font-bold text-xs uppercase tracking-wide">Navigation</div>
@@ -198,6 +198,10 @@
198198 <span class="theme-text-light hidden">Light</span>
199199 <span class="theme-text-system hidden">System</span>
200200 </button>
201+ <button onclick="toggleShape()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left">
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="M4 4h16v16H4z"/></svg>
203+ <span class="shape-text">Squared</span>
204+ </button>
201205 <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">
202206 <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>
203207 Keyboard shortcuts
@@ -235,6 +239,10 @@
235239 <span class="theme-text-light hidden">Light</span>
236240 <span class="theme-text-system hidden">System</span>
237241 </button>
242+ <button onclick="toggleShape()" class="text-xs text-spot-secondary hover:text-spot-text inline-flex gap-1.5 items-center transition">
243+ <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4h16v16H4z"/></svg>
244+ <span class="shape-text">Squared</span>
245+ </button>
238246 </div>
239247 <span class="text-xs text-spot-secondary">&copy; {{now.Format "2006"}} <a href="https://bsky.app/profile/julien.rbrt.fr">julien.rbrt.fr</a> &middot; Made in Europe &#127466;&#127482;</span>
240248 </div>
@@ -269,11 +277,35 @@
269277 applyTheme();
270278 }
271279
280+ function applyShape() {
281+ var shapePref = localStorage.getItem('shape') || 'rounded';
282+ if (shapePref === 'squared') {
283+ document.documentElement.setAttribute('data-shape', 'squared');
284+ } else {
285+ document.documentElement.removeAttribute('data-shape');
286+ }
287+ document.querySelectorAll('.shape-text').forEach(function(el) {
288+ el.textContent = shapePref === 'squared' ? 'Rounded' : 'Squared';
289+ });
290+ }
291+
292+ function toggleShape() {
293+ var current = localStorage.getItem('shape') || 'rounded';
294+ var next = current === 'squared' ? 'rounded' : 'squared';
295+ if (next === 'rounded') {
296+ localStorage.removeItem('shape');
297+ } else {
298+ localStorage.setItem('shape', next);
299+ }
300+ applyShape();
301+ }
302+
272303 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {
273304 if (themePref === 'system') applyTheme();
274305 });
275306
276307 applyTheme();
308+ applyShape();
277309
278310 function closeAnnotate(el) {
279311 var form = el.closest('.annotate-form');
@@ -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 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)})();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);var s=localStorage.getItem('shape');if(s)document.documentElement.setAttribute('data-shape',s)})();
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" onclick="if(event.target===this)this.close()">40+ <dialog id="confirm-dialog" class="bg-spot-surface rounded-xl p-6 max-w-sm shadow-spot-elevated 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" onclick="if(event.target===this)this.close()">47+ <dialog id="shortcuts-dialog" class="bg-spot-surface rounded-xl p-6 max-w-xs shadow-spot-elevated 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>
@@ -198,6 +198,10 @@
198 <span class="theme-text-light hidden">Light</span>198 <span class="theme-text-light hidden">Light</span>
199 <span class="theme-text-system hidden">System</span>199 <span class="theme-text-system hidden">System</span>
200 </button>200 </button>
201+ <button onclick="toggleShape()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left">
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="M4 4h16v16H4z"/></svg>
203+ <span class="shape-text">Squared</span>
204+ </button>
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">205 <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">
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>206 <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>
203 Keyboard shortcuts207 Keyboard shortcuts
@@ -235,6 +239,10 @@
235 <span class="theme-text-light hidden">Light</span>239 <span class="theme-text-light hidden">Light</span>
236 <span class="theme-text-system hidden">System</span>240 <span class="theme-text-system hidden">System</span>
237 </button>241 </button>
242+ <button onclick="toggleShape()" class="text-xs text-spot-secondary hover:text-spot-text inline-flex gap-1.5 items-center transition">
243+ <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4h16v16H4z"/></svg>
244+ <span class="shape-text">Squared</span>
245+ </button>
238 </div>246 </div>
239 <span class="text-xs text-spot-secondary">&copy; {{now.Format "2006"}} <a href="https://bsky.app/profile/julien.rbrt.fr">julien.rbrt.fr</a> &middot; Made in Europe &#127466;&#127482;</span>247 <span class="text-xs text-spot-secondary">&copy; {{now.Format "2006"}} <a href="https://bsky.app/profile/julien.rbrt.fr">julien.rbrt.fr</a> &middot; Made in Europe &#127466;&#127482;</span>
240 </div>248 </div>
@@ -269,11 +277,35 @@
269 applyTheme();277 applyTheme();
270 }278 }
271 279
280+ function applyShape() {
281+ var shapePref = localStorage.getItem('shape') || 'rounded';
282+ if (shapePref === 'squared') {
283+ document.documentElement.setAttribute('data-shape', 'squared');
284+ } else {
285+ document.documentElement.removeAttribute('data-shape');
286+ }
287+ document.querySelectorAll('.shape-text').forEach(function(el) {
288+ el.textContent = shapePref === 'squared' ? 'Rounded' : 'Squared';
289+ });
290+ }
291+
292+ function toggleShape() {
293+ var current = localStorage.getItem('shape') || 'rounded';
294+ var next = current === 'squared' ? 'rounded' : 'squared';
295+ if (next === 'rounded') {
296+ localStorage.removeItem('shape');
297+ } else {
298+ localStorage.setItem('shape', next);
299+ }
300+ applyShape();
301+ }
302+
272 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {303 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {
273 if (themePref === 'system') applyTheme();304 if (themePref === 'system') applyTheme();
274 });305 });
275 306
276 applyTheme();307 applyTheme();
308+ applyShape();
277 309
278 function closeAnnotate(el) {310 function closeAnnotate(el) {
279 var form = el.closest('.annotate-form');311 var form = el.closest('.annotate-form');
modified internal/tmpl/feeds.html +2 -2
@@ -35,9 +35,9 @@ function gleanRefreshPoll(){setTimeout(function(){htmx.ajax('GET','/feeds/list',
3535 <div class="lg:col-span-2">
3636 {{if .Categories}}
3737 <div class="flex gap-2 mb-6 flex-wrap">
38- <a href="/feeds" class="text-sm px-4 py-1.5 rounded-full font-bold {{if not .Category}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}} transition">All</a>
38+ <a href="/feeds" class="text-sm px-4 py-1.5 rounded-pill font-bold {{if not .Category}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}} transition">All</a>
3939 {{range .Categories}}
40- <a href="/feeds?category={{.}}" class="text-sm px-4 py-1.5 rounded-full font-bold {{if eq $.Category .}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}} transition">{{.}}</a>
40+ <a href="/feeds?category={{.}}" class="text-sm px-4 py-1.5 rounded-pill font-bold {{if eq $.Category .}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}} transition">{{.}}</a>
4141 {{end}}
4242 </div>
4343 {{end}}
@@ -35,9 +35,9 @@ function gleanRefreshPoll(){setTimeout(function(){htmx.ajax('GET','/feeds/list',
35 <div class="lg:col-span-2">35 <div class="lg:col-span-2">
36 {{if .Categories}}36 {{if .Categories}}
37 <div class="flex gap-2 mb-6 flex-wrap">37 <div class="flex gap-2 mb-6 flex-wrap">
38- <a href="/feeds" class="text-sm px-4 py-1.5 rounded-full font-bold {{if not .Category}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}} transition">All</a>38+ <a href="/feeds" class="text-sm px-4 py-1.5 rounded-pill font-bold {{if not .Category}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}} transition">All</a>
39 {{range .Categories}}39 {{range .Categories}}
40- <a href="/feeds?category={{.}}" class="text-sm px-4 py-1.5 rounded-full font-bold {{if eq $.Category .}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}} transition">{{.}}</a>40+ <a href="/feeds?category={{.}}" class="text-sm px-4 py-1.5 rounded-pill font-bold {{if eq $.Category .}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}} transition">{{.}}</a>
41 {{end}}41 {{end}}
42 </div>42 </div>
43 {{end}}43 {{end}}
modified internal/tmpl/partials/annotation-card.html +1 -1
@@ -16,7 +16,7 @@
1616 {{end}}
1717 {{if .annotation.Tags.Valid}}
1818 <div class="flex gap-1.5 mt-3 flex-wrap">
19- {{range $tag := split .annotation.Tags.String ","}}<span class="text-xs bg-spot-hover text-spot-secondary px-2.5 py-0.5 rounded-full">{{$tag}}</span>{{end}}
19+ {{range $tag := split .annotation.Tags.String ","}}<span class="text-xs bg-spot-hover text-spot-secondary px-2.5 py-0.5 rounded-pill">{{$tag}}</span>{{end}}
2020 </div>
2121 {{end}}
2222 {{if .annotation.Rating.Valid}}
@@ -16,7 +16,7 @@
16 {{end}}16 {{end}}
17 {{if .annotation.Tags.Valid}}17 {{if .annotation.Tags.Valid}}
18 <div class="flex gap-1.5 mt-3 flex-wrap">18 <div class="flex gap-1.5 mt-3 flex-wrap">
19- {{range $tag := split .annotation.Tags.String ","}}<span class="text-xs bg-spot-hover text-spot-secondary px-2.5 py-0.5 rounded-full">{{$tag}}</span>{{end}}19+ {{range $tag := split .annotation.Tags.String ","}}<span class="text-xs bg-spot-hover text-spot-secondary px-2.5 py-0.5 rounded-pill">{{$tag}}</span>{{end}}
20 </div>20 </div>
21 {{end}}21 {{end}}
22 {{if .annotation.Rating.Valid}}22 {{if .annotation.Rating.Valid}}
modified internal/tmpl/partials/feed-item.html +2 -2
@@ -5,13 +5,13 @@
55 <div class="min-w-0 flex-1">
66 <div class="flex items-center gap-2 flex-wrap">
77 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>
8- {{if and .Category.Valid .Category.String}}<span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-full shrink-0">{{.Category.String}}</span>{{end}}
8+ {{if and .Category.Valid .Category.String}}<span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-pill shrink-0">{{.Category.String}}</span>{{end}}
99 </div>
1010 <div class="text-xs text-spot-muted truncate mt-0.5">{{.FeedURL}}</div>
1111 </div>
1212 </a>
1313 <div class="flex items-center gap-3 shrink-0">
14- {{if .UnreadCount}}<span class="text-xs bg-spot-green/20 text-spot-green px-2.5 py-0.5 rounded-full font-bold">{{.UnreadCount}}</span>{{end}}
14+ {{if .UnreadCount}}<span class="text-xs bg-spot-green/20 text-spot-green px-2.5 py-0.5 rounded-pill font-bold">{{.UnreadCount}}</span>{{end}}
1515 <form hx-delete="/feeds/remove" hx-target="closest .feed-item" hx-swap="outerHTML swap:0.3s"
1616 hx-confirm="Unsubscribe from this feed?" class="inline">
1717 {{csrfInput .CSRFToken}}
@@ -5,13 +5,13 @@
5 <div class="min-w-0 flex-1">5 <div class="min-w-0 flex-1">
6 <div class="flex items-center gap-2 flex-wrap">6 <div class="flex items-center gap-2 flex-wrap">
7 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>7 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>
8- {{if and .Category.Valid .Category.String}}<span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-full shrink-0">{{.Category.String}}</span>{{end}}8+ {{if and .Category.Valid .Category.String}}<span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-pill shrink-0">{{.Category.String}}</span>{{end}}
9 </div>9 </div>
10 <div class="text-xs text-spot-muted truncate mt-0.5">{{.FeedURL}}</div>10 <div class="text-xs text-spot-muted truncate mt-0.5">{{.FeedURL}}</div>
11 </div>11 </div>
12 </a>12 </a>
13 <div class="flex items-center gap-3 shrink-0">13 <div class="flex items-center gap-3 shrink-0">
14- {{if .UnreadCount}}<span class="text-xs bg-spot-green/20 text-spot-green px-2.5 py-0.5 rounded-full font-bold">{{.UnreadCount}}</span>{{end}}14+ {{if .UnreadCount}}<span class="text-xs bg-spot-green/20 text-spot-green px-2.5 py-0.5 rounded-pill font-bold">{{.UnreadCount}}</span>{{end}}
15 <form hx-delete="/feeds/remove" hx-target="closest .feed-item" hx-swap="outerHTML swap:0.3s"15 <form hx-delete="/feeds/remove" hx-target="closest .feed-item" hx-swap="outerHTML swap:0.3s"
16 hx-confirm="Unsubscribe from this feed?" class="inline">16 hx-confirm="Unsubscribe from this feed?" class="inline">
17 {{csrfInput .CSRFToken}}17 {{csrfInput .CSRFToken}}
modified internal/tmpl/partials/profile-card.html +1 -1
@@ -4,7 +4,7 @@
44 <div class="min-w-0 flex-1">
55 <span class="font-bold text-spot-text hover:text-spot-green transition">@{{.Handle}}</span>
66 {{if .IsFollowed}}
7- <span class="inline-flex items-center gap-0.5 text-[10px] font-medium text-spot-green bg-spot-green/10 px-1.5 py-0.5 rounded-full ml-1.5">Following</span>
7+ <span class="inline-flex items-center gap-0.5 text-[10px] font-medium text-spot-green bg-spot-green/10 px-1.5 py-0.5 rounded-pill ml-1.5">Following</span>
88 {{end}}
99 {{if .DisplayName}}<div class="text-sm text-spot-secondary">{{.DisplayName}}</div>{{end}}
1010 </div>
@@ -4,7 +4,7 @@
4 <div class="min-w-0 flex-1">4 <div class="min-w-0 flex-1">
5 <span class="font-bold text-spot-text hover:text-spot-green transition">@{{.Handle}}</span>5 <span class="font-bold text-spot-text hover:text-spot-green transition">@{{.Handle}}</span>
6 {{if .IsFollowed}}6 {{if .IsFollowed}}
7- <span class="inline-flex items-center gap-0.5 text-[10px] font-medium text-spot-green bg-spot-green/10 px-1.5 py-0.5 rounded-full ml-1.5">Following</span>7+ <span class="inline-flex items-center gap-0.5 text-[10px] font-medium text-spot-green bg-spot-green/10 px-1.5 py-0.5 rounded-pill ml-1.5">Following</span>
8 {{end}}8 {{end}}
9 {{if .DisplayName}}<div class="text-sm text-spot-secondary">{{.DisplayName}}</div>{{end}}9 {{if .DisplayName}}<div class="text-sm text-spot-secondary">{{.DisplayName}}</div>{{end}}
10 </div>10 </div>
modified internal/tmpl/profile.html +1 -1
@@ -30,7 +30,7 @@
3030 <div class="min-w-0 flex-1">
3131 <div class="flex items-center gap-2 flex-wrap">
3232 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>
33- {{if and .Category.Valid .Category.String}}<span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-full shrink-0">{{.Category.String}}</span>{{end}}
33+ {{if and .Category.Valid .Category.String}}<span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-pill shrink-0">{{.Category.String}}</span>{{end}}
3434 </div>
3535 <div class="text-xs text-spot-muted truncate mt-0.5">{{.FeedURL}}</div>
3636 </div>
@@ -30,7 +30,7 @@
30 <div class="min-w-0 flex-1">30 <div class="min-w-0 flex-1">
31 <div class="flex items-center gap-2 flex-wrap">31 <div class="flex items-center gap-2 flex-wrap">
32 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>32 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>
33- {{if and .Category.Valid .Category.String}}<span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-full shrink-0">{{.Category.String}}</span>{{end}}33+ {{if and .Category.Valid .Category.String}}<span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-pill shrink-0">{{.Category.String}}</span>{{end}}
34 </div>34 </div>
35 <div class="text-xs text-spot-muted truncate mt-0.5">{{.FeedURL}}</div>35 <div class="text-xs text-spot-muted truncate mt-0.5">{{.FeedURL}}</div>
36 </div>36 </div>
modified internal/tmpl/stats.html +1 -1
@@ -27,7 +27,7 @@
2727 {{if .Labels}}
2828 <div class="flex gap-2 mt-1">
2929 {{range $key, $value := .Labels}}
30- <span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-full">{{$key}}={{$value}}</span>
30+ <span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-pill">{{$key}}={{$value}}</span>
3131 {{end}}
3232 </div>
3333 {{end}}
@@ -27,7 +27,7 @@
27 {{if .Labels}}27 {{if .Labels}}
28 <div class="flex gap-2 mt-1">28 <div class="flex gap-2 mt-1">
29 {{range $key, $value := .Labels}}29 {{range $key, $value := .Labels}}
30- <span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-full">{{$key}}={{$value}}</span>30+ <span class="text-xs bg-spot-hover text-spot-secondary px-2 py-0.5 rounded-pill">{{$key}}={{$value}}</span>
31 {{end}}31 {{end}}
32 </div>32 </div>
33 {{end}}33 {{end}}
modified static/input.css +19 -5
@@ -19,8 +19,14 @@
1919 --spot-placeholder: rgba(255,255,255,0.45);
2020 --spot-active-bg: #ffffff;
2121 --spot-active-text: #1E3932;
22- --spot-shadow: 0 0 0.5px rgba(0,0,0,0.20), 0 1px 1px rgba(0,0,0,0.30);
23- --spot-shadow-heavy: 0 0 6px rgba(0,0,0,0.30), 0 8px 12px rgba(0,0,0,0.20);
22+ --radius-sm: 0.25rem;
23+ --radius-md: 0.5rem;
24+ --radius-lg: 0.75rem;
25+ --radius-pill: 9999px;
26+ --radius-full: 50%;
27+ --spot-shadow: 0 1px 2px rgba(0,0,0,0.40), 0 2px 4px rgba(0,0,0,0.20);
28+ --spot-shadow-heavy: 0 4px 8px rgba(0,0,0,0.35), 0 12px 24px rgba(0,0,0,0.25);
29+ --spot-shadow-elevated: 0 8px 16px rgba(0,0,0,0.40), 0 24px 48px rgba(0,0,0,0.30);
2430 }
2531
2632 [data-theme="light"] {
@@ -39,8 +45,16 @@
3945 --spot-placeholder: rgba(0,0,0,0.30);
4046 --spot-active-bg: #1E3932;
4147 --spot-active-text: #ffffff;
42- --spot-shadow: 0 0 0.5px rgba(0,0,0,0.14), 0 1px 1px rgba(0,0,0,0.24);
43- --spot-shadow-heavy: 0 0 6px rgba(0,0,0,0.14), 0 8px 12px rgba(0,0,0,0.08);
48+ --spot-shadow: 0 1px 2px rgba(0,0,0,0.06), 0 2px 4px rgba(0,0,0,0.04);
49+ --spot-shadow-heavy: 0 4px 12px rgba(0,0,0,0.08), 0 12px 28px rgba(0,0,0,0.06);
50+ --spot-shadow-elevated: 0 8px 24px rgba(0,0,0,0.10), 0 24px 48px rgba(0,0,0,0.08);
51+ }
52+
53+ [data-shape="squared"] {
54+ --radius-sm: 0;
55+ --radius-md: 0;
56+ --radius-lg: 0;
57+ --radius-pill: 0;
4458 }
4559 }
4660
@@ -96,7 +110,7 @@ body {
96110
97111 ::-webkit-scrollbar { width: 8px; }
98112 ::-webkit-scrollbar-track { background: var(--spot-bg); }
99-::-webkit-scrollbar-thumb { background: var(--spot-muted); border-radius: 4px; }
113+::-webkit-scrollbar-thumb { background: var(--spot-muted); border-radius: var(--radius-md); }
100114 ::-webkit-scrollbar-thumb:hover { background: var(--spot-outline); }
101115
102116 .htmx-swapping {
@@ -19,8 +19,14 @@
19 --spot-placeholder: rgba(255,255,255,0.45);19 --spot-placeholder: rgba(255,255,255,0.45);
20 --spot-active-bg: #ffffff;20 --spot-active-bg: #ffffff;
21 --spot-active-text: #1E3932;21 --spot-active-text: #1E3932;
22- --spot-shadow: 0 0 0.5px rgba(0,0,0,0.20), 0 1px 1px rgba(0,0,0,0.30);22+ --radius-sm: 0.25rem;
23- --spot-shadow-heavy: 0 0 6px rgba(0,0,0,0.30), 0 8px 12px rgba(0,0,0,0.20);23+ --radius-md: 0.5rem;
24+ --radius-lg: 0.75rem;
25+ --radius-pill: 9999px;
26+ --radius-full: 50%;
27+ --spot-shadow: 0 1px 2px rgba(0,0,0,0.40), 0 2px 4px rgba(0,0,0,0.20);
28+ --spot-shadow-heavy: 0 4px 8px rgba(0,0,0,0.35), 0 12px 24px rgba(0,0,0,0.25);
29+ --spot-shadow-elevated: 0 8px 16px rgba(0,0,0,0.40), 0 24px 48px rgba(0,0,0,0.30);
24 }30 }
25 31
26 [data-theme="light"] {32 [data-theme="light"] {
@@ -39,8 +45,16 @@
39 --spot-placeholder: rgba(0,0,0,0.30);45 --spot-placeholder: rgba(0,0,0,0.30);
40 --spot-active-bg: #1E3932;46 --spot-active-bg: #1E3932;
41 --spot-active-text: #ffffff;47 --spot-active-text: #ffffff;
42- --spot-shadow: 0 0 0.5px rgba(0,0,0,0.14), 0 1px 1px rgba(0,0,0,0.24);48+ --spot-shadow: 0 1px 2px rgba(0,0,0,0.06), 0 2px 4px rgba(0,0,0,0.04);
43- --spot-shadow-heavy: 0 0 6px rgba(0,0,0,0.14), 0 8px 12px rgba(0,0,0,0.08);49+ --spot-shadow-heavy: 0 4px 12px rgba(0,0,0,0.08), 0 12px 28px rgba(0,0,0,0.06);
50+ --spot-shadow-elevated: 0 8px 24px rgba(0,0,0,0.10), 0 24px 48px rgba(0,0,0,0.08);
51+ }
52+
53+ [data-shape="squared"] {
54+ --radius-sm: 0;
55+ --radius-md: 0;
56+ --radius-lg: 0;
57+ --radius-pill: 0;
44 }58 }
45 }59 }
46 60
@@ -96,7 +110,7 @@ body {
96 110
97 ::-webkit-scrollbar { width: 8px; }111 ::-webkit-scrollbar { width: 8px; }
98 ::-webkit-scrollbar-track { background: var(--spot-bg); }112 ::-webkit-scrollbar-track { background: var(--spot-bg); }
99-::-webkit-scrollbar-thumb { background: var(--spot-muted); border-radius: 4px; }113+::-webkit-scrollbar-thumb { background: var(--spot-muted); border-radius: var(--radius-md); }
100 ::-webkit-scrollbar-thumb:hover { background: var(--spot-outline); }114 ::-webkit-scrollbar-thumb:hover { background: var(--spot-outline); }
101 115
102 .htmx-swapping {116 .htmx-swapping {
modified tailwind.config.js +9 -2
@@ -30,12 +30,19 @@ module.exports = {
3030 }
3131 },
3232 borderRadius: {
33- pill: '9999px',
34- 'pill-lg': '500px',
33+ DEFAULT: 'var(--radius-sm)',
34+ pill: 'var(--radius-pill)',
35+ 'pill-lg': 'var(--radius-pill)',
36+ sm: 'var(--radius-sm)',
37+ md: 'var(--radius-md)',
38+ lg: 'var(--radius-md)',
39+ xl: 'var(--radius-lg)',
40+ full: 'var(--radius-full)',
3541 },
3642 boxShadow: {
3743 'spot': 'var(--spot-shadow)',
3844 'spot-heavy': 'var(--spot-shadow-heavy)',
45+ 'spot-elevated': 'var(--spot-shadow-elevated)',
3946 },
4047 letterSpacing: {
4148 button: '1.4px',
@@ -30,12 +30,19 @@ module.exports = {
30 }30 }
31 },31 },
32 borderRadius: {32 borderRadius: {
33- pill: '9999px',33+ DEFAULT: 'var(--radius-sm)',
34- 'pill-lg': '500px',34+ pill: 'var(--radius-pill)',
35+ 'pill-lg': 'var(--radius-pill)',
36+ sm: 'var(--radius-sm)',
37+ md: 'var(--radius-md)',
38+ lg: 'var(--radius-md)',
39+ xl: 'var(--radius-lg)',
40+ full: 'var(--radius-full)',
35 },41 },
36 boxShadow: {42 boxShadow: {
37 'spot': 'var(--spot-shadow)',43 'spot': 'var(--spot-shadow)',
38 'spot-heavy': 'var(--spot-shadow-heavy)',44 'spot-heavy': 'var(--spot-shadow-heavy)',
45+ 'spot-elevated': 'var(--spot-shadow-elevated)',
39 },46 },
40 letterSpacing: {47 letterSpacing: {
41 button: '1.4px',48 button: '1.4px',