a proof of concept realtime collaborative todo list
0

Configure Feed

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

atodo / style.css
12 kB 675 lines
1:root { 2 color-scheme: light dark; 3 font-family: system-ui, -apple-system, sans-serif; 4 font-size: 22.5px; 5} 6 7*, *::before, *::after { box-sizing: border-box; } 8 9body { 10 max-width: 680px; 11 margin: 0 auto; 12 padding: 0 1rem; 13 line-height: 1.5; 14} 15 16a { color: inherit; } 17 18h1 { 19 font-size: 1.25rem; 20 font-weight: 700; 21 margin: 0; 22} 23 24h1 a { text-decoration: none; } 25 26p { margin: 0.5rem 0; } 27 28/* ── Topbar ── */ 29 30.topbar { 31 display: flex; 32 align-items: center; 33 justify-content: space-between; 34 gap: 1rem; 35 flex-wrap: wrap; 36 37 /* break out of body's max-width to span the full viewport */ 38 width: 100vw; 39 margin-left: calc(50% - 50vw); 40 padding: 0.65rem 1rem; 41 margin-bottom: 2rem; 42 43 position: sticky; 44 top: 0; 45 z-index: 10; 46 background: Canvas; 47 border-bottom: 1px solid light-dark(#e5e5e5, #333); 48} 49 50 51.topbar-left { 52 display: flex; 53 align-items: baseline; 54 gap: 0.75rem; 55} 56 57.back-link { 58 font-size: 0.85rem; 59 opacity: 0.55; 60 text-decoration: none; 61} 62 63.back-link:hover { opacity: 1; } 64 65.list-title { 66 font-size: 1.25rem; 67 font-weight: 700; 68} 69 70.who { 71 display: flex; 72 align-items: center; 73 gap: 0.5rem; 74 font-size: 0.85rem; 75} 76 77.who > span { 78 opacity: 0.55; 79} 80 81.who code { 82 font-size: 0.8em; 83 word-break: break-all; 84} 85 86.who > button:not(.icon-button) { 87 font-size: 0.8rem; 88 padding: 0.3rem 0.6rem; 89} 90 91/* ── Forms ── */ 92 93form { 94 display: flex; 95 gap: 0.5rem; 96 margin: 0.75rem 0; 97 align-items: baseline; 98} 99 100input:not([type="checkbox"]) { 101 flex: 1; 102 padding: 0.4rem 0.5rem; 103 font: inherit; 104 min-width: 0; 105 border: 1px solid light-dark(#ccc, #444); 106 border-radius: 4px; 107 background: light-dark(#fff, #1c1c1e); 108 color: inherit; 109 transition: border-color 0.15s; 110} 111 112input:not([type="checkbox"]):focus { 113 outline: 2px solid rgba(from blue r g b / 0.4); 114 outline-offset: 1px; 115} 116 117button { 118 padding: 0.4rem 0.75rem; 119 font: inherit; 120 cursor: pointer; 121 border: 1px solid light-dark(#ccc, #444); 122 border-radius: 4px; 123 background: light-dark(#fff, #2c2c2e); 124 color: inherit; 125 transition: background 0.15s; 126} 127 128button:hover { background: light-dark(#f5f5f5, #3a3a3c); } 129button:active { background: light-dark(#eee, #444); } 130button:disabled { opacity: 0.4; cursor: default; } 131 132button.x { 133 padding: 0 0.5rem; 134 background: none; 135 border: none; 136 font-size: 1.2em; 137 opacity: 0.4; 138 cursor: pointer; 139} 140 141button.x:hover { opacity: 1; } 142 143/* ── States ── */ 144 145pre { 146 white-space: pre-wrap; 147 word-break: break-word; 148} 149 150.error { color: #c00; } 151.empty { opacity: 0.5; font-style: italic; } 152 153/* ── Lists view ── */ 154 155ul.lists, 156ul.items, 157ul.editors { 158 list-style: none; 159 padding: 0; 160 margin: 1rem 0; 161} 162 163ul.lists li { 164 display: flex; 165 align-items: center; 166 gap: 0.5rem; 167 padding: 0.5rem 0; 168 border-bottom: 1px solid color-mix(in srgb, currentColor 15%, transparent); 169} 170 171ul.lists a { 172 flex: 1; 173 text-decoration: none; 174 font-weight: 500; 175} 176 177ul.lists a:hover { text-decoration: underline; } 178 179.badge { 180 font-size: 0.7em; 181 padding: 0.1em 0.5em; 182 border-radius: 999px; 183 background: color-mix(in srgb, currentColor 12%, transparent); 184 opacity: 0.7; 185} 186 187 188/* ── Todo items ── */ 189 190ul.items li { 191 display: flex; 192 align-items: center; 193 gap: 0.5rem; 194 padding: 0.4rem 0; 195 border-bottom: 1px solid color-mix(in srgb, currentColor 10%, transparent); 196 position: relative; 197} 198 199ul.items .grip { 200 cursor: grab; 201 opacity: 0.25; 202 user-select: none; 203 font-size: 0.9em; 204 line-height: 1; 205} 206 207ul.items li:hover .grip { opacity: 0.6; } 208ul.items li.dragging { opacity: 0.4; } 209 210ul.items li.drop-before::before, 211ul.items li.drop-after::after { 212 content: ""; 213 position: absolute; 214 left: 0; 215 right: 0; 216 height: 2px; 217 background: #4285f4; 218} 219 220ul.items li.drop-before::before { top: -1px; } 221ul.items li.drop-after::after { bottom: -1px; } 222 223ul.items .text { 224 flex: 1; 225 cursor: text; 226 padding: 0.2rem 0; 227} 228 229ul.items input.edit { 230 flex: 1; 231 padding: 0.2rem; 232} 233 234ul.items .item.done .text { 235 text-decoration: line-through; 236 opacity: 0.5; 237} 238 239/* ── Editors list ── */ 240 241ul.editors li { 242 display: flex; 243 align-items: center; 244 gap: 0.5rem; 245 padding: 0.4rem 0; 246 border-bottom: 1px solid color-mix(in srgb, currentColor 10%, transparent); 247} 248 249ul.editors code { 250 flex: 1; 251 font-size: 0.85em; 252 word-break: break-all; 253} 254 255/* ── Modal ── */ 256 257.modal-bg { 258 position: fixed; 259 inset: 0; 260 background: rgba(0, 0, 0, 0.4); 261 display: grid; 262 place-items: center; 263 z-index: 100; 264} 265 266.modal { 267 background: Canvas; 268 color: CanvasText; 269 border-radius: 8px; 270 padding: 1.5rem; 271 max-width: min(500px, 90vw); 272 width: 100%; 273 max-height: 80vh; 274 overflow: auto; 275 box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); 276} 277 278.modal h3 { margin-top: 0; } 279.modal .close { margin-top: 1rem; } 280 281/* ── Icon button ── */ 282 283.icon-button { 284 all: unset; 285 cursor: pointer; 286 display: inline-flex; 287 align-items: center; 288 justify-content: center; 289 padding: 0.25rem; 290 border-radius: 4px; 291 color: #888; 292 vertical-align: middle; 293} 294 295.icon-button:hover { 296 color: #333; 297 background: color-mix(in srgb, currentColor 10%, transparent); 298} 299 300/* ── Accounts popover ── */ 301 302.accounts-popover { 303 position: fixed; 304 inset: auto; 305 top: 3.25rem; 306 right: 1rem; 307 width: 280px; 308 padding: 0; 309 margin: 0; 310 border: 1px solid light-dark(#ddd, #444); 311 border-radius: 10px; 312 box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); 313 background: light-dark(#fff, #1c1c1e); 314 color: inherit; 315 316 &:popover-open { 317 animation: popover-in 0.1s ease; 318 } 319 320 header { 321 display: flex; 322 justify-content: space-between; 323 align-items: center; 324 padding: 10px 12px; 325 border-bottom: 1px solid light-dark(#ddd, #444); 326 } 327 328 h2 { 329 font-size: 0.875rem; 330 font-weight: 600; 331 margin: 0; 332 } 333} 334 335@keyframes popover-in { 336 from { opacity: 0; transform: translateY(-4px); } 337 to { opacity: 1; transform: translateY(0); } 338} 339 340.accounts-list { 341 list-style: none; 342 margin: 0; 343 padding: 8px 0; 344 display: flex; 345 flex-direction: column; 346 347 > li { 348 display: flex; 349 align-items: center; 350 gap: 4px; 351 padding: 0 8px; 352 353 &:not(.active):hover { 354 background: light-dark(#f0f0f0, #2c2c2e); 355 } 356 357 &.active { 358 background: light-dark(#e8f0fe, #1c2a4a); 359 360 .account-row { cursor: default; } 361 } 362 } 363} 364 365.account-row { 366 all: unset; 367 flex: 1; 368 display: flex; 369 align-items: center; 370 gap: 0.5rem; 371 padding: 0.4rem 0; 372 cursor: pointer; 373 min-width: 0; 374 375 .avatar { 376 border-radius: 50%; 377 flex-shrink: 0; 378 } 379 380 .avatar-placeholder { 381 width: 32px; 382 height: 32px; 383 border-radius: 50%; 384 background: light-dark(#e0e0e0, #3a3a3c); 385 flex-shrink: 0; 386 } 387 388 .member-info { 389 flex: 1; 390 display: flex; 391 flex-direction: column; 392 min-width: 0; 393 overflow: hidden; 394 395 strong { 396 font-size: 0.875rem; 397 text-overflow: ellipsis; 398 overflow: hidden; 399 white-space: nowrap; 400 } 401 402 small { 403 font-size: 0.75rem; 404 color: light-dark(#888, #aaa); 405 text-overflow: ellipsis; 406 overflow: hidden; 407 white-space: nowrap; 408 } 409 } 410} 411 412.accounts-footer { 413 border-top: 1px solid light-dark(#ddd, #444); 414 padding: 10px 12px; 415 416 label { 417 display: flex; 418 flex-direction: column; 419 gap: 4px; 420 flex: 1; 421 font-size: 0.8rem; 422 min-width: 0; 423 } 424 425 form { 426 margin: 0; 427 gap: 0.5rem; 428 align-items: flex-end; 429 } 430} 431 432/* ── Devtools panel ── */ 433 434.devtools-fixed-wrapper { 435 position: fixed; 436 bottom: 0; 437 left: 0; 438 right: 0; 439 display: flex; 440 flex-direction: column; 441 z-index: 1000; 442} 443 444.devtools-resize-handle { 445 height: 6px; 446 cursor: ns-resize; 447 flex-shrink: 0; 448 background: transparent; 449} 450 451.devtools-resize-handle:hover { 452 background: color-mix(in srgb, currentColor 8%, transparent); 453} 454 455.devtools-panel { 456 display: flex; 457 flex-direction: column; 458 border-top: 1px solid #ddd; 459 background: #fff; 460} 461 462/* Everything visible actually lives in here, not directly in .devtools-panel. 463 That keeps the panel's own box at its real, unzoomed drag-resized height 464 (so the resize handle keeps tracking the cursor 1:1) while the zoomed 465 content just scrolls internally if it doesn't fit. */ 466.devtools-zoom { 467 display: flex; 468 flex-direction: column; 469 flex: 1; 470 min-height: 0; 471 font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, 472 "DejaVu Sans Mono", monospace; 473 font-size: 12px; 474 zoom: 2; 475} 476 477.devtools-header { 478 display: flex; 479 align-items: center; 480 gap: 4px; 481 background: #f5f5f5; 482 border-bottom: 1px solid #e0e0e0; 483 height: 32px; 484 padding: 0 6px; 485 flex-shrink: 0; 486} 487 488.devtools-tabs { 489 display: flex; 490 height: 100%; 491 margin-right: 4px; 492} 493 494.devtools-tabs button { 495 all: unset; 496 padding: 0 10px; 497 font-size: 11px; 498 font-family: system-ui, sans-serif; 499 cursor: pointer; 500 color: #666; 501 border-bottom: 2px solid transparent; 502 height: 100%; 503} 504 505.devtools-tabs button:hover { 506 color: #333; 507 background: rgba(0, 0, 0, 0.05); 508} 509 510.devtools-tabs button.active { 511 color: #1a73e8; 512 border-bottom-color: #1a73e8; 513} 514 515.devtools-action { 516 display: flex; 517 align-items: center; 518 gap: 4px; 519 font-size: 11px; 520 font-family: system-ui, sans-serif; 521 padding: 3px 6px !important; 522 color: #888; 523} 524 525.devtools-body { 526 flex: 1; 527 display: flex; 528 overflow: hidden; 529 min-height: 0; 530} 531 532.devtools-tab-content { 533 flex: 1; 534 display: flex; 535 flex-direction: column; 536 overflow: hidden; 537 min-height: 0; 538} 539 540.devtools-subtabs { 541 display: flex; 542 flex-shrink: 0; 543 border-bottom: 1px solid #e8e8e8; 544 padding: 0 4px; 545 overflow-x: auto; 546} 547 548.devtools-subtabs button { 549 all: unset; 550 padding: 5px 10px; 551 font-size: 11px; 552 font-family: system-ui, sans-serif; 553 cursor: pointer; 554 color: #888; 555 border-bottom: 2px solid transparent; 556 white-space: nowrap; 557} 558 559.devtools-subtabs button:hover { color: #333; } 560 561.devtools-subtabs button.active { 562 color: #1a73e8; 563 border-bottom-color: #1a73e8; 564} 565 566.devtools-body-inner { 567 flex: 1; 568 display: flex; 569 overflow: hidden; 570 min-width: 0; 571 min-height: 0; 572} 573 574.devtools-body-inner:not(.has-detail) { overflow-y: auto; } 575 576.devtools-body-inner.has-detail > .devtools-timeline { 577 width: 340px; 578 flex-shrink: 0; 579 border-right: 1px solid #e8e8e8; 580 overflow-y: auto; 581} 582 583.devtools-empty { 584 color: #999; 585 text-align: center; 586 padding: 24px; 587 font-family: system-ui, sans-serif; 588} 589 590.devtools-timeline { 591 flex: 1; 592 overflow-y: auto; 593 padding: 6px; 594 display: flex; 595 flex-direction: column; 596 gap: 4px; 597} 598 599.devtools-entry { 600 border: 1px solid #eee; 601 border-radius: 5px; 602 padding: 7px 9px; 603 background: #fafafa; 604 cursor: pointer; 605} 606 607.devtools-entry:hover { background: #f0f4ff; border-color: #c8d8ff; } 608.devtools-entry.active { background: #e8f0fe; border-color: #4285f4; } 609 610.devtools-entry-meta { 611 display: flex; 612 align-items: baseline; 613 gap: 8px; 614 margin-bottom: 3px; 615} 616 617.devtools-entry-index { 618 font-size: 10px; 619 font-weight: 700; 620 color: #bbb; 621 min-width: 14px; 622} 623 624.devtools-entry-author { 625 font-weight: 600; 626 font-size: 11px; 627 font-family: system-ui, sans-serif; 628} 629 630.devtools-entry-time { 631 font-size: 10px; 632 color: #aaa; 633 margin-left: auto; 634} 635 636.devtools-entry-uri { 637 font-size: 10px; 638 color: #1a73e8; 639 margin-bottom: 5px; 640 overflow: hidden; 641 text-overflow: ellipsis; 642 white-space: nowrap; 643} 644 645.devtools-entry-json { 646 font-size: 10px; 647 color: #555; 648 margin: 0; 649 white-space: pre; 650 line-height: 1.5; 651 overflow: hidden; 652 max-height: 60px; 653} 654 655.devtools-detail { 656 flex: 1; 657 overflow-y: auto; 658 padding: 10px; 659 min-width: 0; 660} 661 662.devtools-detail-meta { 663 font-size: 11px; 664 color: #888; 665 margin-bottom: 10px; 666 font-family: system-ui, sans-serif; 667} 668 669.devtools-doc-json { 670 font-size: 12px; 671 color: #333; 672 margin: 0; 673 white-space: pre; 674 line-height: 1.5; 675}