a lightweight, interval-based utility to combat digital strain through "Ma" (intentional pauses) for the eyes and body.
0
fork

Configure Feed

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

feat(ui): add dark theme

+154 -101
+10 -6
ui/overlay.slint
··· 1 1 import { Button, ProgressIndicator, LineEdit } from "std-widgets.slint"; 2 + import { Theme } from "theme.slint"; 2 3 import "../assets/fonts/Nunito-Regular.ttf"; 3 4 import "../assets/fonts/Nunito-Medium.ttf"; 4 5 import "../assets/fonts/Nunito-SemiBold.ttf"; ··· 24 25 callback unlock-clicked(); 25 26 callback unlock-submit-clicked(string /* password */); 26 27 28 + init => { Theme.dark = root.is-dark; } 29 + changed is-dark => { Theme.dark = root.is-dark; } 30 + 27 31 changed unlock-input-visible => { 28 32 if unlock-input-visible { pw-field.focus(); } 29 33 } 30 34 31 35 default-font-family: "Nunito"; 32 - background: is-dark ? #1a1a2e : #f5f5f0; 36 + background: Theme.bg; 33 37 34 38 VerticalLayout { 35 39 alignment: center; ··· 41 45 font-family: "Shippori Mincho"; 42 46 font-size: 28px; 43 47 font-weight: 400; 44 - color: is-dark ? #a0c4ff : #333333; 48 + color: Theme.ink-mid; 45 49 horizontal-alignment: center; 46 50 } 47 51 ··· 50 54 font-family: "Shippori Mincho"; 51 55 font-size: 96px; 52 56 font-weight: 700; 53 - color: is-dark ? #ffffff : #1a1a2e; 57 + color: Theme.ink; 54 58 horizontal-alignment: center; 55 59 } 56 60 ··· 60 64 Rectangle { 61 65 height: 8px; 62 66 width: 320px; 63 - background: is-dark ? #333355 : #d0d0d0; 67 + background: Theme.progress-track; 64 68 border-radius: 4px; 65 69 66 70 Rectangle { 67 71 x: 0; 68 72 width: parent.width * progress; 69 73 height: parent.height; 70 - background: is-dark ? #a0c4ff : #4a90d9; 74 + background: Theme.accent; 71 75 border-radius: 4px; 72 76 } 73 77 } ··· 105 109 106 110 if unlock-error != "" : Text { 107 111 text: unlock-error; 108 - color: #ff6b6b; 112 + color: #E55A4E; 109 113 font-size: 13px; 110 114 horizontal-alignment: center; 111 115 }
+93 -95
ui/settings.slint
··· 1 1 import { SpinBox, Slider, LineEdit, ScrollView } from "std-widgets.slint"; 2 + import { Theme } from "theme.slint"; 2 3 import "../assets/fonts/Nunito-Regular.ttf"; 3 4 import "../assets/fonts/Nunito-Medium.ttf"; 4 5 import "../assets/fonts/Nunito-SemiBold.ttf"; ··· 6 7 import "../assets/fonts/ShipporiMincho-Regular.ttf"; 7 8 import "../assets/fonts/ShipporiMincho-Bold.ttf"; 8 9 9 - // ── Design tokens ──────────────────────────────────────────────────────────── 10 - // bg: #F3EFE7 warm cream 11 - // ink: #232028 near-black with warm cast 12 - // muted: #23202888 (55 % ink) 13 - // line: #2320281A (10 % ink) — hair dividers 14 - // accent: #8A9A82 sage green 15 - // chip: #FFFFFF white chips on profile rows 16 - 17 10 // ── Primitives ─────────────────────────────────────────────────────────────── 18 11 component PaperToggle { 19 12 in-out property <bool> checked: false; ··· 31 24 32 25 Rectangle { 33 26 border-radius: 11px; 34 - background: root.checked ? #8A9A82 : #23202820; 27 + background: root.checked ? Theme.accent : Theme.toggle-off; 35 28 animate background { duration: 180ms; } 36 29 37 30 Rectangle { ··· 55 48 component PaperDivider { 56 49 height: 1px; 57 50 Rectangle { 58 - background: #2320281A; 51 + background: Theme.line; 59 52 } 60 53 } 61 54 ··· 77 70 78 71 Rectangle { 79 72 border-radius: 6px; 80 - background: #FFFFFF80; 73 + background: Theme.surface; 81 74 border-width: 1px; 82 - border-color: #2320281A; 75 + border-color: Theme.line; 83 76 clip: true; 84 77 85 78 HorizontalLayout { ··· 95 88 } 96 89 97 90 Rectangle { 98 - background: btn-minus.has-hover ? #23202812 : transparent; 91 + background: btn-minus.has-hover ? Theme.tint : transparent; 99 92 animate background { duration: 120ms; } 100 93 } 101 94 102 95 Text { 103 96 text: "−"; 104 97 font-size: 13px; 105 - color: root.value <= root.minimum ? #23202838 : #23202888; 98 + color: root.value <= root.minimum ? Theme.ink-dis : Theme.ink-lo; 106 99 horizontal-alignment: center; 107 100 vertical-alignment: center; 108 101 animate color { duration: 120ms; } ··· 111 104 112 105 Rectangle { 113 106 width: 1px; 114 - background: #2320281A; 107 + background: Theme.line; 115 108 } 116 109 117 110 Text { 118 111 text: root.value; 119 112 font-size: 12px; 120 113 font-weight: 500; 121 - color: #232028; 114 + color: Theme.ink; 122 115 horizontal-alignment: center; 123 116 vertical-alignment: center; 124 117 horizontal-stretch: 1; ··· 126 119 127 120 Rectangle { 128 121 width: 1px; 129 - background: #2320281A; 122 + background: Theme.line; 130 123 } 131 124 132 125 btn-plus := TouchArea { ··· 141 134 } 142 135 143 136 Rectangle { 144 - background: btn-plus.has-hover ? #23202812 : transparent; 137 + background: btn-plus.has-hover ? Theme.tint : transparent; 145 138 animate background { duration: 120ms; } 146 139 } 147 140 148 141 Text { 149 142 text: "+"; 150 143 font-size: 13px; 151 - color: root.value >= root.maximum ? #23202838 : #23202888; 144 + color: root.value >= root.maximum ? Theme.ink-dis : Theme.ink-lo; 152 145 horizontal-alignment: center; 153 146 vertical-alignment: center; 154 147 animate color { duration: 120ms; } ··· 158 151 } 159 152 } 160 153 161 - // A ghost button — paper white, thin line border 154 + // A ghost button — semi-transparent surface, thin line border 162 155 component PaperButton { 163 156 in property <string> text; 164 157 callback clicked; ··· 175 168 176 169 Rectangle { 177 170 border-radius: 6px; 178 - background: #FFFFFF80; 171 + background: Theme.surface; 179 172 border-width: 1px; 180 - border-color: #2320281A; 173 + border-color: Theme.line; 181 174 182 175 Text { 183 176 text: root.text; 184 177 font-size: 12px; 185 - color: #232028; 178 + color: Theme.ink; 186 179 horizontal-alignment: center; 187 180 vertical-alignment: center; 188 181 } 189 182 } 190 183 } 191 184 192 - // Primary filled button (ink bg, cream text) 185 + // Primary filled button (inverted: ink bg, cream text in light; cream bg, charcoal text in dark) 193 186 component PaperPrimaryButton { 194 187 in property <string> text; 195 188 callback clicked; ··· 205 198 206 199 Rectangle { 207 200 border-radius: 6px; 208 - background: ta.has-hover ? #3a3542 : #232028; 201 + background: ta.has-hover ? Theme.btn-bg-hov : Theme.btn-bg; 209 202 animate background { duration: 120ms; } 210 203 211 204 Text { 212 205 text: root.text; 213 206 font-size: 12px; 214 207 font-weight: 600; 215 - color: #F3EFE7; 208 + color: Theme.btn-fg; 216 209 horizontal-alignment: center; 217 210 vertical-alignment: center; 218 211 } ··· 237 230 border-radius: 6px; 238 231 background: transparent; 239 232 border-width: 1px; 240 - border-color: #2320281A; 233 + border-color: Theme.line; 241 234 242 235 Text { 243 236 text: root.text; 244 237 font-size: 12px; 245 - color: #232028; 238 + color: Theme.ink; 246 239 horizontal-alignment: center; 247 240 vertical-alignment: center; 248 241 } ··· 264 257 265 258 Rectangle { 266 259 border-radius: 6px; 267 - background: ti.has-focus ? #23202808 : #FFFFFF60; 260 + background: ti.has-focus ? Theme.tint-soft : Theme.surface-inp; 268 261 border-width: 1px; 269 - border-color: ti.has-focus ? #8A9A8260 : #2320281A; 262 + border-color: ti.has-focus ? Theme.accent-muted : Theme.line; 270 263 animate background { duration: 120ms; } 271 264 animate border-color { duration: 120ms; } 272 265 clip: true; ··· 276 269 x: 10px; 277 270 text: root.placeholder-text; 278 271 font-size: 13px; 279 - color: #23202848; 272 + color: Theme.ink-dim; 280 273 vertical-alignment: center; 281 274 } 282 275 ··· 289 282 text <=> root.text; 290 283 font-size: 13px; 291 284 font-weight: 500; 292 - color: #232028; 285 + color: Theme.ink; 293 286 horizontal-alignment: left; 294 - selection-background-color: #8A9A8230; 295 - selection-foreground-color: #232028; 287 + selection-background-color: Theme.accent-sel; 288 + selection-foreground-color: Theme.ink; 296 289 vertical-alignment: center; 297 290 edited => { 298 291 root.edited(self.text); ··· 318 311 319 312 Rectangle { 320 313 border-radius: 8px; 321 - background: #FFFFFF80; 314 + background: Theme.surface; 322 315 border-width: 1px; 323 - border-color: #2320281A; 316 + border-color: Theme.line; 324 317 325 318 HorizontalLayout { 326 319 padding-left: 18px; ··· 339 332 text: root.index; 340 333 font-family: "Shippori Mincho"; 341 334 font-size: 28px; 342 - color: #232028CC; 335 + color: Theme.ink-hi; 343 336 height: 34px; 344 337 horizontal-alignment: center; 345 338 vertical-alignment: bottom; ··· 384 377 Text { 385 378 text: "×"; 386 379 font-size: 14px; 387 - color: ta-rm.has-hover ? #232028 : #23202866; 380 + color: ta-rm.has-hover ? Theme.ink : Theme.ink-sub; 388 381 horizontal-alignment: center; 389 382 vertical-alignment: center; 390 383 animate color { duration: 120ms; } ··· 404 397 Text { 405 398 text: "every"; 406 399 font-size: 12px; 407 - color: #232028AA; 400 + color: Theme.ink-mid; 408 401 vertical-alignment: center; 409 402 } 410 403 ··· 422 415 Text { 423 416 text: "min · pause"; 424 417 font-size: 12px; 425 - color: #232028AA; 418 + color: Theme.ink-mid; 426 419 vertical-alignment: center; 427 420 } 428 421 ··· 440 433 Text { 441 434 text: "min"; 442 435 font-size: 12px; 443 - color: #232028AA; 436 + color: Theme.ink-mid; 444 437 vertical-alignment: center; 445 438 } 446 439 ··· 458 451 Text { 459 452 text: "sec"; 460 453 font-size: 12px; 461 - color: #232028AA; 454 + color: Theme.ink-mid; 462 455 vertical-alignment: center; 463 456 } 464 457 } ··· 489 482 text: root.text; 490 483 font-size: 13px; 491 484 font-weight: root.active ? 600 : 400; 492 - color: root.active ? #232028 : #232028AA; 485 + color: root.active ? Theme.ink : Theme.ink-mid; 493 486 horizontal-alignment: left; 494 487 vertical-alignment: center; 495 488 } ··· 497 490 // Active indicator 498 491 Rectangle { 499 492 height: 2px; 500 - background: root.active ? #232028 : transparent; 493 + background: root.active ? Theme.ink : transparent; 501 494 } 502 495 } 503 496 } ··· 516 509 title: "ioma — Settings"; 517 510 width: 760px; 518 511 height: 680px; 519 - background: #F3EFE7; 512 + background: Theme.bg; 520 513 default-font-family: "Nunito"; 521 514 515 + // Follow system color scheme. Set from Rust before showing the window. 516 + in property <bool> is-dark: false; 517 + init => { Theme.dark = root.is-dark; } 518 + changed is-dark => { Theme.dark = root.is-dark; } 519 + 522 520 // ── Properties (same contract as before) ───────────────────────────────── 523 521 in-out property <bool> enforced-mode: false; 524 522 in-out property <bool> sound-enabled: true; ··· 566 564 text: "ioma"; 567 565 font-family: "Shippori Mincho"; 568 566 font-size: 22px; 569 - color: #232028; 567 + color: Theme.ink; 570 568 vertical-alignment: center; 571 569 } 572 570 ··· 574 572 text: "間"; 575 573 font-family: "Shippori Mincho"; 576 574 font-size: 11px; 577 - color: #23202888; 575 + color: Theme.ink-lo; 578 576 vertical-alignment: bottom; 579 577 } 580 578 } ··· 593 591 width: 22px; 594 592 height: 22px; 595 593 border-radius: 11px; 596 - background: #00000009; 594 + background: Theme.chrome; 597 595 598 596 Text { 599 597 text: glyph; 600 598 font-size: 11px; 601 - color: #23202888; 599 + color: Theme.ink-lo; 602 600 horizontal-alignment: center; 603 601 vertical-alignment: center; 604 602 } ··· 645 643 // Tab underline 646 644 Rectangle { 647 645 height: 1px; 648 - background: #2320281A; 646 + background: Theme.line; 649 647 } 650 648 651 649 // ── Tab content ────────────────────────────────────────────────────── ··· 671 669 text: "Active profile"; 672 670 font-size: 13px; 673 671 font-weight: 500; 674 - color: #232028; 672 + color: Theme.ink; 675 673 } 676 674 677 675 Text { 678 676 text: "The cadence ioma follows today."; 679 677 font-size: 11.5px; 680 - color: #232028AA; 678 + color: Theme.ink-mid; 681 679 } 682 680 } 683 681 ··· 700 698 701 699 Rectangle { 702 700 border-radius: 6px; 703 - background: name == root.active-profile ? #232028 : (profile-chip-ta.has-hover ? #FFFFFF : #FFFFFF80); 701 + background: name == root.active-profile 702 + ? Theme.btn-bg 703 + : (profile-chip-ta.has-hover ? Theme.surface-hov : Theme.surface); 704 704 border-width: 1px; 705 - border-color: name == root.active-profile ? transparent : #2320281A; 705 + border-color: name == root.active-profile ? transparent : Theme.line; 706 706 animate background { duration: 120ms; } 707 707 708 708 HorizontalLayout { ··· 714 714 text: name; 715 715 font-size: 12px; 716 716 font-weight: name == root.active-profile ? 600 : 400; 717 - color: name == root.active-profile ? #F3EFE7 : #232028; 717 + color: name == root.active-profile ? Theme.btn-fg : Theme.ink; 718 718 vertical-alignment: center; 719 719 animate color { duration: 120ms; } 720 720 } ··· 739 739 text: "Enforced mode"; 740 740 font-size: 13px; 741 741 font-weight: 500; 742 - color: #232028; 742 + color: Theme.ink; 743 743 } 744 744 745 745 Text { 746 746 text: "Full-screen break. Emergency unlock requires a password."; 747 747 font-size: 11.5px; 748 - color: #232028AA; 748 + color: Theme.ink-mid; 749 749 } 750 750 } 751 751 ··· 784 784 text: "Pause on idle"; 785 785 font-size: 13px; 786 786 font-weight: 500; 787 - color: #232028; 787 + color: Theme.ink; 788 788 } 789 789 790 790 Text { 791 791 text: "If you've stepped away, ioma waits."; 792 792 font-size: 11.5px; 793 - color: #232028AA; 793 + color: Theme.ink-mid; 794 794 } 795 795 } 796 796 ··· 811 811 Text { 812 812 text: "threshold"; 813 813 font-size: 12px; 814 - color: #232028AA; 814 + color: Theme.ink-mid; 815 815 vertical-alignment: center; 816 816 } 817 817 ··· 827 827 Text { 828 828 text: "minutes"; 829 829 font-size: 12px; 830 - color: #232028AA; 830 + color: Theme.ink-mid; 831 831 vertical-alignment: center; 832 832 } 833 833 } ··· 847 847 text: "Chime on break start"; 848 848 font-size: 13px; 849 849 font-weight: 500; 850 - color: #232028; 850 + color: Theme.ink; 851 851 } 852 852 853 853 Text { 854 854 text: "A single, gentle tone."; 855 855 font-size: 11.5px; 856 - color: #232028AA; 856 + color: Theme.ink-mid; 857 857 } 858 858 } 859 859 ··· 874 874 Text { 875 875 text: "volume"; 876 876 font-size: 12px; 877 - color: #232028AA; 877 + color: Theme.ink-mid; 878 878 vertical-alignment: center; 879 879 } 880 880 ··· 887 887 Rectangle { 888 888 y: (parent.height - 2px) / 2; 889 889 height: 2px; 890 - background: #23202820; 890 + background: Theme.toggle-off; 891 891 border-radius: 1px; 892 892 } 893 893 ··· 896 896 y: (parent.height - 2px) / 2; 897 897 width: parent.width * root.sound-volume; 898 898 height: 2px; 899 - background: #8A9A82; 899 + background: Theme.accent; 900 900 border-radius: 1px; 901 901 animate width { duration: 80ms; } 902 902 } ··· 910 910 border-radius: 6px; 911 911 background: white; 912 912 border-width: 1.5px; 913 - border-color: #8A9A82; 913 + border-color: Theme.accent; 914 914 drop-shadow-blur: 2px; 915 915 drop-shadow-color: #00000020; 916 916 ··· 953 953 text: "Launch with system"; 954 954 font-size: 13px; 955 955 font-weight: 500; 956 - color: #232028; 956 + color: Theme.ink; 957 957 } 958 958 959 959 Text { 960 960 text: "ioma starts quietly at login."; 961 961 font-size: 11.5px; 962 - color: #232028AA; 962 + color: Theme.ink-mid; 963 963 } 964 964 } 965 965 ··· 1003 1003 text: "Break cadence"; 1004 1004 font-size: 13px; 1005 1005 font-weight: 500; 1006 - color: #232028; 1006 + color: Theme.ink; 1007 1007 } 1008 1008 1009 1009 Text { 1010 1010 text: "Each row is an interval. ioma cycles through them in order."; 1011 1011 font-size: 11.5px; 1012 - color: #232028AA; 1012 + color: Theme.ink-mid; 1013 1013 } 1014 1014 1015 1015 Rectangle { ··· 1077 1077 1078 1078 Rectangle { 1079 1079 border-radius: 8px; 1080 - background: add-ta.has-hover ? #FFFFFF60 : transparent; 1080 + background: add-ta.has-hover ? Theme.surface-hov : transparent; 1081 1081 border-width: 1px; 1082 - border-color: #23202828; 1083 - // dashed look via inner text (Slint has no native dashed borders) 1082 + border-color: Theme.line-med; 1084 1083 1085 - Text { 1084 + Text { 1086 1085 text: "+ Add interval"; 1087 1086 font-size: 12px; 1088 - color: add-ta.has-hover ? #232028 : #23202880; 1087 + color: add-ta.has-hover ? Theme.ink : Theme.ink-lo; 1089 1088 horizontal-alignment: center; 1090 1089 vertical-alignment: center; 1091 1090 animate color { duration: 120ms; } ··· 1099 1098 1100 1099 Rectangle { 1101 1100 height: 1px; 1102 - background: #2320281A; 1101 + background: Theme.line; 1103 1102 } 1104 1103 1105 1104 Rectangle { ··· 1118 1117 text: "Long rest"; 1119 1118 font-size: 13px; 1120 1119 font-weight: 500; 1121 - color: #232028; 1120 + color: Theme.ink; 1122 1121 } 1123 1122 1124 1123 Text { 1125 1124 text: "A longer pause after several cycles."; 1126 1125 font-size: 11.5px; 1127 - color: #232028AA; 1126 + color: Theme.ink-mid; 1128 1127 } 1129 1128 } 1130 1129 ··· 1153 1152 Text { 1154 1153 text: "after"; 1155 1154 font-size: 12.5px; 1156 - color: #232028AA; 1155 + color: Theme.ink-mid; 1157 1156 vertical-alignment: center; 1158 1157 } 1159 1158 ··· 1168 1167 Text { 1169 1168 text: "cycles, take"; 1170 1169 font-size: 12.5px; 1171 - color: #232028AA; 1170 + color: Theme.ink-mid; 1172 1171 vertical-alignment: center; 1173 1172 } 1174 1173 ··· 1183 1182 Text { 1184 1183 text: "min"; 1185 1184 font-size: 12.5px; 1186 - color: #232028AA; 1185 + color: Theme.ink-mid; 1187 1186 vertical-alignment: center; 1188 1187 } 1189 1188 1190 1189 Text { 1191 1190 text: "·"; 1192 1191 font-size: 12.5px; 1193 - color: #23202888; 1192 + color: Theme.ink-lo; 1194 1193 vertical-alignment: center; 1195 1194 } 1196 1195 ··· 1213 1212 Text { 1214 1213 text: "Reset after"; 1215 1214 font-size: 11.5px; 1216 - color: #232028AA; 1215 + color: Theme.ink-mid; 1217 1216 vertical-alignment: center; 1218 1217 } 1219 1218 ··· 1228 1227 Text { 1229 1228 text: "min away."; 1230 1229 font-size: 11.5px; 1231 - color: #232028AA; 1230 + color: Theme.ink-mid; 1232 1231 vertical-alignment: center; 1233 1232 } 1234 1233 } ··· 1256 1255 width: 10px * 56 / 64; 1257 1256 height: 10px * 56 / 64; 1258 1257 border-radius: 5px * 56 / 64; 1259 - background: #232028; 1258 + background: Theme.ink; 1260 1259 } 1261 1260 1262 1261 Rectangle { ··· 1265 1264 width: 16px * 56 / 64; 1266 1265 height: 16px * 56 / 64; 1267 1266 border-radius: 8px * 56 / 64; 1268 - background: #232028; 1267 + background: Theme.ink; 1269 1268 } 1270 1269 1271 1270 Rectangle { ··· 1274 1273 width: 10px * 56 / 64; 1275 1274 height: 10px * 56 / 64; 1276 1275 border-radius: 5px * 56 / 64; 1277 - background: #232028; 1276 + background: Theme.ink; 1278 1277 } 1279 1278 1280 1279 Rectangle { ··· 1283 1282 width: 6px * 56 / 64; 1284 1283 height: 2px * 56 / 64; 1285 1284 border-radius: 1px; 1286 - background: #232028; 1285 + background: Theme.ink; 1287 1286 } 1288 1287 1289 1288 Rectangle { ··· 1292 1291 width: 6px * 56 / 64; 1293 1292 height: 2px * 56 / 64; 1294 1293 border-radius: 1px; 1295 - background: #232028; 1294 + background: Theme.ink; 1296 1295 } 1297 1296 } 1298 1297 } ··· 1305 1304 text: "ioma"; 1306 1305 font-family: "Shippori Mincho"; 1307 1306 font-size: 34px; 1308 - color: #232028; 1307 + color: Theme.ink; 1309 1308 horizontal-alignment: center; 1310 1309 } 1311 1310 ··· 1316 1315 Text { 1317 1316 text: "v0.4.2 · the space between"; 1318 1317 font-size: 12px; 1319 - color: #232028AA; 1318 + color: Theme.ink-mid; 1320 1319 horizontal-alignment: center; 1321 1320 } 1322 1321 ··· 1327 1326 Text { 1328 1327 text: "間 (ma) is the Japanese notion of the pause between —\nthe rest in music, the silence between words.\nioma gives that pause back to your eyes and body."; 1329 1328 font-size: 12.5px; 1330 - color: #232028AA; 1329 + color: Theme.ink-mid; 1331 1330 horizontal-alignment: center; 1332 1331 vertical-alignment: center; 1333 1332 wrap: word-wrap; 1334 - // line-height not available in Slint — spacing comes from font metrics 1335 1333 } 1336 1334 } 1337 1335 1338 1336 // ── Footer ─────────────────────────────────────────────────────────── 1339 1337 Rectangle { 1340 1338 height: 1px; 1341 - background: #2320281A; 1339 + background: Theme.line; 1342 1340 } 1343 1341 1344 1342 HorizontalLayout {
+51
ui/theme.slint
··· 1 + // Design token system for ioma. 2 + // Import this file in any .slint UI file that needs themed colors. 3 + // Set Theme.dark = true to switch to warm-slate dark mode. 4 + 5 + export global Theme { 6 + // Set by each window via `changed is-dark => { Theme.dark = root.is-dark; }` 7 + in-out property <bool> dark: false; 8 + 9 + // ── Window background ───────────────────────────────────────────────────── 10 + // Light: warm cream / Dark: deep warm charcoal (not blue-black) 11 + out property <color> bg: self.dark ? #1C1A17 : #F3EFE7; 12 + 13 + // ── Ink scale: primary text → near-invisible ────────────────────────────── 14 + // Light base: #232028 (near-black, warm cast) 15 + // Dark base: #EDE9E1 (warm off-white) 16 + out property <color> ink: self.dark ? #EDE9E1 : #232028; 17 + out property <color> ink-hi: self.dark ? #EDE9E1CC : #232028CC; // prominent secondary 18 + out property <color> ink-mid: self.dark ? #EDE9E1AA : #232028AA; // standard secondary 19 + out property <color> ink-lo: self.dark ? #EDE9E188 : #23202888; // tertiary / muted 20 + out property <color> ink-sub: self.dark ? #EDE9E166 : #23202866; // subdued 21 + out property <color> ink-dim: self.dark ? #EDE9E148 : #23202848; // placeholder 22 + out property <color> ink-dis: self.dark ? #EDE9E138 : #23202838; // disabled 23 + 24 + // ── Structure ───────────────────────────────────────────────────────────── 25 + out property <color> line-med: self.dark ? #EDE9E128 : #23202828; // medium borders 26 + out property <color> line: self.dark ? #EDE9E11A : #2320281A; // hair dividers 27 + out property <color> tint: self.dark ? #EDE9E112 : #23202812; // hover bg tint 28 + out property <color> tint-soft: self.dark ? #EDE9E108 : #23202808; // input focus bg 29 + out property <color> toggle-off: self.dark ? #EDE9E120 : #23202820; // toggle unchecked 30 + 31 + // ── Surfaces ────────────────────────────────────────────────────────────── 32 + out property <color> surface: self.dark ? #EDE9E10F : #FFFFFF80; // cards, chips 33 + out property <color> surface-inp: self.dark ? #EDE9E10A : #FFFFFF60; // input default bg 34 + out property <color> surface-hov: self.dark ? #EDE9E11A : #FFFFFF; // hovered chip/card 35 + 36 + // ── Primary button (inverted palette) ───────────────────────────────────── 37 + out property <color> btn-bg: self.dark ? #EDE9E1 : #232028; 38 + out property <color> btn-bg-hov: self.dark ? #F0ECE5 : #3A3542; 39 + out property <color> btn-fg: self.dark ? #1C1A17 : #F3EFE7; 40 + 41 + // ── Window chrome (decorative circles) ──────────────────────────────────── 42 + out property <color> chrome: self.dark ? #EDE9E109 : #00000009; 43 + 44 + // ── Accent: sage green — same in both modes ──────────────────────────────── 45 + out property <color> accent: #8A9A82; 46 + out property <color> accent-muted: #8A9A8260; // focus border / ring 47 + out property <color> accent-sel: #8A9A8230; // text selection highlight 48 + 49 + // ── Overlay-specific ────────────────────────────────────────────────────── 50 + out property <color> progress-track: self.dark ? #2E2A25 : #D8D2C6; 51 + }