yonigozlan HF Staff commited on
Commit
108efa3
·
1 Parent(s): d7256dc

add night theme

Browse files
Files changed (1) hide show
  1. app.py +509 -18
app.py CHANGED
@@ -916,6 +916,13 @@ def create_timeline_template():
916
  color: #333;
917
  display: flex;
918
  flex-direction: column;
 
 
 
 
 
 
 
919
  }
920
 
921
  .header {
@@ -928,6 +935,14 @@ def create_timeline_template():
928
  top: 0;
929
  z-index: 100;
930
  margin: 0 0 0.3rem 0;
 
 
 
 
 
 
 
 
931
  }
932
 
933
  .header h1 {
@@ -935,12 +950,76 @@ def create_timeline_template():
935
  font-weight: 700;
936
  color: #2d3748;
937
  margin-bottom: 0.1rem;
 
938
  }
939
 
940
  .header p {
941
  color: #666;
942
  font-size: 0.8rem;
943
  margin: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
944
  }
945
 
946
  .controls-wrapper {
@@ -968,11 +1047,26 @@ def create_timeline_template():
968
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
969
  }
970
 
 
 
 
 
 
 
 
 
971
  .controls-toggle:hover {
972
  transform: translateY(-1px);
973
  box-shadow: 0 4px 14px rgba(0,0,0,0.1);
974
  }
975
 
 
 
 
 
 
 
 
976
  .controls {
977
  background: rgba(255, 255, 255, 0.9);
978
  backdrop-filter: blur(10px);
@@ -984,14 +1078,21 @@ def create_timeline_template():
984
  align-items: start;
985
  flex-wrap: nowrap;
986
  overflow: hidden;
987
- transition: max-height 0.25s ease, opacity 0.2s ease;
988
  position: relative;
989
  padding-left: 2.4rem; /* space for the left toggle button */
990
- max-height: none; /* will be set dynamically */
 
 
 
 
 
 
991
  }
992
 
993
  .controls.collapsed {
994
  opacity: 1;
 
995
  }
996
 
997
  /* Blur fade to hint there is more content when collapsed */
@@ -1006,6 +1107,11 @@ def create_timeline_template():
1006
  pointer-events: none;
1007
  }
1008
 
 
 
 
 
 
1009
  .input-group {
1010
  display: flex;
1011
  flex-direction: column;
@@ -1017,6 +1123,12 @@ def create_timeline_template():
1017
  font-weight: 500;
1018
  color: #4a5568;
1019
  font-size: 0.7rem;
 
 
 
 
 
 
1020
  }
1021
 
1022
  .input-group input {
@@ -1028,6 +1140,18 @@ def create_timeline_template():
1028
  background: white;
1029
  }
1030
 
 
 
 
 
 
 
 
 
 
 
 
 
1031
  .input-group input:focus {
1032
  outline: none;
1033
  border-color: #d97706;
@@ -1095,6 +1219,12 @@ def create_timeline_template():
1095
  overflow: hidden;
1096
  }
1097
 
 
 
 
 
 
 
1098
  .modality-checkbox::before {
1099
  content: '';
1100
  position: absolute;
@@ -1121,6 +1251,12 @@ def create_timeline_template():
1121
  border-color: currentColor;
1122
  }
1123
 
 
 
 
 
 
 
1124
  .modality-checkbox.checked::before {
1125
  opacity: 0.08;
1126
  }
@@ -1138,11 +1274,23 @@ def create_timeline_template():
1138
  flex-shrink: 0;
1139
  }
1140
 
 
 
 
 
 
 
1141
  .modality-checkbox input[type="checkbox"]:checked {
1142
  background: var(--modality-color, #8B5CF6);
1143
  border-color: var(--modality-color, #8B5CF6);
1144
  }
1145
 
 
 
 
 
 
 
1146
  .modality-checkbox input[type="checkbox"]:checked::after {
1147
  content: '✓';
1148
  position: absolute;
@@ -1161,6 +1309,12 @@ def create_timeline_template():
1161
  user-select: none;
1162
  color: #374151;
1163
  font-weight: 600;
 
 
 
 
 
 
1164
  }
1165
 
1166
  /* Task filter styles (mirroring modality styles) */
@@ -1180,6 +1334,12 @@ def create_timeline_template():
1180
  overflow: hidden;
1181
  }
1182
 
 
 
 
 
 
 
1183
  .task-checkbox::before {
1184
  content: '';
1185
  position: absolute;
@@ -1206,6 +1366,12 @@ def create_timeline_template():
1206
  border-color: currentColor;
1207
  }
1208
 
 
 
 
 
 
 
1209
  .task-checkbox.checked::before {
1210
  opacity: 0.08;
1211
  }
@@ -1222,11 +1388,23 @@ def create_timeline_template():
1222
  transition: all 0.2s ease;
1223
  }
1224
 
 
 
 
 
 
 
