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);
|