Commit
·
3119164
1
Parent(s):
8c45c35
fix truncated cards at the extremities, improve style
Browse files
app.py
CHANGED
@@ -638,7 +638,7 @@ def create_timeline_template():
|
|
638 |
}
|
639 |
|
640 |
.header h1 {
|
641 |
-
font-size: 1.
|
642 |
font-weight: 700;
|
643 |
color: #2d3748;
|
644 |
margin-bottom: 0.1rem;
|
@@ -647,7 +647,7 @@ def create_timeline_template():
|
|
647 |
|
648 |
.header p {
|
649 |
color: #666;
|
650 |
-
font-size: 0.
|
651 |
margin: 0;
|
652 |
transition: color 0.3s ease;
|
653 |
}
|
@@ -814,7 +814,7 @@ def create_timeline_template():
|
|
814 |
.input-group label {
|
815 |
font-weight: 500;
|
816 |
color: #4a5568;
|
817 |
-
font-size: 0.
|
818 |
transition: color 0.3s ease;
|
819 |
}
|
820 |
|
@@ -824,10 +824,10 @@ def create_timeline_template():
|
|
824 |
}
|
825 |
|
826 |
.input-group input {
|
827 |
-
padding: 0.
|
828 |
border: 1px solid #e2e8f0;
|
829 |
border-radius: 5px;
|
830 |
-
font-size: 0.
|
831 |
transition: all 0.2s ease;
|
832 |
background: white;
|
833 |
}
|
@@ -898,10 +898,10 @@ def create_timeline_template():
|
|
898 |
}
|
899 |
|
900 |
.btn-small {
|
901 |
-
padding: 0.
|
902 |
-
font-size: 0.
|
903 |
margin-top: 0;
|
904 |
-
height:
|
905 |
display: flex;
|
906 |
align-items: center;
|
907 |
justify-content: center;
|
@@ -910,14 +910,14 @@ def create_timeline_template():
|
|
910 |
.modality-checkbox {
|
911 |
display: flex;
|
912 |
align-items: center;
|
913 |
-
gap: 0.
|
914 |
-
padding: 0.
|
915 |
background: rgba(255, 255, 255, 0.9);
|
916 |
border: 1px solid rgba(0, 0, 0, 0.1);
|
917 |
border-radius: 8px;
|
918 |
cursor: pointer;
|
919 |
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
920 |
-
font-size: 0.
|
921 |
font-weight: 500;
|
922 |
position: relative;
|
923 |
overflow: hidden;
|
@@ -967,8 +967,8 @@ def create_timeline_template():
|
|
967 |
|
968 |
.modality-checkbox input[type="checkbox"] {
|
969 |
appearance: none;
|
970 |
-
width:
|
971 |
-
height:
|
972 |
border: 2px solid var(--modality-color, #8B5CF6);
|
973 |
border-radius: 4px;
|
974 |
position: relative;
|
@@ -1025,14 +1025,14 @@ def create_timeline_template():
|
|
1025 |
.task-checkbox {
|
1026 |
display: flex;
|
1027 |
align-items: center;
|
1028 |
-
gap: 0.
|
1029 |
-
padding: 0.
|
1030 |
background: rgba(255, 255, 255, 0.9);
|
1031 |
border: 1px solid rgba(0, 0, 0, 0.1);
|
1032 |
border-radius: 8px;
|
1033 |
cursor: pointer;
|
1034 |
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
1035 |
-
font-size: 0.
|
1036 |
font-weight: 500;
|
1037 |
position: relative;
|
1038 |
overflow: hidden;
|
@@ -1082,8 +1082,8 @@ def create_timeline_template():
|
|
1082 |
|
1083 |
.task-checkbox input[type="checkbox"] {
|
1084 |
appearance: none;
|
1085 |
-
width:
|
1086 |
-
height:
|
1087 |
border: 2px solid var(--task-color, #6366f1);
|
1088 |
border-radius: 4px;
|
1089 |
background: white;
|
@@ -1301,20 +1301,20 @@ def create_timeline_template():
|
|
1301 |
top: 15px;
|
1302 |
right: 15px;
|
1303 |
display: flex;
|
1304 |
-
gap:
|
1305 |
z-index: 20;
|
1306 |
}
|
1307 |
|
1308 |
.zoom-btn {
|
1309 |
-
width:
|
1310 |
-
height:
|
1311 |
background: rgba(255, 255, 255, 0.9);
|
1312 |
-
border-radius:
|
1313 |
display: flex;
|
1314 |
align-items: center;
|
1315 |
justify-content: center;
|
1316 |
cursor: pointer;
|
1317 |
-
font-size:
|
1318 |
font-weight: 600;
|
1319 |
color: #d97706;
|
1320 |
border: 2px solid rgba(217, 119, 6, 0.2);
|
@@ -1351,12 +1351,17 @@ def create_timeline_template():
|
|
1351 |
.zoom-indicator {
|
1352 |
background: rgba(255, 255, 255, 0.95);
|
1353 |
border-radius: 6px;
|
1354 |
-
padding:
|
1355 |
-
font-size: 0.
|
1356 |
color: #d97706;
|
1357 |
font-weight: 500;
|
1358 |
border: 1px solid rgba(217, 119, 6, 0.2);
|
1359 |
transition: all 0.3s ease;
|
|
|
|
|
|
|
|
|
|
|
1360 |
}
|
1361 |
|
1362 |
/* Dark mode zoom indicator */
|
@@ -1490,8 +1495,8 @@ def create_timeline_template():
|
|
1490 |
}
|
1491 |
|
1492 |
.timeline-dot {
|
1493 |
-
width:
|
1494 |
-
height:
|
1495 |
border-radius: 50%;
|
1496 |
background: white;
|
1497 |
border: 3px solid;
|
@@ -1511,12 +1516,12 @@ def create_timeline_template():
|
|
1511 |
|
1512 |
.timeline-label {
|
1513 |
position: absolute;
|
1514 |
-
min-width:
|
1515 |
-
max-width:
|
1516 |
-
padding: 0.
|
1517 |
background: white;
|
1518 |
border-radius: 6px;
|
1519 |
-
font-size: 0.
|
1520 |
font-weight: 500;
|
1521 |
text-align: center;
|
1522 |
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.12);
|
@@ -1555,9 +1560,9 @@ def create_timeline_template():
|
|
1555 |
|
1556 |
/* Expanded card styles */
|
1557 |
.timeline-label.expanded {
|
1558 |
-
max-width:
|
1559 |
-
min-width:
|
1560 |
-
width:
|
1561 |
min-height: 250px !important;
|
1562 |
text-align: left;
|
1563 |
z-index: 9999 !important; /* Much higher than all other elements */
|
@@ -1584,7 +1589,7 @@ def create_timeline_template():
|
|
1584 |
|
1585 |
.timeline-label .model-title {
|
1586 |
font-weight: 600;
|
1587 |
-
font-size: 0.
|
1588 |
margin-bottom: 0.5rem;
|
1589 |
color: #1f2937;
|
1590 |
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
@@ -1602,10 +1607,9 @@ def create_timeline_template():
|
|
1602 |
}
|
1603 |
|
1604 |
.timeline-label .model-description {
|
1605 |
-
font-size: 0.
|
1606 |
line-height: 1.4;
|
1607 |
color: #4b5563;
|
1608 |
-
margin-bottom: 0.5rem;
|
1609 |
max-height: 0;
|
1610 |
overflow: hidden;
|
1611 |
transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1), color 0.3s ease;
|
@@ -1618,8 +1622,8 @@ def create_timeline_template():
|
|
1618 |
}
|
1619 |
|
1620 |
.timeline-label.expanded .model-description {
|
1621 |
-
max-height:
|
1622 |
-
height:
|
1623 |
position: relative;
|
1624 |
overflow: hidden; /* Hide overflow for blur effect */
|
1625 |
}
|
@@ -1631,21 +1635,23 @@ def create_timeline_template():
|
|
1631 |
}
|
1632 |
|
1633 |
.timeline-label.expanded .description-content {
|
1634 |
-
|
1635 |
-
|
|
|
|
|
1636 |
overflow-y: auto;
|
1637 |
padding-right: 8px; /* Space for scrollbar */
|
1638 |
}
|
1639 |
|
1640 |
.timeline-label .description-fade {
|
1641 |
-
position:
|
1642 |
-
bottom:
|
1643 |
left: 0;
|
1644 |
-
|
1645 |
-
height: 43px; /* Increase height to compensate */
|
1646 |
background: linear-gradient(to bottom,
|
1647 |
rgba(255, 255, 255, 0) 0%,
|
1648 |
rgba(255, 255, 255, 0.9) 50%,
|
|
|
1649 |
rgba(255, 255, 255, 1) 100%);
|
1650 |
opacity: 0;
|
1651 |
transition: opacity 0.3s ease;
|
@@ -1658,6 +1664,7 @@ def create_timeline_template():
|
|
1658 |
background: linear-gradient(to bottom,
|
1659 |
rgba(55, 65, 81, 0) 0%,
|
1660 |
rgba(55, 65, 81, 0.9) 50%,
|
|
|
1661 |
rgba(55, 65, 81, 1) 100%);
|
1662 |
}
|
1663 |
|
@@ -1682,9 +1689,9 @@ def create_timeline_template():
|
|
1682 |
color: #f9fafb;
|
1683 |
}
|
1684 |
|
1685 |
-
.timeline-label .model-description h1 { font-size: 0.
|
1686 |
-
.timeline-label .model-description h2 { font-size: 0.
|
1687 |
-
.timeline-label .model-description h3 { font-size: 0.
|
1688 |
|
1689 |
.timeline-label .model-description p {
|
1690 |
margin: 0.5em 0;
|
@@ -1695,7 +1702,7 @@ def create_timeline_template():
|
|
1695 |
padding: 0.1em 0.3em;
|
1696 |
border-radius: 3px;
|
1697 |
font-family: 'Consolas', 'Monaco', monospace;
|
1698 |
-
font-size: 0.
|
1699 |
transition: all 0.3s ease;
|
1700 |
}
|
1701 |
|
@@ -1745,14 +1752,14 @@ def create_timeline_template():
|
|
1745 |
display: none;
|
1746 |
text-decoration: none;
|
1747 |
color: var(--modality-color, #8B5CF6);
|
1748 |
-
font-size: 0.
|
1749 |
font-weight: 600;
|
1750 |
padding: 0.3rem 0.6rem;
|
1751 |
border: 1px solid var(--modality-color, #8B5CF6);
|
1752 |
border-radius: 4px;
|
1753 |
background: rgba(255, 255, 255, 0.8);
|
1754 |
transition: all 0.2s ease;
|
1755 |
-
margin-top: 0.
|
1756 |
text-align: center;
|
1757 |
}
|
1758 |
|
@@ -1807,7 +1814,7 @@ def create_timeline_template():
|
|
1807 |
}
|
1808 |
|
1809 |
.tasks-label {
|
1810 |
-
font-size: 0.
|
1811 |
font-weight: 600;
|
1812 |
color: #4a5568;
|
1813 |
margin-bottom: 0.3rem;
|
@@ -1827,10 +1834,10 @@ def create_timeline_template():
|
|
1827 |
|
1828 |
.task-badge {
|
1829 |
display: inline-block;
|
1830 |
-
padding: 0.
|
1831 |
color: white;
|
1832 |
border-radius: 4px;
|
1833 |
-
font-size: 0.
|
1834 |
font-weight: 500;
|
1835 |
opacity: 0.9;
|
1836 |
transition: all 0.2s ease;
|
@@ -1904,7 +1911,7 @@ def create_timeline_template():
|
|
1904 |
}
|
1905 |
|
1906 |
.timeline-date {
|
1907 |
-
font-size: 0.
|
1908 |
color: #9ca3af;
|
1909 |
margin-top: 0.3rem;
|
1910 |
font-weight: 500;
|
@@ -1944,7 +1951,7 @@ def create_timeline_template():
|
|
1944 |
}
|
1945 |
|
1946 |
.date-input-group label {
|
1947 |
-
font-size: 0.
|
1948 |
color: #4a5568;
|
1949 |
font-weight: 600;
|
1950 |
white-space: nowrap;
|
@@ -1957,13 +1964,13 @@ def create_timeline_template():
|
|
1957 |
}
|
1958 |
|
1959 |
.date-input-group input {
|
1960 |
-
padding: 0.
|
1961 |
border: 2px solid #e2e8f0;
|
1962 |
border-radius: 8px;
|
1963 |
-
font-size: 0.
|
1964 |
background: white;
|
1965 |
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
1966 |
-
min-width:
|
1967 |
text-align: center;
|
1968 |
font-weight: 500;
|
1969 |
color: #374151;
|
@@ -2034,7 +2041,7 @@ def create_timeline_template():
|
|
2034 |
|
2035 |
.stat-label {
|
2036 |
color: #666;
|
2037 |
-
font-size: 0.
|
2038 |
margin-top: 0.15rem;
|
2039 |
transition: color 0.3s ease;
|
2040 |
}
|
@@ -2194,6 +2201,7 @@ def create_timeline_template():
|
|
2194 |
let zoomLevel = 1.0; // 1.0 = 100%, 0.5 = 50%, 2.0 = 200%
|
2195 |
const minZoom = 0.3; // Minimum zoom (30%)
|
2196 |
const maxZoom = 3.0; // Maximum zoom (300%)
|
|
|
2197 |
|
2198 |
// Theme management
|
2199 |
let currentTheme = 'light';
|
@@ -2525,6 +2533,9 @@ def create_timeline_template():
|
|
2525 |
setTimeout(() => {
|
2526 |
otherLabel.style.top = '';
|
2527 |
otherLabel.style.bottom = '';
|
|
|
|
|
|
|
2528 |
otherLabel.parentElement.style.zIndex = '';
|
2529 |
}, 50);
|
2530 |
}, 50);
|
@@ -2548,8 +2559,6 @@ def create_timeline_template():
|
|
2548 |
const storedTasks = label.dataset.tasks ? JSON.parse(label.dataset.tasks) : [];
|
2549 |
const formattedDescription = markdownToHtml(label.dataset.description);
|
2550 |
|
2551 |
-
|
2552 |
-
|
2553 |
// Format tasks for display with task-specific colors
|
2554 |
const tasksHtml = storedTasks && storedTasks.length > 0 ?
|
2555 |
`<div class="model-tasks">
|
@@ -2557,7 +2566,8 @@ def create_timeline_template():
|
|
2557 |
<div class="tasks-list">
|
2558 |
${storedTasks.map(task => {
|
2559 |
const taskColor = getTaskColor(task);
|
2560 |
-
|
|
|
2561 |
}).join('')}
|
2562 |
</div>
|
2563 |
</div>` :
|
@@ -2573,9 +2583,9 @@ def create_timeline_template():
|
|
2573 |
<div class="description-fade"></div>
|
2574 |
</div>
|
2575 |
<a href="${label.dataset.learnMoreUrl}"
|
2576 |
-
|
2577 |
-
|
2578 |
-
|
2579 |
Learn More →
|
2580 |
</a>
|
2581 |
`;
|
@@ -2586,7 +2596,48 @@ def create_timeline_template():
|
|
2586 |
// Ensure this timeline item is on top
|
2587 |
item.style.zIndex = '10000';
|
2588 |
|
2589 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2590 |
if (isAboveAxis) {
|
2591 |
// Keep top edge fixed - set top position
|
2592 |
label.style.bottom = 'auto';
|
@@ -2612,9 +2663,13 @@ def create_timeline_template():
|
|
2612 |
setTimeout(() => {
|
2613 |
label.style.top = '';
|
2614 |
label.style.bottom = '';
|
2615 |
-
|
2616 |
-
|
2617 |
-
|
|
|
|
|
|
|
|
|
2618 |
}
|
2619 |
});
|
2620 |
|
@@ -3018,6 +3073,11 @@ def create_timeline_template():
|
|
3018 |
const taskFilters = document.getElementById('taskFilters');
|
3019 |
taskFilters.innerHTML = '';
|
3020 |
|
|
|
|
|
|
|
|
|
|
|
3021 |
data.tasks.forEach(task => {
|
3022 |
const checkboxContainer = document.createElement('div');
|
3023 |
checkboxContainer.className = 'task-checkbox';
|
@@ -3132,6 +3192,16 @@ def create_timeline_template():
|
|
3132 |
return taskColors[taskKey] || "#6b7280"; // Default gray for unmapped tasks
|
3133 |
}
|
3134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3135 |
async function loadModalities() {
|
3136 |
try {
|
3137 |
const response = await fetch('/api/modalities');
|
@@ -3238,6 +3308,7 @@ def create_timeline_template():
|
|
3238 |
setTimeout(() => {
|
3239 |
label.style.top = '';
|
3240 |
label.style.bottom = '';
|
|
|
3241 |
label.parentElement.style.zIndex = '';
|
3242 |
}, 50);
|
3243 |
}, 50);
|
|
|
638 |
}
|
639 |
|
640 |
.header h1 {
|
641 |
+
font-size: 1.6rem;
|
642 |
font-weight: 700;
|
643 |
color: #2d3748;
|
644 |
margin-bottom: 0.1rem;
|
|
|
647 |
|
648 |
.header p {
|
649 |
color: #666;
|
650 |
+
font-size: 0.85rem;
|
651 |
margin: 0;
|
652 |
transition: color 0.3s ease;
|
653 |
}
|
|
|
814 |
.input-group label {
|
815 |
font-weight: 500;
|
816 |
color: #4a5568;
|
817 |
+
font-size: 0.75rem;
|
818 |
transition: color 0.3s ease;
|
819 |
}
|
820 |
|
|
|
824 |
}
|
825 |
|
826 |
.input-group input {
|
827 |
+
padding: 0.35rem 0.65rem;
|
828 |
border: 1px solid #e2e8f0;
|
829 |
border-radius: 5px;
|
830 |
+
font-size: 0.75rem;
|
831 |
transition: all 0.2s ease;
|
832 |
background: white;
|
833 |
}
|
|
|
898 |
}
|
899 |
|
900 |
.btn-small {
|
901 |
+
padding: 0.45rem 0.65rem;
|
902 |
+
font-size: 0.7rem;
|
903 |
margin-top: 0;
|
904 |
+
height: 34px;
|
905 |
display: flex;
|
906 |
align-items: center;
|
907 |
justify-content: center;
|
|
|
910 |
.modality-checkbox {
|
911 |
display: flex;
|
912 |
align-items: center;
|
913 |
+
gap: 0.35rem;
|
914 |
+
padding: 0.35rem 0.55rem;
|
915 |
background: rgba(255, 255, 255, 0.9);
|
916 |
border: 1px solid rgba(0, 0, 0, 0.1);
|
917 |
border-radius: 8px;
|
918 |
cursor: pointer;
|
919 |
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
920 |
+
font-size: 0.7rem;
|
921 |
font-weight: 500;
|
922 |
position: relative;
|
923 |
overflow: hidden;
|
|
|
967 |
|
968 |
.modality-checkbox input[type="checkbox"] {
|
969 |
appearance: none;
|
970 |
+
width: 17px;
|
971 |
+
height: 17px;
|
972 |
border: 2px solid var(--modality-color, #8B5CF6);
|
973 |
border-radius: 4px;
|
974 |
position: relative;
|
|
|
1025 |
.task-checkbox {
|
1026 |
display: flex;
|
1027 |
align-items: center;
|
1028 |
+
gap: 0.35rem;
|
1029 |
+
padding: 0.35rem 0.55rem;
|
1030 |
background: rgba(255, 255, 255, 0.9);
|
1031 |
border: 1px solid rgba(0, 0, 0, 0.1);
|
1032 |
border-radius: 8px;
|
1033 |
cursor: pointer;
|
1034 |
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
1035 |
+
font-size: 0.7rem;
|
1036 |
font-weight: 500;
|
1037 |
position: relative;
|
1038 |
overflow: hidden;
|
|
|
1082 |
|
1083 |
.task-checkbox input[type="checkbox"] {
|
1084 |
appearance: none;
|
1085 |
+
width: 17px;
|
1086 |
+
height: 17px;
|
1087 |
border: 2px solid var(--task-color, #6366f1);
|
1088 |
border-radius: 4px;
|
1089 |
background: white;
|
|
|
1301 |
top: 15px;
|
1302 |
right: 15px;
|
1303 |
display: flex;
|
1304 |
+
gap: 6px;
|
1305 |
z-index: 20;
|
1306 |
}
|
1307 |
|
1308 |
.zoom-btn {
|
1309 |
+
width: 28px;
|
1310 |
+
height: 28px;
|
1311 |
background: rgba(255, 255, 255, 0.9);
|
1312 |
+
border-radius: 6px;
|
1313 |
display: flex;
|
1314 |
align-items: center;
|
1315 |
justify-content: center;
|
1316 |
cursor: pointer;
|
1317 |
+
font-size: 0.9rem;
|
1318 |
font-weight: 600;
|
1319 |
color: #d97706;
|
1320 |
border: 2px solid rgba(217, 119, 6, 0.2);
|
|
|
1351 |
.zoom-indicator {
|
1352 |
background: rgba(255, 255, 255, 0.95);
|
1353 |
border-radius: 6px;
|
1354 |
+
padding: 2px 6px;
|
1355 |
+
font-size: 0.7rem;
|
1356 |
color: #d97706;
|
1357 |
font-weight: 500;
|
1358 |
border: 1px solid rgba(217, 119, 6, 0.2);
|
1359 |
transition: all 0.3s ease;
|
1360 |
+
display: flex;
|
1361 |
+
align-items: center;
|
1362 |
+
justify-content: center;
|
1363 |
+
min-width: 40px;
|
1364 |
+
height: 28px;
|
1365 |
}
|
1366 |
|
1367 |
/* Dark mode zoom indicator */
|
|
|
1495 |
}
|
1496 |
|
1497 |
.timeline-dot {
|
1498 |
+
width: 19px;
|
1499 |
+
height: 19px;
|
1500 |
border-radius: 50%;
|
1501 |
background: white;
|
1502 |
border: 3px solid;
|
|
|
1516 |
|
1517 |
.timeline-label {
|
1518 |
position: absolute;
|
1519 |
+
min-width: 110px;
|
1520 |
+
max-width: 170px;
|
1521 |
+
padding: 0.5rem 0.7rem;
|
1522 |
background: white;
|
1523 |
border-radius: 6px;
|
1524 |
+
font-size: 0.85rem;
|
1525 |
font-weight: 500;
|
1526 |
text-align: center;
|
1527 |
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.12);
|
|
|
1560 |
|
1561 |
/* Expanded card styles */
|
1562 |
.timeline-label.expanded {
|
1563 |
+
max-width: 550px !important;
|
1564 |
+
min-width: 450px !important;
|
1565 |
+
width: 550px !important;
|
1566 |
min-height: 250px !important;
|
1567 |
text-align: left;
|
1568 |
z-index: 9999 !important; /* Much higher than all other elements */
|
|
|
1589 |
|
1590 |
.timeline-label .model-title {
|
1591 |
font-weight: 600;
|
1592 |
+
font-size: 0.95rem;
|
1593 |
margin-bottom: 0.5rem;
|
1594 |
color: #1f2937;
|
1595 |
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
|
|
1607 |
}
|
1608 |
|
1609 |
.timeline-label .model-description {
|
1610 |
+
font-size: 0.8rem;
|
1611 |
line-height: 1.4;
|
1612 |
color: #4b5563;
|
|
|
1613 |
max-height: 0;
|
1614 |
overflow: hidden;
|
1615 |
transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1), color 0.3s ease;
|
|
|
1622 |
}
|
1623 |
|
1624 |
.timeline-label.expanded .model-description {
|
1625 |
+
max-height: 175px !important;
|
1626 |
+
height: 175px !important;
|
1627 |
position: relative;
|
1628 |
overflow: hidden; /* Hide overflow for blur effect */
|
1629 |
}
|
|
|
1635 |
}
|
1636 |
|
1637 |
.timeline-label.expanded .description-content {
|
1638 |
+
position: relative;
|
1639 |
+
bottom: 2px;
|
1640 |
+
max-height: 175px !important;
|
1641 |
+
height: 175px !important;
|
1642 |
overflow-y: auto;
|
1643 |
padding-right: 8px; /* Space for scrollbar */
|
1644 |
}
|
1645 |
|
1646 |
.timeline-label .description-fade {
|
1647 |
+
position: sticky;
|
1648 |
+
bottom: 0px; /* Position at the very bottom of the container */
|
1649 |
left: 0;
|
1650 |
+
height: 15px;
|
|
|
1651 |
background: linear-gradient(to bottom,
|
1652 |
rgba(255, 255, 255, 0) 0%,
|
1653 |
rgba(255, 255, 255, 0.9) 50%,
|
1654 |
+
rgba(255, 255, 255, 1) 95%);
|
1655 |
rgba(255, 255, 255, 1) 100%);
|
1656 |
opacity: 0;
|
1657 |
transition: opacity 0.3s ease;
|
|
|
1664 |
background: linear-gradient(to bottom,
|
1665 |
rgba(55, 65, 81, 0) 0%,
|
1666 |
rgba(55, 65, 81, 0.9) 50%,
|
1667 |
+
rgba(55, 65, 81, 1) 95%);
|
1668 |
rgba(55, 65, 81, 1) 100%);
|
1669 |
}
|
1670 |
|
|
|
1689 |
color: #f9fafb;
|
1690 |
}
|
1691 |
|
1692 |
+
.timeline-label .model-description h1 { font-size: 0.9rem; }
|
1693 |
+
.timeline-label .model-description h2 { font-size: 0.85rem; }
|
1694 |
+
.timeline-label .model-description h3 { font-size: 0.8rem; }
|
1695 |
|
1696 |
.timeline-label .model-description p {
|
1697 |
margin: 0.5em 0;
|
|
|
1702 |
padding: 0.1em 0.3em;
|
1703 |
border-radius: 3px;
|
1704 |
font-family: 'Consolas', 'Monaco', monospace;
|
1705 |
+
font-size: 0.7rem;
|
1706 |
transition: all 0.3s ease;
|
1707 |
}
|
1708 |
|
|
|
1752 |
display: none;
|
1753 |
text-decoration: none;
|
1754 |
color: var(--modality-color, #8B5CF6);
|
1755 |
+
font-size: 0.8rem;
|
1756 |
font-weight: 600;
|
1757 |
padding: 0.3rem 0.6rem;
|
1758 |
border: 1px solid var(--modality-color, #8B5CF6);
|
1759 |
border-radius: 4px;
|
1760 |
background: rgba(255, 255, 255, 0.8);
|
1761 |
transition: all 0.2s ease;
|
1762 |
+
margin-top: 0.2rem;
|
1763 |
text-align: center;
|
1764 |
}
|
1765 |
|
|
|
1814 |
}
|
1815 |
|
1816 |
.tasks-label {
|
1817 |
+
font-size: 0.8rem;
|
1818 |
font-weight: 600;
|
1819 |
color: #4a5568;
|
1820 |
margin-bottom: 0.3rem;
|
|
|
1834 |
|
1835 |
.task-badge {
|
1836 |
display: inline-block;
|
1837 |
+
padding: 0.25rem 0.45rem;
|
1838 |
color: white;
|
1839 |
border-radius: 4px;
|
1840 |
+
font-size: 0.7rem;
|
1841 |
font-weight: 500;
|
1842 |
opacity: 0.9;
|
1843 |
transition: all 0.2s ease;
|
|
|
1911 |
}
|
1912 |
|
1913 |
.timeline-date {
|
1914 |
+
font-size: 0.75rem;
|
1915 |
color: #9ca3af;
|
1916 |
margin-top: 0.3rem;
|
1917 |
font-weight: 500;
|
|
|
1951 |
}
|
1952 |
|
1953 |
.date-input-group label {
|
1954 |
+
font-size: 0.75rem;
|
1955 |
color: #4a5568;
|
1956 |
font-weight: 600;
|
1957 |
white-space: nowrap;
|
|
|
1964 |
}
|
1965 |
|
1966 |
.date-input-group input {
|
1967 |
+
padding: 0.45rem 0.65rem;
|
1968 |
border: 2px solid #e2e8f0;
|
1969 |
border-radius: 8px;
|
1970 |
+
font-size: 0.8rem;
|
1971 |
background: white;
|
1972 |
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
1973 |
+
min-width: 135px;
|
1974 |
text-align: center;
|
1975 |
font-weight: 500;
|
1976 |
color: #374151;
|
|
|
2041 |
|
2042 |
.stat-label {
|
2043 |
color: #666;
|
2044 |
+
font-size: 0.75rem;
|
2045 |
margin-top: 0.15rem;
|
2046 |
transition: color 0.3s ease;
|
2047 |
}
|
|
|
2201 |
let zoomLevel = 1.0; // 1.0 = 100%, 0.5 = 50%, 2.0 = 200%
|
2202 |
const minZoom = 0.3; // Minimum zoom (30%)
|
2203 |
const maxZoom = 3.0; // Maximum zoom (300%)
|
2204 |
+
let taskData = {}; // Store task data for easy lookup
|
2205 |
|
2206 |
// Theme management
|
2207 |
let currentTheme = 'light';
|
|
|
2533 |
setTimeout(() => {
|
2534 |
otherLabel.style.top = '';
|
2535 |
otherLabel.style.bottom = '';
|
2536 |
+
otherLabel.style.left = '';
|
2537 |
+
otherLabel.style.right = '';
|
2538 |
+
otherLabel.style.transform = 'translateX(-50%)';
|
2539 |
otherLabel.parentElement.style.zIndex = '';
|
2540 |
}, 50);
|
2541 |
}, 50);
|
|
|
2559 |
const storedTasks = label.dataset.tasks ? JSON.parse(label.dataset.tasks) : [];
|
2560 |
const formattedDescription = markdownToHtml(label.dataset.description);
|
2561 |
|
|
|
|
|
2562 |
// Format tasks for display with task-specific colors
|
2563 |
const tasksHtml = storedTasks && storedTasks.length > 0 ?
|
2564 |
`<div class="model-tasks">
|
|
|
2566 |
<div class="tasks-list">
|
2567 |
${storedTasks.map(task => {
|
2568 |
const taskColor = getTaskColor(task);
|
2569 |
+
const taskName = getTaskDisplayName(task);
|
2570 |
+
return `<span class="task-badge" style="background-color: ${taskColor}">${taskName}</span>`;
|
2571 |
}).join('')}
|
2572 |
</div>
|
2573 |
</div>` :
|
|
|
2583 |
<div class="description-fade"></div>
|
2584 |
</div>
|
2585 |
<a href="${label.dataset.learnMoreUrl}"
|
2586 |
+
target="_blank"
|
2587 |
+
class="learn-more"
|
2588 |
+
onclick="event.stopPropagation()">
|
2589 |
Learn More →
|
2590 |
</a>
|
2591 |
`;
|
|
|
2596 |
// Ensure this timeline item is on top
|
2597 |
item.style.zIndex = '10000';
|
2598 |
|
2599 |
+
// Calculate timeline container bounds
|
2600 |
+
const timelineContainer = document.querySelector('.timeline-container');
|
2601 |
+
const containerBounds = timelineContainer.getBoundingClientRect();
|
2602 |
+
const timelineItemRect = item.getBoundingClientRect();
|
2603 |
+
|
2604 |
+
// Get expanded card dimensions (it's now rendered with expanded content)
|
2605 |
+
const expandedRect = label.getBoundingClientRect();
|
2606 |
+
const cardWidth = 550; // Known width from CSS
|
2607 |
+
const cardHalfWidth = cardWidth / 2;
|
2608 |
+
|
2609 |
+
// Calculate timeline item's center position relative to container
|
2610 |
+
const itemCenterX = timelineItemRect.left + (timelineItemRect.width / 2) - containerBounds.left;
|
2611 |
+
|
2612 |
+
// Calculate default centered position bounds
|
2613 |
+
const defaultLeft = itemCenterX - cardHalfWidth;
|
2614 |
+
const defaultRight = itemCenterX + cardHalfWidth;
|
2615 |
+
|
2616 |
+
// Container padding to ensure cards don't touch edges
|
2617 |
+
const padding = 20;
|
2618 |
+
const containerWidth = containerBounds.width;
|
2619 |
+
|
2620 |
+
// Determine optimal positioning
|
2621 |
+
let finalTransform = 'translateX(-50%)'; // Default centered
|
2622 |
+
let finalLeft = '';
|
2623 |
+
let finalRight = '';
|
2624 |
+
|
2625 |
+
if (defaultLeft < padding) {
|
2626 |
+
// Card would extend beyond left edge - align to left with padding
|
2627 |
+
finalTransform = 'translateX(-5%)';
|
2628 |
+
finalLeft = '';
|
2629 |
+
} else if (defaultRight > (containerWidth - padding)) {
|
2630 |
+
// Card would extend beyond right edge - align to right with padding
|
2631 |
+
finalTransform = 'translateX(-95%)';
|
2632 |
+
finalRight = '';
|
2633 |
+
}
|
2634 |
+
|
2635 |
+
// Apply positioning adjustments
|
2636 |
+
label.style.transform = finalTransform;
|
2637 |
+
// if (finalLeft) label.style.left = finalLeft;
|
2638 |
+
// if (finalRight) label.style.right = finalRight;
|
2639 |
+
|
2640 |
+
// Set vertical positioning to keep the correct edge fixed
|
2641 |
if (isAboveAxis) {
|
2642 |
// Keep top edge fixed - set top position
|
2643 |
label.style.bottom = 'auto';
|
|
|
2663 |
setTimeout(() => {
|
2664 |
label.style.top = '';
|
2665 |
label.style.bottom = '';
|
2666 |
+
label.style.left = '';
|
2667 |
+
label.style.right = '';
|
2668 |
+
// Reset transform: depends on current position
|
2669 |
+
label.style.transform = 'translateX(-50%)';
|
2670 |
+
item.style.zIndex = '';
|
2671 |
+
}, 50);
|
2672 |
+
}, 50);
|
2673 |
}
|
2674 |
});
|
2675 |
|
|
|
3073 |
const taskFilters = document.getElementById('taskFilters');
|
3074 |
taskFilters.innerHTML = '';
|
3075 |
|
3076 |
+
// Store task data for easy lookup
|
3077 |
+
data.tasks.forEach(task => {
|
3078 |
+
taskData[task.key] = { name: task.name, color: task.color };
|
3079 |
+
});
|
3080 |
+
|
3081 |
data.tasks.forEach(task => {
|
3082 |
const checkboxContainer = document.createElement('div');
|
3083 |
checkboxContainer.className = 'task-checkbox';
|
|
|
3192 |
return taskColors[taskKey] || "#6b7280"; // Default gray for unmapped tasks
|
3193 |
}
|
3194 |
|
3195 |
+
// Function to get task display name from loaded task data
|
3196 |
+
function getTaskDisplayName(taskKey) {
|
3197 |
+
// Use stored task data if available
|
3198 |
+
if (taskData[taskKey]) {
|
3199 |
+
return taskData[taskKey].name;
|
3200 |
+
}
|
3201 |
+
// Fallback to formatted key if not found
|
3202 |
+
return taskKey.replace(/-/g, ' ').replace(/\b\\w/g, l => l.toUpperCase());
|
3203 |
+
}
|
3204 |
+
|
3205 |
async function loadModalities() {
|
3206 |
try {
|
3207 |
const response = await fetch('/api/modalities');
|
|
|
3308 |
setTimeout(() => {
|
3309 |
label.style.top = '';
|
3310 |
label.style.bottom = '';
|
3311 |
+
label.style.transform = 'translateX(-50%)';
|
3312 |
label.parentElement.style.zIndex = '';
|
3313 |
}, 50);
|
3314 |
}, 50);
|