1225
  .task-checkbox input[type="checkbox"]:checked {
1226
  background: var(--task-color, #6366f1);
1227
  border-color: var(--task-color, #6366f1);
1228
  }
1229
 
 
 
 
 
 
 
1230
  .task-checkbox input[type="checkbox"]:checked::after {
1231
  content: '✓';
1232
  position: absolute;
@@ -1245,6 +1423,12 @@ def create_timeline_template():
1245
  user-select: none;
1246
  color: #374151;
1247
  font-weight: 600;
 
 
 
 
 
 
1248
  }
1249
 
1250
  .modality-checkbox input[type="checkbox"]:not(:checked) {
@@ -1252,6 +1436,12 @@ def create_timeline_template():
1252
  border-color: var(--modality-color, #8B5CF6);
1253
  }
1254
 
 
 
 
 
 
 
1255
  .btn {
1256
  padding: 0.5rem 1rem;
1257
  border: none;
@@ -1278,6 +1468,19 @@ def create_timeline_template():
1278
  background: #f7fafc;
1279
  color: #4a5568;
1280
  border: 2px solid #e2e8f0;
 
 
 
 
 
 
 
 
 
 
 
 
 
1281
  }
1282
 
1283
  .timeline-container {
@@ -1292,6 +1495,13 @@ def create_timeline_template():
1292
  display: flex;
1293
  flex-direction: column;
1294
  height: calc(100vh - 110px);
 
 
 
 
 
 
 
1295
  }
1296
 
1297
  .timeline-wrapper {
@@ -1347,6 +1557,13 @@ def create_timeline_template():
1347
  z-index: 10;
1348
  }
1349
 
 
 
 
 
 
 
 
1350
  .nav-arrow:hover {
1351
  background: rgba(217, 119, 6, 0.1);
1352
  border-color: #d97706;
@@ -1354,6 +1571,13 @@ def create_timeline_template():
1354
  box-shadow: 0 4px 16px rgba(217, 119, 6, 0.3);
1355
  }
1356
 
 
 
 
 
 
 
 
1357
  .nav-arrow.left {
1358
  left: 10px;
1359
  }
@@ -1395,6 +1619,13 @@ def create_timeline_template():
1395
  user-select: none;
1396
  }
1397
 
 
 
 
 
 
 
 
1398
  .zoom-btn:hover {
1399
  background: rgba(217, 119, 6, 0.1);
1400
  border-color: #d97706;
@@ -1402,6 +1633,13 @@ def create_timeline_template():
1402
  box-shadow: 0 4px 16px rgba(217, 119, 6, 0.3);
1403
  }
1404
 
 
 
 
 
 
 
 
1405
  .zoom-btn:active {
1406
  transform: scale(0.95);
1407
  }
@@ -1414,6 +1652,14 @@ def create_timeline_template():
1414
  color: #d97706;
1415
  font-weight: 500;
1416
  border: 1px solid rgba(217, 119, 6, 0.2);
 
 
 
 
 
 
 
 
1417
  }
1418
 
1419
  .timeline-line {
@@ -1459,6 +1705,13 @@ def create_timeline_template():
1459
  opacity: 0.8;
1460
  pointer-events: none;
1461
  z-index: 1; /* In background, below everything */
 
 
 
 
 
 
 
1462
  }
1463
 
1464
  .date-label {
@@ -1477,6 +1730,15 @@ def create_timeline_template():
1477
  white-space: nowrap;
1478
  z-index: 2; /* Just above the dotted line but below everything else */
1479
  backdrop-filter: blur(4px);
 
 
 
 
 
 
 
 
 
1480
  }
1481
 
1482
  .date-marker.year {
@@ -1485,6 +1747,12 @@ def create_timeline_template():
1485
  width: 3px;
1486
  }
1487
 
 
 
 
 
 
 
1488
  .date-marker.year .date-label {
1489
  font-weight: 600;
1490
  color: #4b5563;
@@ -1493,6 +1761,13 @@ def create_timeline_template():
1493
  border-color: #9ca3af;
1494
  }
1495
 
 
 
 
 
 
 
 
1496
  .date-marker.quarter {
1497
  opacity: 0.7;
1498
  }
@@ -1501,6 +1776,15 @@ def create_timeline_template():
1501
  opacity: 0.8;
1502
  }
1503
 
 
 
 
 
 
 
 
 
 
1504
  .timeline-dot {
1505
  width: 18px;
1506
  height: 18px;
@@ -1542,6 +1826,14 @@ def create_timeline_template():
1542
  cursor: pointer;
1543
  }
1544
 
 
 
 
 
 
 
 
 
1545
  .timeline-label:not(.expanded):hover {
1546
  background: rgba(255, 255, 255, 0.98);
1547
  box-shadow: 0 6px 25px rgba(0, 0, 0, 0.15),
@@ -1549,6 +1841,14 @@ def create_timeline_template():
1549
  border-color: var(--modality-color, #8B5CF6);
1550
  }
1551
 
 
 
 
 
 
 
 
 
1552
  /* Expanded card styles */
1553
  .timeline-label.expanded {
1554
  max-width: 500px !important;
@@ -1588,6 +1888,13 @@ def create_timeline_template():
1588
  white-space: nowrap;
1589
  overflow: hidden;
1590
  text-overflow: ellipsis;
 
 
 
 
 
 
 
1591
  }
1592
 
1593
  .timeline-label .model-description {
@@ -1597,10 +1904,15 @@ def create_timeline_template():
1597
  margin-bottom: 0.5rem;
1598
  max-height: 0;
1599
  overflow: hidden;
1600
- transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1);
1601
  position: relative;
1602
  }
1603
 
 
 
 
 
 
1604
  .timeline-label.expanded .model-description {
1605
  max-height: 200px !important;
1606
  height: 200px !important;
@@ -1637,6 +1949,14 @@ def create_timeline_template():
1637
  z-index: 10;
1638
  }
1639
 
 
 
 
 
 
 
 
 
1640
  .timeline-label.expanded .description-fade {
1641
  opacity: 1;
1642
  }
@@ -1648,6 +1968,14 @@ def create_timeline_template():
1648
  font-weight: 600;
1649
  margin: 0.8em 0 0.4em 0;
1650
  color: #1f2937;
 
 
 
 
 
 
 
 
1651
  }
1652
 
1653
  .timeline-label .model-description h1 { font-size: 0.85rem; }
@@ -1664,17 +1992,30 @@ def create_timeline_template():
1664
  border-radius: 3px;
1665
  font-family: 'Consolas', 'Monaco', monospace;
1666
  font-size: 0.65rem;
 
 
 
 
 
 
 
1667
  }
1668
 
1669
  .timeline-label .model-description strong {
1670
  font-weight: 600;
1671
  color: #1f2937;
 
1672
  }
1673
 
1674
  .timeline-label .model-description em {
1675
  font-style: italic;
1676
  }
1677
 
 
 
 
 
 
1678
  .timeline-label .model-description ul,
1679
  .timeline-label .model-description ol {
1680
  margin: 0.5em 0;
@@ -1711,6 +2052,11 @@ def create_timeline_template():
1711
  text-align: center;
1712
  }
1713
 
 
 
 
 
 
1714
  .timeline-label.expanded .learn-more {
1715
  display: inline-block;
1716
  }
