Rewild Your Web
18
fork

Configure Feed

Select the types of activity you want to include in your feed.

ui: cleanup styling

Signed-off-by: webbeef <me@webbeef.org>

webbeef d5a5d7f2 287c4217

+700 -427
+80 -26
ui/atproto/explorer.css
··· 14 14 } 15 15 16 16 header { 17 - padding: var(--spacing-md); 17 + padding: var(--spacing-lg) var(--spacing-lg) var(--spacing-md); 18 18 border-bottom: 1px solid var(--color-border); 19 + background: var(--bg-menu); 19 20 } 20 21 21 22 header h1 { 22 - font-size: 1.3rem; 23 + font-size: var(--font-size-xl); 23 24 margin-bottom: var(--spacing-sm); 24 25 display: flex; 25 26 align-items: center; 26 27 gap: var(--spacing-xs); 27 28 } 28 29 30 + header h1 lucide-icon { 31 + color: var(--color-primary); 32 + } 33 + 29 34 .search-bar { 30 35 display: flex; 31 36 gap: var(--spacing-sm); ··· 36 41 padding: var(--spacing-sm) var(--spacing-md); 37 42 border: 1px solid var(--color-border); 38 43 border-radius: var(--radius-sm); 39 - background: var(--bg-surface); 44 + background: var(--bg-webview); 40 45 color: var(--color-text); 41 - font-size: 0.9rem; 46 + font-size: var(--font-size-menu); 42 47 font-family: inherit; 48 + outline: none; 49 + transition: 50 + border-color var(--transition-fast), 51 + box-shadow var(--transition-fast); 52 + } 53 + 54 + .search-bar input:focus { 55 + border-color: var(--color-primary); 56 + box-shadow: 0 0 0 2px var(--color-focus-ring); 57 + } 58 + 59 + .search-bar input::placeholder { 60 + color: var(--color-text-tertiary); 43 61 } 44 62 45 63 .search-bar button { 46 64 padding: var(--spacing-sm) var(--spacing-md); 47 - border: 1px solid var(--color-border); 65 + border: 1px solid var(--color-primary); 48 66 border-radius: var(--radius-sm); 49 67 background: var(--color-primary); 50 - color: white; 68 + color: var(--color-text-on-header); 51 69 cursor: pointer; 52 - font-size: 0.9rem; 70 + font-size: var(--font-size-menu); 53 71 font-family: inherit; 72 + font-weight: var(--font-weight-bold); 73 + transition: 74 + background var(--transition-fast), 75 + border-color var(--transition-fast); 54 76 } 55 77 56 78 .search-bar button:hover { 57 - opacity: 0.9; 79 + filter: brightness(0.9); 58 80 } 59 81 60 82 .breadcrumb { 61 - padding: var(--spacing-sm) var(--spacing-md); 83 + padding: var(--spacing-sm) var(--spacing-lg); 62 84 font-size: var(--font-size-sm); 63 85 color: var(--color-text-secondary); 64 86 border-bottom: 1px solid var(--color-border); 87 + background: var(--bg-menu); 65 88 display: flex; 66 89 align-items: center; 67 90 gap: var(--spacing-xs); ··· 83 106 } 84 107 85 108 .breadcrumb .separator { 86 - opacity: 0.5; 109 + color: var(--color-text-tertiary); 87 110 } 88 111 89 112 main { 90 - padding: var(--spacing-md); 113 + padding: var(--spacing-lg); 114 + max-width: 900px; 91 115 } 92 116 93 117 .empty-state { 94 118 text-align: center; 95 - padding: var(--spacing-lg); 119 + padding: var(--spacing-xl); 96 120 color: var(--color-text-secondary); 97 121 } 98 122 ··· 108 132 margin-bottom: var(--spacing-md); 109 133 padding: var(--spacing-md); 110 134 background: var(--bg-menu); 111 - border-radius: var(--radius-sm); 135 + border-radius: var(--radius-md); 112 136 border: 1px solid var(--color-border); 113 137 } 114 138 115 139 .repo-info h2 { 116 - font-size: 1.1rem; 140 + font-size: var(--font-size-lg); 117 141 margin-bottom: var(--spacing-xs); 118 142 } 119 143 ··· 139 163 border: 1px solid var(--color-border); 140 164 border-radius: var(--radius-sm); 141 165 cursor: pointer; 142 - transition: background var(--transition-fast); 166 + transition: 167 + background var(--transition-fast), 168 + border-color var(--transition-fast); 143 169 } 144 170 145 171 .collection-item:hover { 146 172 background: var(--bg-hover); 173 + border-color: var(--color-text-tertiary); 147 174 } 148 175 149 176 .collection-item lucide-icon { ··· 171 198 border: 1px solid var(--color-border); 172 199 border-radius: var(--radius-sm); 173 200 cursor: pointer; 174 - transition: background var(--transition-fast); 201 + transition: 202 + background var(--transition-fast), 203 + border-color var(--transition-fast); 175 204 } 176 205 177 206 .record-item:hover { 178 207 background: var(--bg-hover); 208 + border-color: var(--color-text-tertiary); 179 209 } 180 210 181 211 .record-item lucide-icon { ··· 191 221 .record-detail { 192 222 background: var(--bg-menu); 193 223 border: 1px solid var(--color-border); 194 - border-radius: var(--radius-sm); 224 + border-radius: var(--radius-md); 195 225 padding: var(--spacing-md); 196 226 } 197 227 ··· 199 229 white-space: pre-wrap; 200 230 word-break: break-all; 201 231 font-size: var(--font-size-sm); 202 - line-height: 1.5; 232 + line-height: 1.6; 203 233 max-height: 80vh; 204 234 overflow-y: auto; 205 235 } ··· 214 244 /* Loading / error */ 215 245 .loading { 216 246 text-align: center; 217 - padding: var(--spacing-lg); 247 + padding: var(--spacing-xl); 218 248 color: var(--color-text-secondary); 219 249 } 220 250 ··· 222 252 text-align: center; 223 253 padding: var(--spacing-md); 224 254 color: var(--color-danger); 255 + background: oklch(55% 0.15 25 / 0.08); 256 + border-radius: var(--radius-sm); 225 257 } 226 258 227 259 /* Delete button inline in record list */ ··· 235 267 display: flex; 236 268 align-items: center; 237 269 opacity: 0; 238 - transition: opacity var(--transition-fast); 270 + transition: 271 + opacity var(--transition-fast), 272 + color var(--transition-fast), 273 + background var(--transition-fast); 239 274 } 240 275 241 276 .record-item:hover .btn-delete-inline { ··· 244 279 245 280 .btn-delete-inline:hover { 246 281 color: var(--color-danger); 282 + background: oklch(55% 0.15 25 / 0.1); 247 283 } 248 284 249 285 /* Delete button in record detail */ ··· 263 299 display: inline-flex; 264 300 align-items: center; 265 301 gap: var(--spacing-xs); 302 + transition: 303 + background var(--transition-fast), 304 + color var(--transition-fast); 266 305 } 267 306 268 307 .btn-delete:hover { 269 308 background: var(--color-danger); 270 - color: white; 309 + color: var(--color-text-on-header); 271 310 } 272 311 273 312 /* Create record form */ ··· 275 314 margin-bottom: var(--spacing-md); 276 315 background: var(--bg-menu); 277 316 border: 1px solid var(--color-border); 278 - border-radius: var(--radius-sm); 317 + border-radius: var(--radius-md); 279 318 } 280 319 281 320 .create-record-form summary { ··· 286 325 gap: var(--spacing-sm); 287 326 font-weight: var(--font-weight-bold); 288 327 font-size: var(--font-size-menu); 328 + border-radius: var(--radius-md); 329 + transition: background var(--transition-fast); 289 330 } 290 331 291 332 .create-record-form summary:hover { ··· 293 334 } 294 335 295 336 .create-record-body { 296 - padding: 0 var(--spacing-md) var(--spacing-md); 337 + padding: var(--spacing-sm) var(--spacing-md) var(--spacing-md); 297 338 } 298 339 299 340 .create-record-body textarea { ··· 301 342 padding: var(--spacing-sm); 302 343 border: 1px solid var(--color-border); 303 344 border-radius: var(--radius-sm); 304 - background: var(--bg-surface); 345 + background: var(--bg-webview); 305 346 color: var(--color-text); 306 347 font-family: monospace; 307 348 font-size: var(--font-size-sm); 308 349 resize: vertical; 309 350 margin-bottom: var(--spacing-sm); 351 + outline: none; 352 + transition: 353 + border-color var(--transition-fast), 354 + box-shadow var(--transition-fast); 355 + } 356 + 357 + .create-record-body textarea:focus { 358 + border-color: var(--color-primary); 359 + box-shadow: 0 0 0 2px var(--color-focus-ring); 310 360 } 311 361 312 362 .btn-create { ··· 314 364 border: 1px solid var(--color-primary); 315 365 border-radius: var(--radius-sm); 316 366 background: var(--color-primary); 317 - color: white; 367 + color: var(--color-text-on-header); 318 368 cursor: pointer; 319 369 font-size: var(--font-size-sm); 320 370 font-family: inherit; 371 + font-weight: var(--font-weight-bold); 321 372 display: inline-flex; 322 373 align-items: center; 323 374 gap: var(--spacing-xs); 375 + transition: 376 + background var(--transition-fast), 377 + border-color var(--transition-fast); 324 378 } 325 379 326 380 .btn-create:hover { 327 - opacity: 0.9; 381 + filter: brightness(0.9); 328 382 }
+3 -1
ui/atproto/explorer.js
··· 269 269 `; 270 270 } 271 271 272 + let href = `at://${encodeURIComponent(handle)}/${collection}/${rkey}`; 273 + 272 274 content.innerHTML = ` 273 275 <div class="record-detail"> 274 - <div class="at-uri">${escapeHtml(uri)}</div> 276 + <div class="at-uri"><a href="${href}" target="_blank">${escapeHtml(uri)}</a></div> 275 277 ${actions} 276 278 <pre>${syntaxHighlight(JSON.stringify(value, null, 2))}</pre> 277 279 </div>
+47 -26
ui/homescreen/index.css
··· 28 28 29 29 /* Widgets area at top */ 30 30 .widgets-area { 31 - padding: var(--spacing-md); 32 - padding-top: var(--spacing-md); 31 + padding: var(--spacing-md) var(--spacing-md) 0; 33 32 display: flex; 34 33 flex-direction: column; 35 34 gap: var(--spacing-sm); ··· 45 44 .bookmarks-area { 46 45 flex: 1; 47 46 overflow-y: auto; 48 - padding: var(--spacing-md); 49 - padding-bottom: var(--spacing-sm); 47 + padding: var(--spacing-lg) var(--spacing-md) var(--spacing-sm); 50 48 display: flex; 51 49 flex-direction: column; 52 50 justify-content: flex-end; ··· 55 53 /* Bookmarks grid */ 56 54 .bookmarks-grid { 57 55 display: grid; 58 - grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); 59 - gap: var(--spacing-xs); 56 + grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); 57 + gap: var(--spacing-sm); 60 58 justify-items: center; 61 - max-width: 600px; 59 + max-width: 560px; 62 60 margin: 0 auto; 63 61 width: 100%; 64 62 } ··· 69 67 align-items: center; 70 68 text-decoration: none; 71 69 color: inherit; 72 - padding: var(--spacing-xs); 70 + padding: var(--spacing-sm) var(--spacing-xs); 73 71 border-radius: var(--radius-md); 74 - transition: background var(--transition-fast); 72 + transition: 73 + background var(--transition-fast), 74 + transform var(--transition-fast); 75 75 cursor: pointer; 76 76 } 77 77 78 78 .bookmark-item:hover { 79 79 background: var(--bg-hover); 80 + transform: translateY(-2px); 80 81 } 81 82 82 83 .bookmark-item:active { 83 - transform: scale(0.95); 84 + transform: scale(0.93); 84 85 } 85 86 86 87 .bookmark-icon { 87 - width: 56px; 88 - height: 56px; 88 + width: 52px; 89 + height: 52px; 89 90 border-radius: var(--radius-md); 90 91 background: var(--bg-surface); 91 92 display: flex; ··· 93 94 justify-content: center; 94 95 margin-bottom: var(--spacing-xs); 95 96 overflow: hidden; 97 + box-shadow: 0 1px 4px var(--color-shadow-menu); 98 + transition: box-shadow var(--transition-fast); 99 + } 100 + 101 + .bookmark-item:hover .bookmark-icon { 102 + box-shadow: 0 3px 10px var(--color-shadow); 96 103 } 97 104 98 105 .bookmark-icon img { 99 - width: 40px; 100 - height: 40px; 106 + width: 36px; 107 + height: 36px; 101 108 border-radius: var(--radius-sm); 102 109 object-fit: contain; 103 110 } 104 111 105 112 .bookmark-title { 106 - font-size: var(--font-size-sm); 113 + font-size: var(--font-size-xs); 107 114 text-align: center; 108 115 max-width: 80px; 109 116 overflow: hidden; 110 117 text-overflow: ellipsis; 111 118 white-space: nowrap; 112 - color: var(--color-text-menu); 119 + color: var(--color-text-secondary); 120 + margin-top: 2px; 113 121 } 114 122 115 123 /* Results area - overlays bookmarks when searching */ ··· 118 126 flex: 1; 119 127 overflow-y: auto; 120 128 padding: var(--spacing-lg); 121 - padding-top: var(--spacing-lg); 122 129 background: var(--bg-main); 123 130 } 124 131 ··· 136 143 137 144 /* Search bar fixed at bottom */ 138 145 .search-bar { 139 - padding: var(--spacing-md); 140 - padding-bottom: var(--spacing-md); 141 - background: var(--bg-menu); 142 - border-top: 1px solid var(--color-border); 146 + padding: var(--spacing-sm) var(--spacing-md) var(--spacing-md); 143 147 } 144 148 145 149 .search-input-container { 146 150 display: flex; 147 151 align-items: center; 148 - background: var(--bg-webview); 149 - border-radius: var(--radius-md); 152 + background: var(--bg-menu); 153 + border-radius: var(--radius-lg); 150 154 padding: var(--spacing-sm) var(--spacing-md); 151 - max-width: 600px; 155 + max-width: 560px; 152 156 margin: 0 auto; 157 + box-shadow: 0 2px 8px var(--color-shadow-menu); 158 + transition: 159 + box-shadow 0.25s cubic-bezier(0.16, 1, 0.3, 1), 160 + background 0.25s cubic-bezier(0.16, 1, 0.3, 1); 161 + } 162 + 163 + .search-input-container:focus-within { 164 + background: var(--bg-webview); 165 + box-shadow: 166 + 0 2px 12px var(--color-shadow), 167 + 0 0 0 2px var(--color-focus-ring); 153 168 } 154 169 155 170 .search-input-container lucide-icon { 156 171 color: var(--color-text-tertiary); 157 172 margin-right: var(--spacing-sm); 158 173 flex-shrink: 0; 174 + transition: color var(--transition-fast); 175 + } 176 + 177 + .search-input-container:focus-within lucide-icon { 178 + color: var(--color-primary); 159 179 } 160 180 161 181 .search-input { ··· 163 183 border: none; 164 184 background: transparent; 165 185 font-size: 16px; 186 + font-family: var(--font-family-base); 166 187 color: var(--color-text); 167 188 outline: none; 168 189 min-width: 0; ··· 172 193 color: var(--color-text-tertiary); 173 194 } 174 195 175 - /* Results list styling (adapted from new_view.css) */ 196 + /* Results list styling */ 176 197 .results-list { 177 198 list-style: none; 178 - max-width: 600px; 199 + max-width: 560px; 179 200 margin: 0 auto; 180 201 } 181 202
+2 -2
ui/homescreen/index.js
··· 47 47 function renderBookmarks(bookmarks) { 48 48 bookmarksGrid.innerHTML = ""; 49 49 50 - for (const bookmark of bookmarks) { 50 + bookmarks.forEach((bookmark, i) => { 51 51 const item = document.createElement("div"); 52 52 item.className = "bookmark-item"; 53 53 item.innerHTML = ` ··· 61 61 navigate(bookmark.url); 62 62 }); 63 63 bookmarksGrid.appendChild(item); 64 - } 64 + }); 65 65 } 66 66 67 67 // Reset search UI to initial state
+6
ui/homescreen/resources/widgets.json
··· 1 1 [ 2 2 { 3 + "id": "clock", 4 + "url": "widgets/clock/index.html", 5 + "width": "100%", 6 + "height": "80px" 7 + }, 8 + { 3 9 "id": "weather", 4 10 "url": "widgets/weather/index.html", 5 11 "width": "100%",
+29
ui/homescreen/widgets/clock/index.css
··· 1 + /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 + 3 + body { 4 + margin: 0; 5 + padding: 0; 6 + background: transparent; 7 + font-family: var(--font-family-base); 8 + color: var(--color-text-menu); 9 + } 10 + 11 + .clock-widget { 12 + display: flex; 13 + flex-direction: column; 14 + align-items: center; 15 + justify-content: center; 16 + padding: var(--spacing-sm) var(--spacing-md); 17 + } 18 + 19 + .clock-time { 20 + font-family: Pacifico, cursive; 21 + font-size: 2.4em; 22 + line-height: 1.2; 23 + } 24 + 25 + .clock-date { 26 + font-size: var(--font-size-sm); 27 + color: var(--color-text-secondary); 28 + margin-top: 2px; 29 + }
+19
ui/homescreen/widgets/clock/index.html
··· 1 + <!DOCTYPE html> 2 + <html> 3 + <!-- SPDX-License-Identifier: AGPL-3.0-or-later --> 4 + <head> 5 + <meta charset="UTF-8" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 + <link rel="stylesheet" href="beaver://theme/index.css" /> 8 + <link rel="stylesheet" href="beaver://shared/fonts/fonts.css" /> 9 + <link rel="stylesheet" href="index.css" /> 10 + <script type="module" src="beaver://shared/theme.js"></script> 11 + <script type="module" src="index.js"></script> 12 + </head> 13 + <body> 14 + <div class="clock-widget"> 15 + <div class="clock-time" id="clock-time"></div> 16 + <div class="clock-date" id="clock-date"></div> 17 + </div> 18 + </body> 19 + </html>
+21
ui/homescreen/widgets/clock/index.js
··· 1 + // SPDX-License-Identifier: AGPL-3.0-or-later 2 + 3 + const clockTime = document.getElementById("clock-time"); 4 + const clockDate = document.getElementById("clock-date"); 5 + 6 + function update() { 7 + const now = new Date(); 8 + const hours = now.getHours(); 9 + const minutes = now.getMinutes().toString().padStart(2, "0"); 10 + 11 + clockTime.textContent = `${hours}:${minutes}`; 12 + 13 + clockDate.textContent = now.toLocaleDateString(undefined, { 14 + weekday: "long", 15 + month: "long", 16 + day: "numeric", 17 + }); 18 + } 19 + 20 + update(); 21 + setInterval(update, 30_000);
+7 -7
ui/homescreen/widgets/weather/index.css
··· 18 18 } 19 19 20 20 .weather-icon lucide-icon { 21 - font-size: 48px; 21 + font-size: 2.5em; 22 22 opacity: 0.9; 23 23 } 24 24 25 25 .temperature { 26 - font-size: 32px; 27 - font-weight: bold; 26 + font-size: 1.8em; 27 + font-weight: var(--font-weight-bold); 28 28 } 29 29 30 30 .condition { 31 - font-size: 14px; 32 - opacity: 0.8; 31 + font-size: var(--font-size-sm); 32 + color: var(--color-text-secondary); 33 33 } 34 34 35 35 .location { 36 - font-size: 12px; 37 - opacity: 0.6; 36 + font-size: var(--font-size-xs); 37 + color: var(--color-text-tertiary); 38 38 }
+45 -23
ui/keyboard/index.css
··· 1 1 /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 2 3 + /* 4 + * Keyboard derives its own dark palette from theme tokens. 5 + * Keys are always dark (readable, high-contrast tap targets) 6 + * but tinted toward the theme's brand hue. 7 + */ 8 + 3 9 * { 4 10 box-sizing: border-box; 5 11 } 6 12 7 13 :root { 8 14 --default-key-width: calc(100vw / 10); 15 + 16 + /* Keyboard-specific palette — dark surfaces tinted from theme */ 17 + --kb-bg: color-mix(in oklch, var(--bg-footer) 30%, oklch(18% 0.01 105)); 18 + --kb-key: color-mix(in oklch, var(--bg-footer) 20%, oklch(30% 0.01 105)); 19 + --kb-key-active: color-mix(in oklch, var(--color-primary) 40%, oklch(45% 0.02 105)); 20 + --kb-key-pressed: color-mix(in oklch, var(--bg-footer) 25%, oklch(50% 0.02 105)); 21 + --kb-text: color-mix(in oklch, var(--color-text-on-header) 90%, oklch(95% 0 0)); 22 + --kb-text-muted: color-mix(in oklch, var(--color-text-on-header) 50%, oklch(60% 0 0)); 23 + --kb-border: color-mix(in oklch, var(--bg-footer) 20%, oklch(25% 0.01 105)); 24 + --kb-separator: color-mix(in oklch, var(--bg-footer) 15%, oklch(28% 0.01 105)); 9 25 } 10 26 11 27 html, ··· 16 32 body { 17 33 margin: 0; 18 34 padding: 4px; 19 - background: #2a2a2a; 20 - font-family: sans-serif; 35 + background: var(--kb-bg); 36 + font-family: var(--font-family-base); 21 37 display: flex; 22 38 justify-content: center; 23 39 align-items: flex-end; ··· 46 62 height: 40px; 47 63 padding: 0 10px; 48 64 overflow: hidden; 49 - background: #404040; 65 + background: var(--kb-key); 50 66 border: none; 51 - border-radius: 6px; 52 - color: white; 67 + border-radius: 8px; 68 + color: var(--kb-text); 69 + font-family: var(--font-family-base); 53 70 font-size: 16px; 54 71 font-weight: 500; 55 72 cursor: pointer; 56 73 display: flex; 57 74 align-items: center; 58 75 justify-content: center; 59 - transition: background-color 0.05s ease; 76 + transition: background-color 0.05s cubic-bezier(0.16, 1, 0.3, 1); 60 77 user-select: none; 78 + box-shadow: 79 + 0 1px 0 var(--kb-border), 80 + 0 1px 2px var(--kb-bg); 61 81 } 62 82 63 83 .key:active, 64 84 .emoji-tab.abc:active, 65 85 .emoji-tab.backspace:active { 66 - background-color: #808080; 86 + background-color: var(--kb-key-pressed); 87 + box-shadow: none; 67 88 transform: translateY(1px); 68 89 } 69 90 ··· 94 115 } 95 116 96 117 .key.active { 97 - background: #5a8cff; 118 + background: var(--kb-key-active); 98 119 } 99 120 100 121 @keyframes layout-label { ··· 102 123 color: transparent; 103 124 } 104 125 15% { 105 - color: lightgray; 126 + color: var(--kb-text-muted); 106 127 } 107 128 70% { 108 - color: lightgray; 129 + color: var(--kb-text-muted); 109 130 } 110 131 100% { 111 132 color: transparent; ··· 115 136 .key.layout-label { 116 137 font-size: 13px; 117 138 color: transparent; 118 - animation: layout-label 1s ease forwards; 139 + animation: layout-label 1s cubic-bezier(0.16, 1, 0.3, 1) forwards; 119 140 } 120 141 121 142 /* Hidden state */ ··· 141 162 overflow: scroll; 142 163 padding: 0 4px; 143 164 scrollbar-width: thin; 144 - scrollbar-color: #555 transparent; 165 + scrollbar-color: var(--kb-key) transparent; 145 166 } 146 167 147 168 .emoji-category-header { 148 169 padding: 4px 2px; 149 170 font-size: 11px; 150 - color: #999; 171 + color: var(--kb-text-muted); 151 172 } 152 173 153 174 .emoji-grid { ··· 160 181 height: 36px; 161 182 background: none; 162 183 border: none; 163 - border-radius: 6px; 184 + border-radius: 8px; 164 185 font-size: 22px; 165 186 cursor: pointer; 166 187 display: flex; ··· 171 192 } 172 193 173 194 .emoji-key:active { 174 - background: #404040; 195 + background: var(--kb-key); 175 196 } 176 197 177 198 .emoji-category-bar { 178 199 display: flex; 179 200 gap: 2px; 180 201 padding: 4px; 181 - border-top: 1px solid #404040; 202 + border-top: 1px solid var(--kb-separator); 182 203 align-items: center; 183 204 } 184 205 ··· 187 208 height: 30px; 188 209 background: none; 189 210 border: none; 190 - border-radius: 4px; 211 + border-radius: 6px; 191 212 font-size: 16px; 192 - color: white; 213 + color: var(--kb-text); 193 214 cursor: pointer; 194 215 display: flex; 195 216 align-items: center; 196 217 justify-content: center; 197 218 padding: 0; 198 219 opacity: 0.5; 199 - transition: opacity 0.15s ease; 220 + transition: opacity 0.15s cubic-bezier(0.16, 1, 0.3, 1); 200 221 } 201 222 202 223 .emoji-tab.active { 203 224 opacity: 1; 204 - background: #404040; 225 + background: var(--kb-key); 205 226 } 206 227 207 - .emoji-tab.abc, .emoji-tab.backspace { 208 - transition: background-color 0.05s ease; 228 + .emoji-tab.abc, 229 + .emoji-tab.backspace { 230 + transition: background-color 0.05s cubic-bezier(0.16, 1, 0.3, 1); 209 231 font-size: 16px; 210 - font-weight: bolder; 232 + font-weight: var(--font-weight-bold); 211 233 }
+3
ui/keyboard/index.html
··· 4 4 <head> 5 5 <meta charset="utf-8"> 6 6 <title>Virtual Keyboard</title> 7 + <link rel="stylesheet" href="beaver://theme/index.css" /> 8 + <link rel="stylesheet" href="beaver://shared/fonts/fonts.css" /> 9 + <script type="module" src="beaver://shared/theme.js"></script> 7 10 <link rel="stylesheet" href="index.css" /> 8 11 </head> 9 12 <body>
+112 -80
ui/settings/index.css
··· 15 15 color: var(--color-text-menu); 16 16 } 17 17 18 - /* TODO: extract this styling to some shared stylsheet */ 19 - input { 18 + /* ===== Shared form elements ===== */ 19 + /* TODO: extract this styling to some shared stylesheet */ 20 + 21 + input, 22 + select { 20 23 padding: var(--spacing-sm) var(--spacing-md); 21 24 font-size: 1em; 22 - border: 2px solid var(--color-border); 23 - border-radius: var(--radius-md); 25 + font-family: var(--font-family-base); 26 + border: 1px solid var(--color-border); 27 + border-radius: var(--radius-sm); 24 28 background: var(--bg-webview); 25 29 color: inherit; 26 30 outline: none; 27 - transition: border-color var(--transition-fast); 31 + transition: 32 + border-color var(--transition-fast), 33 + box-shadow var(--transition-fast); 28 34 } 29 35 30 - input:focus { 31 - border-color: var(--color-focus-ring); 36 + input:focus, 37 + select:focus { 38 + border-color: var(--color-primary); 39 + box-shadow: 0 0 0 2px var(--color-focus-ring); 32 40 } 33 41 34 42 input::placeholder { 35 43 color: var(--color-text-tertiary); 36 44 } 37 45 38 - select { 39 - padding: var(--spacing-sm) var(--spacing-sm); 40 - } 41 - 42 - /* End of shareable styling */ 43 - 44 46 input { 45 47 width: 100%; 46 48 } ··· 51 53 text-align: right; 52 54 } 53 55 54 - /* Main layout with sidebar */ 56 + /* Shared button base */ 57 + button { 58 + font-family: var(--font-family-base); 59 + transition: 60 + background var(--transition-fast), 61 + color var(--transition-fast), 62 + border-color var(--transition-fast); 63 + } 64 + 65 + /* ===== Main layout ===== */ 66 + 55 67 body { 56 68 display: flex; 57 69 } ··· 63 75 /* Left sidebar */ 64 76 .settings-sidebar { 65 77 width: 200px; 66 - background: var(--bg-header); 78 + background: var(--bg-surface); 67 79 display: flex; 68 80 flex-direction: column; 69 81 border-right: 1px solid var(--color-border); 70 82 } 71 83 72 84 .settings-sidebar h1 { 73 - font-size: 1.2em; 85 + font-size: var(--font-size-xl); 74 86 font-weight: var(--font-weight-bold); 75 87 padding: var(--spacing-md); 76 88 border-bottom: 1px solid var(--color-border); ··· 81 93 display: flex; 82 94 flex-direction: column; 83 95 padding: var(--spacing-sm); 84 - gap: var(--spacing-xs); 96 + gap: 2px; 85 97 } 86 98 87 99 .nav-item { ··· 90 102 gap: var(--spacing-sm); 91 103 padding: var(--spacing-sm) var(--spacing-md); 92 104 border-radius: var(--radius-sm); 93 - color: inherit; 105 + color: var(--color-text-secondary); 94 106 text-decoration: none; 95 107 cursor: pointer; 96 - transition: background var(--transition-fast); 108 + transition: 109 + background var(--transition-fast), 110 + color var(--transition-fast); 97 111 } 98 112 99 113 .nav-item:hover { 100 114 background: var(--color-menu-item-hover); 115 + color: var(--color-text-menu); 101 116 } 102 117 103 118 .nav-item.active { 104 119 background: var(--bg-menu); 120 + color: var(--color-text-menu); 105 121 font-weight: var(--font-weight-bold); 106 122 } 107 123 108 124 .nav-item lucide-icon { 109 - font-size: 1.1em; 125 + font-size: var(--font-size-lg); 110 126 } 111 127 112 128 /* Right content area */ 113 129 .settings-content { 114 130 flex: 1; 115 131 overflow-y: auto; 116 - padding: var(--spacing-md); 132 + padding: var(--spacing-lg); 117 133 } 118 134 119 135 .settings-category { ··· 124 140 details { 125 141 background: var(--bg-menu); 126 142 border-radius: var(--radius-md); 127 - box-shadow: 0 2px 8px var(--color-shadow); 143 + border: 1px solid var(--color-border); 128 144 } 129 145 130 146 summary { ··· 132 148 align-items: center; 133 149 gap: var(--spacing-sm); 134 150 padding: var(--spacing-md); 135 - font-size: 1.1em; 151 + font-size: var(--font-size-lg); 136 152 font-weight: var(--font-weight-bold); 137 153 cursor: pointer; 138 154 user-select: none; ··· 156 172 157 173 summary lucide-icon { 158 174 font-size: 1.2em; 175 + color: var(--color-primary); 159 176 } 160 177 161 178 .category-content { 162 - padding: var(--spacing-md); 163 - padding-top: 0; 179 + padding: var(--spacing-sm) var(--spacing-md) var(--spacing-md); 164 180 } 165 181 166 182 .category-description { 167 - opacity: var(--opacity-muted); 168 - margin-bottom: var(--spacing-md); 169 - font-size: var(--font-size-menu); 183 + color: var(--color-text-secondary); 184 + margin-bottom: var(--spacing-sm); 185 + margin-top: var(--spacing-md); 186 + font-size: var(--font-size-sm); 187 + } 188 + 189 + .category-description:first-child { 190 + margin-top: 0; 170 191 } 171 192 172 193 /* Theme grid */ 173 194 .theme-grid { 174 195 display: grid; 175 - grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); 196 + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); 176 197 gap: var(--spacing-md); 198 + margin-top: var(--spacing-sm); 177 199 } 178 200 179 201 .theme-card { 180 - border-radius: var(--radius-sm); 202 + border-radius: var(--radius-md); 181 203 overflow: hidden; 182 204 cursor: pointer; 183 205 transition: 184 206 transform var(--transition-fast), 185 - box-shadow var(--transition-fast); 186 - border: 3px solid transparent; 207 + box-shadow var(--transition-fast), 208 + border-color var(--transition-fast); 209 + border: 2px solid var(--color-border); 187 210 background: var(--bg-webview); 188 211 } 189 212 190 213 .theme-card:hover { 191 214 transform: translateY(-2px); 192 215 box-shadow: 0 4px 12px var(--color-shadow); 216 + border-color: var(--color-text-tertiary); 193 217 } 194 218 195 219 .theme-card.selected { 196 - border-color: var(--color-focus-ring); 197 - box-shadow: 0 0 0 2px var(--color-focus-ring); 220 + border-color: var(--color-primary); 221 + box-shadow: 0 0 0 2px var(--color-primary); 198 222 } 199 223 200 224 .theme-preview { 201 - height: 80px; 225 + height: 72px; 202 226 display: flex; 203 227 flex-direction: column; 204 228 position: relative; 205 229 } 206 230 207 231 .theme-preview-header { 208 - height: 20px; 209 - border-radius: var(--radius-sm) var(--radius-sm) 0 0; 232 + height: 18px; 210 233 } 211 234 212 235 .theme-preview-main { ··· 230 253 231 254 .theme-name { 232 255 font-weight: var(--font-weight-bold); 233 - font-size: var(--font-size-menu); 256 + font-size: var(--font-size-sm); 234 257 } 235 258 236 259 .theme-description { 237 - font-size: var(--font-size-sm); 238 - opacity: var(--opacity-muted); 239 - margin-top: 2px; 260 + font-size: var(--font-size-xs); 261 + color: var(--color-text-tertiary); 262 + margin-top: var(--spacing-xs); 240 263 } 241 264 242 265 /* Theme-specific preview colors */ 243 266 /* TODO: Don't hardcode the previews! */ 244 267 .preview-default .theme-preview-header { 245 - background: oklch(95% 0.5 110); 268 + background: oklch(94% 0.08 115); 246 269 } 247 270 .preview-default .theme-preview-main { 248 271 background: linear-gradient( 249 272 to bottom right, 250 - oklch(95% 0.5 110), 251 - oklch(72% 0.5 90) 273 + oklch(94% 0.08 115), 274 + oklch(82% 0.1 100) 252 275 ); 253 276 } 254 277 .preview-default .theme-preview-webview { 255 - background: white; 278 + background: oklch(99% 0.005 105); 256 279 } 257 280 258 281 .preview-lcars .theme-preview-header { ··· 299 322 padding: var(--spacing-sm) 0; 300 323 } 301 324 325 + .setting-row + .setting-row { 326 + border-top: 1px solid var(--color-border); 327 + } 328 + 302 329 .setting-info { 303 330 display: flex; 304 331 flex-direction: column; 305 - gap: var(--spacing-xs); 332 + gap: 2px; 306 333 } 307 334 308 335 .setting-label { ··· 312 339 313 340 .setting-description { 314 341 font-size: var(--font-size-sm); 315 - opacity: var(--opacity-muted); 342 + color: var(--color-text-secondary); 316 343 } 317 344 318 345 /* Toggle switch */ 319 346 .toggle-switch { 320 347 position: relative; 321 348 display: inline-block; 322 - width: 48px; 323 - height: 26px; 349 + width: 44px; 350 + height: 24px; 324 351 flex-shrink: 0; 325 352 } 326 353 ··· 338 365 right: 0; 339 366 bottom: 0; 340 367 background-color: var(--color-border); 341 - transition: var(--transition-fast); 342 - border-radius: 26px; 368 + transition: background-color var(--transition-fast); 369 + border-radius: 24px; 343 370 } 344 371 345 372 .toggle-slider::before { 346 373 position: absolute; 347 374 content: ""; 348 - height: 20px; 349 - width: 20px; 375 + height: 18px; 376 + width: 18px; 350 377 left: 3px; 351 378 bottom: 3px; 352 - background-color: white; 353 - transition: var(--transition-fast); 379 + background-color: var(--bg-webview); 380 + transition: transform var(--transition-fast); 354 381 border-radius: 50%; 382 + box-shadow: 0 1px 3px var(--color-shadow-menu); 355 383 } 356 384 357 385 input:checked + .toggle-slider { 358 - background-color: var(--color-focus-ring); 386 + background-color: var(--color-primary); 359 387 } 360 388 361 389 input:checked + .toggle-slider::before { 362 - transform: translateX(22px); 390 + transform: translateX(20px); 363 391 } 364 392 365 - input:focus + .toggle-slider { 366 - box-shadow: 0 0 0 2px var(--color-shadow); 393 + input:focus-visible + .toggle-slider { 394 + box-shadow: 0 0 0 2px var(--color-focus-ring); 367 395 } 368 396 369 397 /* Mobile header - hidden on desktop */ ··· 409 437 display: flex; 410 438 align-items: center; 411 439 gap: var(--spacing-sm); 412 - background: var(--bg-header); 440 + background: var(--bg-surface); 413 441 border-bottom: 1px solid var(--color-border); 414 442 } 415 443 ··· 424 452 } 425 453 426 454 .mobile-title { 427 - font-size: 1.1em; 455 + font-size: var(--font-size-lg); 428 456 font-weight: var(--font-weight-bold); 429 457 } 430 458 ··· 433 461 padding: var(--spacing-md); 434 462 border-bottom: 1px solid var(--color-border); 435 463 border-radius: 0; 464 + color: var(--color-text-menu); 436 465 } 437 466 438 467 /* Add chevron indicator */ ··· 440 469 content: "›"; 441 470 margin-left: auto; 442 471 font-size: 1.2em; 443 - opacity: 0.5; 472 + color: var(--color-text-tertiary); 444 473 } 445 474 446 475 /* In detail view, hide all categories except active */ ··· 461 490 flex-direction: column; 462 491 flex: 1; 463 492 border-radius: 0; 464 - box-shadow: none; 493 + border: none; 465 494 } 466 495 467 496 body.show-detail .settings-category.active summary { ··· 476 505 } 477 506 } 478 507 479 - /* P2P settings */ 508 + /* ===== P2P settings ===== */ 509 + 480 510 .p2p-section { 481 511 margin-top: var(--spacing-md); 482 512 padding-top: var(--spacing-md); ··· 487 517 display: flex; 488 518 gap: var(--spacing-sm); 489 519 margin-top: var(--spacing-sm); 490 - justify-items: center; 491 520 align-items: center; 492 521 } 493 522 ··· 507 536 white-space: nowrap; 508 537 } 509 538 510 - /* TODO: move to shared button styling */ 511 539 .p2p-name-row button:hover, 512 540 #p2p-refresh-peers:hover { 513 541 background: var(--color-menu-item-hover); ··· 565 593 566 594 .p2p-peer-id { 567 595 font-size: var(--font-size-sm); 568 - opacity: var(--opacity-muted); 596 + color: var(--color-text-tertiary); 569 597 word-break: break-all; 570 598 } 571 599 572 600 .p2p-peer-status { 573 - font-size: var(--font-size-sm); 601 + font-size: var(--font-size-xs); 602 + font-weight: var(--font-weight-bold); 574 603 padding: 2px var(--spacing-sm); 575 604 border-radius: var(--radius-sm); 576 605 white-space: nowrap; 577 606 } 578 607 579 608 .p2p-peer-status.discovered { 580 - background: var(--color-border); 609 + background: var(--bg-hover); 610 + color: var(--color-text-secondary); 581 611 } 582 612 583 613 /* TODO: don't hardcode colors */ 584 614 .p2p-peer-status.paired-connected { 585 - background: #2d5a2d; 586 - color: #8fdf8f; 615 + background: oklch(40% 0.08 145 / 0.5); 616 + color: oklch(75% 0.12 145); 587 617 } 588 618 589 619 .p2p-peer-status.paired-disconnected { 590 - background: #5a3a2d; 591 - color: #df9f8f; 620 + background: oklch(40% 0.08 45 / 0.5); 621 + color: oklch(75% 0.1 45); 592 622 } 593 623 594 624 .p2p-peer-actions { ··· 610 640 611 641 .p2p-remove-btn:hover { 612 642 background: var(--color-danger); 613 - color: white; 643 + color: var(--color-text-on-header); 614 644 } 615 645 616 646 .p2p-remove-btn:disabled { ··· 618 648 cursor: not-allowed; 619 649 } 620 650 621 - /* ATProto */ 651 + /* ===== ATProto ===== */ 652 + 622 653 .atproto-btn { 623 654 padding: var(--spacing-sm) var(--spacing-md); 624 655 border: 1px solid var(--color-border); ··· 646 677 647 678 .atproto-btn-danger:hover { 648 679 background: var(--color-danger); 649 - color: white; 680 + color: var(--color-text-on-header); 650 681 } 651 682 652 683 .atproto-error { ··· 654 685 font-size: var(--font-size-sm); 655 686 margin-top: var(--spacing-xs); 656 687 padding: var(--spacing-xs) var(--spacing-sm); 657 - background: rgba(255, 0, 0, 0.1); 688 + background: oklch(55% 0.15 25 / 0.1); 658 689 border-radius: var(--radius-sm); 659 690 } 660 691 ··· 666 697 display: flex; 667 698 align-items: center; 668 699 justify-content: space-between; 669 - padding: var(--spacing-xs) 0; 700 + padding: var(--spacing-sm) 0; 670 701 border-bottom: 1px solid var(--color-border); 702 + gap: var(--spacing-md); 671 703 } 672 704 673 705 .atproto-origin-item:last-child { ··· 684 716 border: 1px solid var(--color-danger); 685 717 color: var(--color-danger); 686 718 cursor: pointer; 687 - padding: var(--spacing-sm) var(--spacing-md); 719 + padding: var(--spacing-xs) var(--spacing-sm); 688 720 font-size: var(--font-size-sm); 689 721 white-space: nowrap; 690 722 border-radius: var(--radius-sm); ··· 695 727 696 728 .atproto-origin-remove:hover { 697 729 background: var(--color-danger); 698 - color: white; 730 + color: var(--color-text-on-header); 699 731 } 700 732 701 733 .atproto-origin-remove:disabled {
+24 -24
ui/system/index.css
··· 316 316 background: var(--bg-menu); 317 317 color: var(--color-text-menu); 318 318 border: 1px solid var(--color-border); 319 - border-radius: 12px; 320 - padding: 1.5rem; 319 + border-radius: var(--radius-md); 320 + padding: var(--spacing-lg); 321 321 min-width: 320px; 322 322 max-width: 90vw; 323 - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); 323 + box-shadow: 0 8px 32px var(--color-shadow); 324 324 } 325 325 326 326 #pairing-dialog::backdrop, 327 327 #p2p-open-dialog::backdrop { 328 - background: rgba(0, 0, 0, 0.6); 328 + background: var(--color-backdrop); 329 329 z-index: 9999; 330 330 } 331 331 332 332 #pairing-dialog h2, 333 333 #p2p-open-dialog h2 { 334 - font-size: 1.1rem; 335 - margin: 0 0 1rem; 334 + font-size: var(--font-size-lg); 335 + margin: 0 0 var(--spacing-md); 336 336 } 337 337 338 338 .pairing-request-item { 339 - padding: 0.75rem; 340 - margin: 0.5rem 0; 339 + padding: var(--spacing-sm) var(--spacing-md); 340 + margin: var(--spacing-sm) 0; 341 341 background: var(--bg-webview); 342 - border-radius: 8px; 342 + border-radius: var(--radius-sm); 343 343 } 344 344 345 345 .pairing-request-name { 346 - font-weight: bold; 346 + font-weight: var(--font-weight-bold); 347 347 } 348 348 349 349 .pairing-request-id { 350 - font-size: 0.75rem; 351 - opacity: 0.7; 350 + font-size: var(--font-size-xs); 351 + color: var(--color-text-tertiary); 352 352 word-break: break-all; 353 - margin-bottom: 0.5rem; 353 + margin-bottom: var(--spacing-sm); 354 354 } 355 355 356 356 .pairing-request-buttons { 357 357 display: flex; 358 - gap: 0.5rem; 358 + gap: var(--spacing-sm); 359 359 } 360 360 361 361 .pairing-request-buttons button { 362 - padding: 0.4rem 1rem; 362 + padding: 0.4rem var(--spacing-md); 363 363 border: none; 364 - border-radius: 6px; 364 + border-radius: var(--radius-sm); 365 365 cursor: pointer; 366 - font-size: 0.85rem; 366 + font-size: var(--font-size-sm); 367 367 } 368 368 369 369 .btn-accept { 370 - background: #2d7a2d; 371 - color: white; 370 + background: var(--color-primary); 371 + color: var(--color-text-on-header); 372 372 } 373 373 374 374 .btn-reject { 375 - background: #7a2d2d; 376 - color: white; 375 + background: var(--color-danger); 376 + color: var(--color-text-on-header); 377 377 } 378 378 379 379 .btn-close-dialog { 380 - margin-top: 1rem; 381 - padding: 0.5rem 1.5rem; 380 + margin-top: var(--spacing-md); 381 + padding: var(--spacing-sm) var(--spacing-lg); 382 382 background: transparent; 383 383 border: 1px solid var(--color-border); 384 384 color: inherit; 385 - border-radius: 6px; 385 + border-radius: var(--radius-sm); 386 386 cursor: pointer; 387 387 }
+19 -7
ui/system/menu_shared.css
··· 4 4 5 5 menu { 6 6 background: var(--bg-menu); 7 + border: 1px solid var(--color-border); 7 8 border-radius: var(--radius-sm); 8 - box-shadow: 0 4px 12px var(--color-shadow-menu); 9 + box-shadow: 0 4px 16px var(--color-shadow-menu); 9 10 min-width: var(--size-menu-width); 10 11 overflow: hidden; 11 12 font-family: var(--font-family-base); 12 13 font-size: var(--font-size-menu); 13 14 padding-left: 0; 15 + animation: menu-in 0.15s cubic-bezier(0.16, 1, 0.3, 1); 16 + transform-origin: top left; 14 17 } 15 18 16 19 menu li { 17 20 display: flex; 18 21 align-items: center; 19 22 gap: var(--spacing-md); 20 - padding: var(--spacing-sm) 0.75em; 23 + padding: var(--spacing-sm) var(--spacing-md); 21 24 cursor: pointer; 22 25 color: var(--color-text-menu); 23 26 white-space: nowrap; 24 - } 25 - 26 - menu li.menu-separator { 27 - padding-top: 0; 28 - padding-bottom: 0; 27 + transition: background var(--transition-fast); 29 28 } 30 29 31 30 menu li.menu-separator { 32 31 height: 1px; 33 32 background: var(--color-border); 34 33 margin: var(--spacing-xs); 34 + padding: 0; 35 + pointer-events: none; 35 36 } 36 37 37 38 menu li:hover { ··· 50 51 :host([open]) { 51 52 display: block; 52 53 } 54 + 55 + @keyframes menu-in { 56 + from { 57 + opacity: 0; 58 + transform: scale(0.95); 59 + } 60 + to { 61 + opacity: 1; 62 + transform: scale(1); 63 + } 64 + }
+32 -31
ui/system/mobile.css
··· 27 27 opacity: 0; 28 28 visibility: hidden; 29 29 transition: 30 - opacity 0.3s ease, 31 - visibility 0.3s ease, 32 - bottom 0.3s ease; 30 + opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1), 31 + visibility 0.3s cubic-bezier(0.16, 1, 0.3, 1), 32 + bottom 0.3s cubic-bezier(0.16, 1, 0.3, 1); 33 33 z-index: var(--z-base); 34 34 } 35 35 ··· 61 61 62 62 /* Mobile action bar adjustments when keyboard is open */ 63 63 body.mobile-mode mobile-action-bar { 64 - transition: bottom var(--transition-fast) ease; 64 + transition: bottom var(--transition-fast); 65 65 } 66 66 67 67 body.mobile-mode.keyboard-open mobile-action-bar { ··· 81 81 z-index: var(--z-gesture); 82 82 display: flex; 83 83 flex-direction: column; 84 - box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); 84 + box-shadow: 0 0 20px var(--color-shadow); 85 85 opacity: 0; 86 86 visibility: hidden; 87 87 } ··· 119 119 width: 20px; 120 120 height: 20px; 121 121 object-fit: contain; 122 - border-radius: 4px; 122 + border-radius: var(--radius-sm); 123 123 } 124 124 125 125 .peek-favicon[src=""] { ··· 128 128 129 129 .peek-title { 130 130 flex: 1; 131 - font-size: 14px; 132 - font-weight: 600; 131 + font-size: var(--font-size-sm); 132 + font-weight: var(--font-weight-bold); 133 133 color: var(--color-text-menu); 134 134 white-space: nowrap; 135 135 overflow: hidden; ··· 154 154 transform: translateX(-50%); 155 155 display: flex; 156 156 gap: 6px; 157 - padding: 8px 12px; 158 - background: rgba(0, 0, 0, 0.6); 159 - border-radius: 16px; 157 + padding: var(--spacing-sm) var(--spacing-md); 158 + background: var(--color-backdrop); 159 + border-radius: var(--radius-lg); 160 160 z-index: var(--z-gesture); 161 161 opacity: 0; 162 162 visibility: hidden; 163 163 transition: 164 - opacity 0.2s ease, 165 - visibility 0.2s ease; 164 + opacity var(--transition-fast), 165 + visibility var(--transition-fast); 166 166 } 167 167 168 168 .mobile-tab-indicator.visible { ··· 174 174 width: 8px; 175 175 height: 8px; 176 176 border-radius: 50%; 177 - background: rgba(255, 255, 255, 0.3); 177 + background: var(--color-text-on-header); 178 + opacity: 0.3; 178 179 transition: 179 - background 0.2s ease, 180 - transform 0.2s ease; 180 + opacity var(--transition-fast), 181 + transform var(--transition-fast); 181 182 } 182 183 183 184 .tab-dot.active { 184 185 background: var(--color-focus-ring); 186 + opacity: 1; 185 187 transform: scale(1.2); 186 188 } 187 189 ··· 227 229 } 228 230 229 231 body.mobile-mode .mobile-webview-container.slide-in-left { 230 - animation: slideInFromLeft 0.3s ease forwards; 232 + animation: slideInFromLeft 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards; 231 233 } 232 234 233 235 body.mobile-mode .mobile-webview-container.slide-in-right { 234 - animation: slideInFromRight 0.3s ease forwards; 236 + animation: slideInFromRight 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards; 235 237 } 236 238 237 239 body.mobile-mode .mobile-webview-container.slide-out-left { 238 - animation: slideOutToLeft 0.3s ease forwards; 240 + animation: slideOutToLeft 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards; 239 241 } 240 242 241 243 body.mobile-mode .mobile-webview-container.slide-out-right { 242 - animation: slideOutToRight 0.3s ease forwards; 244 + animation: slideOutToRight 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards; 243 245 } 244 246 245 247 /* ============================================================================ ··· 251 253 z-index: var(--z-gesture); 252 254 pointer-events: none; 253 255 opacity: 0; 254 - transition: opacity 0.15s ease; 256 + transition: opacity var(--transition-fast); 255 257 } 256 258 257 259 .edge-feedback.active { ··· 296 298 touch-action: none; 297 299 pointer-events: auto; 298 300 background: transparent; 299 - /* background: rgba(77, 215, 220, 0.49); */ 300 301 } 301 302 302 303 /* Expand edge overlay to full screen during active gesture, ··· 321 322 right: 0; 322 323 bottom: 0; 323 324 z-index: var(--z-modal); 324 - background: black; 325 + background: oklch(12% 0.02 105); 325 326 display: none; 326 327 align-items: center; 327 328 justify-content: center; 328 329 opacity: 1; 329 - transition: opacity 0.4s ease-out; 330 + transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1); 330 331 } 331 332 332 333 body.mobile-mode .mobile-splash.active { ··· 347 348 348 349 .splash-logo { 349 350 font-size: 2.5em; 350 - color: wheat; 351 + color: oklch(85% 0.06 85); 351 352 } 352 353 353 354 .splash-spinner { 354 355 font-size: 2em; 355 - color: wheat; 356 + color: oklch(85% 0.06 85); 356 357 animation: splash-spin 1.5s linear infinite; 357 358 } 358 359 ··· 369 370 display: flex; 370 371 flex-direction: column; 371 372 align-items: center; 372 - font-family: monospace; 373 - color: lightgray; 374 - gap: 0.5em; 373 + font-family: var(--font-family-base); 374 + color: oklch(70% 0.01 105); 375 + gap: var(--spacing-sm); 375 376 } 376 377 377 378 #powered-by-logos { 378 379 display: flex; 379 - gap: 1em; 380 + gap: var(--spacing-md); 380 381 } 381 382 382 383 #powered-by-logos img { 383 384 height: 16px; 384 - } 385 + }
+55 -35
ui/system/mobile_action_bar.css
··· 19 19 left: 0; 20 20 right: 0; 21 21 bottom: var(--keyboard-offset); 22 - background: rgba(0, 0, 0, 0.3); 22 + background: var(--color-backdrop); 23 23 opacity: 0; 24 - transition: opacity 0.2s ease; 24 + transition: opacity var(--transition-fast); 25 25 pointer-events: none; 26 26 } 27 27 ··· 32 32 33 33 .action-bar { 34 34 position: relative; 35 - background: var(--bg-menu); 36 - border-radius: var(--radius-md) var(--radius-md) 0 0; 37 - padding: var(--spacing-xs); 35 + background: var(--bg-surface); 36 + border-radius: var(--radius-lg) var(--radius-lg) 0 0; 37 + padding: var(--spacing-sm) var(--spacing-sm) 0; 38 38 transform: translateY(100%); 39 - transition: transform 0.3s ease; 39 + transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1); 40 40 pointer-events: auto; 41 - box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.3); 41 + box-shadow: 0 -2px 16px var(--color-shadow); 42 42 } 43 43 44 44 :host([open]) .action-bar { 45 45 transform: translateY(0); 46 46 } 47 47 48 + /* Search input — pill style matching homescreen */ 48 49 .url-input-container { 49 50 display: flex; 50 51 align-items: center; 51 - background: var(--bg-webview); 52 - border: 2px solid var(--color-border); 53 - border-radius: var(--radius-md); 54 - padding: var(--spacing-xs) var(--spacing-md); 55 - margin-bottom: var(--spacing-xs); 52 + background: var(--bg-menu); 53 + border: none; 54 + border-radius: var(--radius-lg); 55 + padding: var(--spacing-sm) var(--spacing-md); 56 + box-shadow: 0 1px 4px var(--color-shadow-menu); 57 + transition: 58 + box-shadow 0.25s cubic-bezier(0.16, 1, 0.3, 1), 59 + background 0.25s cubic-bezier(0.16, 1, 0.3, 1); 56 60 } 57 61 58 - .url-input-container:focus { 59 - border-color: var(--color-focus-ring); 62 + .url-input-container:focus-within { 63 + background: var(--bg-webview); 64 + box-shadow: 65 + 0 2px 8px var(--color-shadow), 66 + 0 0 0 2px var(--color-focus-ring); 60 67 } 61 68 62 69 .url-input-container lucide-icon { 63 70 color: var(--color-text-tertiary); 64 - margin-right: var(--spacing-xs); 71 + margin-right: var(--spacing-sm); 65 72 flex-shrink: 0; 73 + transition: color var(--transition-fast); 74 + } 75 + 76 + .url-input-container:focus-within lucide-icon { 77 + color: var(--color-primary); 66 78 } 67 79 68 80 .url-input { ··· 70 82 border: none; 71 83 background: transparent; 72 84 font-size: 16px; 85 + font-family: var(--font-family-base); 73 86 color: var(--color-text-menu); 74 87 outline: none; 75 88 } ··· 78 91 color: var(--color-text-tertiary); 79 92 } 80 93 94 + /* Quick actions — more presence */ 81 95 .quick-actions { 82 96 display: flex; 83 97 justify-content: space-around; 84 98 align-items: center; 85 - padding: var(--spacing-xs) 0; 99 + padding: var(--spacing-sm) 0; 86 100 } 87 101 88 102 .action-button { 89 103 display: flex; 90 104 flex-direction: column; 91 105 align-items: center; 92 - gap: 4px; 93 - padding: var(--spacing-xs); 106 + gap: var(--spacing-xs); 107 + padding: var(--spacing-sm); 94 108 background: transparent; 95 109 border: none; 96 - color: var(--color-text-menu); 110 + color: var(--color-text-secondary); 97 111 cursor: pointer; 98 - border-radius: var(--radius-sm); 99 - transition: background 0.2s ease; 100 - min-width: 60px; 112 + border-radius: var(--radius-md); 113 + transition: 114 + background var(--transition-fast), 115 + color var(--transition-fast); 116 + min-width: 52px; 101 117 } 102 118 103 119 .action-button:hover, 104 120 .action-button:active { 105 - background: var(--color-menu-item-hover)); 121 + background: var(--bg-hover); 122 + color: var(--color-text-menu); 106 123 } 107 124 108 125 .action-button:disabled { 109 - opacity: 0.3; 126 + opacity: 0.25; 110 127 cursor: not-allowed; 111 128 } 112 129 113 130 .action-button lucide-icon { 114 - font-size: 24px; 131 + font-size: 22px; 115 132 } 116 133 117 134 .view-count { 118 135 position: absolute; 119 136 top: -4px; 120 137 right: -4px; 121 - background: var(--color-focus-ring); 122 - color: white; 138 + background: var(--color-primary); 139 + color: var(--color-text-on-header); 123 140 font-size: 10px; 124 141 min-width: 16px; 125 142 height: 16px; ··· 128 145 align-items: center; 129 146 justify-content: center; 130 147 padding: 0 4px; 148 + font-weight: var(--font-weight-bold); 131 149 } 132 150 133 151 .views-button { 134 152 position: relative; 135 153 } 136 154 137 - /* Search Results */ 155 + /* Search Results — visually separated from the bar */ 138 156 .results-area { 139 157 max-height: 40vh; 140 158 overflow-y: auto; 141 - margin-bottom: var(--spacing-xs); 159 + padding: 0 var(--spacing-xs) var(--spacing-sm); 160 + margin-bottom: var(--spacing-sm); 161 + border-bottom: 1px solid var(--color-border); 142 162 } 143 163 144 164 .result-group { ··· 156 176 157 177 .result-group-icon lucide-icon { 158 178 font-size: 1em; 159 - opacity: 0.5; 179 + color: var(--color-text-tertiary); 160 180 } 161 181 162 182 .result-group-items { ··· 165 185 166 186 .result-item { 167 187 padding: var(--spacing-sm) var(--spacing-md); 168 - background: var(--bg-webview); 169 - transition: background 0.15s ease; 188 + background: var(--bg-menu); 189 + transition: background var(--transition-fast); 170 190 } 171 191 172 192 .result-group-items .result-item:first-child { ··· 190 210 .result-item[data-kind="link"]:active, 191 211 .result-item[data-kind="webview"]:hover, 192 212 .result-item[data-kind="webview"]:active { 193 - background: var(--bg-header); 213 + background: var(--bg-hover); 194 214 } 195 215 196 216 .result-link { 197 217 color: var(--color-primary); 198 218 text-decoration: none; 199 - font-weight: 600; 219 + font-weight: var(--font-weight-bold); 200 220 display: block; 201 221 } 202 222 203 223 .result-item[data-kind="link"]:hover .result-link, 204 224 .result-item[data-kind="webview"]:hover .result-link { 205 - color: var(--color-text-on-header); 225 + color: var(--color-text-menu); 206 226 } 207 227 208 228 .result-item[data-kind="text"] {
+33 -25
ui/system/mobile_notification_sheet.css
··· 16 16 left: 0; 17 17 right: 0; 18 18 bottom: 0; 19 - background: rgba(0, 0, 0, 0.3); 19 + background: var(--color-backdrop); 20 20 opacity: 0; 21 - transition: opacity 0.2s ease; 21 + transition: opacity var(--transition-fast); 22 22 pointer-events: none; 23 23 } 24 24 ··· 36 36 background: var(--bg-menu); 37 37 border-radius: 0 0 var(--radius-lg) var(--radius-lg); 38 38 transform: translateY(-100%); 39 - transition: transform 0.3s ease; 39 + transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1); 40 40 pointer-events: auto; 41 - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); 41 + box-shadow: 0 4px 20px var(--color-shadow); 42 42 display: flex; 43 43 flex-direction: column; 44 44 overflow: hidden; ··· 60 60 display: flex; 61 61 align-items: center; 62 62 gap: var(--spacing-sm); 63 - font-size: 14px; 63 + font-size: var(--font-size-sm); 64 64 color: var(--color-text-menu); 65 65 } 66 66 67 67 .tab-count { 68 - background: var(--color-focus-ring); 69 - color: white; 68 + background: var(--color-primary); 69 + color: var(--color-text-on-header); 70 70 padding: 2px 8px; 71 71 border-radius: 12px; 72 - font-size: 12px; 73 - font-weight: 600; 72 + font-size: var(--font-size-xs); 73 + font-weight: var(--font-weight-bold); 74 74 } 75 75 76 76 .clear-all-button { 77 77 background: transparent; 78 78 border: none; 79 - color: var(--color-focus-ring); 80 - font-size: 14px; 79 + color: var(--color-primary); 80 + font-size: var(--font-size-sm); 81 81 cursor: pointer; 82 82 padding: var(--spacing-xs) var(--spacing-sm); 83 + border-radius: var(--radius-sm); 84 + transition: background var(--transition-fast); 85 + } 86 + 87 + .clear-all-button:hover { 88 + background: var(--bg-hover); 83 89 } 84 90 85 91 .clear-all-button:disabled { ··· 102 108 border-radius: var(--radius-md); 103 109 margin-bottom: var(--spacing-sm); 104 110 cursor: pointer; 105 - transition: background 0.2s ease, transform 0.2s ease; 111 + transition: 112 + background var(--transition-fast), 113 + transform var(--transition-fast); 106 114 position: relative; 107 115 } 108 116 ··· 117 125 .notification-icon { 118 126 width: 40px; 119 127 height: 40px; 120 - border-radius: 8px; 121 - background: var(--bg-header); 128 + border-radius: var(--radius-sm); 129 + background: var(--bg-icon); 122 130 display: flex; 123 131 align-items: center; 124 132 justify-content: center; ··· 133 141 134 142 .notification-icon lucide-icon { 135 143 font-size: 20px; 136 - color: var(--color-text-tertiary); 144 + color: var(--color-primary); 137 145 } 138 146 139 147 .notification-content { ··· 142 150 } 143 151 144 152 .notification-title { 145 - font-weight: 600; 146 - font-size: 14px; 153 + font-weight: var(--font-weight-bold); 154 + font-size: var(--font-size-sm); 147 155 color: var(--color-text-menu); 148 156 white-space: nowrap; 149 157 overflow: hidden; ··· 151 159 } 152 160 153 161 .notification-body { 154 - font-size: 13px; 155 - color: var(--color-text-tertiary); 162 + font-size: var(--font-size-xs); 163 + color: var(--color-text-secondary); 156 164 margin-top: 2px; 157 165 overflow: hidden; 158 166 } 159 167 160 168 .notification-time { 161 - font-size: 11px; 169 + font-size: var(--font-size-xs); 162 170 color: var(--color-text-tertiary); 163 - margin-top: 4px; 171 + margin-top: var(--spacing-xs); 164 172 } 165 173 166 174 .dismiss-button { ··· 170 178 padding: var(--spacing-xs); 171 179 cursor: pointer; 172 180 opacity: 0; 173 - transition: opacity 0.2s ease; 181 + transition: opacity var(--transition-fast); 174 182 } 175 183 176 184 .notification-item:hover .dismiss-button { ··· 182 190 flex-direction: column; 183 191 align-items: center; 184 192 justify-content: center; 185 - padding: var(--spacing-md); 193 + padding: var(--spacing-lg); 186 194 color: var(--color-text-tertiary); 187 195 } 188 196 189 197 .empty-state lucide-icon { 190 198 font-size: 48px; 191 199 margin-bottom: var(--spacing-md); 192 - opacity: 0.5; 200 + opacity: var(--opacity-muted); 193 201 } 194 202 195 203 .empty-state-text { 196 - font-size: 14px; 204 + font-size: var(--font-size-sm); 197 205 }
+19 -20
ui/system/mobile_overview.css
··· 22 22 bottom: 0; 23 23 background: var(--bg-main); 24 24 opacity: 0; 25 - transition: opacity 0.3s ease; 25 + transition: opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1); 26 26 } 27 27 28 28 :host([open]) .overlay { ··· 40 40 opacity: 0; 41 41 transform: scale(0.9); 42 42 transition: 43 - opacity 0.3s ease, 44 - transform 0.3s ease; 43 + opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1), 44 + transform 0.3s cubic-bezier(0.16, 1, 0.3, 1); 45 45 } 46 46 47 47 :host([open]) .container { ··· 54 54 align-items: center; 55 55 justify-content: space-between; 56 56 padding: var(--spacing-md); 57 - padding-top: var(--spacing-md); 58 57 } 59 58 60 59 .header-title { 61 - font-size: 18px; 62 - font-weight: 600; 60 + font-size: var(--font-size-xl); 61 + font-weight: var(--font-weight-bold); 63 62 color: var(--color-text-menu); 64 63 } 65 64 ··· 84 83 overflow: hidden; 85 84 cursor: pointer; 86 85 transition: 87 - transform 0.2s ease, 88 - box-shadow 0.2s ease; 86 + transform var(--transition-fast), 87 + box-shadow var(--transition-fast); 89 88 position: relative; 90 89 } 91 90 92 91 .tab-card:hover { 93 92 transform: translateY(-2px); 94 - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); 93 + box-shadow: 0 4px 16px var(--color-shadow); 95 94 } 96 95 97 96 .tab-card.active { ··· 99 98 } 100 99 101 100 .tab-card.closing { 102 - animation: cardClose 0.3s ease forwards; 101 + animation: cardClose 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards; 103 102 } 104 103 105 104 @keyframes cardClose { ··· 129 128 .tab-screenshot-placeholder lucide-icon { 130 129 font-size: 32px; 131 130 color: var(--color-text-tertiary); 132 - opacity: 0.5; 131 + opacity: var(--opacity-muted); 133 132 } 134 133 135 134 .tab-info { ··· 153 152 154 153 .tab-title { 155 154 flex: 1; 156 - font-size: 12px; 155 + font-size: var(--font-size-xs); 157 156 color: var(--color-text-menu); 158 157 white-space: nowrap; 159 158 overflow: hidden; ··· 166 165 right: var(--spacing-xs); 167 166 width: 24px; 168 167 height: 24px; 169 - background: rgba(0, 0, 0, 0.6); 168 + background: var(--color-backdrop); 170 169 border: none; 171 170 border-radius: 50%; 172 - color: white; 171 + color: var(--color-text-on-header); 173 172 display: flex; 174 173 align-items: center; 175 174 justify-content: center; ··· 177 176 } 178 177 179 178 .close-button lucide-icon { 180 - font-size: 14px; 179 + font-size: var(--font-size-sm); 181 180 } 182 181 183 182 .home-card { ··· 190 189 justify-content: center; 191 190 cursor: pointer; 192 191 transition: 193 - border-color 0.2s ease, 194 - background 0.2s ease; 192 + border-color var(--transition-fast), 193 + background var(--transition-fast); 195 194 min-height: 120px; 196 195 } 197 196 198 197 .home-card:hover { 199 - border-color: var(--color-focus-ring); 200 - background: rgba(0, 122, 255, 0.1); 198 + border-color: var(--color-primary); 199 + background: var(--bg-hover); 201 200 } 202 201 203 202 .home-card lucide-icon { ··· 207 206 } 208 207 209 208 .home-card span { 210 - font-size: 14px; 209 + font-size: var(--font-size-sm); 211 210 color: var(--color-text-tertiary); 212 211 }
+11 -11
ui/system/mobile_radial_menu.css
··· 20 20 left: 0; 21 21 right: 0; 22 22 bottom: 0; 23 - background: rgba(0, 0, 0, 0.3); 23 + background: var(--color-backdrop); 24 24 opacity: 0; 25 - transition: opacity 0.15s ease; 26 - z-index: 1000; 25 + transition: opacity var(--transition-fast); 26 + z-index: var(--z-dialog); 27 27 } 28 28 29 29 :host([open]) .overlay { ··· 38 38 margin-left: -100px; 39 39 margin-top: -100px; 40 40 opacity: 0; 41 - transition: opacity 0.15s ease; 42 - z-index: 2000; 41 + transition: opacity var(--transition-fast); 42 + z-index: var(--z-modal); 43 43 } 44 44 45 45 :host([open]) menu { ··· 58 58 display: flex; 59 59 align-items: center; 60 60 justify-content: center; 61 - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); 61 + box-shadow: 0 2px 10px var(--color-shadow); 62 62 transform: scale(0); 63 63 transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1); 64 64 } ··· 85 85 flex-direction: column; 86 86 align-items: center; 87 87 justify-content: center; 88 - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); 88 + box-shadow: 0 2px 10px var(--color-shadow-menu); 89 89 cursor: pointer; 90 90 /* Start at center, scale down */ 91 91 transform: translate(var(--start-x), var(--start-y)) scale(0); 92 92 transition: 93 93 transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), 94 - background 0.15s ease, 95 - box-shadow 0.15s ease; 94 + background var(--transition-fast), 95 + box-shadow var(--transition-fast); 96 96 } 97 97 98 98 :host([open]) .zone { ··· 133 133 .zone lucide-icon { 134 134 font-size: 20px; 135 135 color: var(--color-text-menu); 136 - transition: color 0.15s ease; 136 + transition: color var(--transition-fast); 137 137 } 138 138 139 139 .zone:active { 140 140 transform: translate(0, 0) scale(0.9); 141 141 background: var(--color-focus-ring); 142 - box-shadow: 0 4px 20px rgba(0, 122, 255, 0.5); 142 + box-shadow: 0 4px 20px var(--color-focus-ring); 143 143 } 144 144 145 145 .zone.disabled {
+2 -2
ui/system/new_view.css
··· 27 27 flex-direction: column; 28 28 align-items: center; 29 29 justify-content: center; 30 - transition: justify-content 0.3s ease; 30 + /* justify-content is not animatable — state change is instant */ 31 31 } 32 32 33 33 .container.has-results { ··· 89 89 max-height: 0; 90 90 overflow-y: auto; 91 91 margin-top: var(--spacing-md); 92 - transition: max-height 0.3s ease; 92 + transition: max-height 0.3s cubic-bezier(0.16, 1, 0.3, 1); 93 93 } 94 94 95 95 .container.has-results .results-container {
+4 -1
ui/system/notification_panel.css
··· 63 63 cursor: pointer; 64 64 padding: var(--spacing-xs) var(--spacing-sm); 65 65 border-radius: var(--radius-sm); 66 + transition: background var(--transition-fast); 66 67 } 67 68 68 69 .clear-btn:hover { ··· 72 73 .close-btn { 73 74 background: none; 74 75 border: none; 76 + color: var(--color-text-secondary); 75 77 cursor: pointer; 76 78 padding: var(--spacing-xs); 77 79 border-radius: var(--radius-sm); 78 80 display: flex; 79 81 align-items: center; 80 82 justify-content: center; 83 + transition: background var(--transition-fast); 81 84 } 82 85 83 86 .close-btn:hover { ··· 143 146 font-weight: var(--font-weight-bold); 144 147 font-size: var(--font-size-menu); 145 148 color: var(--color-text); 146 - margin-bottom: 2px; 149 + margin-bottom: var(--spacing-xs); 147 150 white-space: nowrap; 148 151 overflow: hidden; 149 152 text-overflow: ellipsis;
+2 -2
ui/system/overview.css
··· 69 69 70 70 .thumbnail.active { 71 71 box-shadow: 72 - 0 0 0 3px var(--color-focus-ring), 72 + 0 0 0 2px var(--color-focus-ring), 73 73 0 4px 16px var(--color-shadow); 74 74 } 75 75 76 76 .thumbnail.active:hover { 77 77 box-shadow: 78 - 0 0 0 3px var(--color-focus-ring), 78 + 0 0 0 2px var(--color-focus-ring), 79 79 0 8px 24px var(--color-shadow); 80 80 } 81 81
+2 -2
ui/system/search.css
··· 90 90 margin-top: 0; 91 91 padding: 0 var(--spacing-sm); 92 92 transition: 93 - max-height 0.3s ease, 94 - margin-top 0.3s ease; 93 + max-height 0.3s cubic-bezier(0.16, 1, 0.3, 1), 94 + margin-top 0.3s cubic-bezier(0.16, 1, 0.3, 1); 95 95 } 96 96 97 97 .container.has-results .results-container {
+38 -36
ui/system/task_chooser.js
··· 24 24 display: none; 25 25 position: fixed; 26 26 inset: 0; 27 - z-index: var(--z-modal, 8000); 27 + z-index: var(--z-modal); 28 28 } 29 29 30 30 :host([open]) { ··· 34 34 .overlay { 35 35 position: absolute; 36 36 inset: 0; 37 - background: var(--color-backdrop, rgba(0, 0, 0, 0.4)); 37 + background: var(--color-backdrop); 38 38 display: flex; 39 39 align-items: flex-end; 40 40 justify-content: center; 41 41 } 42 42 43 43 .panel { 44 - background: var(--bg-surface, #fff); 45 - border-radius: var(--radius-md, 12px) var(--radius-md, 12px) 0 0; 46 - padding: 1em; 44 + background: var(--bg-surface); 45 + border-radius: var(--radius-md) var(--radius-md) 0 0; 46 + padding: var(--spacing-md); 47 47 width: 100%; 48 48 max-width: 400px; 49 49 max-height: 60vh; 50 50 overflow-y: auto; 51 - box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.15); 52 - font-family: var(--font-family-base, system-ui, sans-serif); 51 + box-shadow: 0 -4px 20px var(--color-shadow); 52 + font-family: var(--font-family-base); 53 53 } 54 54 55 55 .title { 56 - font-size: 0.95em; 57 - font-weight: 600; 58 - color: var(--color-text, #333); 59 - margin-bottom: 0.75em; 56 + font-size: var(--font-size-menu); 57 + font-weight: var(--font-weight-bold); 58 + color: var(--color-text); 59 + margin-bottom: var(--spacing-md); 60 60 } 61 61 62 62 .provider { 63 63 display: flex; 64 64 align-items: center; 65 - gap: 0.75em; 66 - padding: 0.6em 0.5em; 67 - border-radius: var(--radius-sm, 8px); 65 + gap: var(--spacing-md); 66 + padding: var(--spacing-sm); 67 + border-radius: var(--radius-sm); 68 68 cursor: pointer; 69 - transition: background 0.15s; 69 + transition: background var(--transition-fast); 70 70 } 71 71 72 72 .provider:hover { 73 - background: var(--bg-hover, #f0f0f0); 73 + background: var(--bg-hover); 74 74 } 75 75 76 76 .provider-icon { 77 77 width: 24px; 78 78 height: 24px; 79 - border-radius: 4px; 79 + border-radius: var(--radius-sm); 80 80 object-fit: contain; 81 81 flex-shrink: 0; 82 82 } 83 83 84 84 .provider-title { 85 - font-size: 0.9em; 86 - font-weight: 500; 87 - color: var(--color-text, #333); 85 + font-size: var(--font-size-menu); 86 + font-weight: var(--font-weight-bold); 87 + color: var(--color-text); 88 88 } 89 89 90 90 .provider-description { 91 - font-size: 0.8em; 92 - color: var(--color-text-secondary, #666); 91 + font-size: var(--font-size-sm); 92 + color: var(--color-text-secondary); 93 93 } 94 94 95 95 .provider-origin { 96 - font-size: 0.75em; 97 - color: var(--color-text-secondary, #999); 96 + font-size: var(--font-size-xs); 97 + color: var(--color-text-tertiary); 98 98 } 99 99 100 100 .cancel { 101 101 display: block; 102 102 width: 100%; 103 - margin-top: 0.75em; 104 - padding: 0.6em; 105 - border: 1px solid var(--color-border, #ddd); 106 - border-radius: var(--radius-sm, 8px); 107 - background: var(--bg-surface, #fff); 108 - color: var(--color-text, #333); 109 - font-size: 0.9em; 103 + margin-top: var(--spacing-md); 104 + padding: var(--spacing-sm); 105 + border: 1px solid var(--color-border); 106 + border-radius: var(--radius-sm); 107 + background: var(--bg-surface); 108 + color: var(--color-text); 109 + font-size: var(--font-size-menu); 110 + font-family: var(--font-family-base); 110 111 cursor: pointer; 111 112 text-align: center; 113 + transition: background var(--transition-fast); 112 114 } 113 115 114 116 .cancel:hover { 115 - background: var(--bg-hover, #f0f0f0); 117 + background: var(--bg-hover); 116 118 } 117 119 118 120 .always-use { 119 121 display: flex; 120 122 align-items: center; 121 - gap: 0.5em; 122 - padding: 0.5em; 123 - font-size: 0.8em; 124 - color: var(--color-text-secondary, #666); 123 + gap: var(--spacing-sm); 124 + padding: var(--spacing-sm); 125 + font-size: var(--font-size-sm); 126 + color: var(--color-text-secondary); 125 127 cursor: pointer; 126 128 } 127 129 `;
+9 -7
ui/system/toasts.css
··· 10 10 flex-direction: column; 11 11 align-items: center; 12 12 pointer-events: none; 13 + padding-top: var(--spacing-sm); 13 14 } 14 15 15 16 .toast { ··· 17 18 color: var(--color-text); 18 19 font-family: var(--font-family-base); 19 20 font-size: var(--font-size-menu); 20 - padding: var(--spacing-sm) var(--spacing-md); 21 + padding: var(--spacing-sm) var(--spacing-lg); 21 22 margin: var(--spacing-xs); 22 - border-radius: var(--radius-md); 23 - box-shadow: 0 2px 12px var(--color-shadow); 23 + border: 1px solid var(--color-border); 24 + border-radius: var(--radius-lg); 25 + box-shadow: 0 4px 16px var(--color-shadow); 24 26 max-width: 90vw; 25 27 text-align: center; 26 - transform: translateY(-100%); 28 + transform: translateY(-8px); 27 29 opacity: 0; 28 30 transition: 29 - transform 0.3s ease, 30 - opacity 0.3s ease; 31 + transform 0.25s cubic-bezier(0.16, 1, 0.3, 1), 32 + opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1); 31 33 } 32 34 33 35 .toast.visible { ··· 36 38 } 37 39 38 40 .toast.hiding { 39 - transform: translateY(-100%); 41 + transform: translateY(-8px); 40 42 opacity: 0; 41 43 }
+38 -34
ui/system/web_view.css
··· 15 15 flex: 1; 16 16 min-width: 0; 17 17 min-height: 0; 18 - box-shadow: 0 4px 4px var(--color-shadow); 18 + box-shadow: 0 2px 8px var(--color-shadow-menu); 19 19 transition: box-shadow var(--transition-fast); 20 20 position: relative; /* Needed for absolutely positioned menu overlay */ 21 21 } 22 22 23 23 :host .wrapper.active { 24 24 box-shadow: 25 - 0 0 0 3px var(--color-focus-ring), 26 - 0 4px 4px var(--color-shadow); 25 + 0 0 0 2px var(--color-focus-ring), 26 + 0 2px 12px var(--color-shadow); 27 27 } 28 28 29 29 /* Container for iframe and dialog overlay */ ··· 49 49 padding: var(--spacing-xs) var(--spacing-sm) var(--spacing-xs) 50 50 var(--spacing-sm); 51 51 border-radius: var(--radius-md) var(--radius-md) 0 0; 52 - box-shadow: 0 4px 4px var(--color-shadow); 52 + box-shadow: 0 1px 4px var(--color-shadow-menu); 53 53 position: relative; 54 54 transition: 55 55 opacity var(--transition-fast), ··· 220 220 position: absolute; 221 221 bottom: 0; 222 222 left: 0; 223 - height: 3px; 223 + height: 2px; 224 224 background: var(--color-primary); 225 225 transition: 226 - width 0.3s ease-out, 227 - opacity 0.3s ease; 226 + width 0.3s cubic-bezier(0.16, 1, 0.3, 1), 227 + opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1); 228 228 opacity: 0; 229 229 width: 0; 230 230 z-index: var(--z-base); ··· 233 233 :host .load-progress.load-started { 234 234 width: 30%; 235 235 opacity: 1; 236 - animation: load-shimmer 1.5s infinite; 236 + animation: load-travel 1.8s cubic-bezier(0.4, 0, 0.2, 1) infinite; 237 237 } 238 238 239 239 :host .load-progress.load-headparsed { 240 240 width: 65%; 241 241 opacity: 1; 242 - animation: load-shimmer 1.5s infinite; 242 + animation: load-travel 1.8s cubic-bezier(0.4, 0, 0.2, 1) infinite; 243 243 } 244 244 245 245 :host .load-progress.load-complete { 246 246 width: 100%; 247 247 opacity: 0; 248 + animation: none; 248 249 transition: 249 - width 0.2s ease-out, 250 - opacity 0.4s ease 0.2s; 250 + width 0.2s cubic-bezier(0.16, 1, 0.3, 1), 251 + opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1) 0.2s; 251 252 } 252 253 253 - @keyframes load-shimmer { 254 - 0%, 255 - 100% { 256 - filter: brightness(1); 254 + @keyframes load-travel { 255 + 0% { 256 + opacity: 1; 257 257 } 258 258 50% { 259 - filter: brightness(1.3); 259 + opacity: 0.5; 260 + } 261 + 100% { 262 + opacity: 1; 260 263 } 261 264 } 262 265 ··· 288 291 :host .inline-provider-overlay { 289 292 position: absolute; 290 293 inset: 0; 291 - background: var(--color-backdrop, rgba(0, 0, 0, 0.4)); 294 + background: var(--color-backdrop); 292 295 display: flex; 293 296 align-items: center; 294 297 justify-content: center; 295 - z-index: var(--z-dialog, 1000); 298 + z-index: var(--z-dialog); 296 299 } 297 300 298 301 :host .inline-provider-dialog { 299 - background: var(--bg-surface, #fff); 300 - border-radius: var(--radius-md, 12px); 302 + background: var(--bg-surface); 303 + border-radius: var(--radius-md); 301 304 width: 90%; 302 305 max-width: 500px; 303 306 height: 70%; 304 307 max-height: 600px; 305 308 display: flex; 306 309 flex-direction: column; 307 - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); 310 + box-shadow: 0 8px 32px var(--color-shadow); 308 311 overflow: hidden; 309 312 } 310 313 311 314 :host .inline-provider-header { 312 315 display: flex; 313 316 align-items: center; 314 - gap: 0.5em; 315 - padding: var(--spacing-xs, 0.5em) var(--spacing-sm, 0.75em); 316 - background: var(--bg-surface, #f5f5f5); 317 - border-bottom: 1px solid var(--color-border, #ddd); 318 - font-family: var(--font-family-base, system-ui, sans-serif); 317 + gap: var(--spacing-sm); 318 + padding: var(--spacing-xs) var(--spacing-sm); 319 + background: var(--bg-surface); 320 + border-bottom: 1px solid var(--color-border); 321 + font-family: var(--font-family-base); 319 322 } 320 323 321 324 :host .inline-provider-title { 322 325 flex: 1; 323 - font-size: 0.85em; 324 - font-weight: 600; 325 - color: var(--color-text, #333); 326 + font-size: var(--font-size-sm); 327 + font-weight: var(--font-weight-bold); 328 + color: var(--color-text); 326 329 } 327 330 328 331 :host .inline-provider-close { 329 332 background: none; 330 333 border: none; 331 - font-size: 1.2em; 334 + font-size: var(--font-size-lg); 332 335 cursor: pointer; 333 - padding: 0.2em 0.4em; 334 - color: var(--color-text, #666); 335 - border-radius: 4px; 336 + padding: var(--spacing-xs) var(--spacing-sm); 337 + color: var(--color-text-secondary); 338 + border-radius: var(--radius-sm); 339 + transition: background var(--transition-fast); 336 340 } 337 341 338 342 :host .inline-provider-close:hover { 339 - background: var(--bg-hover, #e0e0e0); 343 + background: var(--bg-hover); 340 344 } 341 345 342 346 :host .inline-provider-dialog iframe {
+1
ui/system/webview_menu.css
··· 15 15 menu { 16 16 position: absolute; 17 17 z-index: 1001; 18 + transform-origin: top right; 18 19 }
+27 -24
ui/themes/default/index.css
··· 5 5 --font-family-base: ReadexPro; 6 6 --font-weight-normal: normal; 7 7 --font-weight-bold: bolder; 8 + --font-size-xl: 1.5em; 9 + --font-size-lg: 1.15em; 8 10 --font-size-menu: 0.9em; 9 11 --font-size-sm: 0.85em; 10 12 --font-size-xs: 0.75em; ··· 12 14 /* ===== Backgrounds ===== */ 13 15 --bg-main: linear-gradient( 14 16 to bottom right in oklab, 15 - oklch(95% 0.5 110) 0%, 16 - oklch(72% 0.5 90) 100% 17 + oklch(94% 0.08 115) 0%, 18 + oklch(82% 0.1 100) 100% 17 19 ); 18 - --bg-header: oklch(95% 0.5 110); 19 - --bg-footer: oklch(72% 0.5 90); 20 - --bg-webview: white; 21 - --bg-menu: white; 22 - --bg-surface: white; 23 - --bg-hover: rgba(0, 0, 0, 0.05); 24 - --bg-icon: oklch(92% 0.05 220); 20 + --bg-header: oklch(94% 0.08 115); 21 + --bg-footer: oklch(82% 0.1 100); 22 + --bg-webview: oklch(99% 0.005 105); 23 + --bg-menu: oklch(98% 0.008 105); 24 + --bg-surface: oklch(97% 0.01 105); 25 + --bg-hover: oklch(88% 0.03 105 / 0.4); 26 + --bg-icon: oklch(92% 0.04 105); 25 27 26 28 /* ===== Colors - Text ===== */ 27 - --color-text-menu: black; 28 - --color-text: black; 29 - --color-text-secondary: oklch(45% 0 0); 30 - --color-text-tertiary: oklch(60% 0 0); 29 + --color-text-menu: oklch(22% 0.02 105); 30 + --color-text: oklch(22% 0.02 105); 31 + --color-text-secondary: oklch(42% 0.015 105); 32 + --color-text-tertiary: oklch(58% 0.01 105); 31 33 /* Contrast text for use on header/primary backgrounds */ 32 - --color-text-on-header: white; 34 + --color-text-on-header: oklch(99% 0.005 105); 33 35 34 36 /* ===== Colors - Interactive ===== */ 35 - --color-focus-ring: rgba(0, 120, 255, 0.5); 36 - --color-resize-handle-hover: rgba(0, 120, 255, 0.3); 37 - --color-primary: oklch(55% 0.2 250); 38 - --color-danger: oklch(55% 0.2 25); 37 + --color-focus-ring: oklch(55% 0.12 145 / 0.5); 38 + --color-resize-handle-hover: oklch(55% 0.12 145 / 0.3); 39 + --color-primary: oklch(48% 0.12 155); 40 + --color-danger: oklch(52% 0.15 25); 39 41 40 - --color-menu-item-hover: rgba(0, 0, 0, 0.1); 42 + --color-menu-item-hover: oklch(70% 0.04 105 / 0.2); 41 43 42 44 /* ===== Colors - Borders ===== */ 43 - --color-border: rgba(0, 0, 0, 0.15); 45 + --color-border: oklch(50% 0.02 105 / 0.18); 44 46 45 47 /* ===== Colors - Shadow ===== */ 46 - --color-shadow: rgba(0, 0, 0, 0.3); 47 - --color-shadow-menu: rgba(0, 0, 0, 0.2); 48 - --color-backdrop: rgba(0, 0, 0, 0.5); 48 + --color-shadow: oklch(35% 0.03 105 / 0.2); 49 + --color-shadow-menu: oklch(35% 0.03 105 / 0.12); 50 + --color-backdrop: oklch(25% 0.02 105 / 0.45); 49 51 50 52 /* ===== Border Radius ===== */ 51 53 --radius-sm: 0.5em; ··· 57 59 --spacing-sm: 0.5em; 58 60 --spacing-md: 1em; 59 61 --spacing-lg: 1.5em; 62 + --spacing-xl: 2.5em; 60 63 61 64 /* ===== Sizes ===== */ 62 65 --size-header-height: 2em; ··· 69 72 --size-notification-icon: 2em; 70 73 71 74 /* ===== Transitions ===== */ 72 - --transition-fast: 0.15s ease; 75 + --transition-fast: 0.18s cubic-bezier(0.16, 1, 0.3, 1); 73 76 74 77 /* ===== Opacity ===== */ 75 78 --opacity-muted: 0.6;
+3
ui/themes/lcars/index.css
··· 8 8 --font-size-menu: 0.9em; 9 9 --font-size-sm: 0.85em; 10 10 --font-size-xs: 0.75em; 11 + --font-size-lg: 1.15em; 12 + --font-size-xl: 1.5em; 11 13 12 14 /* ===== Backgrounds ===== */ 13 15 --bg-main: #000000; ··· 53 55 --spacing-sm: 0.5em; 54 56 --spacing-md: 1em; 55 57 --spacing-lg: 1.5em; 58 + --spacing-xl: 2.5em; 56 59 57 60 /* ===== Sizes ===== */ 58 61 --size-header-height: 2em;
+4 -1
ui/themes/meadow/index.css
··· 7 7 --font-size-menu: 0.9em; 8 8 --font-size-sm: 0.85em; 9 9 --font-size-xs: 0.75em; 10 + --font-size-lg: 1.15em; 11 + --font-size-xl: 1.5em; 10 12 11 13 /* ===== Backgrounds ===== */ 12 14 --bg-main: linear-gradient( ··· 27 29 --color-text: oklch(35% 0.05 145); 28 30 --color-text-secondary: oklch(45% 0.04 145); 29 31 --color-text-tertiary: oklch(55% 0.03 145); 30 - --color-text-on-header: white; 32 + --color-text-on-header: oklch(98% 0.01 90); 31 33 32 34 /* ===== Colors - Interactive ===== */ 33 35 --color-focus-ring: oklch(70% 0.15 300 / 0.5); ··· 55 57 --spacing-sm: 0.5em; 56 58 --spacing-md: 1em; 57 59 --spacing-lg: 1.5em; 60 + --spacing-xl: 2.5em; 58 61 59 62 /* ===== Sizes ===== */ 60 63 --size-header-height: 2em;
+3
ui/themes/winamp/index.css
··· 8 8 --font-size-menu: 0.9em; 9 9 --font-size-sm: 0.85em; 10 10 --font-size-xs: 0.75em; 11 + --font-size-lg: 1.15em; 12 + --font-size-xl: 1.5em; 11 13 12 14 /* ===== Backgrounds ===== */ 13 15 --bg-main: #232323; ··· 53 55 --spacing-sm: 0.5em; 54 56 --spacing-md: 1em; 55 57 --spacing-lg: 1.5em; 58 + --spacing-xl: 2.5em; 56 59 57 60 /* ===== Sizes ===== */ 58 61 --size-header-height: 2em;