style.css (15045B)
1 :root { 2 --polar1: #2E3440; 3 --polar2: #3B4252; 4 --polar3: #434C5E; 5 --polar4: #4C566A; 6 --snow1: #D8DEE9; 7 --snow2: #E5E9F0; 8 --snow3: #ECEFF4; 9 --turquoise: #8FBCBB; 10 --lightblue: #88C0D0; 11 --midblue: #81A1C1; 12 --darkblue: #5E81AC; 13 --red: #BF616A; 14 --orange: #D08770; 15 --yellow: #EBCB8B; 16 --green: #A3BE8C; 17 --violet: #B48EAD; 18 } 19 20 *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } 21 html, body { height: 100%; overflow: hidden; } 22 23 body { 24 background: var(--polar1); 25 font-family: 'Inter', system-ui, sans-serif; 26 color: var(--snow1); 27 font-size: 1rem; 28 display: flex; 29 flex-direction: column; 30 } 31 32 /* ── Topbar ── */ 33 .topbar { 34 flex-shrink: 0; 35 background: var(--polar2); 36 border-bottom: 1px solid var(--polar3); 37 z-index: 100; 38 } 39 .topbar-inner { 40 height: 56px; 41 padding: 0 1.5rem; 42 display: flex; 43 align-items: center; 44 justify-content: space-between; 45 } 46 .topbar-left { display: flex; align-items: center; gap: 1rem; } 47 .topbar-name { 48 font-size: 0.95rem; 49 font-weight: 600; 50 color: var(--snow3); 51 letter-spacing: 0.02em; 52 } 53 .topbar-right { display: flex; align-items: center; gap: 1.25rem; } 54 .topbar-username { 55 font-size: 0.8rem; 56 color: var(--snow1); 57 opacity: 0.45; 58 } 59 .nav-link { 60 color: var(--snow1); 61 text-decoration: none; 62 font-size: 0.875rem; 63 font-weight: 400; 64 letter-spacing: 0.03em; 65 transition: color 0.15s; 66 } 67 .nav-link:hover { color: var(--lightblue); } 68 .nav-link.signout:hover { color: var(--red); } 69 .lang-switcher { 70 display: inline-flex; 71 align-items: center; 72 background: var(--polar3); 73 border-radius: 6px; 74 padding: 3px; 75 gap: 1px; 76 } 77 .lang-opt { 78 background: none; 79 border: none; 80 border-radius: 4px; 81 color: var(--snow1); 82 cursor: pointer; 83 font-family: inherit; 84 font-size: 0.7rem; 85 font-weight: 600; 86 letter-spacing: 0.1em; 87 line-height: 1; 88 opacity: 0.4; 89 padding: 4px 8px; 90 transition: background 0.15s, color 0.15s, opacity 0.15s, box-shadow 0.15s; 91 } 92 .lang-opt.lang-active { 93 background: var(--polar1); 94 box-shadow: 0 1px 3px rgba(0,0,0,0.35); 95 color: var(--lightblue); 96 opacity: 1; 97 } 98 .lang-opt:not(.lang-active):hover { opacity: 0.75; } 99 .topbar-home { 100 display: flex; align-items: center; 101 color: var(--snow1); opacity: 0.45; 102 transition: opacity 0.15s, color 0.15s; 103 } 104 .topbar-home:hover { opacity: 1; color: var(--lightblue); } 105 .topbar-home svg { width: 1rem; height: 1rem; } 106 107 /* ── App body ── */ 108 .app-body { 109 display: flex; 110 flex: 1; 111 min-height: 0; 112 overflow: hidden; 113 } 114 115 /* ── Sidebar ── */ 116 .sidebar { 117 width: 220px; 118 flex-shrink: 0; 119 background: var(--polar2); 120 border-right: 1px solid var(--polar3); 121 display: flex; 122 flex-direction: column; 123 overflow: hidden; 124 transition: width 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); 125 } 126 .sidebar.collapsed { width: 0 !important; } 127 128 .sidebar-header { 129 padding: 1.25rem 1rem 0.75rem; 130 font-size: 0.7rem; 131 font-weight: 500; 132 letter-spacing: 0.14em; 133 text-transform: uppercase; 134 color: var(--snow1); 135 opacity: 0.45; 136 flex-shrink: 0; 137 } 138 .tree-list { 139 flex: 1; 140 overflow-y: auto; 141 padding: 0 0.5rem; 142 } 143 .tree-item { 144 display: flex; 145 align-items: center; 146 gap: 0.5rem; 147 padding: 0.5rem 0.5rem; 148 border-radius: 6px; 149 cursor: pointer; 150 transition: background 0.15s; 151 user-select: none; 152 } 153 .tree-item:hover { background: var(--polar3); } 154 .tree-item.active { background: rgba(136,192,208,0.08); } 155 .tree-item-name { 156 flex: 1; 157 font-size: 0.875rem; 158 color: var(--snow2); 159 white-space: nowrap; 160 overflow: hidden; 161 text-overflow: ellipsis; 162 } 163 .tree-item-role { 164 font-size: 0.65rem; 165 color: var(--snow1); 166 opacity: 0.4; 167 letter-spacing: 0.05em; 168 flex-shrink: 0; 169 } 170 .tree-item-icon { 171 width: 14px; height: 14px; 172 color: var(--lightblue); 173 flex-shrink: 0; 174 } 175 176 .sidebar-actions { 177 padding: 0.75rem 1rem 1.25rem; 178 border-top: 1px solid var(--polar3); 179 flex-shrink: 0; 180 } 181 .btn-new-tree { 182 width: 100%; 183 padding: 0.5rem 0.75rem; 184 background: transparent; 185 border: 1px solid var(--polar4); 186 border-radius: 7px; 187 color: var(--snow1); 188 font-size: 0.8rem; 189 font-family: inherit; 190 cursor: pointer; 191 display: flex; 192 align-items: center; 193 gap: 0.5rem; 194 transition: border-color 0.15s, color 0.15s; 195 } 196 .btn-new-tree:hover { border-color: var(--lightblue); color: var(--lightblue); } 197 .btn-new-tree svg { width: 14px; height: 14px; } 198 199 /* ── Canvas area ── */ 200 .canvas-area { 201 flex: 1; 202 min-width: 0; 203 position: relative; 204 overflow: hidden; 205 background: var(--polar1); 206 } 207 208 #treeCanvas { 209 position: absolute; 210 inset: 0; 211 width: 100%; 212 height: 100%; 213 cursor: grab; 214 } 215 #treeCanvas:active { cursor: grabbing; } 216 217 /* ── Canvas toolbar ── */ 218 .canvas-toolbar { 219 position: absolute; 220 top: 1rem; 221 left: 1rem; 222 z-index: 10; 223 display: flex; 224 gap: 0.4rem; 225 align-items: center; 226 } 227 .toolbar-btn { 228 width: 34px; height: 34px; 229 border-radius: 7px; 230 border: 1px solid var(--polar3); 231 background: var(--polar2); 232 color: var(--snow1); 233 cursor: pointer; 234 display: flex; align-items: center; justify-content: center; 235 transition: border-color 0.15s, color 0.15s; 236 } 237 .toolbar-btn:hover { border-color: var(--lightblue); color: var(--lightblue); } 238 .toolbar-btn svg { width: 16px; height: 16px; } 239 .toolbar-btn-primary { 240 width: auto; 241 padding: 0 0.85rem; 242 gap: 0.4rem; 243 font-size: 0.8rem; 244 font-family: inherit; 245 font-weight: 500; 246 color: var(--lightblue); 247 border-color: var(--lightblue); 248 } 249 .toolbar-sep { 250 width: 1px; height: 22px; 251 background: var(--polar3); 252 margin: 0 0.1rem; 253 } 254 255 /* ── Empty state ── */ 256 .empty-state { 257 position: absolute; 258 inset: 0; 259 display: flex; 260 flex-direction: column; 261 align-items: center; 262 justify-content: center; 263 gap: 0.75rem; 264 pointer-events: none; 265 } 266 .empty-state button { pointer-events: all; } 267 .empty-icon svg { 268 width: 64px; height: 64px; 269 color: var(--polar4); 270 stroke-width: 1; 271 } 272 .empty-title { 273 font-family: 'EB Garamond', Georgia, serif; 274 font-size: 1.5rem; 275 color: var(--snow2); 276 } 277 .empty-sub { 278 font-size: 0.875rem; 279 color: var(--snow1); 280 opacity: 0.45; 281 margin-bottom: 0.5rem; 282 } 283 284 /* ── D3 node styles (applied via JS/SVG attributes + these classes) ── */ 285 .node-card { 286 fill: var(--polar3); 287 stroke: var(--polar4); 288 stroke-width: 1; 289 rx: 8; 290 ry: 8; 291 transition: stroke 0.15s; 292 } 293 .node-card.hovered, .node-card.selected { 294 stroke: var(--lightblue); 295 } 296 .node-name { 297 font-family: 'EB Garamond', Georgia, serif; 298 fill: var(--snow3); 299 font-size: 14px; 300 font-weight: 600; 301 } 302 .node-dates { 303 font-family: 'Inter', sans-serif; 304 fill: var(--snow1); 305 font-size: 11px; 306 opacity: 0.6; 307 } 308 .edge-line { 309 stroke: var(--polar4); 310 stroke-width: 2; 311 fill: none; 312 } 313 .partner-dot { 314 fill: var(--polar3); 315 stroke: var(--polar4); 316 stroke-width: 1.5; 317 cursor: pointer; 318 transition: stroke 0.15s; 319 } 320 .partner-dot:hover { stroke: var(--lightblue); } 321 322 /* ── Detail panel ── */ 323 .detail-panel { 324 width: 0; 325 flex-shrink: 0; 326 background: var(--polar2); 327 border-left: 1px solid transparent; 328 display: flex; 329 flex-direction: column; 330 overflow: hidden; 331 transition: width 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94), border-color 0.3s; 332 } 333 .detail-panel.open { 334 width: 300px; 335 border-color: var(--polar3); 336 } 337 .detail-header { 338 display: flex; 339 align-items: center; 340 justify-content: space-between; 341 padding: 1.25rem 1rem 0.75rem; 342 border-bottom: 1px solid var(--polar3); 343 flex-shrink: 0; 344 gap: 0.5rem; 345 } 346 .detail-name { 347 font-family: 'EB Garamond', Georgia, serif; 348 font-size: 1.15rem; 349 font-weight: 600; 350 color: var(--snow3); 351 flex: 1; 352 min-width: 0; 353 overflow: hidden; 354 text-overflow: ellipsis; 355 white-space: nowrap; 356 } 357 .detail-header-actions { display: flex; gap: 0.3rem; flex-shrink: 0; } 358 .detail-body { 359 flex: 1; 360 overflow-y: auto; 361 padding: 1rem; 362 } 363 .detail-field { margin-bottom: 1rem; } 364 .detail-field-label { 365 font-size: 0.68rem; 366 font-weight: 500; 367 letter-spacing: 0.1em; 368 text-transform: uppercase; 369 color: var(--snow1); 370 opacity: 0.45; 371 margin-bottom: 0.2rem; 372 } 373 .detail-field-value { 374 font-size: 0.875rem; 375 color: var(--snow2); 376 line-height: 1.5; 377 } 378 .detail-section-title { 379 font-size: 0.7rem; 380 font-weight: 500; 381 letter-spacing: 0.12em; 382 text-transform: uppercase; 383 color: var(--snow1); 384 opacity: 0.35; 385 margin: 1.25rem 0 0.5rem; 386 padding-top: 1rem; 387 border-top: 1px solid var(--polar3); 388 } 389 .detail-rel-item { 390 font-size: 0.875rem; 391 color: var(--snow1); 392 padding: 0.3rem 0; 393 display: flex; 394 align-items: center; 395 gap: 0.5rem; 396 cursor: pointer; 397 border-radius: 4px; 398 padding: 0.3rem 0.4rem; 399 transition: background 0.1s; 400 } 401 .detail-rel-item:hover { background: var(--polar3); } 402 .detail-rel-badge { 403 font-size: 0.65rem; 404 color: var(--snow1); 405 opacity: 0.45; 406 background: var(--polar3); 407 border-radius: 3px; 408 padding: 0.1rem 0.35rem; 409 flex-shrink: 0; 410 } 411 .detail-actions { 412 padding: 1rem; 413 border-top: 1px solid var(--polar3); 414 display: flex; 415 flex-direction: column; 416 gap: 0.5rem; 417 flex-shrink: 0; 418 } 419 .detail-actions .btn { width: 100%; justify-content: center; } 420 421 /* ── Connect options ── */ 422 .connect-options { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 0.5rem; } 423 .connect-btn { 424 justify-content: flex-start; 425 gap: 0.75rem; 426 padding: 0.75rem 1rem; 427 font-size: 0.9rem; 428 border-color: var(--polar3); 429 } 430 .connect-btn:hover { border-color: var(--lightblue); color: var(--lightblue); } 431 .connect-btn svg { width: 16px; height: 16px; flex-shrink: 0; } 432 433 /* ── Modal ── */ 434 .modal-overlay { 435 position: fixed; 436 inset: 0; 437 background: rgba(0,0,0,0.55); 438 z-index: 200; 439 display: flex; 440 align-items: center; 441 justify-content: center; 442 opacity: 0; 443 pointer-events: none; 444 transition: opacity 0.2s; 445 } 446 .modal-overlay.open { opacity: 1; pointer-events: all; } 447 .modal { 448 background: var(--polar2); 449 border: 1px solid var(--polar3); 450 border-radius: 12px; 451 padding: 2rem; 452 width: 420px; 453 max-width: calc(100vw - 2rem); 454 max-height: calc(100vh - 4rem); 455 overflow-y: auto; 456 transform: translateY(12px); 457 transition: transform 0.2s; 458 } 459 .modal-overlay.open .modal { transform: translateY(0); } 460 .modal-wide { width: 520px; } 461 .modal h2 { 462 font-family: 'EB Garamond', Georgia, serif; 463 font-size: 1.4rem; 464 font-weight: 600; 465 color: var(--snow3); 466 margin-bottom: 1.5rem; 467 } 468 .form-group { margin-bottom: 1.1rem; } 469 .form-label { 470 display: block; 471 font-size: 0.75rem; 472 font-weight: 500; 473 letter-spacing: 0.08em; 474 text-transform: uppercase; 475 color: var(--snow1); 476 opacity: 0.55; 477 margin-bottom: 0.4rem; 478 } 479 .form-input { 480 width: 100%; 481 padding: 0.55rem 0.75rem; 482 background: var(--polar1); 483 border: 1px solid var(--polar3); 484 border-radius: 7px; 485 color: var(--snow2); 486 font-family: inherit; 487 font-size: 0.9rem; 488 outline: none; 489 transition: border-color 0.15s; 490 } 491 .form-input:focus { border-color: var(--lightblue); } 492 .form-input::placeholder { color: var(--snow1); opacity: 0.3; } 493 textarea.form-input { resize: vertical; min-height: 72px; line-height: 1.5; } 494 select.form-input { 495 appearance: none; 496 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23D8DEE9' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); 497 background-repeat: no-repeat; 498 background-position: right 0.75rem center; 499 cursor: pointer; 500 } 501 select.form-input option { background: var(--polar2); color: var(--snow1); } 502 .form-row { display: flex; gap: 0.75rem; margin-bottom: 1.1rem; } 503 .form-row .form-group { flex: 1; margin-bottom: 0; } 504 .modal-actions { 505 display: flex; 506 justify-content: flex-end; 507 gap: 0.6rem; 508 margin-top: 1.75rem; 509 } 510 .invite-row { display: flex; gap: 0.5rem; align-items: center; } 511 .invite-row .form-input { flex: 1; } 512 513 /* Members list */ 514 .member-row { 515 display: flex; 516 align-items: center; 517 gap: 0.5rem; 518 padding: 0.5rem 0; 519 border-bottom: 1px solid var(--polar3); 520 font-size: 0.875rem; 521 } 522 .member-username { flex: 1; color: var(--snow2); } 523 .member-role { 524 font-size: 0.7rem; 525 color: var(--snow1); 526 opacity: 0.5; 527 letter-spacing: 0.06em; 528 text-transform: uppercase; 529 } 530 .pending-row { 531 display: flex; 532 align-items: center; 533 gap: 0.5rem; 534 padding: 0.4rem 0; 535 font-size: 0.8rem; 536 color: var(--snow1); 537 opacity: 0.6; 538 } 539 .pending-row span { flex: 1; } 540 541 /* ── Buttons ── */ 542 .btn { 543 padding: 0.5rem 1.1rem; 544 border-radius: 7px; 545 font-family: inherit; 546 font-size: 0.875rem; 547 font-weight: 500; 548 cursor: pointer; 549 border: 1px solid var(--polar3); 550 background: transparent; 551 color: var(--snow1); 552 display: inline-flex; align-items: center; gap: 0.4rem; 553 transition: border-color 0.15s, color 0.15s, background 0.15s; 554 } 555 .btn:hover { border-color: var(--snow1); } 556 .btn-primary { 557 background: var(--lightblue); 558 border-color: var(--lightblue); 559 color: var(--polar1); 560 } 561 .btn-primary:hover { background: var(--turquoise); border-color: var(--turquoise); } 562 .btn-danger { border-color: var(--red); color: var(--red); } 563 .btn-danger:hover { background: rgba(191,97,106,0.15); } 564 .btn-icon { 565 width: 30px; height: 30px; 566 border-radius: 6px; 567 border: 1px solid var(--polar3); 568 background: transparent; 569 color: var(--snow1); 570 cursor: pointer; 571 display: flex; align-items: center; justify-content: center; 572 flex-shrink: 0; 573 transition: border-color 0.15s, color 0.15s; 574 } 575 .btn-icon:hover { border-color: var(--lightblue); color: var(--lightblue); } 576 .btn-icon.danger:hover { border-color: var(--red); color: var(--red); } 577 .btn-icon svg { width: 14px; height: 14px; } 578 .btn-sidebar-toggle { 579 width: 28px; height: 28px; 580 border-radius: 6px; 581 border: 1px solid var(--polar3); 582 background: transparent; 583 color: var(--snow1); 584 cursor: pointer; 585 display: flex; align-items: center; justify-content: center; 586 transition: border-color 0.15s, color 0.15s; 587 } 588 .btn-sidebar-toggle:hover { border-color: var(--lightblue); color: var(--lightblue); } 589 .btn-sidebar-toggle svg { width: 14px; height: 14px; } 590 591 /* ── Context menu ── */ 592 .ctx-menu { 593 position: fixed; 594 z-index: 300; 595 background: var(--polar2); 596 border: 1px solid var(--polar3); 597 border-radius: 8px; 598 padding: 0.3rem; 599 min-width: 168px; 600 box-shadow: 0 8px 24px rgba(0,0,0,0.4); 601 display: none; 602 } 603 .ctx-menu.open { display: block; } 604 .ctx-item { 605 padding: 0.45rem 0.75rem; 606 border-radius: 5px; 607 font-size: 0.85rem; 608 cursor: pointer; 609 color: var(--snow1); 610 transition: background 0.1s; 611 display: flex; align-items: center; gap: 0.5rem; 612 } 613 .ctx-item:hover { background: var(--polar3); } 614 .ctx-item.danger { color: var(--red); } 615 .ctx-item.danger:hover { background: rgba(191,97,106,0.15); } 616 617 /* ── Scrollbar ── */ 618 ::-webkit-scrollbar { width: 5px; } 619 ::-webkit-scrollbar-track { background: transparent; } 620 ::-webkit-scrollbar-thumb { background: var(--polar4); border-radius: 3px; } 621 ::-webkit-scrollbar-thumb:hover { background: var(--snow1); opacity: 0.3; } 622 623 /* ── Mobile ── */ 624 @media (max-width: 700px) { 625 .sidebar { width: 0; } 626 .detail-panel.open { width: 100%; position: absolute; right: 0; top: 0; bottom: 0; z-index: 50; } 627 }