/* Keep the app font + background; let Bootstrap do the rest */ :root { --sidebar-width: 420px; /* --sidebar-width: 28vw; */ /* If the sidebar ever feels too dominant, you can later refine: */ /* --sidebar-width: clamp(380px, 22vw, 520px); */ } /* Let the app actually fill the viewport */ html, body { height: 100%; } body { margin: 0; font-family: "Roboto", system-ui, -apple-system, Segoe UI, Arial, sans-serif; background: #f4f6f8; /* Optional but recommended: prevent the page itself from scrolling */ overflow: hidden; } /* Your top-level bootstrap container becomes the app frame */ .app-frame { height: 100dvh; /* or 100vh if you prefer */ box-sizing: border-box; /* IMPORTANT: includes py-3 padding inside height */ display: flex; flex-direction: column; gap: 12px; } /* Utility */ .hidden { display: none !important; } /* --- Main visualization layout should consume remaining height --- */ .visualization-area { flex: 1; /* ✅ THIS makes
fill the screen */ display: flex; gap: 1rem; min-height: 0; /* ✅ allow children to shrink + scroll */ } /* Graph Wrapper & Cytoscape container */ .graph-wrapper { flex: 1; position: relative; min-height: 0; border-radius: 0.5rem; overflow: hidden; background: #fff; border: 1px solid #dee2e6; } /* Cytoscape canvas fills wrapper */ .graph-container { position: absolute; inset: 0; } /* Details panel */ .details-panel { font-size: 1.10rem; /* slightly larger base */ width: var(--sidebar-width); min-width: var(--sidebar-width); display: flex; flex-direction: column; min-height: 0; background: #fff; border: 1px solid #dee2e6; border-radius: 0.5rem; overflow: hidden; } .details-panel .small { font-size: 1.25rem; /* don't make metadata tiny */ } .details-panel .badge { font-size: 1.0rem; } /* .details-panel h3 { font-size: 1.3rem; margin: 0; padding: 0.75rem 1rem; border-bottom: 1px solid #dee2e6; } */ .details-panel .text-muted { color: #495057 !important; /* darker than default muted */ } .details-header { padding: 0.75rem 1rem; border-bottom: 1px solid #dee2e6; } .details-header h3 { font-size: 1.3rem; margin: 0; padding: 0; border-bottom: 0; } .details-content { line-height: 1.6; padding: 1rem; overflow-y: auto; flex: 1; min-height: 0; } .placeholder-text { color: #6c757d; font-style: italic; text-align: center; margin-top: 2rem; } /* Make tab-content fill graph-wrapper */ #view-tabs-content { height: 100%; min-height: 0; } /* Compact tabs for space-constrained layouts */ .nav-tabs .nav-link { padding: 0.35rem 0.65rem; /* default is ~0.5rem 1rem */ font-size: 0.9rem; } /* ------------------------------------------------------------ Oversight layout: keep everything bounded inside #oversight-view ------------------------------------------------------------ */ /* The section must also be a flex column and shrinkable */ #oversight-section { flex: 1 1 auto; min-height: 0; /* CRITICAL */ display: flex; flex-direction: column; overflow: hidden; /* prevent section content from escaping */ max-height: 90%; } /* Oversight table readability */ #oversight-section .table td, #oversight-section .table th { padding-top: 0.85rem; padding-bottom: 0.85rem; } #oversight-section .quality-cell { /* font-size: 1.02rem; */ /* line-height: 1.35; */ } /* Bigger checkbox */ .oversight-checkbox { transform: scale(1.25); transform-origin: center; } /* The Oversight tab-pane must be a flex column that can shrink */ #oversight-view { display: flex; flex-direction: column; min-height: 0; /* CRITICAL */ overflow: hidden; /* keep scrolling inside inner container */ } /* The split container should fill the remaining section height */ .oversight-split-container { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; } /* The top area owns the vertical space; bottom is hidden for now */ .oversight-top { flex: 1 1 auto; min-height: 0; overflow: hidden; } /* This is the ONLY scrolling viewport */ #oversight-inner-tabs-content { flex: 1 1 auto; min-height: 0; overflow: auto; /* give the pager some breathing room so it never looks clipped */ padding-bottom: 1rem; } /* Optional: ensure each pane doesn’t fight heights */ #oversight-inner-tabs-content .tab-pane { height: auto !important; } /* Triplets panel: header stays fixed, only table scrolls */ #oversight-bottom { max-height: 60vh; /* keep whatever height you liked */ overflow: hidden; /* prevent the whole panel from scrolling */ display: flex; flex-direction: column; } /* The table area becomes the scroll container */ #triplets-table-wrap { flex: 1; /* take remaining space under header/toolbars */ min-height: 0; /* CRITICAL in flex layouts for scrolling */ overflow-y: auto; overflow-x: auto; /* keep horizontal scroll if needed */ } /* Optional: sticky table header while scrolling */ #triplets-table-wrap thead th { position: sticky; top: 0; background: #fff; z-index: 2; } .relation-card:hover { background: rgba(13, 110, 253, 0.05); /* bootstrap primary-ish tint */ border-color: rgba(13, 110, 253, 0.35); } .relation-card:focus { outline: 2px solid rgba(13, 110, 253, 0.35); outline-offset: 2px; } /* Tiny emoji confetti */ .confetti-box { position: fixed; inset: 0; pointer-events: none; z-index: 4000; /* above toast */ } .confetti-particle { position: absolute; font-size: 18px; animation-name: confetti-fly; animation-timing-function: ease-out; animation-fill-mode: forwards; filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.15)); } @keyframes confetti-fly { from { transform: translate(0, 0) rotate(0deg); opacity: 1; } to { transform: translate(var(--dx), var(--dy)) rotate(var(--rot)); opacity: 0; } }