Spaces:
Running
Running
| /* section-umap.css, §6 Embedding space (WebGL scatter, 571K points) | |
| styling: framing canvas, hover tooltip, status overlay, in-place | |
| cluster annotations, and the colour legend strip below. */ | |
| .umap-frame { | |
| position: relative; | |
| width: 100%; | |
| aspect-ratio: 16 / 10; | |
| /* Slight off-white that matches the editorial paper tone (body uses | |
| #f7f5ee). Pure white made the desaturated minority biotypes vanish | |
| into the page and made the saturated palette look harsh. */ | |
| background: #fbfaf6; | |
| border: 1px solid #e5e3da; | |
| overflow: hidden; | |
| } | |
| .umap-canvas { | |
| position: absolute; inset: 0; | |
| width: 100%; height: 100%; | |
| display: block; | |
| cursor: grab; | |
| touch-action: none; | |
| } | |
| .umap-canvas.panning { cursor: grabbing; } | |
| .umap-tooltip { | |
| position: absolute; | |
| pointer-events: none; | |
| background: #1f1f1d; color: #f7f5ee; | |
| font-family: "JetBrains Mono", monospace; | |
| font-size: 10px; line-height: 1.4; | |
| padding: 6px 9px; | |
| border-radius: 2px; | |
| white-space: nowrap; | |
| opacity: 0; | |
| transform: translate(8px, -100%); | |
| transition: opacity 0.12s; | |
| z-index: 4; | |
| } | |
| .umap-tooltip.visible { opacity: 0.96; } | |
| .umap-tooltip .t-label { | |
| color: #8c918b; | |
| text-transform: uppercase; letter-spacing: 1px; | |
| font-size: 8px; | |
| margin-right: 4px; | |
| } | |
| .umap-status-overlay { | |
| position: absolute; inset: 0; | |
| display: flex; align-items: center; justify-content: center; | |
| color: #aaa; | |
| font-family: "JetBrains Mono", monospace; | |
| font-size: 11px; letter-spacing: 1.5px; | |
| text-transform: uppercase; | |
| background: rgba(247, 245, 238, 0.85); | |
| pointer-events: none; | |
| transition: opacity 0.2s; | |
| } | |
| .umap-status-overlay.hidden { opacity: 0; } | |
| /* Cluster-name annotations sit DIRECTLY on top of each cluster's | |
| centroid, no leader lines, no margin anchors, no body text. | |
| Editorial choice: the names *are* the annotation, set in heavier | |
| type with a strong paper-coloured halo so they read clean against | |
| coloured data underneath. Cf. classic Hillis radial trees, Tufte's | |
| "small multiples with labels-in-place". pointer-events:none so the | |
| canvas keeps every hover. */ | |
| .umap-annotations { | |
| position: absolute; inset: 0; | |
| pointer-events: none; | |
| z-index: 3; | |
| } | |
| .ann-label { | |
| position: absolute; | |
| /* Centre on (left, top), JS sets those to the screen-space | |
| coordinates of the cluster centroid. */ | |
| transform: translate(-50%, -50%); | |
| white-space: nowrap; | |
| font-family: "Inter", sans-serif; | |
| font-size: 13px; | |
| font-weight: 700; | |
| letter-spacing: 0.2px; | |
| color: #1f1f1d; | |
| /* Real glyph outline (not a rectangle, not a blurred halo). The | |
| trick is `paint-order: stroke fill`, without it `-webkit-text- | |
| stroke` paints centred on the glyph contour, eating half its | |
| inside and turning bold type into spindly outlined type. With | |
| stroke-then-fill, the cream stroke is painted first as a | |
| silhouette, then the dark fill drops on top at full thickness. | |
| Net visible: a clean ~2.5 px cream halo following each letter | |
| shape exactly. Reads cleanly over any colour underneath | |
| (including the saturated vertebrates blue + AT-rich teal that | |
| killed earlier blur-shadow attempts). */ | |
| -webkit-text-stroke: 5px #fbfaf6; | |
| text-stroke: 5px #fbfaf6; | |
| paint-order: stroke fill; | |
| transition: opacity 0.18s; | |
| } | |
| /* Highlights toolbar: a second row under "color by" listing curated | |
| gene sets a colleague flagged (HOX paralogs, mitochondrial genome…). */ | |
| .umap-highlight-toolbar { | |
| margin-top: -8px; /* tighten gap to the colour-by row above */ | |
| margin-bottom: 12px; | |
| } | |
| /* Per-mode description above the chart. One short paragraph that swaps | |
| to whatever colour-by or highlight is active, replacing what used to | |
| be a static "N sequences · M species" stat-line — the stats moved | |
| into the stat-row below the canvas, so this slot is free to carry | |
| real editorial. */ | |
| .umap-mode-desc { | |
| font-family: "Inter", sans-serif; | |
| font-size: 13px; | |
| line-height: 1.5; | |
| color: #4a4a48; | |
| margin: 0 0 12px; | |
| /* Hold ~4 lines so the canvas doesn't bounce around as the user | |
| switches between a short mode (strand) and a long one (GC content | |
| or mt-DNA). Longer descriptions still grow past this without | |
| clamping, just with a smaller visual jump. */ | |
| min-height: 6em; | |
| } | |
| /* Navigation hint lives inside .stat-row as a right-floated sibling of | |
| the stat-pairs. margin-left:auto absorbs the flex gap so it pins to | |
| the right edge regardless of how many stats sit on the left, and | |
| align-self:flex-end keeps it lined up with the *values* row (the | |
| visually heavier line) rather than centred between label and value. */ | |
| .umap-nav-hint { | |
| margin-left: auto; | |
| align-self: flex-end; | |
| font-family: "JetBrains Mono", monospace; | |
| font-size: 10px; | |
| color: #888; | |
| text-transform: uppercase; | |
| letter-spacing: 1.5px; | |
| } | |
| .umap-legend { | |
| display: flex; flex-wrap: wrap; | |
| gap: 6px 14px; | |
| margin-top: 10px; | |
| font-family: "JetBrains Mono", monospace; | |
| font-size: 10px; | |
| color: #666; | |
| } | |
| .umap-legend .swatch { | |
| display: inline-block; | |
| width: 9px; height: 9px; | |
| margin-right: 5px; | |
| vertical-align: middle; | |
| border-radius: 2px; | |
| } | |
| .umap-legend .item { | |
| display: inline-flex; | |
| align-items: center; | |
| cursor: default; | |
| } | |
| .umap-legend .item.gc-grad { | |
| gap: 8px; | |
| } | |
| .umap-legend .item.gc-grad svg { | |
| border-radius: 2px; | |
| display: block; | |
| } | |
| .umap-legend .item.gc-grad .gc-ticks { | |
| letter-spacing: 0.5px; | |
| color: #888; | |
| } | |