Spaces:
Running
Running
| /* ============================================================ | |
| HydroPD design system: instrument, product discipline. | |
| Hanken Grotesk (display + UI/body) · Spline Sans Mono (data/codes/numerals). | |
| Self-hosted WOFF2, Latin subset, light theme only. See DESIGN.md. | |
| ============================================================ */ | |
| /* ---------- fonts (self-hosted, offline-safe) ---------- */ | |
| @font-face { | |
| font-family: 'Hanken Grotesk'; | |
| font-style: normal; font-weight: 400; font-display: swap; | |
| src: url('./assets/fonts/hanken-400.woff2') format('woff2'); | |
| } | |
| @font-face { | |
| font-family: 'Hanken Grotesk'; | |
| font-style: normal; font-weight: 600; font-display: swap; | |
| src: url('./assets/fonts/hanken-600.woff2') format('woff2'); | |
| } | |
| @font-face { | |
| font-family: 'Hanken Grotesk'; | |
| font-style: normal; font-weight: 800; font-display: swap; | |
| src: url('./assets/fonts/hanken-800.woff2') format('woff2'); | |
| } | |
| @font-face { | |
| font-family: 'Spline Sans Mono'; | |
| font-style: normal; font-weight: 400; font-display: swap; | |
| src: url('./assets/fonts/spline-mono-400.woff2') format('woff2'); | |
| } | |
| @font-face { | |
| font-family: 'Spline Sans Mono'; | |
| font-style: normal; font-weight: 600; font-display: swap; | |
| src: url('./assets/fonts/spline-mono-600.woff2') format('woff2'); | |
| } | |
| :root { | |
| /* ---- brand: deepened teal (committed identity, preserved) ---- */ | |
| --accent: oklch(0.55 0.09 182); /* borders, focus ring, selection, non-text accent */ | |
| --accent-strong: oklch(0.47 0.088 185); /* accent TEXT (links) + primary button bg (white passes AA) */ | |
| --accent-hover: oklch(0.40 0.08 186); /* primary button hover/active */ | |
| --accent-soft: oklch(0.95 0.03 185); /* selected rows, accent badges */ | |
| --accent-tint: oklch(0.975 0.016 185); /* 4-8% surface wash */ | |
| /* ---- secondary / info (data-viz + info states only, never decoration) ---- */ | |
| --blue: oklch(0.52 0.12 245); | |
| --blue-soft: oklch(0.94 0.035 245); | |
| /* ---- neutrals, tinted toward the brand hue (~205) ---- */ | |
| --bg: oklch(0.984 0.004 205); /* canvas */ | |
| --surface: oklch(0.997 0.0015 205); /* cards (lighter than canvas) */ | |
| --surface-2: oklch(0.963 0.005 205); /* nav, toolbars, table heads, insets */ | |
| --border: oklch(0.905 0.006 210); | |
| --border-strong: oklch(0.85 0.009 210); | |
| /* ---- ink ---- */ | |
| --text: oklch(0.28 0.02 225); | |
| --text-muted: oklch(0.49 0.018 225); /* AA body (>=4.5:1 on surface) */ | |
| --text-faint: oklch(0.60 0.014 225); /* captions / large only (>=3:1) */ | |
| /* ---- semantic (consistent meaning; AA on their -soft fills) ---- */ | |
| --good: oklch(0.50 0.11 155); | |
| --good-soft: oklch(0.94 0.04 158); | |
| --warn: oklch(0.50 0.10 60); | |
| --warn-soft: oklch(0.93 0.055 72); | |
| --bad: oklch(0.52 0.17 25); | |
| --bad-soft: oklch(0.93 0.05 25); | |
| /* ---- radii (over-rounding is a tell) ---- */ | |
| --radius-sm: 4px; | |
| --radius: 6px; | |
| --radius-lg: 8px; | |
| /* ---- shadow (used sparingly: navbar + floating elements) ---- */ | |
| --shadow: 0 1px 2px oklch(0.28 0.02 225 / 0.05), 0 6px 16px oklch(0.28 0.02 225 / 0.06); | |
| --shadow-sm: 0 1px 2px oklch(0.28 0.02 225 / 0.06); | |
| /* ---- spacing scale ---- */ | |
| --space-1: 4px; | |
| --space-2: 8px; | |
| --space-3: 12px; | |
| --space-4: 16px; | |
| --space-5: 24px; | |
| --space-6: 32px; | |
| --space-7: 48px; | |
| --space-8: 64px; | |
| /* ---- type scale (fixed rem, ratio ~1.2) ---- */ | |
| --text-xs: 0.75rem; | |
| --text-sm: 0.875rem; | |
| --text-base: 1rem; | |
| --text-md: 1.125rem; | |
| --text-lg: 1.375rem; | |
| --text-xl: 1.75rem; | |
| --text-2xl: 2.25rem; | |
| --text-display: clamp(2.1rem, 1.55rem + 2.2vw, 2.75rem); /* single hero display only */ | |
| /* ---- families (grotesque display + UI, distinctive mono for data) ---- */ | |
| --font-display: 'Hanken Grotesk', -apple-system, BlinkMacSystemFont, system-ui, sans-serif; | |
| --font: 'Hanken Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; | |
| --mono: 'Spline Sans Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| } | |
| html, | |
| body, | |
| #root { | |
| margin: 0; | |
| padding: 0; | |
| min-height: 100%; | |
| } | |
| body { | |
| font-family: var(--font); | |
| font-size: var(--text-base); | |
| background: var(--bg); | |
| color: var(--text); | |
| line-height: 1.55; | |
| font-kerning: normal; | |
| text-rendering: optimizeLegibility; | |
| -webkit-font-smoothing: antialiased; | |
| -moz-osx-font-smoothing: grayscale; | |
| } | |
| a { | |
| color: var(--accent-strong); | |
| text-decoration: none; | |
| } | |
| a:hover { | |
| text-decoration: underline; | |
| } | |
| /* Grotesque display carries page and section headings; mono is reserved for data. */ | |
| h1, | |
| h2, | |
| h3 { | |
| font-family: var(--font-display); | |
| color: var(--text); | |
| font-weight: 800; | |
| line-height: 1.12; | |
| letter-spacing: -0.022em; | |
| text-wrap: balance; | |
| margin: 0 0 0.4em; | |
| } | |
| h4 { | |
| font-family: var(--font); | |
| color: var(--text); | |
| font-weight: 600; | |
| line-height: 1.3; | |
| margin: 0 0 0.4em; | |
| } | |
| h1 { | |
| font-size: var(--text-2xl); | |
| } | |
| h2 { | |
| font-size: var(--text-xl); | |
| } | |
| h3 { | |
| font-size: var(--text-lg); | |
| } | |
| h4 { | |
| font-size: var(--text-base); | |
| } | |
| p { | |
| margin: 0 0 1rem; | |
| text-wrap: pretty; | |
| } | |
| code, | |
| .mono { | |
| font-family: var(--mono); | |
| font-size: 0.85em; | |
| font-variant-numeric: tabular-nums; | |
| } | |
| /* Reduced-motion: honor globally; individual components add crossfade fallbacks. */ | |
| @media (prefers-reduced-motion: reduce) { | |
| *, | |
| *::before, | |
| *::after { | |
| animation-duration: 0.001ms ; | |
| animation-iteration-count: 1 ; | |
| transition-duration: 0.001ms ; | |
| scroll-behavior: auto ; | |
| } | |
| } | |
| /* ---------- layout ---------- */ | |
| .app-shell { | |
| display: flex; | |
| flex-direction: column; | |
| min-height: 100vh; | |
| } | |
| .navbar { | |
| position: sticky; | |
| top: 0; | |
| z-index: 20; | |
| background: var(--surface); | |
| border-bottom: 1px solid var(--border); | |
| box-shadow: var(--shadow-sm); | |
| } | |
| .navbar-inner { | |
| max-width: 1180px; | |
| margin: 0 auto; | |
| padding: 0 24px; | |
| height: 62px; | |
| display: flex; | |
| align-items: center; | |
| gap: 28px; | |
| } | |
| .brand { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| text-decoration: none; | |
| color: var(--text); | |
| } | |
| .brand:hover { | |
| text-decoration: none; | |
| } | |
| .brand-mark { | |
| width: 30px; | |
| height: 30px; | |
| border-radius: var(--radius-sm); | |
| background: var(--accent-strong); | |
| display: grid; | |
| place-items: center; | |
| color: var(--surface); | |
| font-family: var(--font-display); | |
| font-weight: 600; | |
| font-size: 0.98rem; | |
| letter-spacing: 0; | |
| } | |
| .brand-name { | |
| font-family: var(--font-display); | |
| font-weight: 600; | |
| font-size: 1.2rem; | |
| letter-spacing: -0.01em; | |
| } | |
| .brand-tag { | |
| font-size: var(--text-xs); | |
| color: var(--text-muted); | |
| font-weight: 400; | |
| } | |
| .nav-links { | |
| display: flex; | |
| align-items: center; | |
| gap: 4px; | |
| margin-left: auto; | |
| flex-wrap: wrap; | |
| } | |
| .nav-link { | |
| padding: 7px 12px; | |
| border-radius: var(--radius-sm); | |
| color: var(--text-muted); | |
| font-size: var(--text-sm); | |
| font-weight: 500; | |
| transition: color 0.15s ease, background 0.15s ease; | |
| } | |
| .nav-link:hover { | |
| background: var(--surface-2); | |
| color: var(--text); | |
| text-decoration: none; | |
| } | |
| .nav-link.active { | |
| color: var(--accent-strong); | |
| background: var(--accent-soft); | |
| } | |
| .page { | |
| flex: 1; | |
| max-width: 1180px; | |
| width: 100%; | |
| margin: 0 auto; | |
| padding: var(--space-7) var(--space-6) var(--space-8); | |
| } | |
| .page-header { | |
| margin-bottom: var(--space-6); | |
| padding-bottom: var(--space-5); | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .page-header h1 { | |
| font-size: var(--text-2xl); | |
| margin-bottom: var(--space-3); | |
| } | |
| .page-header p.lead { | |
| color: var(--text-muted); | |
| font-size: var(--text-md); | |
| max-width: 68ch; | |
| margin: 0; | |
| } | |
| /* The in-card labeled hairline-rule section device lives in `.type-detail-head`. */ | |
| .rule { | |
| height: 1px; | |
| background: var(--border); | |
| border: 0; | |
| margin: var(--space-5) 0; | |
| } | |
| .grid-2 { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 20px; | |
| } | |
| @media (max-width: 860px) { | |
| .grid-2 { | |
| grid-template-columns: 1fr; | |
| } | |
| .nav-links { | |
| gap: 0; | |
| } | |
| } | |
| .footer { | |
| border-top: 1px solid var(--border); | |
| background: var(--surface-2); | |
| color: var(--text-muted); | |
| font-size: var(--text-sm); | |
| } | |
| .footer-inner { | |
| max-width: 1180px; | |
| margin: 0 auto; | |
| padding: var(--space-5) var(--space-6); | |
| display: flex; | |
| justify-content: space-between; | |
| gap: var(--space-3); | |
| flex-wrap: wrap; | |
| } | |
| /* ---------- card ---------- */ | |
| /* Editorial flat: hairline border carries the surface, no drop shadow | |
| (the hairline-border-plus-diffuse-shadow combo is an AI signature). */ | |
| .card { | |
| background: var(--surface); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| padding: var(--space-5); | |
| } | |
| .card + .card { | |
| margin-top: var(--space-5); | |
| } | |
| .card-title { | |
| display: flex; | |
| align-items: center; | |
| gap: var(--space-2); | |
| margin-bottom: var(--space-1); | |
| } | |
| .card-title h3 { | |
| margin: 0; | |
| } | |
| .card-subtitle { | |
| color: var(--text-muted); | |
| font-size: var(--text-sm); | |
| margin: 0 0 var(--space-4); | |
| } | |
| /* ---------- buttons ---------- */ | |
| .btn { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 7px; | |
| font-family: var(--font); | |
| font-size: var(--text-sm); | |
| font-weight: 600; | |
| padding: 9px 16px; | |
| border-radius: var(--radius-sm); | |
| border: 1px solid transparent; | |
| cursor: pointer; | |
| transition: background 0.15s ease, border-color 0.15s ease, opacity 0.15s ease; | |
| white-space: nowrap; | |
| } | |
| .btn:focus-visible { | |
| outline: none; | |
| box-shadow: 0 0 0 3px var(--accent-soft); | |
| } | |
| .btn:disabled { | |
| opacity: 0.5; | |
| cursor: not-allowed; | |
| } | |
| .btn-primary { | |
| background: var(--accent-strong); | |
| color: var(--surface); | |
| } | |
| .btn-primary:hover:not(:disabled) { | |
| background: var(--accent-hover); | |
| } | |
| .btn-secondary { | |
| background: var(--surface); | |
| color: var(--text); | |
| border-color: var(--border-strong); | |
| } | |
| .btn-secondary:hover:not(:disabled) { | |
| background: var(--surface-2); | |
| border-color: var(--text-faint); | |
| } | |
| .btn-ghost { | |
| background: transparent; | |
| color: var(--accent-strong); | |
| padding: 6px 10px; | |
| } | |
| .btn-ghost:hover:not(:disabled) { | |
| background: var(--accent-soft); | |
| } | |
| .btn-sm { | |
| padding: 6px 11px; | |
| font-size: var(--text-xs); | |
| } | |
| /* ---------- forms ---------- */ | |
| .field { | |
| margin-bottom: 16px; | |
| } | |
| .field:last-child { | |
| margin-bottom: 0; | |
| } | |
| .field-label { | |
| display: block; | |
| font-weight: 600; | |
| font-size: var(--text-sm); | |
| margin-bottom: 6px; | |
| } | |
| .field-hint { | |
| color: var(--text-muted); | |
| font-size: var(--text-xs); | |
| font-weight: 400; | |
| margin-left: 6px; | |
| } | |
| input[type='text'], | |
| input[type='number'], | |
| select, | |
| textarea { | |
| width: 100%; | |
| font-family: var(--font); | |
| font-size: var(--text-sm); | |
| color: var(--text); | |
| background: var(--surface); | |
| border: 1px solid var(--border-strong); | |
| border-radius: var(--radius-sm); | |
| padding: 9px 11px; | |
| transition: border-color 0.15s ease, box-shadow 0.15s ease; | |
| } | |
| textarea { | |
| resize: vertical; | |
| min-height: 120px; | |
| font-family: var(--mono); | |
| font-size: var(--text-sm); | |
| line-height: 1.5; | |
| } | |
| input:focus-visible, | |
| select:focus-visible, | |
| textarea:focus-visible, | |
| input:focus, | |
| select:focus, | |
| textarea:focus { | |
| outline: none; | |
| border-color: var(--accent); | |
| box-shadow: 0 0 0 3px var(--accent-soft); | |
| } | |
| /* ---------- badges → squared editorial tags ---------- */ | |
| .badge { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 5px; | |
| font-size: var(--text-xs); | |
| font-weight: 600; | |
| padding: 2px 8px; | |
| border-radius: var(--radius-sm); | |
| background: var(--surface-2); | |
| color: var(--text-muted); | |
| border: 1px solid var(--border); | |
| } | |
| .badge-accent { | |
| background: var(--accent-soft); | |
| color: var(--accent-strong); | |
| border-color: transparent; | |
| } | |
| .badge-blue { | |
| background: var(--blue-soft); | |
| color: var(--blue); | |
| border-color: transparent; | |
| } | |
| .badge-good { | |
| background: var(--good-soft); | |
| color: var(--good); | |
| border-color: transparent; | |
| } | |
| .badge-muted { | |
| background: var(--bg); | |
| color: var(--text-faint); | |
| } | |
| .badge-warn { | |
| background: var(--warn-soft); | |
| color: var(--warn); | |
| border-color: transparent; | |
| } | |
| /* ---------- condition matcher (detectability ranking) ---------- */ | |
| .cond-selects { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); | |
| gap: 10px; | |
| margin-bottom: 12px; | |
| } | |
| .cond-select { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 4px; | |
| font-size: 0.76rem; | |
| font-weight: 600; | |
| color: var(--text-muted); | |
| } | |
| .cond-select select { | |
| font: inherit; | |
| font-weight: 500; | |
| padding: 7px 8px; | |
| border-radius: var(--radius); | |
| border: 1px solid var(--border); | |
| background: var(--surface); | |
| color: var(--text); | |
| } | |
| .cond-ranked { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 6px; | |
| padding: 10px; | |
| margin-bottom: 12px; | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| background: var(--bg); | |
| } | |
| .cond-rank-row { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| width: 100%; | |
| text-align: left; | |
| padding: 8px 10px; | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| background: var(--surface); | |
| cursor: pointer; | |
| } | |
| .cond-rank-row:hover { | |
| border-color: var(--border-strong); | |
| } | |
| .cond-rank-row.selected { | |
| border-color: var(--accent-strong); | |
| box-shadow: inset 0 0 0 1px var(--accent-strong); | |
| } | |
| .cond-rank-pos { | |
| font-weight: 700; | |
| color: var(--accent-strong); | |
| min-width: 1.6em; | |
| text-align: center; | |
| } | |
| .cond-rank-body { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 3px; | |
| flex: 1; | |
| } | |
| .cond-rank-title { | |
| font-size: 0.86rem; | |
| } | |
| .cond-rank-tags { | |
| display: flex; | |
| gap: 6px; | |
| align-items: center; | |
| flex-wrap: wrap; | |
| } | |
| .cond-rank-tags .tag { | |
| font-size: 0.7rem; | |
| font-weight: 600; | |
| padding: 1px 7px; | |
| border-radius: var(--radius-sm); | |
| background: var(--surface-2); | |
| color: var(--text-faint); | |
| border: 1px solid var(--border); | |
| } | |
| .cond-rank-tags .tag.tag-on { | |
| background: var(--good-soft); | |
| color: var(--good); | |
| border-color: transparent; | |
| } | |
| /* ---------- bioactivity screening: activity filter + DB links ---------- */ | |
| .filter-block { | |
| margin-top: 14px; | |
| padding: 12px 14px; | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| background: var(--bg); | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| } | |
| .filter-head { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: 10px; | |
| } | |
| .filter-actions { | |
| display: flex; | |
| gap: 4px; | |
| } | |
| .filter-axis { | |
| display: flex; | |
| align-items: baseline; | |
| gap: 10px; | |
| flex-wrap: wrap; | |
| } | |
| .filter-axis-label { | |
| font-size: 0.72rem; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| letter-spacing: 0.04em; | |
| color: var(--text-faint); | |
| min-width: 84px; | |
| } | |
| .filter-chip { | |
| font: inherit; | |
| font-size: var(--text-xs); | |
| font-weight: 500; | |
| padding: 4px 11px; | |
| border-radius: var(--radius-sm); | |
| border: 1px solid var(--border-strong); | |
| background: var(--surface); | |
| color: var(--text-muted); | |
| cursor: pointer; | |
| transition: background 0.12s, color 0.12s, border-color 0.12s; | |
| } | |
| .filter-chip:hover { | |
| border-color: var(--accent-strong); | |
| } | |
| .filter-chip.on { | |
| background: var(--accent-soft); | |
| color: var(--accent-strong); | |
| border-color: transparent; | |
| font-weight: 600; | |
| } | |
| .db-links a { | |
| color: var(--accent-strong); | |
| text-decoration: none; | |
| border-bottom: 1px solid var(--accent-soft); | |
| white-space: nowrap; | |
| } | |
| .db-links a:hover { | |
| border-bottom-color: var(--accent-strong); | |
| } | |
| .selected-model { | |
| margin-top: 14px; | |
| padding: 8px 12px; | |
| border-radius: var(--radius); | |
| background: var(--accent-soft); | |
| color: var(--accent-strong); | |
| font-size: 0.82rem; | |
| font-weight: 500; | |
| } | |
| /* ---------- species accordion (model picker) ---------- */ | |
| .species-accordion { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 6px; | |
| } | |
| .species-group { | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| overflow: hidden; | |
| background: var(--surface); | |
| } | |
| .species-group.open { | |
| border-color: var(--border-strong); | |
| } | |
| .species-head { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| width: 100%; | |
| padding: 9px 12px; | |
| background: var(--bg); | |
| border: 0; | |
| font: inherit; | |
| cursor: pointer; | |
| text-align: left; | |
| } | |
| .species-head:hover { | |
| background: var(--surface-2, var(--bg)); | |
| } | |
| .species-caret { | |
| color: var(--text-faint); | |
| font-size: 0.8rem; | |
| flex: none; | |
| } | |
| .species-name { | |
| font-weight: 600; | |
| text-transform: capitalize; | |
| } | |
| .species-count { | |
| color: var(--text-faint); | |
| font-size: 0.78rem; | |
| } | |
| .species-sel { | |
| margin-left: auto; | |
| } | |
| .species-body { | |
| padding: 8px; | |
| } | |
| /* In-card sub-section header: the labeled hairline-rule signature device. */ | |
| .type-detail-head { | |
| display: flex; | |
| align-items: center; | |
| gap: var(--space-4); | |
| font-size: var(--text-xs); | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| letter-spacing: 0.06em; | |
| color: var(--text-muted); | |
| margin: var(--space-4) 0 var(--space-3); | |
| } | |
| .type-detail-head::after { | |
| content: ''; | |
| flex: 1; | |
| height: 1px; | |
| background: var(--border); | |
| } | |
| /* ---------- legend ---------- */ | |
| .legend { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 6px 16px; | |
| font-size: 0.78rem; | |
| color: var(--text-muted); | |
| } | |
| .legend-item { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .legend-swatch { | |
| width: 11px; | |
| height: 11px; | |
| border-radius: 3px; | |
| display: inline-block; | |
| } | |
| /* ---------- inline bar charts ---------- */ | |
| .bar-row { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| padding: 3px 0; | |
| font-size: 0.82rem; | |
| } | |
| .bar-label { | |
| flex: none; | |
| color: var(--text-muted); | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .bar-track { | |
| position: relative; | |
| flex: 1; | |
| height: 15px; | |
| background: var(--bg); | |
| border: 1px solid var(--border); | |
| border-radius: 4px; | |
| overflow: hidden; | |
| min-width: 60px; | |
| } | |
| .bar-fill { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| height: 100%; | |
| border-radius: 4px 0 0 4px; | |
| } | |
| /* range whisker: vertical caps via inset shadow (not side borders). */ | |
| .bar-whisker { | |
| position: absolute; | |
| top: 50%; | |
| transform: translateY(-50%); | |
| height: 9px; | |
| box-shadow: inset 2px 0 0 var(--text), inset -2px 0 0 var(--text); | |
| opacity: 0.45; | |
| } | |
| .bar-value { | |
| flex: none; | |
| width: auto; | |
| min-width: 48px; | |
| text-align: right; | |
| font-variant-numeric: tabular-nums; | |
| font-weight: 600; | |
| color: var(--text); | |
| } | |
| .bar-note { | |
| color: var(--text-faint); | |
| font-weight: 400; | |
| font-size: 0.74rem; | |
| } | |
| /* ---------- tables ---------- */ | |
| .table-wrap { | |
| overflow-x: auto; | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| } | |
| table.table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| font-size: var(--text-sm); | |
| } | |
| .table thead th { | |
| background: var(--surface-2); | |
| text-align: left; | |
| font-weight: 600; | |
| font-size: var(--text-xs); | |
| text-transform: uppercase; | |
| letter-spacing: 0.03em; | |
| color: var(--text-muted); | |
| padding: 10px 14px; | |
| border-bottom: 1px solid var(--border-strong); | |
| white-space: nowrap; | |
| position: sticky; | |
| top: 0; | |
| } | |
| .table thead th.sortable { | |
| cursor: pointer; | |
| user-select: none; | |
| } | |
| .table thead th.sortable:hover { | |
| color: var(--text); | |
| } | |
| .table tbody td { | |
| padding: 9px 14px; | |
| border-bottom: 1px solid var(--border); | |
| vertical-align: middle; | |
| } | |
| .table tbody tr:last-child td { | |
| border-bottom: none; | |
| } | |
| .table tbody tr:hover { | |
| background: var(--surface-2); | |
| } | |
| .table td.mono, | |
| .table td .mono { | |
| font-family: var(--mono); | |
| font-size: 0.8rem; | |
| font-variant-numeric: tabular-nums; | |
| } | |
| .table .num { | |
| text-align: right; | |
| font-variant-numeric: tabular-nums; | |
| } | |
| .row-clickable { | |
| cursor: pointer; | |
| } | |
| .row-clickable:hover { | |
| background: var(--accent-soft) ; | |
| } | |
| /* ---------- misc ---------- */ | |
| .toolbar { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: 12px; | |
| margin-bottom: 14px; | |
| flex-wrap: wrap; | |
| } | |
| .stat-row { | |
| display: flex; | |
| gap: 14px; | |
| flex-wrap: wrap; | |
| margin-bottom: 16px; | |
| } | |
| /* Figure-style stat block: a mono tabular number over a rule and a caption. */ | |
| .stat { | |
| flex: 1; | |
| min-width: 130px; | |
| background: var(--surface); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-sm); | |
| padding: var(--space-4); | |
| } | |
| .stat-value { | |
| font-family: var(--mono); | |
| font-size: 1.55rem; | |
| font-weight: 500; | |
| letter-spacing: -0.01em; | |
| line-height: 1.1; | |
| color: var(--text); | |
| font-variant-numeric: tabular-nums; | |
| } | |
| .stat-label { | |
| font-size: var(--text-xs); | |
| text-transform: uppercase; | |
| letter-spacing: 0.05em; | |
| color: var(--text-muted); | |
| margin-top: var(--space-2); | |
| padding-top: var(--space-2); | |
| border-top: 1px solid var(--border); | |
| } | |
| .muted { | |
| color: var(--text-muted); | |
| } | |
| .empty-state { | |
| text-align: center; | |
| color: var(--text-muted); | |
| padding: 40px 20px; | |
| border: 1px dashed var(--border-strong); | |
| border-radius: var(--radius); | |
| background: var(--bg); | |
| } | |
| /* checkbox / radio lists */ | |
| .option-list { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 8px; | |
| } | |
| .option-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); | |
| gap: 8px; | |
| } | |
| .option { | |
| display: flex; | |
| align-items: flex-start; | |
| gap: 9px; | |
| padding: 10px 12px; | |
| border: 1px solid var(--border-strong); | |
| border-radius: var(--radius-sm); | |
| cursor: pointer; | |
| transition: border-color 0.12s, background 0.12s; | |
| } | |
| .option:hover { | |
| border-color: var(--accent); | |
| } | |
| .option.selected { | |
| border-color: var(--accent); | |
| background: var(--accent-soft); | |
| } | |
| .option input { | |
| width: auto; | |
| margin-top: 3px; | |
| } | |
| .option-body { | |
| flex: 1; | |
| } | |
| .option-title { | |
| font-weight: 600; | |
| font-size: 0.88rem; | |
| } | |
| .option-desc { | |
| font-size: 0.76rem; | |
| color: var(--text-muted); | |
| } | |
| /* Compact single-line option (enzyme multi-select): center the checkbox with the label. */ | |
| .option-compact { | |
| align-items: center; | |
| padding: 8px 10px; | |
| } | |
| .option-compact input { | |
| margin-top: 0; | |
| } | |
| /* tabs */ | |
| .tabs { | |
| display: flex; | |
| gap: 4px; | |
| border-bottom: 1px solid var(--border); | |
| margin-bottom: 20px; | |
| } | |
| .tab { | |
| padding: 10px 16px; | |
| font-weight: 600; | |
| font-size: 0.92rem; | |
| color: var(--text-muted); | |
| border: none; | |
| background: none; | |
| cursor: pointer; | |
| border-bottom: 2px solid transparent; | |
| margin-bottom: -1px; | |
| } | |
| .tab:hover { | |
| color: var(--text); | |
| } | |
| .tab.active { | |
| color: var(--accent-strong); | |
| border-bottom-color: var(--accent); | |
| } | |
| /* dropzone */ | |
| .dropzone { | |
| border: 2px dashed var(--border-strong); | |
| border-radius: var(--radius); | |
| background: var(--bg); | |
| padding: 22px; | |
| text-align: center; | |
| cursor: pointer; | |
| transition: border-color 0.12s, background 0.12s; | |
| } | |
| .dropzone:hover { | |
| border-color: var(--accent); | |
| } | |
| .dropzone.dragging { | |
| border-color: var(--accent); | |
| background: var(--accent-soft); | |
| } | |
| .dropzone-icon { | |
| font-size: 1.5rem; | |
| } | |
| .dropzone-main { | |
| font-weight: 600; | |
| font-size: 0.9rem; | |
| margin-top: 4px; | |
| } | |
| .dropzone-sub { | |
| font-size: 0.78rem; | |
| color: var(--text-muted); | |
| } | |
| /* detail panel */ | |
| .detail-panel { | |
| background: var(--surface-2); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-sm); | |
| padding: 16px 18px; | |
| margin-top: -1px; | |
| } | |
| .detail-grid { | |
| display: grid; | |
| grid-template-columns: 150px 1fr; | |
| gap: 8px 16px; | |
| font-size: 0.85rem; | |
| } | |
| .detail-grid dt { | |
| color: var(--text-muted); | |
| font-weight: 600; | |
| } | |
| .detail-grid dd { | |
| margin: 0; | |
| } | |
| .chip-list { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 5px; | |
| } | |
| /* home hero (instrument) + tool index */ | |
| .hero { | |
| padding: var(--space-7) 0 var(--space-7); | |
| margin-bottom: var(--space-6); | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .hero-eyebrow { | |
| font-family: var(--mono); | |
| font-size: var(--text-xs); | |
| font-weight: 600; | |
| letter-spacing: 0.06em; | |
| text-transform: uppercase; | |
| color: var(--accent-strong); | |
| margin-bottom: var(--space-3); | |
| } | |
| .hero h1 { | |
| font-size: var(--text-display); | |
| line-height: 1.04; | |
| margin-bottom: var(--space-4); | |
| } | |
| .hero h1 .nowrap { | |
| white-space: nowrap; | |
| } | |
| /* On very narrow screens let the long first line wrap instead of overflowing. */ | |
| @media (max-width: 520px) { | |
| .hero h1 .nowrap { | |
| white-space: normal; | |
| } | |
| } | |
| .hero p.lead { | |
| color: var(--text-muted); | |
| max-width: 62ch; | |
| font-size: var(--text-md); | |
| margin: 0; | |
| } | |
| /* mass-spectrum hero visual */ | |
| .spectrum { | |
| width: 100%; | |
| height: 128px; | |
| margin: var(--space-6) 0 var(--space-5); | |
| display: block; | |
| } | |
| /* instrument metric readout */ | |
| .readout { | |
| display: flex; | |
| flex-wrap: wrap; | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| overflow: hidden; | |
| background: var(--surface); | |
| } | |
| .readout-cell { | |
| flex: 1; | |
| min-width: 130px; | |
| padding: var(--space-4) var(--space-4); | |
| border-right: 1px solid var(--border); | |
| } | |
| .readout-cell:last-child { border-right: 0; } | |
| .readout-k { | |
| font-family: var(--mono); | |
| font-size: var(--text-xs); | |
| letter-spacing: 0.05em; | |
| text-transform: uppercase; | |
| color: var(--text-muted); | |
| white-space: nowrap; | |
| } | |
| .readout-v { | |
| font-family: var(--mono); | |
| font-weight: 600; | |
| font-size: 1.4rem; | |
| color: var(--text); | |
| margin-top: var(--space-1); | |
| font-variant-numeric: tabular-nums; | |
| } | |
| .hero-btns { | |
| display: flex; | |
| gap: var(--space-3); | |
| flex-wrap: wrap; | |
| margin-top: var(--space-5); | |
| } | |
| .hero-btns .btn { font-size: var(--text-base); padding: 11px 20px; } | |
| @media (max-width: 640px) { | |
| .readout-cell { border-right: 0; border-bottom: 1px solid var(--border); } | |
| .hero h1 { max-width: none; } | |
| } | |
| /* Editorial index, not an identical icon-card grid. */ | |
| .tool-grid { | |
| display: flex; | |
| flex-direction: column; | |
| border-top: 1px solid var(--border); | |
| } | |
| .tool-card { | |
| display: grid; | |
| grid-template-columns: 1fr auto; | |
| align-items: baseline; | |
| column-gap: var(--space-5); | |
| row-gap: var(--space-2); | |
| padding: var(--space-5) var(--space-4); | |
| border-bottom: 1px solid var(--border); | |
| color: var(--text); | |
| transition: background 0.15s ease; | |
| } | |
| .tool-card:hover { | |
| background: var(--surface-2); | |
| text-decoration: none; | |
| } | |
| .tool-card .tool-go { | |
| transition: transform 0.15s ease; | |
| } | |
| .tool-card:hover .tool-go { | |
| transform: translateX(3px); | |
| } | |
| .tool-card p { | |
| grid-column: 1 / -1; | |
| } | |
| .tool-card h3 { | |
| margin: 0; | |
| font-size: var(--text-lg); | |
| } | |
| .tool-card p { | |
| color: var(--text-muted); | |
| font-size: var(--text-sm); | |
| margin: 0; | |
| max-width: 56ch; | |
| } | |
| .tool-card .tool-go { | |
| color: var(--accent-strong); | |
| font-weight: 600; | |
| font-size: var(--text-sm); | |
| } | |
| /* preview / info banners */ | |
| .preview-banner { | |
| background: var(--warn-soft); | |
| border: 1px solid var(--warn); | |
| color: var(--warn); | |
| border-radius: var(--radius-sm); | |
| padding: 11px 14px; | |
| font-size: var(--text-sm); | |
| margin-bottom: 20px; | |
| } | |
| .info-banner { | |
| background: var(--blue-soft); | |
| border: 1px solid var(--blue); | |
| color: var(--blue); | |
| border-radius: var(--radius-sm); | |
| padding: 11px 14px; | |
| font-size: var(--text-sm); | |
| } | |
| /* segmented toggle (Data tab audience) */ | |
| .segmented { | |
| display: inline-flex; | |
| background: var(--surface-2); | |
| border: 1px solid var(--border-strong); | |
| border-radius: var(--radius); | |
| padding: 3px; | |
| gap: 3px; | |
| } | |
| .segmented button { | |
| border: none; | |
| background: none; | |
| font-family: var(--font); | |
| font-size: var(--text-sm); | |
| font-weight: 600; | |
| color: var(--text-muted); | |
| padding: 7px 16px; | |
| border-radius: var(--radius-sm); | |
| cursor: pointer; | |
| transition: background 0.15s ease, color 0.15s ease; | |
| } | |
| .segmented button.active { | |
| background: var(--accent-strong); | |
| color: var(--surface); | |
| } | |
| /* priority tags for data gaps */ | |
| .prio-high { | |
| background: var(--bad-soft); | |
| color: var(--bad); | |
| border-color: transparent; | |
| } | |
| .prio-medium { | |
| background: var(--warn-soft); | |
| color: var(--warn); | |
| border-color: transparent; | |
| } | |
| .prio-low { | |
| background: var(--surface-2); | |
| color: var(--text-muted); | |
| } | |
| tr.zero-used td { | |
| background: var(--warn-soft); | |
| } | |
| /* download card */ | |
| .dl-card { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: 14px; | |
| padding: var(--space-4); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-sm); | |
| background: var(--surface-2); | |
| margin-bottom: var(--space-3); | |
| } | |
| .dl-card .dl-meta { | |
| font-size: var(--text-sm); | |
| color: var(--text-muted); | |
| } | |
| /* schema tier grid */ | |
| .tier-badge-min { | |
| background: var(--good-soft); | |
| color: var(--good); | |
| border-color: transparent; | |
| } | |
| .tier-badge-ideal { | |
| background: var(--blue-soft); | |
| color: var(--blue); | |
| border-color: transparent; | |
| } | |
| /* ============================================================ | |
| Consistency utilities (Impeccable deep pass) | |
| ============================================================ */ | |
| /* One shared disclosure caret (single glyph, rotates on open). */ | |
| .caret { | |
| display: inline-block; | |
| color: var(--text-faint); | |
| font-size: 0.7em; | |
| line-height: 1; | |
| transition: transform 0.15s ease; | |
| } | |
| .caret.open { | |
| transform: rotate(90deg); | |
| } | |
| /* Data numerals in tables use the mono family (matches the stat tiles). */ | |
| .table tbody td.num { | |
| font-family: var(--mono); | |
| } | |
| /* Keyboard focus is non-optional on every custom control. */ | |
| .tab:focus-visible, | |
| .segmented button:focus-visible, | |
| .filter-chip:focus-visible, | |
| .species-head:focus-visible, | |
| .cond-rank-row:focus-visible, | |
| .tool-card:focus-visible, | |
| .dropzone:focus-visible, | |
| tr.row-clickable:focus-visible { | |
| outline: none; | |
| box-shadow: inset 0 0 0 2px var(--accent); | |
| } | |
| .option:focus-within { | |
| border-color: var(--accent); | |
| box-shadow: 0 0 0 3px var(--accent-soft); | |
| } | |
| /* Captions / footnotes / page notes. */ | |
| .footnote, | |
| .caption { | |
| font-size: var(--text-xs); | |
| color: var(--text-faint); | |
| } | |
| .page-note { | |
| text-align: center; | |
| font-size: var(--text-sm); | |
| color: var(--text-muted); | |
| margin-top: var(--space-6); | |
| } | |
| /* Error affordance (parallels .info-banner / .preview-banner). */ | |
| .error-banner { | |
| background: var(--bad-soft); | |
| border: 1px solid var(--bad); | |
| color: var(--bad); | |
| border-radius: var(--radius-sm); | |
| padding: 11px 14px; | |
| font-size: var(--text-sm); | |
| } | |
| /* Small segmented variant (in-card sort toggles). */ | |
| .segmented-sm { | |
| padding: 2px; | |
| } | |
| .segmented-sm button { | |
| padding: 5px 12px; | |
| font-size: var(--text-xs); | |
| } | |
| /* Disabled form controls (e.g. locked feature set for Pfly). */ | |
| input:disabled, | |
| select:disabled, | |
| textarea:disabled { | |
| opacity: 0.6; | |
| cursor: not-allowed; | |
| background: var(--surface-2); | |
| } | |
| /* ---------- code block (API docs) ---------- */ | |
| /* Monospace snippet on the second neutral surface; a labeled bar carries a copy button. | |
| Wide lines scroll inside the block so the page body never scrolls horizontally. */ | |
| .codeblock { | |
| margin: 0 0 var(--space-3); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| background: var(--surface-2); | |
| overflow: hidden; | |
| } | |
| .codeblock-bar { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: var(--space-3); | |
| padding: 6px 10px 6px 12px; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .codeblock-label { | |
| font-family: var(--font); | |
| font-size: var(--text-xs); | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| letter-spacing: 0.06em; | |
| color: var(--text-faint); | |
| } | |
| .codeblock-copy { | |
| font-family: var(--font); | |
| font-size: var(--text-xs); | |
| font-weight: 600; | |
| color: var(--accent-strong); | |
| background: none; | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-sm); | |
| padding: 3px 10px; | |
| cursor: pointer; | |
| transition: background 160ms ease-out, border-color 160ms ease-out; | |
| } | |
| .codeblock-copy:hover { | |
| background: var(--accent-tint); | |
| border-color: var(--border-strong); | |
| } | |
| .codeblock-copy:focus-visible { | |
| outline: 3px solid var(--accent); | |
| outline-offset: 1px; | |
| } | |
| .codeblock-pre { | |
| margin: 0; | |
| padding: var(--space-4); | |
| overflow-x: auto; | |
| font-family: var(--mono); | |
| font-size: var(--text-sm); | |
| line-height: 1.6; | |
| color: var(--text); | |
| tab-size: 2; | |
| white-space: pre; | |
| } | |
| /* ---------- API endpoint blocks ---------- */ | |
| .api-endpoint-head { | |
| display: flex; | |
| align-items: center; | |
| gap: var(--space-3); | |
| margin-bottom: var(--space-3); | |
| } | |
| .api-method { | |
| font-family: var(--mono); | |
| font-size: var(--text-xs); | |
| font-weight: 500; | |
| letter-spacing: 0.04em; | |
| padding: 2px 8px; | |
| border-radius: var(--radius-sm); | |
| } | |
| .api-method-get { | |
| color: var(--blue); | |
| background: var(--blue-soft); | |
| } | |
| .api-method-post { | |
| color: var(--accent-strong); | |
| background: var(--accent-soft); | |
| } | |
| .api-path { | |
| font-family: var(--mono); | |
| font-size: var(--text-md); | |
| font-weight: 500; | |
| color: var(--text); | |
| } | |
| .api-endpoint-summary { | |
| color: var(--text-muted); | |
| font-size: var(--text-sm); | |
| line-height: 1.55; | |
| max-width: 72ch; | |
| margin: 0 0 var(--space-3); | |
| } | |
| .api-endpoint-note { | |
| color: var(--text-muted); | |
| font-size: var(--text-sm); | |
| line-height: 1.55; | |
| max-width: 72ch; | |
| margin: 0 0 var(--space-3); | |
| padding: 10px 12px; | |
| background: var(--surface-2); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-sm); | |
| } | |
| .api-inline, | |
| .api-endpoint-summary code, | |
| .api-table code { | |
| font-family: var(--mono); | |
| font-size: 0.9em; | |
| color: var(--text); | |
| } | |
| /* ---------- API rate-limit table ---------- */ | |
| .api-table-wrap { | |
| overflow-x: auto; | |
| } | |
| .api-table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| font-size: var(--text-sm); | |
| } | |
| .api-table th { | |
| text-align: left; | |
| font-weight: 600; | |
| color: var(--text-muted); | |
| background: var(--surface-2); | |
| padding: 8px 12px; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .api-table td { | |
| padding: 8px 12px; | |
| border-bottom: 1px solid var(--border); | |
| color: var(--text); | |
| } | |
| .api-table tr:last-child td { | |
| border-bottom: 0; | |
| } | |
| .api-num { | |
| font-family: var(--mono); | |
| color: var(--text-muted); | |
| white-space: nowrap; | |
| } | |