@@ -1747,6 +2093,13 @@ def create_timeline_template():
1747
  background: rgba(248, 250, 252, 0.8);
1748
  border-radius: 8px;
1749
  border: 1px solid rgba(226, 232, 240, 0.5);
 
 
 
 
 
 
 
1750
  }
1751
 
1752
  .tasks-label {
@@ -1754,6 +2107,12 @@ def create_timeline_template():
1754
  font-weight: 600;
1755
  color: #4a5568;
1756
  margin-bottom: 0.3rem;
 
 
 
 
 
 
1757
  }
1758
 
1759
  .tasks-list {
@@ -1845,6 +2204,12 @@ def create_timeline_template():
1845
  color: #9ca3af;
1846
  margin-top: 0.3rem;
1847
  font-weight: 500;
 
 
 
 
 
 
1848
  }
1849
 
1850
  .date-controls {
@@ -1857,6 +2222,14 @@ def create_timeline_template():
1857
  border-radius: 12px;
1858
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
1859
  border: 1px solid rgba(255, 255, 255, 0.5);
 
 
 
 
 
 
 
 
1860
  }
1861
 
1862
  .date-input-group {
@@ -1871,6 +2244,12 @@ def create_timeline_template():
1871
  color: #4a5568;
1872
  font-weight: 600;
1873
  white-space: nowrap;
 
 
 
 
 
 
1874
  }
1875
 
1876
  .date-input-group input {
@@ -1886,6 +2265,22 @@ def create_timeline_template():
1886
  color: #374151;
1887
  }
1888
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1889
  .date-input-group input:hover {
1890
  border-color: #cbd5e0;
1891
  transform: translateY(-1px);
@@ -1917,6 +2312,13 @@ def create_timeline_template():
1917
  flex: 1;
1918
  min-width: 140px;
1919
  text-align: center;
 
 
 
 
 
 
 
1920
  }
1921
 
1922
  .stat-number {
@@ -1930,6 +2332,12 @@ def create_timeline_template():
1930
  color: #666;
1931
  font-size: 0.7rem;
1932
  margin-top: 0.15rem;
 
 
 
 
 
 
1933
  }
1934
 
1935
  .loading {
@@ -1939,6 +2347,12 @@ def create_timeline_template():
1939
  height: 200px;
1940
  font-size: 1.1rem;
1941
  color: #666;
 
 
 
 
 
 
1942
  }
1943
 
1944
  .loading::after {
@@ -1964,13 +2378,27 @@ def create_timeline_template():
1964
  background: #fed7d7;
1965
  border-radius: 8px;
1966
  margin: 2rem;
 
 
 
 
 
 
 
1967
  }
1968
  </style>
1969
  </head>
1970
  <body>
1971
  <div class="header">
1972
- <h1>🤗 Transformers Models Timeline</h1>
1973
- <p>Interactive timeline to explore models supported by the Hugging Face Transformers library!</p>
 
 
 
 
 
 
 
1974
  </div>
1975
 
1976
  <div class="controls-wrapper">
@@ -2063,6 +2491,53 @@ def create_timeline_template():
2063
  const minZoom = 0.3; // Minimum zoom (30%)
2064
  const maxZoom = 3.0; // Maximum zoom (300%)
2065
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2066
  async function loadTimeline() {
2067
  const timeline = document.getElementById('timeline');
2068
  timeline.innerHTML = '<div class="loading">Loading timeline...</div>';
@@ -2320,6 +2795,7 @@ def create_timeline_template():
2320
  label.dataset.tasks = JSON.stringify(model.tasks);
2321
  }
2322
 
 
2323
  // Add click handler for expansion
