style.css (46120B)
1 /* ===== RESET & BASE ===== */ 2 *, *::before, *::after { 3 box-sizing: border-box; 4 margin: 0; 5 padding: 0; 6 } 7 8 :root { 9 --font-sans: 'Space Grotesk', -apple-system, sans-serif; 10 --font-mono: 'JetBrains Mono', 'Fira Code', monospace; 11 --radius-sm: 10px; 12 --radius-md: 16px; 13 --radius-lg: 22px; 14 --transition: 200ms ease; 15 16 /* Tokyo Night Storm (dark) */ 17 --base: #24283b; 18 --base-light: #292e42; 19 --base-dark: #1f2335; 20 --inset: #1a1b26; 21 --border: #3b4261; 22 --border-light: #3b4261; 23 --shadow-dark: rgba(0, 0, 0, 0.55); 24 --shadow-light: rgba(255, 255, 255, 0.06); 25 --neu-raised: 4px 4px 10px var(--shadow-dark), -4px -4px 10px var(--shadow-light); 26 --neu-raised-sm: 3px 3px 7px var(--shadow-dark), -3px -3px 7px var(--shadow-light); 27 --neu-raised-lg: 6px 6px 14px var(--shadow-dark), -6px -6px 14px var(--shadow-light); 28 --neu-pressed: inset 3px 3px 7px var(--shadow-dark), inset -3px -3px 7px var(--shadow-light); 29 --neu-pressed-deep: inset 4px 4px 10px var(--shadow-dark), inset -4px -4px 10px var(--shadow-light); 30 --neu-flat: 0 0 0 transparent; 31 32 --text-primary: #c0caf5; 33 --text-secondary: #a9b1d6; 34 --text-muted: #737ba3; 35 --accent: #7aa2f7; 36 --accent-dark: #3d59a1; 37 --accent-glow: rgba(122, 162, 247, 0.25); 38 --success: #9ece6a; 39 --success-glow: rgba(158, 206, 106, 0.2); 40 --warning: #e0af68; 41 --warning-glow: rgba(224, 175, 104, 0.2); 42 --error: #f7768e; 43 --error-glow: rgba(247, 118, 142, 0.2); 44 --streak: #ff9e64; 45 --streak-glow: rgba(255, 158, 100, 0.2); 46 --text-on-color: #1f2335; 47 48 --chart-blue: #7aa2f7; 49 --chart-green: #9ece6a; 50 --chart-red: #f7768e; 51 --heatmap-1: #1a2740; 52 --heatmap-2: #1f3d5c; 53 --heatmap-3: #2a6490; 54 --heatmap-4: #7aa2f7; 55 --cyan: #7dcfff; 56 --magenta: #bb9af7; 57 --teal: #73daca; 58 --edge-highlight: rgba(255, 255, 255, 0.05); 59 --navbar-bg: rgba(36, 40, 59, 0.7); 60 } 61 62 [data-theme="light"] { 63 /* Tokyo Night Day (light) */ 64 --base: #d5d6db; 65 --base-light: #e1e2e7; 66 --base-dark: #c8c9ce; 67 --inset: #cbccd1; 68 --border: #b4b5b9; 69 --border-light: #b4b5b9; 70 --shadow-dark: rgba(0, 0, 0, 0.15); 71 --shadow-light: rgba(255, 255, 255, 0.7); 72 73 --text-primary: #343b58; 74 --text-secondary: #4c505e; 75 --text-muted: #6e717b; 76 --accent: #2367c5; 77 --accent-dark: #1e5dba; 78 --accent-glow: rgba(35, 103, 197, 0.2); 79 --success: #587539; 80 --success-glow: rgba(88, 117, 57, 0.15); 81 --warning: #8f5e15; 82 --warning-glow: rgba(143, 94, 21, 0.15); 83 --error: #c2204d; 84 --error-glow: rgba(194, 32, 77, 0.15); 85 --streak: #b15c00; 86 --streak-glow: rgba(177, 92, 0, 0.15); 87 --text-on-color: #ffffff; 88 89 --chart-blue: #2367c5; 90 --chart-green: #587539; 91 --chart-red: #c2204d; 92 --heatmap-1: #c8daf0; 93 --heatmap-2: #9bbde0; 94 --heatmap-3: #5a9bd4; 95 --heatmap-4: #2367c5; 96 --cyan: #007197; 97 --magenta: #7847bd; 98 --teal: #387068; 99 --edge-highlight: rgba(255, 255, 255, 0.5); 100 --navbar-bg: rgba(213, 214, 219, 0.7); 101 } 102 103 html { 104 font-size: 16px; 105 -webkit-font-smoothing: antialiased; 106 -moz-osx-font-smoothing: grayscale; 107 } 108 109 body { 110 font-family: var(--font-sans); 111 background: radial-gradient(ellipse at 50% 15%, var(--base-light) 0%, var(--base) 55%, var(--base-dark) 100%); 112 background-attachment: fixed; 113 color: var(--text-primary); 114 line-height: 1.6; 115 min-height: 100vh; 116 font-weight: 500; 117 transition: color 0.3s ease; 118 } 119 120 a { 121 color: var(--accent); 122 text-decoration: none; 123 transition: color var(--transition); 124 } 125 a:hover { color: var(--text-primary); } 126 127 /* ===== NAVBAR ===== */ 128 .navbar { 129 position: sticky; 130 top: 0; 131 z-index: 100; 132 background: var(--navbar-bg); 133 backdrop-filter: blur(16px); 134 -webkit-backdrop-filter: blur(16px); 135 border-bottom: 1px solid var(--edge-highlight); 136 } 137 138 .nav-inner { 139 max-width: 1200px; 140 margin: 0 auto; 141 padding: 0 1.5rem; 142 display: flex; 143 align-items: center; 144 justify-content: space-between; 145 height: 56px; 146 } 147 148 .nav-brand { 149 display: inline-flex; 150 align-items: center; 151 gap: 0.5rem; 152 font-size: 1.25rem; 153 font-weight: 700; 154 color: var(--text-primary); 155 letter-spacing: -0.02em; 156 text-transform: uppercase; 157 } 158 .nav-brand:hover { color: var(--accent); } 159 160 .nav-logo { 161 width: 28px; 162 height: 28px; 163 color: var(--accent); 164 } 165 166 .nav-links { 167 list-style: none; 168 display: flex; 169 gap: 0.25rem; 170 align-items: center; 171 } 172 173 .nav-link { 174 display: block; 175 padding: 0.5rem 1rem; 176 border-radius: var(--radius-sm); 177 color: var(--text-secondary); 178 font-size: 0.875rem; 179 font-weight: 600; 180 text-transform: uppercase; 181 letter-spacing: 0.03em; 182 transition: all var(--transition); 183 } 184 .nav-link:hover { 185 color: var(--text-primary); 186 } 187 188 /* ===== HAMBURGER ===== */ 189 .nav-hamburger { 190 display: none; 191 flex-direction: column; 192 justify-content: center; 193 gap: 5px; 194 width: 36px; 195 height: 36px; 196 padding: 6px; 197 background: none; 198 border: none; 199 cursor: pointer; 200 z-index: 301; 201 } 202 .nav-hamburger span { 203 display: block; 204 height: 2px; 205 background: var(--text-primary); 206 border-radius: 2px; 207 transition: all 0.3s ease; 208 } 209 .nav-hamburger.active span:nth-child(1) { 210 transform: translateY(7px) rotate(45deg); 211 } 212 .nav-hamburger.active span:nth-child(2) { 213 opacity: 0; 214 } 215 .nav-hamburger.active span:nth-child(3) { 216 transform: translateY(-7px) rotate(-45deg); 217 } 218 219 /* ===== MAIN CONTENT ===== */ 220 .main-content { 221 max-width: 1200px; 222 margin: 0 auto; 223 padding: 2rem 1.5rem; 224 } 225 226 /* ===== CARDS ===== */ 227 .card { 228 background: linear-gradient(145deg, var(--base-light), var(--base)); 229 border-radius: var(--radius-md); 230 padding: 1.5rem; 231 box-shadow: var(--neu-raised); 232 border-top: 1px solid var(--edge-highlight); 233 border-left: 1px solid var(--edge-highlight); 234 } 235 236 .stat-card { 237 background: linear-gradient(145deg, var(--base-light), var(--base)); 238 border-radius: var(--radius-md); 239 padding: 1.25rem; 240 text-align: center; 241 transition: all var(--transition); 242 box-shadow: var(--neu-raised); 243 border-top: 1px solid var(--edge-highlight); 244 border-left: 1px solid var(--edge-highlight); 245 --rx: 0deg; 246 --ry: 0deg; 247 --lift: 0px; 248 transform: rotateX(var(--rx)) rotateY(var(--ry)) translateY(var(--lift)); 249 will-change: transform; 250 } 251 .stat-card:hover { 252 box-shadow: var(--neu-raised-lg); 253 --lift: -2px; 254 position: relative; 255 z-index: 1; 256 } 257 258 .stat-card--streak { 259 position: relative; 260 overflow: hidden; 261 } 262 263 .stat-card__icon { 264 width: 36px; 265 height: 36px; 266 margin: 0 auto 0.5rem; 267 border-radius: 50%; 268 display: flex; 269 align-items: center; 270 justify-content: center; 271 } 272 273 .streak-fire { background: var(--streak); } 274 .stat-icon--words { background: var(--accent); } 275 .stat-icon--mastered { background: var(--success); } 276 .stat-icon--review { background: var(--warning); } 277 278 .stat-card__value { 279 font-size: 2rem; 280 font-weight: 700; 281 line-height: 1.2; 282 } 283 284 .stat-card__label { 285 font-size: 0.8rem; 286 color: var(--text-secondary); 287 text-transform: uppercase; 288 letter-spacing: 0.08em; 289 font-weight: 600; 290 margin-top: 0.25rem; 291 } 292 293 .stat-card__sub { 294 display: block; 295 font-size: 0.75rem; 296 color: var(--text-muted); 297 text-transform: none; 298 letter-spacing: 0; 299 margin-top: 0.125rem; 300 } 301 302 .stat-card__action { 303 display: inline-block; 304 margin-top: 0.5rem; 305 font-size: 0.8rem; 306 padding: 0.3rem 0.8rem; 307 background: var(--warning); 308 color: var(--text-on-color); 309 border-radius: var(--radius-sm); 310 font-weight: 600; 311 border: none; 312 box-shadow: var(--neu-raised-sm); 313 transition: all var(--transition); 314 cursor: pointer; 315 } 316 .stat-card__action:hover { 317 box-shadow: var(--neu-pressed); 318 color: var(--text-on-color); 319 } 320 321 /* ===== BUTTONS ===== */ 322 .btn { 323 display: inline-flex; 324 align-items: center; 325 justify-content: center; 326 gap: 0.5rem; 327 padding: 0.625rem 1.25rem; 328 border: none; 329 border-radius: var(--radius-sm); 330 background: var(--base); 331 color: var(--text-primary); 332 font-family: var(--font-sans); 333 font-size: 0.875rem; 334 font-weight: 600; 335 cursor: pointer; 336 transition: all var(--transition); 337 text-decoration: none; 338 line-height: 1.4; 339 text-transform: uppercase; 340 letter-spacing: 0.03em; 341 box-shadow: var(--neu-raised-sm); 342 } 343 .btn:hover { 344 box-shadow: var(--neu-raised); 345 color: var(--text-primary); 346 transform: translateY(-1px); 347 } 348 .btn:active { 349 box-shadow: var(--neu-pressed); 350 transform: translateY(0); 351 } 352 353 .btn--primary { 354 background: var(--accent); 355 color: var(--text-on-color); 356 } 357 .btn--primary:hover { 358 color: var(--text-on-color); 359 } 360 361 .btn--danger { 362 background: var(--error); 363 color: var(--text-on-color); 364 } 365 .btn--danger:hover { 366 color: var(--text-on-color); 367 } 368 369 .btn--ghost { 370 background: transparent; 371 color: var(--text-secondary); 372 box-shadow: none; 373 } 374 .btn--ghost:hover { 375 color: var(--text-primary); 376 background: var(--base); 377 box-shadow: var(--neu-raised-sm); 378 } 379 .btn--ghost:active { 380 box-shadow: var(--neu-pressed); 381 } 382 383 .btn--small { 384 padding: 0.375rem 0.75rem; 385 font-size: 0.8rem; 386 } 387 388 /* ===== BADGES ===== */ 389 .badge { 390 display: inline-block; 391 padding: 0.2rem 0.6rem; 392 border-radius: 999px; 393 font-size: 0.7rem; 394 font-weight: 700; 395 text-transform: uppercase; 396 letter-spacing: 0.05em; 397 border: none; 398 background: var(--base-light); 399 } 400 .badge--common { color: var(--accent); } 401 .badge--new { color: var(--success); } 402 .badge--weak { color: var(--error); } 403 .badge--speed { color: var(--warning); } 404 .badge--review { color: var(--streak); } 405 .badge--random { color: var(--text-secondary); } 406 .badge--sentences { color: var(--cyan); } 407 .badge--phrases { color: var(--streak); } 408 .badge--lesson { color: var(--magenta); } 409 .badge--beginner { color: var(--success); } 410 .badge--intermediate { color: var(--warning); } 411 .badge--advanced { color: var(--error); } 412 .badge--expert { color: var(--magenta); } 413 .badge--master { color: var(--teal); } 414 415 /* ===== PROGRESS BAR ===== */ 416 .progress-bar { 417 height: 10px; 418 background: var(--base); 419 border-radius: 999px; 420 overflow: hidden; 421 box-shadow: var(--neu-pressed); 422 } 423 424 .progress-bar__fill { 425 height: 100%; 426 background: var(--accent); 427 border-radius: 999px; 428 transition: width 0.3s ease; 429 } 430 431 .progress-bar__label { 432 font-size: 0.8rem; 433 color: var(--text-secondary); 434 margin-top: 0.5rem; 435 text-align: center; 436 font-weight: 600; 437 } 438 439 /* ===== TABLES ===== */ 440 .table-wrapper { 441 overflow-x: auto; 442 border-radius: var(--radius-md); 443 box-shadow: var(--neu-pressed); 444 background: var(--base); 445 } 446 447 .table { 448 width: 100%; 449 border-collapse: separate; 450 border-spacing: 0; 451 font-size: 0.875rem; 452 } 453 454 .table thead { 455 position: relative; 456 } 457 458 .table thead tr { 459 position: relative; 460 } 461 462 .table th { 463 text-align: left; 464 padding: 0.75rem 1rem; 465 background: var(--base); 466 color: var(--text-secondary); 467 font-weight: 700; 468 font-size: 0.75rem; 469 text-transform: uppercase; 470 letter-spacing: 0.08em; 471 box-shadow: var(--neu-raised-sm); 472 } 473 474 .table th:first-child { border-radius: var(--radius-sm) 0 0 0; } 475 .table th:last-child { border-radius: 0 var(--radius-sm) 0 0; } 476 477 .table td { 478 padding: 0.625rem 1rem; 479 border-bottom: 1px solid rgba(128,128,160,0.06); 480 } 481 482 .table tbody tr:last-child td { border-bottom: none; } 483 .table tbody tr:hover { background: var(--base-light); } 484 485 .table-empty { 486 text-align: center; 487 color: var(--text-muted); 488 padding: 2rem 1rem; 489 } 490 491 .sortable { cursor: pointer; user-select: none; } 492 .sortable:hover { color: var(--accent); } 493 .sortable::after { content: ' \2195'; font-size: 0.7em; opacity: 0.5; } 494 495 .accuracy-cell { font-weight: 700; } 496 .accuracy--good { color: var(--success); } 497 .accuracy--mid { color: var(--warning); } 498 .accuracy--low { color: var(--error); } 499 500 /* ===== DASHBOARD ===== */ 501 .dashboard { 502 display: flex; 503 flex-direction: column; 504 gap: 2.5rem; 505 } 506 507 .hero-stats { 508 display: grid; 509 grid-template-columns: repeat(4, 1fr); 510 gap: 1.25rem; 511 perspective: 800px; 512 } 513 514 .section-title { 515 font-size: 1rem; 516 font-weight: 700; 517 margin-bottom: 1rem; 518 color: var(--text-secondary); 519 text-transform: uppercase; 520 letter-spacing: 0.1em; 521 } 522 523 .page-title { 524 font-size: 1.5rem; 525 font-weight: 700; 526 margin-bottom: 1.5rem; 527 text-transform: uppercase; 528 letter-spacing: 0.06em; 529 } 530 531 /* ===== LESSON GRID ===== */ 532 .lesson-grid { 533 display: flex; 534 flex-direction: column; 535 gap: 0.75rem; 536 background: var(--base); 537 border-radius: var(--radius-lg); 538 padding: 1rem; 539 box-shadow: var(--neu-pressed-deep); 540 } 541 542 .lesson-card { 543 display: flex; 544 align-items: center; 545 gap: 1rem; 546 padding: 0.875rem 1.125rem; 547 background: var(--base); 548 border-radius: var(--radius-md); 549 text-decoration: none; 550 transition: all var(--transition); 551 box-shadow: var(--neu-raised-sm); 552 } 553 .lesson-card:hover { 554 box-shadow: var(--neu-raised); 555 transform: translateY(-1px); 556 color: var(--text-primary); 557 position: relative; 558 z-index: 1; 559 } 560 .lesson-card:active { 561 box-shadow: var(--neu-pressed); 562 transform: translateY(0); 563 } 564 565 .lesson-card__order { 566 width: 34px; 567 height: 34px; 568 display: flex; 569 align-items: center; 570 justify-content: center; 571 border-radius: 50%; 572 font-size: 0.85rem; 573 font-weight: 700; 574 flex-shrink: 0; 575 color: var(--text-on-color); 576 } 577 578 .lesson-card--beginner .lesson-card__order { background: var(--success); color: var(--text-on-color); } 579 .lesson-card--intermediate .lesson-card__order { background: var(--warning); color: var(--text-on-color); } 580 .lesson-card--advanced .lesson-card__order { background: var(--error); color: var(--text-on-color); } 581 .lesson-card--expert .lesson-card__order { background: var(--magenta); color: var(--text-on-color); } 582 .lesson-card--master .lesson-card__order { background: var(--teal); color: var(--text-on-color); } 583 584 .lesson-card__info { flex: 1; min-width: 0; } 585 .lesson-card__title { font-weight: 600; font-size: 0.95rem; color: var(--text-primary); } 586 .lesson-card__subtitle { font-size: 0.8rem; color: var(--text-secondary); } 587 .lesson-card__level { flex-shrink: 0; } 588 589 .lesson-progress { margin-top: 0.35rem; } 590 .lesson-progress__bar { 591 position: relative; 592 height: 4px; 593 background: var(--surface-hover); 594 border-radius: 2px; 595 overflow: hidden; 596 } 597 .lesson-progress__fill { 598 position: absolute; 599 top: 0; left: 0; height: 100%; 600 border-radius: 2px; 601 transition: width 0.3s ease; 602 } 603 .lesson-progress__fill--practiced { 604 background: var(--text-muted); 605 opacity: 0.3; 606 } 607 .lesson-progress__fill--mastered { 608 background: var(--success); 609 } 610 .lesson-progress__text { 611 display: flex; 612 justify-content: space-between; 613 font-size: 0.7rem; 614 color: var(--text-muted); 615 margin-top: 0.2rem; 616 } 617 618 /* ===== MODE GRID ===== */ 619 .mode-grid { 620 display: grid; 621 grid-template-columns: repeat(4, 1fr); 622 gap: 1rem; 623 background: var(--base); 624 border-radius: var(--radius-lg); 625 padding: 1rem; 626 box-shadow: var(--neu-pressed-deep); 627 perspective: 800px; 628 } 629 630 .mode-card { 631 display: flex; 632 flex-direction: column; 633 align-items: center; 634 text-align: center; 635 padding: 1.25rem 0.75rem; 636 background: linear-gradient(145deg, var(--base-light), var(--base)); 637 border-radius: var(--radius-md); 638 transition: all var(--transition); 639 text-decoration: none; 640 box-shadow: var(--neu-raised-sm); 641 border-top: 1px solid var(--edge-highlight); 642 border-left: 1px solid var(--edge-highlight); 643 --rx: 0deg; 644 --ry: 0deg; 645 --lift: 0px; 646 transform: rotateX(var(--rx)) rotateY(var(--ry)) translateY(var(--lift)); 647 will-change: transform; 648 } 649 .mode-card:hover { 650 box-shadow: var(--neu-raised); 651 --lift: -2px; 652 color: var(--text-primary); 653 position: relative; 654 z-index: 1; 655 } 656 .mode-card:active { 657 box-shadow: var(--neu-pressed); 658 --lift: 0px; 659 --rx: 0deg; 660 --ry: 0deg; 661 } 662 663 .mode-card__icon { 664 width: 44px; 665 height: 44px; 666 border-radius: 50%; 667 margin-bottom: 0.75rem; 668 } 669 670 .mode-icon--common { background: var(--accent); } 671 .mode-icon--new { background: var(--success); } 672 .mode-icon--weak { background: var(--error); } 673 .mode-icon--speed { background: var(--warning); } 674 .mode-icon--review { background: #7c3aed; } 675 .mode-icon--random { background: #64748b; } 676 .mode-icon--sentences { background: #0ea5e9; } 677 .mode-icon--phrases { background: var(--streak); } 678 679 .mode-card__title { 680 font-weight: 700; 681 font-size: 0.9rem; 682 color: var(--text-primary); 683 margin-bottom: 0.25rem; 684 text-transform: uppercase; 685 letter-spacing: 0.03em; 686 } 687 688 .mode-card__desc { 689 font-size: 0.8rem; 690 color: var(--text-secondary); 691 } 692 693 /* ===== TODAY'S PROGRESS ===== */ 694 .progress-container { 695 background: var(--base); 696 border-radius: var(--radius-md); 697 padding: 1.25rem; 698 box-shadow: var(--neu-pressed); 699 } 700 701 /* ===== EMPTY STATE ===== */ 702 .empty-state { 703 text-align: center; 704 padding: 3rem 1.5rem; 705 color: var(--text-secondary); 706 background: var(--base); 707 border-radius: var(--radius-md); 708 box-shadow: var(--neu-pressed); 709 } 710 711 /* ===== PRACTICE PAGE ===== */ 712 #practice-container { 713 min-height: calc(100vh - 56px - 4rem); 714 display: flex; 715 flex-direction: column; 716 justify-content: center; 717 } 718 719 .practice-header { 720 display: flex; 721 align-items: center; 722 justify-content: space-between; 723 margin-bottom: 1.5rem; 724 } 725 726 .practice-mode-label { 727 font-size: 1rem; 728 font-weight: 700; 729 color: var(--text-secondary); 730 text-transform: uppercase; 731 letter-spacing: 0.05em; 732 } 733 734 .practice-loading { 735 display: flex; 736 flex-direction: column; 737 align-items: center; 738 justify-content: center; 739 padding: 4rem; 740 color: var(--text-secondary); 741 gap: 1rem; 742 } 743 744 .session-config { 745 display: flex; 746 flex-direction: column; 747 align-items: center; 748 gap: 1rem; 749 } 750 .session-config__label { 751 font-size: 0.85rem; 752 font-weight: 600; 753 color: var(--text-secondary); 754 text-transform: uppercase; 755 letter-spacing: 0.05em; 756 } 757 .session-config__options { 758 display: flex; 759 gap: 0.5rem; 760 } 761 .session-config__btn { 762 padding: 0.5rem 1.2rem; 763 border-radius: var(--radius); 764 border: 1px solid var(--border); 765 background: var(--surface); 766 color: var(--text-secondary); 767 cursor: pointer; 768 font-size: 0.85rem; 769 transition: all 0.15s ease; 770 } 771 .session-config__btn:hover { 772 border-color: var(--accent); 773 color: var(--text-primary); 774 } 775 .session-config__btn--active { 776 background: var(--accent); 777 color: var(--base); 778 border-color: var(--accent); 779 font-weight: 600; 780 } 781 .session-config__start { 782 margin-top: 0.5rem; 783 padding: 0.65rem 2rem; 784 font-size: 1rem; 785 } 786 787 .spinner { 788 width: 32px; 789 height: 32px; 790 border: 3px solid var(--base-light); 791 border-top-color: var(--accent); 792 border-radius: 50%; 793 animation: spin 0.8s linear infinite; 794 } 795 796 @keyframes spin { to { transform: rotate(360deg); } } 797 798 .practice-area { 799 display: flex; 800 flex-direction: column; 801 align-items: stretch; 802 gap: 1.5rem; 803 max-width: 1200px; 804 margin: 0 auto; 805 } 806 807 .practice-main { 808 display: flex; 809 gap: 1.5rem; 810 align-items: flex-start; 811 } 812 813 .practice-left { 814 flex: 1; 815 min-width: 0; 816 display: flex; 817 flex-direction: column; 818 gap: 1.5rem; 819 } 820 821 /* ===== MONKEYTYPE TYPING DISPLAY ===== */ 822 .typing-display { 823 width: 100%; 824 background: var(--base); 825 border-radius: var(--radius-lg); 826 padding: 2rem 2.5rem; 827 min-height: 180px; 828 max-height: 220px; 829 overflow-y: auto; 830 scrollbar-width: none; 831 cursor: text; 832 position: relative; 833 transition: box-shadow var(--transition); 834 box-shadow: var(--neu-pressed-deep); 835 } 836 837 .typing-display::-webkit-scrollbar { 838 display: none; 839 } 840 841 .typing-display.typing-display--focused { 842 box-shadow: var(--neu-pressed-deep); 843 } 844 845 .typing-input { 846 position: fixed; 847 top: -100px; 848 left: -100px; 849 opacity: 0; 850 pointer-events: none; 851 width: 1px; 852 height: 1px; 853 } 854 855 .typing-words { 856 font-family: var(--font-mono); 857 font-size: 1.5rem; 858 line-height: 2.4; 859 color: var(--text-muted); 860 user-select: none; 861 } 862 863 .tw-word { transition: color 0.1s ease; } 864 .tw-word--active { color: var(--text-primary); } 865 .tw-word--correct { color: var(--text-muted); } 866 .tw-word--incorrect { 867 color: var(--error); 868 text-decoration: underline; 869 text-decoration-color: var(--error); 870 text-decoration-thickness: 3px; 871 text-underline-offset: 4px; 872 } 873 .tw-word--punct { 874 color: var(--accent); 875 } 876 .tw-word--phrase { 877 color: var(--streak); 878 background: rgba(251, 146, 60, 0.08); 879 border-radius: 3px; 880 padding: 0 2px; 881 } 882 883 .tw-char { position: relative; } 884 .tw-char--correct { color: var(--success); } 885 .tw-char--incorrect { color: var(--error); } 886 .tw-char--extra { color: var(--error); opacity: 0.7; } 887 .tw-space-sep { 888 display: inline-block; 889 width: 1ch; 890 text-align: center; 891 color: var(--text-muted); 892 opacity: 0.25; 893 user-select: none; 894 } 895 .tw-space-sep--done { color: var(--success); opacity: 0.2; } 896 .tw-space-sep--correct { color: var(--success); opacity: 0.5; } 897 .tw-space-sep--incorrect { color: var(--error); opacity: 1; } 898 .tw-space-sep--missed { color: var(--error); opacity: 0.7; text-decoration: line-through; } 899 .tw-space-sep--pending { color: var(--accent); opacity: 0.5; } 900 901 .tw-cursor { 902 display: inline-block; 903 width: 3px; 904 height: 1.4em; 905 background: var(--accent); 906 vertical-align: text-bottom; 907 animation: cursor-blink 1s step-end infinite; 908 margin-left: 1px; 909 border-radius: 2px; 910 } 911 912 @keyframes cursor-blink { 913 0%, 100% { opacity: 1; } 914 50% { opacity: 0; } 915 } 916 917 /* ===== TYPED TEXT DISPLAY ===== */ 918 .typed-text-display { 919 font-family: var(--font-mono); 920 font-size: 0.9rem; 921 color: var(--text-secondary); 922 min-height: 1.6em; 923 padding: 0.5rem 0.75rem; 924 background: var(--base); 925 border-radius: var(--radius-sm); 926 white-space: pre-wrap; 927 word-break: break-all; 928 box-shadow: var(--neu-pressed); 929 } 930 931 /* ===== STENO HINT ===== */ 932 .steno-hint { 933 width: 100%; 934 background: var(--base); 935 border-radius: var(--radius-md); 936 padding: 1rem; 937 box-shadow: var(--neu-pressed); 938 } 939 940 .steno-hint--revealed { } 941 942 .steno-keyboards { 943 display: flex; 944 gap: 1rem; 945 flex-wrap: wrap; 946 } 947 948 .steno-keyboard-section { flex: 1; min-width: 0; } 949 .steno-keyboard-section--multi { flex-basis: 100%; } 950 951 .steno-keyboards-row { 952 display: flex; 953 gap: 0.5rem; 954 align-items: flex-start; 955 } 956 957 .steno-keyboard-cell { flex: 1; min-width: 0; text-align: center; } 958 959 .steno-keyboard-cell__label { 960 font-family: var(--font-mono); 961 font-size: 0.75rem; 962 font-weight: 700; 963 color: var(--accent); 964 margin-bottom: 0.25rem; 965 } 966 .steno-keyboard-cell__label--phrase { color: var(--streak); } 967 968 .steno-hint__header { 969 display: flex; 970 align-items: center; 971 justify-content: space-between; 972 margin-bottom: 0.75rem; 973 } 974 975 .steno-hint__title { 976 font-size: 0.75rem; 977 text-transform: uppercase; 978 letter-spacing: 0.08em; 979 color: var(--text-muted); 980 font-weight: 700; 981 } 982 .steno-hint__title--phrase { color: var(--streak); } 983 984 .steno-stroke { 985 font-family: var(--font-mono); 986 font-size: 1.2rem; 987 font-weight: 700; 988 color: var(--accent); 989 } 990 .steno-stroke--phrase { color: var(--streak); } 991 992 .steno-hint__keyboard { display: flex; justify-content: center; } 993 994 .steno-keyboard { 995 width: 100%; 996 max-width: 520px; 997 height: auto; 998 } 999 1000 .steno-key { 1001 fill: var(--base-light); 1002 stroke: none; 1003 transition: fill 0.15s ease, filter 0.15s ease; 1004 } 1005 1006 .steno-key.active { 1007 fill: var(--accent); 1008 } 1009 1010 .steno-keyboard--phrase .steno-key.active { 1011 fill: var(--streak); 1012 } 1013 1014 .steno-key-label { 1015 fill: var(--text-secondary); 1016 font-family: var(--font-sans); 1017 font-size: 12px; 1018 font-weight: 700; 1019 text-anchor: middle; 1020 dominant-baseline: central; 1021 pointer-events: none; 1022 } 1023 .steno-key-label--small { font-size: 10px; } 1024 1025 /* ===== SIDE HINTS PANEL ===== */ 1026 .hints-panel { 1027 width: 260px; 1028 flex-shrink: 0; 1029 background: var(--base); 1030 border-radius: var(--radius-md); 1031 padding: 1rem; 1032 max-height: 600px; 1033 overflow-y: auto; 1034 position: sticky; 1035 top: 72px; 1036 box-shadow: var(--neu-pressed); 1037 } 1038 1039 .hints-panel__header { 1040 font-size: 0.7rem; 1041 text-transform: uppercase; 1042 letter-spacing: 0.1em; 1043 color: var(--text-muted); 1044 margin-bottom: 0.75rem; 1045 font-weight: 700; 1046 } 1047 1048 .hints-list { 1049 display: flex; 1050 flex-direction: column; 1051 gap: 0.375rem; 1052 } 1053 1054 .hint-item { 1055 display: flex; 1056 flex-direction: column; 1057 gap: 0.125rem; 1058 padding: 0.5rem 0.625rem; 1059 background: var(--base); 1060 border-radius: var(--radius-sm); 1061 cursor: pointer; 1062 transition: all var(--transition); 1063 box-shadow: var(--neu-raised-sm); 1064 } 1065 .hint-item:hover { 1066 box-shadow: var(--neu-raised); 1067 transform: translateY(-1px); 1068 position: relative; 1069 z-index: 1; 1070 } 1071 .hint-item:active { 1072 box-shadow: var(--neu-pressed); 1073 transform: translateY(0); 1074 } 1075 1076 .hint-item--best { 1077 background: var(--accent); 1078 color: var(--text-on-color); 1079 box-shadow: var(--neu-raised-sm); 1080 } 1081 .hint-item--best .hint-item__stroke { color: var(--text-on-color); } 1082 .hint-item--best .hint-item__meta { opacity: 0.75; color: var(--text-on-color); } 1083 1084 .hint-item--empty { 1085 color: var(--text-muted); 1086 font-size: 0.8rem; 1087 cursor: default; 1088 text-align: center; 1089 box-shadow: none; 1090 } 1091 1092 .hint-item--punct { opacity: 0.8; } 1093 .hint-item--punct .hint-item__stroke { 1094 font-size: 0.8rem; 1095 color: var(--text-secondary); 1096 } 1097 .hint-item--cap { opacity: 0.8; } 1098 .hint-item--cap .hint-item__stroke { 1099 font-size: 0.8rem; 1100 color: var(--accent); 1101 } 1102 1103 .hint-item__stroke { 1104 font-family: var(--font-mono); 1105 font-size: 0.9rem; 1106 font-weight: 700; 1107 color: var(--text-primary); 1108 } 1109 1110 .hint-item__meta { 1111 font-size: 0.7rem; 1112 color: var(--text-muted); 1113 } 1114 1115 .hint-item__label { 1116 display: inline-block; 1117 background: var(--accent); 1118 color: var(--base-dark); 1119 padding: 0 5px; 1120 border-radius: 3px; 1121 font-weight: 600; 1122 font-size: 0.65rem; 1123 margin-left: 4px; 1124 vertical-align: middle; 1125 } 1126 1127 /* ===== PHRASE HINTS ===== */ 1128 .phrase-hints { 1129 margin-bottom: 1rem; 1130 padding-bottom: 0.75rem; 1131 border-bottom: 1px solid rgba(128,128,160,0.08); 1132 } 1133 1134 .phrase-hints__header { 1135 font-size: 0.7rem; 1136 text-transform: uppercase; 1137 letter-spacing: 0.1em; 1138 color: var(--streak); 1139 margin-bottom: 0.5rem; 1140 font-weight: 700; 1141 } 1142 1143 .phrase-hints-list { 1144 display: flex; 1145 flex-direction: column; 1146 gap: 0.375rem; 1147 } 1148 1149 .phrase-hint-item { 1150 padding: 0.5rem 0.625rem; 1151 background: var(--base); 1152 border-radius: var(--radius-sm); 1153 display: flex; 1154 flex-direction: column; 1155 gap: 0.2rem; 1156 box-shadow: var(--neu-raised-sm); 1157 } 1158 1159 .phrase-hint-item--single { 1160 background: var(--streak); 1161 box-shadow: var(--neu-raised-sm); 1162 } 1163 .phrase-hint-item--single .phrase-hint-item__phrase { color: var(--text-on-color); } 1164 .phrase-hint-item--single .phrase-hint-item__stroke { color: var(--text-on-color); opacity: 0.9; } 1165 .phrase-hint-item--single .phrase-hint-item__words { color: var(--text-on-color); opacity: 0.6; } 1166 1167 .phrase-hint-item__phrase { 1168 font-size: 0.8rem; 1169 font-weight: 700; 1170 color: var(--text-primary); 1171 font-style: italic; 1172 } 1173 1174 .phrase-hint-item__words { 1175 font-size: 0.65rem; 1176 color: var(--text-muted); 1177 } 1178 1179 .phrase-hint-item__stroke { 1180 font-family: var(--font-mono); 1181 font-size: 0.8rem; 1182 font-weight: 700; 1183 color: var(--streak); 1184 } 1185 1186 /* ===== SESSION STATS BAR ===== */ 1187 .session-stats { 1188 display: flex; 1189 gap: 1.5rem; 1190 padding: 0.75rem 1.5rem; 1191 background: var(--base); 1192 border-radius: var(--radius-md); 1193 width: 100%; 1194 justify-content: center; 1195 box-shadow: var(--neu-pressed); 1196 } 1197 1198 .session-stat { 1199 display: flex; 1200 align-items: center; 1201 gap: 0.4rem; 1202 font-size: 0.85rem; 1203 } 1204 1205 .session-stat__icon { 1206 width: 8px; 1207 height: 8px; 1208 border-radius: 50%; 1209 } 1210 1211 .session-stat__icon--time { background: var(--accent); } 1212 .session-stat__icon--accuracy { background: var(--success); } 1213 .session-stat__icon--streak { background: var(--streak); } 1214 .session-stat__icon--wpm { background: var(--warning); } 1215 .session-stat__icon--progress { background: #a78bfa; } 1216 1217 .session-stat__value { 1218 font-weight: 700; 1219 color: var(--text-primary); 1220 } 1221 1222 /* ===== MODAL / SESSION SUMMARY ===== */ 1223 .modal-overlay { 1224 position: fixed; 1225 inset: 0; 1226 background: rgba(0, 0, 0, 0.5); 1227 display: flex; 1228 align-items: center; 1229 justify-content: center; 1230 z-index: 1000; 1231 backdrop-filter: blur(8px); 1232 } 1233 1234 .modal { 1235 background: var(--base); 1236 border-radius: var(--radius-lg); 1237 padding: 2.5rem; 1238 max-width: 500px; 1239 width: 90%; 1240 box-shadow: var(--neu-raised-lg), 0 20px 60px rgba(0,0,0,0.3); 1241 } 1242 1243 .modal__title { 1244 text-align: center; 1245 font-size: 1.25rem; 1246 font-weight: 700; 1247 margin-bottom: 1.5rem; 1248 color: var(--text-primary); 1249 text-transform: uppercase; 1250 letter-spacing: 0.05em; 1251 } 1252 1253 .summary-accuracy { 1254 text-align: center; 1255 font-size: 3.5rem; 1256 font-weight: 800; 1257 margin-bottom: 1.5rem; 1258 } 1259 1260 .summary-accuracy--good { color: var(--success); text-shadow: 0 0 20px var(--success-glow); } 1261 .summary-accuracy--mid { color: var(--warning); text-shadow: 0 0 20px var(--warning-glow); } 1262 .summary-accuracy--low { color: var(--error); text-shadow: 0 0 20px var(--error-glow); } 1263 1264 .summary-stats { 1265 display: grid; 1266 grid-template-columns: repeat(3, 1fr); 1267 gap: 1rem; 1268 margin-bottom: 1.5rem; 1269 text-align: center; 1270 } 1271 1272 .summary-stat__label { 1273 display: block; 1274 font-size: 0.75rem; 1275 color: var(--text-secondary); 1276 text-transform: uppercase; 1277 letter-spacing: 0.08em; 1278 font-weight: 600; 1279 } 1280 1281 .summary-stat__value { 1282 display: block; 1283 font-size: 1.5rem; 1284 font-weight: 700; 1285 margin-top: 0.25rem; 1286 } 1287 1288 .summary-weak-words { margin-bottom: 1.5rem; } 1289 1290 .summary-weak-words__title { 1291 font-size: 0.85rem; 1292 font-weight: 700; 1293 color: var(--text-secondary); 1294 margin-bottom: 0.5rem; 1295 text-transform: uppercase; 1296 letter-spacing: 0.05em; 1297 } 1298 1299 .summary-weak-words__list { 1300 display: flex; 1301 flex-wrap: wrap; 1302 gap: 0.5rem; 1303 } 1304 1305 .weak-word-chip { 1306 display: inline-flex; 1307 align-items: center; 1308 gap: 0.4rem; 1309 padding: 0.3rem 0.7rem; 1310 background: var(--base); 1311 border-radius: 999px; 1312 font-size: 0.8rem; 1313 box-shadow: var(--neu-raised-sm); 1314 } 1315 1316 .weak-word-chip__word { font-weight: 700; color: var(--error); } 1317 .weak-word-chip__stroke { 1318 font-family: var(--font-mono); 1319 font-size: 0.7rem; 1320 color: var(--text-muted); 1321 } 1322 1323 .summary-errors__list { 1324 display: flex; 1325 flex-direction: column; 1326 gap: 0.4rem; 1327 max-height: 200px; 1328 overflow-y: auto; 1329 } 1330 .error-detail { 1331 display: flex; 1332 align-items: center; 1333 justify-content: space-between; 1334 gap: 0.75rem; 1335 padding: 0.35rem 0.7rem; 1336 background: var(--base); 1337 border-radius: var(--radius); 1338 font-size: 0.8rem; 1339 } 1340 .error-detail__words { 1341 display: flex; 1342 align-items: center; 1343 gap: 0.4rem; 1344 min-width: 0; 1345 } 1346 .error-detail__expected { 1347 font-weight: 700; 1348 color: var(--success); 1349 } 1350 .error-detail__arrow { 1351 color: var(--text-muted); 1352 font-size: 0.7rem; 1353 } 1354 .error-detail__typed { 1355 font-weight: 600; 1356 color: var(--error); 1357 } 1358 .error-detail__stroke { 1359 font-family: var(--font-mono); 1360 font-size: 0.7rem; 1361 color: var(--text-muted); 1362 white-space: nowrap; 1363 } 1364 1365 .modal__actions { 1366 display: flex; 1367 gap: 0.75rem; 1368 justify-content: center; 1369 } 1370 1371 /* ===== STATS PAGE ===== */ 1372 .stats-page { 1373 display: flex; 1374 flex-direction: column; 1375 gap: 2rem; 1376 } 1377 1378 .stats-overview { 1379 display: grid; 1380 grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); 1381 gap: 1rem; 1382 } 1383 1384 .stats-section { 1385 background: var(--base); 1386 border-radius: var(--radius-md); 1387 padding: 1.5rem; 1388 box-shadow: var(--neu-pressed); 1389 } 1390 1391 .stats-section .section-title { margin-bottom: 1.25rem; } 1392 1393 .chart-container { 1394 position: relative; 1395 width: 100%; 1396 height: 280px; 1397 } 1398 .chart-container canvas { width: 100% !important; height: 100% !important; } 1399 1400 /* ===== HEATMAP ===== */ 1401 .heatmap-container { overflow-x: auto; padding-bottom: 0.5rem; } 1402 1403 .heatmap { 1404 display: inline-grid; 1405 grid-template-rows: repeat(7, 14px); 1406 grid-auto-flow: column; 1407 grid-auto-columns: 14px; 1408 gap: 3px; 1409 } 1410 1411 .heatmap-cell { 1412 width: 14px; 1413 height: 14px; 1414 border-radius: 3px; 1415 background: var(--base-dark); 1416 box-shadow: var(--neu-pressed); 1417 } 1418 1419 .heatmap-cell[data-level="1"] { background: var(--heatmap-1); box-shadow: none; } 1420 .heatmap-cell[data-level="2"] { background: var(--heatmap-2); box-shadow: none; } 1421 .heatmap-cell[data-level="3"] { background: var(--heatmap-3); box-shadow: none; } 1422 .heatmap-cell[data-level="4"] { background: var(--heatmap-4); box-shadow: none; } 1423 1424 .heatmap-months { 1425 display: flex; 1426 gap: 0; 1427 margin-bottom: 0.5rem; 1428 font-size: 0.65rem; 1429 color: var(--text-muted); 1430 } 1431 .heatmap-month { text-align: left; } 1432 1433 .heatmap-legend { 1434 display: flex; 1435 align-items: center; 1436 gap: 0.25rem; 1437 margin-top: 0.75rem; 1438 font-size: 0.7rem; 1439 color: var(--text-muted); 1440 } 1441 .heatmap-legend__cell { width: 12px; height: 12px; border-radius: 3px; } 1442 1443 /* ===== SETTINGS PAGE ===== */ 1444 .settings-page { } 1445 1446 .settings-section { 1447 background: var(--base); 1448 border-radius: var(--radius-md); 1449 padding: 1.5rem; 1450 margin-bottom: 1.5rem; 1451 box-shadow: var(--neu-pressed); 1452 } 1453 1454 .settings-section--danger { 1455 box-shadow: var(--neu-pressed); 1456 } 1457 1458 .setting-row { 1459 display: flex; 1460 align-items: flex-start; 1461 justify-content: space-between; 1462 gap: 1rem; 1463 margin-bottom: 1rem; 1464 } 1465 .setting-row:last-child { margin-bottom: 0; } 1466 1467 .setting-label { font-weight: 700; font-size: 0.9rem; color: var(--text-primary); margin-bottom: 0.25rem; } 1468 .setting-help { font-size: 0.8rem; color: var(--text-muted); margin-top: 0.25rem; } 1469 1470 .setting-input-group { 1471 display: flex; 1472 gap: 0.5rem; 1473 align-items: center; 1474 } 1475 1476 .setting-input { 1477 padding: 0.5rem 0.75rem; 1478 background: var(--base); 1479 border: none; 1480 border-radius: var(--radius-sm); 1481 color: var(--text-primary); 1482 font-family: var(--font-sans); 1483 font-size: 0.875rem; 1484 min-width: 300px; 1485 transition: box-shadow var(--transition); 1486 box-shadow: var(--neu-pressed); 1487 } 1488 .setting-input--short { min-width: 80px; max-width: 100px; } 1489 .setting-input:focus { 1490 outline: none; 1491 box-shadow: var(--neu-pressed-deep), 0 0 0 2px var(--accent); 1492 } 1493 1494 .settings-toast { 1495 position: fixed; 1496 bottom: 2rem; 1497 right: 2rem; 1498 padding: 0.75rem 1.5rem; 1499 border-radius: var(--radius-sm); 1500 font-size: 0.875rem; 1501 font-weight: 600; 1502 z-index: 1000; 1503 border: none; 1504 } 1505 1506 .settings-toast--success { 1507 background: var(--success); 1508 color: var(--text-on-color); 1509 box-shadow: var(--neu-raised-sm); 1510 } 1511 1512 .settings-toast--error { 1513 background: var(--error); 1514 color: var(--text-on-color); 1515 box-shadow: var(--neu-raised-sm); 1516 } 1517 1518 /* ===== THEME TOGGLE ===== */ 1519 .theme-toggle { 1520 display: inline-flex; 1521 align-items: center; 1522 justify-content: center; 1523 width: 36px; 1524 height: 36px; 1525 padding: 0; 1526 background: var(--base); 1527 border: none; 1528 border-radius: 50%; 1529 color: var(--text-secondary); 1530 cursor: pointer; 1531 transition: all var(--transition); 1532 font-size: 1.1rem; 1533 line-height: 1; 1534 box-shadow: var(--neu-raised-sm); 1535 } 1536 .theme-toggle:hover { 1537 color: var(--accent); 1538 box-shadow: var(--neu-raised); 1539 transform: translateY(-1px); 1540 } 1541 .theme-toggle:active { 1542 box-shadow: var(--neu-pressed); 1543 transform: translateY(0); 1544 } 1545 1546 /* ===== RESPONSIVE ===== */ 1547 @media (max-width: 768px) { 1548 /* --- Mobile Nav Overlay --- */ 1549 .nav-hamburger { display: flex; } 1550 .nav-links { 1551 position: fixed; 1552 inset: 0; 1553 background: var(--base); 1554 flex-direction: column; 1555 align-items: center; 1556 justify-content: center; 1557 gap: 0.5rem; 1558 z-index: 300; 1559 opacity: 0; 1560 pointer-events: none; 1561 transition: opacity 0.3s ease; 1562 } 1563 .nav-links.open { 1564 opacity: 1; 1565 pointer-events: all; 1566 } 1567 .nav-links .nav-link { 1568 font-size: 1.5rem; 1569 padding: 1rem 2rem; 1570 } 1571 .nav-links .theme-toggle { 1572 margin-top: 1rem; 1573 width: 48px; 1574 height: 48px; 1575 font-size: 1.4rem; 1576 } 1577 1578 /* --- Dashboard --- */ 1579 .hero-stats { grid-template-columns: repeat(2, 1fr); } 1580 .mode-grid { grid-template-columns: repeat(2, 1fr); } 1581 .nav-inner { padding: 0 1rem; } 1582 .main-content { padding: 1.5rem 1rem; } 1583 .summary-stats { grid-template-columns: 1fr; gap: 0.75rem; } 1584 .modal { padding: 1.5rem; } 1585 .stats-overview { grid-template-columns: repeat(2, 1fr); } 1586 .setting-row { flex-direction: column; } 1587 .setting-input { min-width: unset; width: 100%; } 1588 1589 /* --- Practice Mobile (portrait) --- */ 1590 #practice-container { 1591 min-height: calc(100dvh - 56px); 1592 justify-content: flex-start; 1593 padding: 0; 1594 } 1595 .practice-header { 1596 padding: 0.5rem 0; 1597 margin-bottom: 0.5rem; 1598 } 1599 .practice-header .btn { font-size: 0.75rem; padding: 0.4rem 0.75rem; } 1600 .practice-mode-label { font-size: 0.85rem; } 1601 .practice-area { gap: 0.5rem; } 1602 .practice-main { 1603 flex-direction: column; 1604 gap: 0.5rem; 1605 } 1606 .practice-left { gap: 0.5rem; } 1607 .typing-display { 1608 min-height: unset; 1609 max-height: 130px; 1610 padding: 0.75rem 1rem; 1611 border-radius: var(--radius-md); 1612 } 1613 .typing-words { 1614 font-size: 1.1rem; 1615 line-height: 2; 1616 } 1617 .typed-text-display { display: none; } 1618 .steno-hint { padding: 0.5rem; } 1619 .steno-keyboard { max-width: 360px; } 1620 .hints-panel { 1621 width: 100%; 1622 max-height: 120px; 1623 position: static; 1624 padding: 0.75rem; 1625 } 1626 .hints-list { flex-direction: row; flex-wrap: wrap; gap: 0.25rem; } 1627 .hint-item { padding: 0.35rem 0.5rem; } 1628 .hint-item__stroke { font-size: 0.8rem; } 1629 .hint-item__meta { display: none; } 1630 .session-stats { 1631 flex-wrap: wrap; 1632 gap: 0.5rem 1rem; 1633 padding: 0.5rem 1rem; 1634 font-size: 0.8rem; 1635 } 1636 } 1637 1638 @media (max-width: 480px) { 1639 .hero-stats { grid-template-columns: repeat(2, 1fr); } 1640 .mode-grid { grid-template-columns: repeat(2, 1fr); } 1641 .practice-header { flex-wrap: wrap; gap: 0.5rem; } 1642 1643 .typing-display { max-height: 110px; padding: 0.6rem 0.75rem; } 1644 .typing-words { font-size: 1rem; line-height: 1.9; } 1645 .hints-panel { max-height: 100px; } 1646 .steno-keyboard { max-width: 300px; } 1647 } 1648 1649 /* --- Practice Landscape Mobile --- */ 1650 @media (max-height: 500px) and (orientation: landscape) { 1651 #practice-container { 1652 min-height: calc(100dvh - 56px); 1653 justify-content: flex-start; 1654 padding: 0; 1655 } 1656 .main-content { padding: 0.5rem 1rem; } 1657 .practice-header { margin-bottom: 0.25rem; padding: 0.25rem 0; } 1658 .practice-header .btn { font-size: 0.7rem; padding: 0.3rem 0.6rem; } 1659 .practice-mode-label { font-size: 0.8rem; } 1660 .practice-area { gap: 0.35rem; } 1661 .practice-main { 1662 flex-direction: row; 1663 gap: 0.5rem; 1664 align-items: stretch; 1665 } 1666 .practice-left { gap: 0.35rem; flex: 1; } 1667 .typing-display { 1668 min-height: unset; 1669 max-height: 90px; 1670 padding: 0.5rem 0.75rem; 1671 border-radius: var(--radius-sm); 1672 } 1673 .typing-words { font-size: 0.95rem; line-height: 1.8; } 1674 .typed-text-display { display: none; } 1675 .steno-hint { padding: 0.35rem; } 1676 .steno-keyboard { max-width: 280px; } 1677 .steno-keyboard-cell__label { font-size: 0.65rem; } 1678 .hints-panel { 1679 width: 180px; 1680 max-height: unset; 1681 position: static; 1682 padding: 0.5rem; 1683 flex-shrink: 0; 1684 } 1685 .hints-panel__header { font-size: 0.6rem; margin-bottom: 0.35rem; } 1686 .hint-item { padding: 0.25rem 0.4rem; } 1687 .hint-item__stroke { font-size: 0.75rem; } 1688 .hint-item__meta { display: none; } 1689 .session-stats { 1690 padding: 0.35rem 0.75rem; 1691 gap: 0.75rem; 1692 font-size: 0.75rem; 1693 } 1694 .session-stat__value { font-size: 0.75rem; } 1695 } 1696 1697 /* ===== LOGIN PAGE ===== */ 1698 .login-page { 1699 min-height: 100vh; 1700 display: flex; 1701 align-items: center; 1702 justify-content: center; 1703 padding: 2rem; 1704 } 1705 1706 .login-card { 1707 background: linear-gradient(145deg, var(--base-light), var(--base)); 1708 border-radius: var(--radius-lg); 1709 padding: 3rem 2.5rem; 1710 max-width: 400px; 1711 width: 100%; 1712 text-align: center; 1713 box-shadow: var(--neu-raised-lg); 1714 border-top: 1px solid var(--edge-highlight); 1715 border-left: 1px solid var(--edge-highlight); 1716 } 1717 1718 .login-brand { 1719 margin-bottom: 2rem; 1720 } 1721 1722 .login-logo { 1723 width: 56px; 1724 height: 56px; 1725 color: var(--accent); 1726 margin-bottom: 0.75rem; 1727 } 1728 1729 .login-title { 1730 font-size: 1.75rem; 1731 font-weight: 700; 1732 text-transform: uppercase; 1733 letter-spacing: 0.05em; 1734 margin-bottom: 0.25rem; 1735 } 1736 1737 .login-subtitle { 1738 font-size: 0.9rem; 1739 color: var(--text-secondary); 1740 } 1741 1742 .login-error { 1743 background: var(--error); 1744 color: var(--text-on-color); 1745 padding: 0.75rem 1rem; 1746 border-radius: var(--radius-sm); 1747 margin-bottom: 1.5rem; 1748 font-size: 0.875rem; 1749 font-weight: 600; 1750 } 1751 1752 .btn--google { 1753 width: 100%; 1754 padding: 0.75rem 1.5rem; 1755 background: var(--base); 1756 color: var(--text-primary); 1757 font-size: 0.95rem; 1758 gap: 0.75rem; 1759 box-shadow: var(--neu-raised); 1760 margin-bottom: 1.5rem; 1761 } 1762 .btn--google:hover { 1763 box-shadow: var(--neu-raised); 1764 transform: translateY(-1px); 1765 } 1766 1767 .google-icon { 1768 flex-shrink: 0; 1769 } 1770 1771 .login-footer { 1772 font-size: 0.8rem; 1773 color: var(--text-muted); 1774 } 1775 1776 /* ===== NAV USER ===== */ 1777 .nav-user { 1778 display: flex; 1779 align-items: center; 1780 gap: 0.5rem; 1781 } 1782 1783 .nav-avatar { 1784 width: 28px; 1785 height: 28px; 1786 border-radius: 50%; 1787 box-shadow: var(--neu-raised-sm); 1788 } 1789 1790 .nav-link--logout { 1791 color: var(--text-muted); 1792 font-size: 0.8rem; 1793 } 1794 1795 /* ===== DICTIONARY BANNER ===== */ 1796 .dict-banner { 1797 display: flex; 1798 align-items: center; 1799 gap: 1rem; 1800 padding: 1rem 1.25rem; 1801 background: var(--base); 1802 border-radius: var(--radius-md); 1803 box-shadow: var(--neu-pressed); 1804 border-left: 4px solid var(--warning); 1805 margin-bottom: 0; 1806 } 1807 1808 .dict-banner__icon { 1809 flex-shrink: 0; 1810 color: var(--warning); 1811 } 1812 1813 .dict-banner__text { 1814 font-size: 0.875rem; 1815 color: var(--text-secondary); 1816 line-height: 1.5; 1817 } 1818 .dict-banner__text strong { 1819 color: var(--text-primary); 1820 } 1821 1822 /* ===== DICTIONARY MANAGEMENT ===== */ 1823 .dict-upload-row { 1824 margin-bottom: 1rem; 1825 } 1826 1827 .dict-actions { 1828 display: flex; 1829 gap: 0.75rem; 1830 flex-wrap: wrap; 1831 align-items: center; 1832 } 1833 1834 .dict-upload-group { 1835 display: flex; 1836 gap: 0.75rem; 1837 flex-wrap: wrap; 1838 } 1839 1840 .dict-upload-btn { 1841 cursor: pointer; 1842 } 1843 1844 .dict-list { 1845 display: flex; 1846 flex-direction: column; 1847 gap: 0.375rem; 1848 } 1849 1850 .dict-item { 1851 display: flex; 1852 align-items: center; 1853 gap: 0.75rem; 1854 padding: 0.625rem 0.875rem; 1855 background: var(--base); 1856 border-radius: var(--radius-sm); 1857 box-shadow: var(--neu-raised-sm); 1858 transition: all var(--transition); 1859 } 1860 .dict-item:hover { 1861 box-shadow: var(--neu-raised); 1862 } 1863 1864 .dict-item--missing { 1865 opacity: 0.6; 1866 } 1867 .dict-item--missing .dict-item__count { 1868 color: var(--warning); 1869 } 1870 1871 .dict-item__handle { 1872 display: flex; 1873 align-items: center; 1874 justify-content: center; 1875 width: 20px; 1876 flex-shrink: 0; 1877 cursor: grab; 1878 color: var(--text-muted); 1879 opacity: 0.5; 1880 transition: opacity var(--transition), color var(--transition); 1881 touch-action: none; 1882 } 1883 .dict-item__handle:active { cursor: grabbing; } 1884 .dict-item:hover .dict-item__handle { opacity: 1; color: var(--text-secondary); } 1885 1886 .dict-item--dragging { 1887 opacity: 0.4; 1888 box-shadow: var(--neu-pressed); 1889 } 1890 1891 .dict-item--drop-above { 1892 box-shadow: var(--neu-raised-sm), inset 0 3px 0 0 var(--accent); 1893 } 1894 .dict-item--drop-below { 1895 box-shadow: var(--neu-raised-sm), inset 0 -3px 0 0 var(--accent); 1896 } 1897 1898 .dict-item__name { 1899 flex: 1; 1900 min-width: 0; 1901 font-size: 0.875rem; 1902 font-weight: 600; 1903 overflow: hidden; 1904 text-overflow: ellipsis; 1905 white-space: nowrap; 1906 } 1907 1908 .dict-item__count { 1909 font-size: 0.75rem; 1910 color: var(--text-muted); 1911 flex-shrink: 0; 1912 } 1913 1914 .dict-item__swap { 1915 flex-shrink: 0; 1916 cursor: pointer; 1917 color: var(--accent); 1918 } 1919 1920 .dict-item__toggle { 1921 flex-shrink: 0; 1922 cursor: pointer; 1923 } 1924 1925 .dict-item__toggle input[type="checkbox"] { 1926 width: 16px; 1927 height: 16px; 1928 accent-color: var(--accent); 1929 cursor: pointer; 1930 } 1931 1932 .dict-item__delete { 1933 padding: 0.25rem 0.4rem; 1934 font-size: 0.8rem; 1935 color: var(--text-muted); 1936 } 1937 .dict-item__delete:hover { 1938 color: var(--error); 1939 } 1940 1941 .dict-empty { 1942 text-align: center; 1943 padding: 1.5rem; 1944 color: var(--text-muted); 1945 font-size: 0.875rem; 1946 } 1947 1948 .upload-progress { 1949 display: flex; 1950 align-items: center; 1951 gap: 0.75rem; 1952 padding: 0.75rem 1rem; 1953 margin-bottom: 0.75rem; 1954 background: var(--base); 1955 border-radius: var(--radius-sm); 1956 box-shadow: var(--neu-pressed); 1957 font-size: 0.85rem; 1958 color: var(--text-secondary); 1959 font-weight: 600; 1960 } 1961 1962 .dict-status { 1963 margin-top: 0.75rem; 1964 padding: 0.5rem 0.75rem; 1965 border-radius: var(--radius-sm); 1966 font-size: 0.8rem; 1967 font-weight: 600; 1968 } 1969 1970 @media (max-width: 768px) { 1971 .login-card { padding: 2rem 1.5rem; } 1972 .nav-user { flex-direction: column; gap: 0.25rem; } 1973 .nav-avatar { width: 40px; height: 40px; } 1974 .dict-actions { flex-direction: column; } 1975 .dict-actions .btn { width: 100%; } 1976 .dict-upload-group { flex-direction: column; } 1977 .dict-item { flex-wrap: wrap; } 1978 .dict-item__handle { opacity: 1; } 1979 .dict-item__name { flex-basis: calc(100% - 100px); } 1980 }