2324
  label.addEventListener('click', (e) => {
2325
  e.stopPropagation();
@@ -2368,6 +2844,8 @@ def create_timeline_template():
2368
  const storedTasks = label.dataset.tasks ? JSON.parse(label.dataset.tasks) : [];
2369
  const formattedDescription = markdownToHtml(label.dataset.description);
2370
 
 
 
2371
  // Format tasks for display with task-specific colors
2372
  const tasksHtml = storedTasks && storedTasks.length > 0 ?
2373
  `<div class="model-tasks">
@@ -3011,6 +3489,16 @@ def create_timeline_template():
3011
  });
3012
 
3013
  document.addEventListener('DOMContentLoaded', async () => {
 
 
 
 
 
 
 
 
 
 
3014
  await loadModalities();
3015
  await loadTasks();
3016
  loadTimeline();
@@ -3061,19 +3549,22 @@ def create_timeline_template():
3061
  const btn = document.getElementById('toggleFilters');
3062
  if (!panel || !btn) return;
3063
 
3064
- // Restore persisted state, default to collapsed
3065
- const saved = localStorage.getItem('filtersCollapsed');
3066
- if (saved === 'false') {
3067
- // Set natural max-height to allow animation on first collapse
3068
- panel.style.maxHeight = panel.scrollHeight + 'px';
3069
- btn.textContent = '▾';
3070
- } else {
3071
- // set partial height (~2 rows) when collapsed (default state)
3072
- const partial = 74; // pixels to show when collapsed
3073
- panel.style.maxHeight = partial + 'px';
3074
- panel.classList.add('collapsed');
3075
- btn.textContent = '';
3076
- }
 
 
 
3077
  }
3078
 
3079
  function toggleFilters() {
 
916
  color: #333;
917
  display: flex;
918
  flex-direction: column;
919
+ transition: all 0.3s ease;
920
+ }
921
+
922
+ /* Dark mode body */
923
+ [data-theme="dark"] body {
924
+ background: linear-gradient(135deg, #1f2937 0%, #111827 100%);
925
+ color: #f9fafb;
926
  }
927
 
928
  .header {
 
935
  top: 0;
936
  z-index: 100;
937
  margin: 0 0 0.3rem 0;
938
+ transition: all 0.3s ease;
939
+ }
940
+
941
+ /* Dark mode styles */
942
+ [data-theme="dark"] .header {
943
+ background: rgba(17, 24, 39, 0.9);
944
+ border-bottom: 1px solid rgba(55, 65, 81, 0.5);
945
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
946
  }
947
 
948
  .header h1 {
 
950
  font-weight: 700;
951
  color: #2d3748;
952
  margin-bottom: 0.1rem;
953
+ transition: color 0.3s ease;
954
  }
955
 
956
  .header p {
957
  color: #666;
958
  font-size: 0.8rem;
959
  margin: 0;
960
+ transition: color 0.3s ease;
961
+ }
962
+
963
+ /* Dark mode header text */
964
+ [data-theme="dark"] .header h1 {
965
+ color: #f9fafb;
966
+ }
967
+
968
+ [data-theme="dark"] .header p {
969
+ color: #d1d5db;
970
+ }
971
+
972
+ /* Header layout */
973
+ .header-content {
974
+ display: flex;
975
+ justify-content: space-between;
976
+ align-items: center;
977
+ }
978
+
979
+ .header-text {
980
+ flex: 1;
981
+ }
982
+
983
+ /* Theme toggle button */
984
+ .theme-toggle {
985
+ background: rgba(255, 255, 255, 0.9);
986
+ border: 2px solid #e2e8f0;
987
+ border-radius: 50%;
988
+ width: 48px;
989
+ height: 48px;
990
+ display: flex;
991
+ align-items: center;
992
+ justify-content: center;
993
+ cursor: pointer;
994
+ transition: all 0.3s ease;
995
+ font-size: 1.2rem;
996
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
997
+ backdrop-filter: blur(10px);
998
+ }
999
+
1000
+ .theme-toggle:hover {
1001
+ transform: translateY(-2px);
1002
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
1003
+ border-color: #d97706;
1004
+ }
1005
+
1006
+ .theme-toggle:active {
1007
+ transform: translateY(0);
1008
+ }
1009
+
1010
+ .theme-icon {
1011
+ transition: transform 0.3s ease;
1012
+ }
1013
+
1014
+ /* Dark mode theme toggle */
1015
+ [data-theme="dark"] .theme-toggle {
1016
+ background: rgba(17, 24, 39, 0.9);
1017
+ border-color: #4b5563;
1018
+ color: #f9fafb;
1019
+ }
1020
+
1021
+ [data-theme="dark"] .theme-toggle:hover {
1022
+ border-color: #f59e0b;
1023
  }
1024
 
1025
  .controls-wrapper {
 
1047
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
1048
  }
1049
 
1050
+ /* Dark mode controls toggle */
1051
+ [data-theme="dark"] .controls-toggle {
1052
+ background: #374151;
1053
+ border: 1px solid #4b5563;
1054
+ color: #f9fafb;
1055
+ box-shadow: 0 2px 8px rgba(0,0,0,0.3);
1056
+ }
1057
+
1058
  .controls-toggle:hover {
1059
  transform: translateY(-1px);
1060
  box-shadow: 0 4px 14px rgba(0,0,0,0.1);
1061
  }
1062
 
1063
+ /* Dark mode controls toggle hover */
1064
+ [data-theme="dark"] .controls-toggle:hover {
1065
+ background: #4b5563;
1066
+ border-color: #6b7280;
1067
+ box-shadow: 0 4px 14px rgba(0,0,0,0.4);
1068
+ }
1069
+
1070
  .controls {
1071
  background: rgba(255, 255, 255, 0.9);
1072
  backdrop-filter: blur(10px);
 
1078
  align-items: start;
1079
  flex-wrap: nowrap;
1080
  overflow: hidden;
1081
+ transition: max-height 0.25s ease, opacity 0.2s ease, background 0.3s ease, box-shadow 0.3s ease;
1082
  position: relative;
1083
  padding-left: 2.4rem; /* space for the left toggle button */
1084
+ max-height: 74px; /* default collapsed height */
1085
+ }
1086
+
1087
+ /* Dark mode controls */
1088
+ [data-theme="dark"] .controls {
1089
+ background: rgba(17, 24, 39, 0.9);
1090
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
1091
  }
1092
 
1093
  .controls.collapsed {
1094
  opacity: 1;
1095
+ max-height: 74px !important;
1096
  }
1097
 
1098
  /* Blur fade to hint there is more content when collapsed */
 
1107
  pointer-events: none;
1108
  }
1109
 
1110
+ /* Dark mode blur fade */
1111
+ [data-theme="dark"] .controls.collapsed::after {
1112
+ background: linear-gradient(to bottom, rgba(17,24,39,0), rgba(17,24,39,0.94) 60%, rgba(17,24,39,1));
1113
+ }
1114
+
1115
  .input-group {
1116
  display: flex;
1117
  flex-direction: column;
 
1123
  font-weight: 500;
1124
  color: #4a5568;
1125
  font-size: 0.7rem;
1126
+ transition: color 0.3s ease;
1127
+ }
1128
+
1129
+ /* Dark mode labels */
1130
+ [data-theme="dark"] .input-group label {
1131
+ color: #d1d5db;
1132
  }
1133
 
1134
  .input-group input {
 
1140
  background: white;
1141
  }
1142
 
1143
+ /* Dark mode input elements */
1144
+ [data-theme="dark"] .input-group input {
1145
+ background: #374151;
1146
+ border-color: #4b5563;
1147
+ color: #f9fafb;
1148
+ }
1149
+
1150
+ [data-theme="dark"] .input-group input:focus {
1151
+ border-color: #f59e0b;
1152
+ box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.1);
1153
+ }
1154
+
1155
  .input-group input:focus {
1156
  outline: none;
1157
  border-color: #d97706;
 
1219
  overflow: hidden;
1220
  }
1221
 
1222
+ /* Dark mode modality checkboxes */
1223
+ [data-theme="dark"] .modality-checkbox {
1224
+ background: rgba(17, 24, 39, 0.9);
1225
+ border: 1px solid rgba(55, 65, 81, 0.5);
1226
+ }
1227
+
1228
  .modality-checkbox::before {
1229
  content: '';
1230
  position: absolute;
 
1251
  border-color: currentColor;
1252
  }
1253
 
1254
+ /* Dark mode checked modality checkbox cards */
1255
+ [data-theme="dark"] .modality-checkbox.checked {
1256
+ background: rgba(31, 41, 55, 0.95);
1257
+ border-color: currentColor;
1258
+ }
1259
+
1260
  .modality-checkbox.checked::before {
1261
  opacity: 0.08;
1262
  }
 
1274
  flex-shrink: 0;
1275
  }
1276
 
1277
+ /* Dark mode unchecked checkboxes */
1278
+ [data-theme="dark"] .modality-checkbox input[type="checkbox"] {
1279
+ background: #374151;
1280
+ border-color: var(--modality-color, #8B5CF6);
1281
+ }
1282
+
1283
  .modality-checkbox input[type="checkbox"]:checked {
1284
  background: var(--modality-color, #8B5CF6);
1285
  border-color: var(--modality-color, #8B5CF6);
1286
  }
1287
 
1288
+ /* Dark mode checked checkboxes */
1289
+ [data-theme="dark"] .modality-checkbox input[type="checkbox"]:checked {
1290
+ background: var(--modality-color, #8B5CF6);
1291
+ border-color: var(--modality-color, #8B5CF6);
1292
+ }
1293
+
1294
  .modality-checkbox input[type="checkbox"]:checked::after {
1295
  content: '✓';
1296
  position: absolute;
 
1309
  user-select: none;
1310
  color: #374151;
1311
  font-weight: 600;
1312
+ transition: color 0.3s ease;
1313
+ }
1314
+
1315
+ /* Dark mode modality checkbox labels */
1316
+ [data-theme="dark"] .modality-checkbox label {
1317
+ color: #f9fafb;
1318
  }
1319
 
1320
  /* Task filter styles (mirroring modality styles) */
 
1334
  overflow: hidden;
1335
  }
1336
 
1337
+ /* Dark mode task checkboxes */
1338
+ [data-theme="dark"] .task-checkbox {
1339
+ background: rgba(17, 24, 39, 0.9);
1340
+ border: 1px solid rgba(55, 65, 81, 0.5);
1341
+ }
1342
+
1343
  .task-checkbox::before {
1344
  content: '';
1345
  position: absolute;
 
1366
  border-color: currentColor;
1367
  }
1368
 
1369
+ /* Dark mode checked task checkbox cards */
1370
+ [data-theme="dark"] .task-checkbox.checked {
1371
+ background: rgba(31, 41, 55, 0.95);
1372
+ border-color: currentColor;
1373
+ }
1374
+
1375
  .task-checkbox.checked::before {
1376
  opacity: 0.08;
1377
  }
 
1388
  transition: all 0.2s ease;
1389
  }
1390
 
1391
+ /* Dark mode unchecked task checkboxes */
1392
+ [data-theme="dark"] .task-checkbox input[type="checkbox"] {
1393
+ background: #374151;
1394
+ border-color: var(--task-color, #6366f1);
1395
+ }
1396
+
1397
  .task-checkbox input[type="checkbox"]:checked {
1398
  background: var(--task-color, #6366f1);
1399
  border-color: var(--task-color, #6366f1);
1400
  }
1401
 
1402
+ /* Dark mode checked task checkboxes */
1403
+ [data-theme="dark"] .task-checkbox input[type="checkbox"]:checked {
1404
+ background: var(--task-color, #6366f1);
1405
+ border-color: var(--task-color, #6366f1);
1406
+ }
1407
+
1408
  .task-checkbox input[type="checkbox"]:checked::after {
1409
  content: '✓';
1410
  position: absolute;
 
1423
  user-select: none;
1424
  color: #374151;
1425
  font-weight: 600;
1426
+ transition: color 0.3s ease;
1427
+ }
1428
+
1429
+ /* Dark mode task checkbox labels */
1430
+ [data-theme="dark"] .task-checkbox label {
1431
+ color: #f9fafb;
1432
  }
1433
 
1434
  .modality-checkbox input[type="checkbox"]:not(:checked) {
 
1436
  border-color: var(--modality-color, #8B5CF6);
1437
  }
1438
 
1439
+ /* Dark mode unchecked checkboxes override */
1440
+ [data-theme="dark"] .modality-checkbox input[type="checkbox"]:not(:checked) {
1441
+ background: #374151;
1442
+ border-color: var(--modality-color, #8B5CF6);
1443
+ }
1444
+
1445
  .btn {
1446
  padding: 0.5rem 1rem;
1447
  border: none;
 
1468
  background: #f7fafc;
1469
  color: #4a5568;
1470
  border: 2px solid #e2e8f0;
1471
+ transition: all 0.3s ease;
1472
+ }
1473
+
1474
+ /* Dark mode secondary buttons */
1475
+ [data-theme="dark"] .btn-secondary {
1476
+ background: #374151;
1477
+ color: #f9fafb;
1478
+ border: 2px solid #4b5563;
1479
+ }
1480
+
1481
+ [data-theme="dark"] .btn-secondary:hover {
1482
+ background: #4b5563;
1483
+ border-color: #6b7280;
1484
  }
1485
 
1486
  .timeline-container {
 
1495
  display: flex;
1496
  flex-direction: column;
1497
  height: calc(100vh - 110px);
1498
+ transition: all 0.3s ease;
1499
+ }
1500
+
1501
+ /* Dark mode timeline container */
1502
+ [data-theme="dark"] .timeline-container {
1503
+ background: rgba(17, 24, 39, 0.95);
1504
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
1505
  }
1506
 
1507
  .timeline-wrapper {
 
1557
  z-index: 10;
1558
  }
1559
 
1560
+ /* Dark mode navigation arrows */
1561
+ [data-theme="dark"] .nav-arrow {
1562
+ background: rgba(17, 24, 39, 0.9);
1563
+ color: #f59e0b;
1564
+ border: 2px solid rgba(245, 158, 11, 0.2);
1565
+ }
1566
+
1567
  .nav-arrow:hover {
1568
  background: rgba(217, 119, 6, 0.1);
1569
  border-color: #d97706;
 
1571
  box-shadow: 0 4px 16px rgba(217, 119, 6, 0.3);
1572
  }
1573
 
1574
+ /* Dark mode navigation arrow hover */
1575
+ [data-theme="dark"] .nav-arrow:hover {
1576
+ background: rgba(245, 158, 11, 0.1);
1577
+ border-color: #f59e0b;
1578
+ box-shadow: 0 4px 16px rgba(245, 158, 11, 0.3);
1579
+ }
1580
+
1581
  .nav-arrow.left {
1582
  left: 10px;
1583
  }
 
1619
  user-select: none;
1620
  }
1621
 
1622
+ /* Dark mode zoom buttons */
1623
+ [data-theme="dark"] .zoom-btn {
1624
+ background: rgba(17, 24, 39, 0.9);
1625
+ border: 2px solid rgba(245, 158, 11, 0.2);
1626
+ color: #f59e0b;
1627
+ }
1628
+
1629
  .zoom-btn:hover {
1630
  background: rgba(217, 119, 6, 0.1);
1631
  border-color: #d97706;
 
1633
  box-shadow: 0 4px 16px rgba(217, 119, 6, 0.3);
1634
  }
1635
 
1636
+ /* Dark mode zoom button hover */
1637
+ [data-theme="dark"] .zoom-btn:hover {
1638
+ background: rgba(245, 158, 11, 0.1);
1639
+ border-color: #f59e0b;
1640
+ box-shadow: 0 4px 16px rgba(245, 158, 11, 0.3);
1641
+ }
1642
+
1643
  .zoom-btn:active {
1644
  transform: scale(0.95);
1645
  }
 
1652
  color: #d97706;
1653
  font-weight: 500;
1654
  border: 1px solid rgba(217, 119, 6, 0.2);
1655
+ transition: all 0.3s ease;
1656
+ }
1657
+
1658
+ /* Dark mode zoom indicator */
1659
+ [data-theme="dark"] .zoom-indicator {
1660
+ background: rgba(17, 24, 39, 0.95);
1661
+ color: #f59e0b;
1662
+ border: 1px solid rgba(245, 158, 11, 0.2);
1663
  }
1664
 
1665
  .timeline-line {
 
1705
  opacity: 0.8;
1706
  pointer-events: none;
1707
  z-index: 1; /* In background, below everything */
1708
+ transition: all 0.3s ease;
1709
+ }
1710
+
1711
+ /* Dark mode date markers */
1712
+ [data-theme="dark"] .date-marker {
1713
+ background: #6b7280;
1714
+ opacity: 0.9;
1715
  }
1716
 
1717
  .date-label {
 
1730
  white-space: nowrap;
1731
  z-index: 2; /* Just above the dotted line but below everything else */
1732
  backdrop-filter: blur(4px);
1733
+ transition: all 0.3s ease;
1734
+ }
1735
+
1736
+ /* Dark mode date labels */
1737
+ [data-theme="dark"] .date-label {
1738
+ color: #d1d5db;
1739
+ background: rgba(17, 24, 39, 0.8);
1740
+ border: 1px solid rgba(75, 85, 99, 0.4);
1741
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
1742
  }
1743
 
1744
  .date-marker.year {
 
1747
  width: 3px;
1748
  }
1749
 
1750
+ /* Dark mode year markers */
1751
+ [data-theme="dark"] .date-marker.year {
1752
+ background: #9ca3af;
1753
+ opacity: 1.0;
1754
+ }
1755
+
1756
  .date-marker.year .date-label {
1757
  font-weight: 600;
1758
  color: #4b5563;
 
1761
  border-color: #9ca3af;
1762
  }
1763
 
1764
+ /* Dark mode year date labels */
1765
+ [data-theme="dark"] .date-marker.year .date-label {
1766
+ color: #f9fafb;
1767
+ background: rgba(17, 24, 39, 0.9);
1768
+ border-color: #6b7280;
1769
+ }
1770
+
1771
  .date-marker.quarter {
1772
  opacity: 0.7;
1773
  }
 
1776
  opacity: 0.8;
1777
  }
1778
 
1779
+ /* Dark mode quarter and month markers */
1780
+ [data-theme="dark"] .date-marker.quarter {
1781
+ opacity: 0.8;
1782
+ }
1783
+
1784
+ [data-theme="dark"] .date-marker.month {
1785
+ opacity: 0.9;
1786
+ }
1787
+
1788
  .timeline-dot {
1789
  width: 18px;
1790
  height: 18px;
 
1826
  cursor: pointer;
1827
  }
1828
 
1829
+ /* Dark mode timeline labels */
1830
+ [data-theme="dark"] .timeline-label {
1831
+ background: #374151;
1832
+ border: 1px solid #4b5563;
1833
+ color: #f9fafb;
1834
+ box-shadow: 0 3px 12px rgba(0, 0, 0, 0.4);
1835
+ }
1836
+
1837
  .timeline-label:not(.expanded):hover {
1838
  background: rgba(255, 255, 255, 0.98);
1839
  box-shadow: 0 6px 25px rgba(0, 0, 0, 0.15),
 
1841
  border-color: var(--modality-color, #8B5CF6);
1842
  }
1843
 
1844
+ /* Dark mode timeline label hover */
1845
+ [data-theme="dark"] .timeline-label:not(.expanded):hover {
1846
+ background: rgba(55, 65, 81, 0.98);
1847
+ box-shadow: 0 6px 25px rgba(0, 0, 0, 0.4),
1848
+ 0 0 4px var(--modality-color, #8B5CF6);
1849
+ border-color: var(--modality-color, #8B5CF6);
1850
+ }
1851
+
1852
  /* Expanded card styles */
1853
  .timeline-label.expanded {
1854
  max-width: 500px !important;
 
1888
  white-space: nowrap;
1889
  overflow: hidden;
1890
  text-overflow: ellipsis;
1891
+ transition: color 0.3s ease;
1892
+ }
1893
+
1894
+ /* Dark mode model title */
1895
+ [data-theme="dark"] .timeline-label .model-title {
1896
+ color: #f9fafb;
1897
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
1898
  }
1899
 
1900
  .timeline-label .model-description {
 
1904
  margin-bottom: 0.5rem;
1905
  max-height: 0;
1906
  overflow: hidden;
1907
+ transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1), color 0.3s ease;
1908
  position: relative;
1909
  }
1910
 
1911
+ /* Dark mode model description */
1912
+ [data-theme="dark"] .timeline-label .model-description {
1913
+ color: #d1d5db;
1914
+ }
1915
+
1916
  .timeline-label.expanded .model-description {
1917
  max-height: 200px !important;
1918
  height: 200px !important;
 
1949
  z-index: 10;
1950
  }
1951
 
1952
+ /* Dark mode description fade */
1953
+ [data-theme="dark"] .timeline-label .description-fade {
1954
+ background: linear-gradient(to bottom,
1955
+ rgba(55, 65, 81, 0) 0%,
1956
+ rgba(55, 65, 81, 0.9) 50%,
1957
+ rgba(55, 65, 81, 1) 100%);
1958
+ }
1959
+
1960
  .timeline-label.expanded .description-fade {
1961
  opacity: 1;
1962
  }
 
1968
  font-weight: 600;
1969
  margin: 0.8em 0 0.4em 0;
1970
  color: #1f2937;
1971
+ transition: color 0.3s ease;
1972
+ }
1973
+
1974
+ /* Dark mode markdown headers */
1975
+ [data-theme="dark"] .timeline-label .model-description h1,
1976
+ [data-theme="dark"] .timeline-label .model-description h2,
1977
+ [data-theme="dark"] .timeline-label .model-description h3 {
1978
+ color: #f9fafb;
1979
  }
1980
 
1981
  .timeline-label .model-description h1 { font-size: 0.85rem; }
 
1992
  border-radius: 3px;
1993
  font-family: 'Consolas', 'Monaco', monospace;
1994
  font-size: 0.65rem;
1995
+ transition: all 0.3s ease;
1996
+ }
1997
+
1998
+ /* Dark mode code */
1999
+ [data-theme="dark"] .timeline-label .model-description code {
2000
+ background: #374151;
2001
+ color: #f9fafb;
2002
  }
2003
 
2004
  .timeline-label .model-description strong {
2005
  font-weight: 600;
2006
  color: #1f2937;
2007
+ transition: color 0.3s ease;
2008
  }
2009
 
2010
  .timeline-label .model-description em {
2011
  font-style: italic;
2012
  }
2013
 
2014
+ /* Dark mode strong and em */
2015
+ [data-theme="dark"] .timeline-label .model-description strong {
2016
+ color: #f9fafb;
2017
+ }
2018
+
2019
  .timeline-label .model-description ul,
2020
  .timeline-label .model-description ol {
2021
  margin: 0.5em 0;
 
2052
  text-align: center;
2053
  }
2054
 
2055
+ /* Dark mode learn more button */
2056
+ [data-theme="dark"] .timeline-label .learn-more {
2057
+ background: rgba(55, 65, 81, 0.8);
2058
+ }
2059
+
2060
  .timeline-label.expanded .learn-more {
2061
  display: inline-block;
2062
  }
 
2093
  background: rgba(248, 250, 252, 0.8);
2094
  border-radius: 8px;
2095
  border: 1px solid rgba(226, 232, 240, 0.5);
2096
+ transition: all 0.3s ease;
2097
+ }
2098
+
2099
+ /* Dark mode model tasks */
2100
+ [data-theme="dark"] .model-tasks {
2101
+ background: rgba(31, 41, 55, 0.8);
2102
+ border: 1px solid rgba(55, 65, 81, 0.5);
2103
  }
2104
 
2105
  .tasks-label {
 
2107
  font-weight: 600;
2108
  color: #4a5568;
2109
  margin-bottom: 0.3rem;
2110
+ transition: color 0.3s ease;
2111
+ }
2112
+
2113
+ /* Dark mode tasks label */
2114
+ [data-theme="dark"] .tasks-label {
2115
+ color: #d1d5db;
2116
  }
2117
 
2118
  .tasks-list {
 
2204
  color: #9ca3af;
2205
  margin-top: 0.3rem;
2206
  font-weight: 500;
2207
+ transition: color 0.3s ease;
2208
+ }
2209
+
2210
+ /* Dark mode timeline date */
2211
+ [data-theme="dark"] .timeline-date {
2212
+ color: #9ca3af;
2213
  }
2214
 
2215
  .date-controls {
 
2222
  border-radius: 12px;
2223
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
2224
  border: 1px solid rgba(255, 255, 255, 0.5);
2225
+ transition: all 0.3s ease;
2226
+ }
2227
+
2228
+ /* Dark mode date controls */
2229
+ [data-theme="dark"] .date-controls {
2230
+ background: rgba(17, 24, 39, 0.95);
2231
+ border: 1px solid rgba(55, 65, 81, 0.5);
2232
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
2233
  }
2234
 
2235
  .date-input-group {
 
2244
  color: #4a5568;
2245
  font-weight: 600;
2246
  white-space: nowrap;
2247
+ transition: color 0.3s ease;
2248
+ }
2249
+
2250
+ /* Dark mode date labels */
2251
+ [data-theme="dark"] .date-input-group label {
2252
+ color: #d1d5db;
2253
  }
2254
 
2255
  .date-input-group input {
 
2265
  color: #374151;
2266
  }
2267
 
2268
+ /* Dark mode date inputs */
2269
+ [data-theme="dark"] .date-input-group input {
2270
+ background: #374151;
2271
+ border-color: #4b5563;
2272
+ color: #f9fafb;
2273
+ }
2274
+
2275
+ [data-theme="dark"] .date-input-group input:hover {
2276
+ border-color: #6b7280;
2277
+ }
2278
+
2279
+ [data-theme="dark"] .date-input-group input:focus {
2280
+ border-color: #f59e0b;
2281
+ box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.15);
2282
+ }
2283
+
2284
  .date-input-group input:hover {
2285
  border-color: #cbd5e0;
2286
  transform: translateY(-1px);
 
2312
  flex: 1;
2313
  min-width: 140px;
2314
  text-align: center;
2315
+ transition: all 0.3s ease;
2316
+ }
2317
+
2318
+ /* Dark mode stat cards */
2319
+ [data-theme="dark"] .stat-card {
2320
+ background: rgba(17, 24, 39, 0.9);
2321
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
2322
  }
2323
 
2324
  .stat-number {
 
2332
  color: #666;
2333
  font-size: 0.7rem;
2334
  margin-top: 0.15rem;
2335
+ transition: color 0.3s ease;
2336
+ }
2337
+
2338
+ /* Dark mode stat labels */
2339
+ [data-theme="dark"] .stat-label {
2340
+ color: #9ca3af;
2341
  }
2342
 
2343
  .loading {
 
2347
  height: 200px;
2348
  font-size: 1.1rem;
2349
  color: #666;
2350
+ transition: color 0.3s ease;
2351
+ }
2352
+
2353
+ /* Dark mode loading */
2354
+ [data-theme="dark"] .loading {
2355
+ color: #9ca3af;
2356
  }
2357
 
2358
  .loading::after {
 
2378
  background: #fed7d7;
2379
  border-radius: 8px;
2380
  margin: 2rem;
2381
+ transition: all 0.3s ease;
2382
+ }
2383
+
2384
+ /* Dark mode error */
2385
+ [data-theme="dark"] .error {
2386
+ color: #fca5a5;
2387
+ background: #7f1d1d;
2388
  }
2389
  </style>
2390
  </head>
2391
  <body>
2392
  <div class="header">
2393
+ <div class="header-content">
2394
+ <div class="header-text">
2395
+ <h1>🤗 Transformers Models Timeline</h1>
2396
+ <p>Interactive timeline to explore models supported by the Hugging Face Transformers library!</p>
2397
+ </div>
2398
+ <button id="themeToggle" class="theme-toggle" title="Toggle dark/light mode">
2399
+ <span class="theme-icon">����</span>
2400
+ </button>
2401
+ </div>
2402
  </div>
2403
 
2404
  <div class="controls-wrapper">
 
2491
  const minZoom = 0.3; // Minimum zoom (30%)
2492
  const maxZoom = 3.0; // Maximum zoom (300%)
2493
 
2494
+ // Theme management
2495
+ let currentTheme = 'light';
2496
+
2497
+ // Theme detection and switching functions
2498
+ function detectSystemTheme() {
2499
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
2500
+ }
2501
+
2502
+ function loadTheme() {
2503
+ // Check localStorage first, then system preference
2504
+ const savedTheme = localStorage.getItem('theme');
2505
+ const systemTheme = detectSystemTheme();
2506
+ currentTheme = savedTheme || systemTheme;
2507
+ applyTheme(currentTheme);
2508
+ }
2509
+
2510
+ function applyTheme(theme) {
2511
+ currentTheme = theme;
2512
+ document.documentElement.setAttribute('data-theme', theme);
2513
+
2514
+ // Update theme toggle icon
2515
+ const themeIcon = document.querySelector('.theme-icon');
2516
+ if (themeIcon) {
2517
+ themeIcon.textContent = theme === 'dark' ? '☀️' : '🌙';
2518
+ }
2519
+
2520
+ // Save to localStorage
2521
+ localStorage.setItem('theme', theme);
2522
+ }
2523
+
2524
+ function toggleTheme() {
2525
+ const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
2526
+ applyTheme(newTheme);
2527
+ }
2528
+
2529
+ // Listen for system theme changes
2530
+ function setupThemeListener() {
2531
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
2532
+ mediaQuery.addEventListener('change', (e) => {
2533
+ // Only auto-switch if user hasn't manually set a preference
2534
+ if (!localStorage.getItem('theme')) {
2535
+ const newTheme = e.matches ? 'dark' : 'light';
2536
+ applyTheme(newTheme);
2537
+ }
2538
+ });
2539
+ }
2540
+
2541
  async function loadTimeline() {
2542
  const timeline = document.getElementById('timeline');
2543
  timeline.innerHTML = '<div class="loading">Loading timeline...</div>';
 
2795
  label.dataset.tasks = JSON.stringify(model.tasks);
2796
  }
2797
 
2798
+
2799
  // Add click handler for expansion
2800
  label.addEventListener('click', (e) => {
2801
  e.stopPropagation();
 
2844
  const storedTasks = label.dataset.tasks ? JSON.parse(label.dataset.tasks) : [];
2845
  const formattedDescription = markdownToHtml(label.dataset.description);
2846
 
2847
+
2848
+
2849
  // Format tasks for display with task-specific colors
2850
  const tasksHtml = storedTasks && storedTasks.length > 0 ?
2851
  `<div class="model-tasks">
 
3489
  });
3490
 
3491
  document.addEventListener('DOMContentLoaded', async () => {
3492
+ // Initialize theme
3493
+ loadTheme();
3494
+ setupThemeListener();
3495
+
3496
+ // Add theme toggle event listener
3497
+ const themeToggle = document.getElementById('themeToggle');
3498
+ if (themeToggle) {
3499
+ themeToggle.addEventListener('click', toggleTheme);
3500
+ }
3501
+
3502
  await loadModalities();
3503
  await loadTasks();
3504
  loadTimeline();
 
3549
  const btn = document.getElementById('toggleFilters');
3550
  if (!panel || !btn) return;
3551
 
3552
+ // Ensure panel starts collapsed by default
3553
+ panel.classList.add('collapsed');
3554
+ panel.style.maxHeight = '74px';
3555
+ btn.textContent = '▸';
3556
+
3557
+ // Restore persisted state after a short delay to ensure DOM is ready
3558
+ setTimeout(() => {
3559
+ const saved = localStorage.getItem('filtersCollapsed');
3560
+ if (saved === 'false') {
3561
+ // Expand to full content height
3562
+ panel.classList.remove('collapsed');
3563
+ panel.style.maxHeight = panel.scrollHeight + 'px';
3564
+ btn.textContent = '▾';
3565
+ }
3566
+ // If saved is 'true' or null, keep collapsed (default state)
3567
+ }, 50);
3568
  }
3569
 
3570
  function toggleFilters() {