spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1@import 'tailwindcss';23/*4 CancerIndex design language (CLAUDE.md UI rules): scientific / editorial / institutional / dense.5 Off-white paper, deep charcoal ink, muted neutrals, ONE restrained accent (deep teal) for links and6 active states, thin rules, tabular numerals. No gradients, no card grids, no decorative colour.7 Colour is never the sole carrier of meaning: every badge also carries text.8*/910@theme {11 --font-sans: var(--font-ui), ui-sans-serif, system-ui, sans-serif;12 --font-serif: var(--font-display), 'Iowan Old Style', Georgia, serif;13 --font-mono: var(--font-code), ui-monospace, 'SF Mono', Menlo, monospace;1415 --color-paper: #fafaf7;16 --color-paper-2: #f3f3ee;17 --color-paper-3: #ebebe4;18 --color-ink: #1c1c1a;19 --color-ink-2: #4a4a46;20 --color-ink-3: #7b7b75;21 --color-ink-4: #a8a8a1;22 --color-rule: #dcdcd4;23 --color-rule-strong: #b8b8ae;24 --color-accent: #0f5f63;25 --color-accent-2: #0b4a4d;26 --color-accent-soft: #e2eeee;27 --color-warn: #8a4b0a;28 --color-warn-soft: #f6ead8;29 --color-danger: #8b1e2d;30 --color-danger-soft: #f4e1e4;31 --color-ok: #2d5f2e;32 --color-ok-soft: #e1ecdf;3334 --color-series-1: #0f5f63;35 --color-series-2: #8a4b0a;36 --color-series-3: #4a4a46;37 --color-series-4: #2d5f2e;38 --color-series-5: #8b1e2d;39 --color-series-6: #7b7b75;40 --color-series-7: #5b3a8c;41 --color-series-8: #1f5fa8;4243 --radius-sm: 2px;44 --radius-md: 3px;45}4647/*48 Dark mode (SPEC §86). Same tokens, inverted values; charts and badges reference the tokens only.49 `--color-white` is re-pointed so Tailwind's `bg-white` form controls follow the theme.50 Applied when the user chose "dark" (data-theme) or follows the OS preference (no explicit choice).51*/52:root[data-theme='dark'],53:root:not([data-theme='light']):not([data-theme='dark']).ci-system-dark {54 color-scheme: dark;55 --color-paper: #151514;56 --color-paper-2: #1d1d1b;57 --color-paper-3: #282826;58 --color-ink: #ecece6;59 --color-ink-2: #c3c3bb;60 --color-ink-3: #8f8f88;61 --color-ink-4: #626259;62 --color-rule: #2f2f2c;63 --color-rule-strong: #47473f;64 --color-accent: #6cc3c6;65 --color-accent-2: #8fd3d5;66 --color-accent-soft: #16353a;67 --color-warn: #e0a860;68 --color-warn-soft: #3a2a13;69 --color-danger: #ee8a95;70 --color-danger-soft: #3f1c22;71 --color-ok: #93c692;72 --color-ok-soft: #1d301d;73 --color-white: #1d1d1b;74 --color-series-1: #6cc3c6;75 --color-series-2: #e0a860;76 --color-series-3: #b9b9b1;77 --color-series-4: #93c692;78 --color-series-5: #ee8a95;79 --color-series-6: #8f8f88;80 --color-series-7: #b39ddb;81 --color-series-8: #7fb2ea;82}83@media (prefers-color-scheme: dark) {84 :root:not([data-theme='light']) {85 color-scheme: dark;86 --color-paper: #151514;87 --color-paper-2: #1d1d1b;88 --color-paper-3: #282826;89 --color-ink: #ecece6;90 --color-ink-2: #c3c3bb;91 --color-ink-3: #8f8f88;92 --color-ink-4: #626259;93 --color-rule: #2f2f2c;94 --color-rule-strong: #47473f;95 --color-accent: #6cc3c6;96 --color-accent-2: #8fd3d5;97 --color-accent-soft: #16353a;98 --color-warn: #e0a860;99 --color-warn-soft: #3a2a13;100 --color-danger: #ee8a95;101 --color-danger-soft: #3f1c22;102 --color-ok: #93c692;103 --color-ok-soft: #1d301d;104 --color-white: #1d1d1b;105 --color-series-1: #6cc3c6;106 --color-series-2: #e0a860;107 --color-series-3: #b9b9b1;108 --color-series-4: #93c692;109 --color-series-5: #ee8a95;110 --color-series-6: #8f8f88;111 --color-series-7: #b39ddb;112 --color-series-8: #7fb2ea;113 }114}115116:root {117 color-scheme: light;118 --ci-header-h: 56px;119}120121html {122 background: var(--color-paper);123 color: var(--color-ink);124 font-family: var(--font-sans);125 font-size: 15px;126 line-height: 1.5;127 -webkit-text-size-adjust: 100%;128 scroll-padding-top: calc(var(--ci-header-h) + 56px);129}130131body {132 font-variant-numeric: tabular-nums;133 font-feature-settings: 'tnum' 1, 'cv11' 1;134 text-rendering: optimizeLegibility;135}136137h1,138h2,139h3,140.font-display {141 font-family: var(--font-serif);142 font-weight: 500;143 letter-spacing: -0.005em;144 text-wrap: balance;145}146147a {148 text-underline-offset: 2px;149}150151:focus-visible {152 outline: 2px solid var(--color-accent);153 outline-offset: 2px;154}155156::selection {157 background: var(--color-accent-soft);158}159160/*161 Grid children default to min-width:auto, so a wide SVG, a long identifier or a mono formula162 would stretch a column past the viewport on mobile. Let columns shrink; inner tables scroll163 inside .ci-table-wrap and long strings wrap through overflow-wrap.164*/165.grid > * {166 min-width: 0;167}168code,169kbd,170.ci-mono {171 overflow-wrap: anywhere;172}173174/* --- Utility classes shared by components (kept minimal; Tailwind does the rest) --- */175176.ci-link {177 color: var(--color-accent);178 text-decoration: underline;179 text-decoration-color: color-mix(in oklab, var(--color-accent) 35%, transparent);180}181.ci-link:hover {182 text-decoration-color: var(--color-accent);183}184185.ci-rule {186 border-top: 1px solid var(--color-rule);187}188189.ci-kicker {190 font-family: var(--font-sans);191 font-size: 11px;192 font-weight: 600;193 letter-spacing: 0.08em;194 text-transform: uppercase;195 color: var(--color-ink-3);196}197198.ci-mono {199 font-family: var(--font-mono);200 font-size: 0.86em;201 letter-spacing: 0;202}203204.ci-num {205 font-variant-numeric: tabular-nums;206 text-align: right;207 white-space: nowrap;208}209210/* Dense data table */211.ci-table-wrap {212 overflow-x: auto;213 -webkit-overflow-scrolling: touch;214 border-top: 1px solid var(--color-rule-strong);215 border-bottom: 1px solid var(--color-rule);216}217.ci-table {218 width: 100%;219 min-width: 100%;220 border-collapse: separate;221 border-spacing: 0;222 font-size: 13.5px;223}224.ci-table thead th {225 position: sticky;226 top: 0;227 z-index: 1;228 background: var(--color-paper);229 border-bottom: 1px solid var(--color-rule-strong);230 padding: 8px 10px;231 text-align: left;232 font-family: var(--font-sans);233 font-size: 11px;234 font-weight: 600;235 letter-spacing: 0.06em;236 text-transform: uppercase;237 color: var(--color-ink-3);238 white-space: nowrap;239}240.ci-table thead th.num,241.ci-table td.num {242 text-align: right;243}244.ci-table tbody td {245 padding: 7px 10px;246 border-bottom: 1px solid var(--color-rule);247 vertical-align: top;248}249.ci-table tbody tr:hover td {250 background: var(--color-paper-2);251}252.ci-table th.sticky-col,253.ci-table td.sticky-col {254 position: sticky;255 left: 0;256 background: var(--color-paper);257 z-index: 2;258}259260/* Sticky in-page tabs */261.ci-tabs {262 position: sticky;263 top: var(--ci-header-h);264 z-index: 20;265 background: color-mix(in oklab, var(--color-paper) 94%, transparent);266 backdrop-filter: saturate(120%) blur(6px);267 border-bottom: 1px solid var(--color-rule);268 overflow-x: auto;269 scrollbar-width: none;270}271.ci-tabs::-webkit-scrollbar {272 display: none;273}274.ci-tab {275 display: inline-block;276 padding: 10px 2px;277 margin-right: 18px;278 font-size: 13.5px;279 color: var(--color-ink-2);280 border-bottom: 2px solid transparent;281 white-space: nowrap;282}283.ci-tab:hover {284 color: var(--color-ink);285}286.ci-tab[aria-current='page'] {287 color: var(--color-accent);288 border-bottom-color: var(--color-accent);289 font-weight: 500;290}291292/* Popover used for provenance (CSS-only, hover + focus) */293.ci-pop {294 position: relative;295 display: inline-block;296}297.ci-pop > .ci-pop-panel {298 display: none;299 position: absolute;300 z-index: 40;301 left: 0;302 top: calc(100% + 4px);303 min-width: 260px;304 max-width: 360px;305 background: var(--color-paper);306 border: 1px solid var(--color-rule-strong);307 box-shadow: 0 6px 24px -10px rgba(0, 0, 0, 0.35);308 padding: 10px 12px;309 font-size: 12.5px;310 line-height: 1.45;311 text-align: left;312 white-space: normal;313 font-weight: 400;314 text-transform: none;315 letter-spacing: 0;316 color: var(--color-ink);317}318.ci-pop:hover > .ci-pop-panel,319.ci-pop:focus-within > .ci-pop-panel {320 display: block;321}322@media (max-width: 640px) {323 .ci-pop > .ci-pop-panel {324 position: fixed;325 left: 12px;326 right: 12px;327 top: auto;328 bottom: 12px;329 max-width: none;330 }331}332333/* Completeness dots */334.ci-dots {335 display: inline-flex;336 gap: 3px;337 vertical-align: middle;338}339.ci-dot {340 width: 7px;341 height: 7px;342 border-radius: 50%;343 border: 1px solid var(--color-ink-4);344 background: transparent;345}346.ci-dot.on {347 background: var(--color-accent);348 border-color: var(--color-accent);349}350351details > summary {352 cursor: pointer;353 list-style: none;354}355details > summary::-webkit-details-marker {356 display: none;357}358359.ci-prose p + p {360 margin-top: 0.75em;361}362.ci-prose h2 {363 font-size: 1.35rem;364 margin-top: 2rem;365 margin-bottom: 0.5rem;366}367.ci-prose h3 {368 font-size: 1.1rem;369 margin-top: 1.4rem;370 margin-bottom: 0.35rem;371}372.ci-prose ul {373 list-style: disc;374 padding-left: 1.25rem;375 margin: 0.5rem 0;376}377.ci-prose li + li {378 margin-top: 0.25rem;379}380.ci-prose code {381 font-family: var(--font-mono);382 font-size: 0.85em;383 background: var(--color-paper-3);384 padding: 0 4px;385}386387pre.ci-code {388 font-family: var(--font-mono);389 font-size: 12.5px;390 line-height: 1.5;391 background: var(--color-paper-2);392 border: 1px solid var(--color-rule);393 padding: 10px 12px;394 overflow-x: auto;395 white-space: pre;396}397398@media print {399 .no-print {400 display: none !important;401 }402}403404/* ------------------------------------------------------------------------------------------------405 Hardening pass (pagination, table weight, accessibility). Appended; nothing above is rewritten.406 ------------------------------------------------------------------------------------------------ */407408/* Badges: one short class per tone instead of a long utility string repeated on every table row409 (every className ships twice — HTML + RSC payload). Text always accompanies the colour. */410.ci-badge {411 display: inline-flex;412 align-items: center;413 gap: 4px;414 border: 1px solid transparent;415 border-radius: var(--radius-sm);416 padding: 1px 6px;417 font-size: 11px;418 font-weight: 500;419 line-height: 16px;420 letter-spacing: 0.02em;421}422.ci-badge--neutral {423 background: var(--color-paper-3);424 color: var(--color-ink-2);425}426.ci-badge--accent {427 background: var(--color-accent-soft);428 color: var(--color-accent-2);429}430.ci-badge--warn {431 background: var(--color-warn-soft);432 color: var(--color-warn);433}434.ci-badge--danger {435 background: var(--color-danger-soft);436 color: var(--color-danger);437}438.ci-badge--ok {439 background: var(--color-ok-soft);440 color: var(--color-ok);441}442.ci-badge--outline {443 background: transparent;444 color: var(--color-ink-2);445 border-color: var(--color-rule-strong);446}447448/* Source badge link (compact rows and popover trigger share one class) */449.ci-src {450 font-family: var(--font-mono);451 display: inline-flex;452 align-items: center;453 border: 1px solid var(--color-rule-strong);454 border-radius: var(--radius-sm);455 background: var(--color-paper);456 padding: 0 4px;457 font-size: 10.5px;458 line-height: 16px;459 color: var(--color-ink-2);460 text-decoration: none;461 white-space: nowrap;462}463.ci-src:hover,464.ci-src:focus-visible {465 border-color: var(--color-accent);466 color: var(--color-accent);467}468469/* Pager */470.ci-pager-link {471 display: inline-block;472 min-width: 28px;473 border: 1px solid var(--color-rule);474 padding: 4px 8px;475 text-align: center;476 color: var(--color-ink-2);477 text-decoration: none;478 line-height: 1.2;479}480.ci-pager-link:hover {481 border-color: var(--color-accent);482 color: var(--color-accent);483}484.ci-pager-link.is-current {485 border-color: var(--color-accent);486 background: var(--color-accent-soft);487 color: var(--color-accent-2);488 font-weight: 500;489}490.ci-pager-link.is-disabled {491 color: var(--color-ink-4);492 cursor: default;493}494495/* Filter chips (status / phase / cohort / jurisdiction selectors) */496.ci-chip {497 display: inline-block;498 border: 1px solid var(--color-rule);499 padding: 2px 8px;500 color: var(--color-ink-2);501 text-decoration: none;502 line-height: 1.35;503}504.ci-chip:hover {505 border-color: var(--color-accent);506}507.ci-chip[aria-current='page'],508.ci-chip.is-selected {509 border-color: var(--color-accent);510 background: var(--color-accent-soft);511 color: var(--color-accent-2);512}513514/* Focus visibility: links inside dense tables, tabs, chips and pager get a visible ring even when515 the surrounding element clips overflow (outline-offset 0 keeps the ring inside table cells). */516.ci-tab:focus-visible,517.ci-chip:focus-visible,518.ci-pager-link:focus-visible,519.ci-src:focus-visible,520.ci-table a:focus-visible,521.ci-table summary:focus-visible {522 outline: 2px solid var(--color-accent);523 outline-offset: 0;524 border-radius: 2px;525}526.ci-tabs a:focus-visible {527 outline-offset: -2px;528}529details > summary:focus-visible {530 outline: 2px solid var(--color-accent);531 outline-offset: 2px;532}533534/* Table captions live above the table (visible text, not sr-only) — the caption is the place where535 the ONE provenance popover per table sits. */536.ci-table caption {537 caption-side: top;538 text-align: left;539 padding: 0 0 6px;540 font-size: 12px;541 color: var(--color-ink-3);542}543.ci-table thead th[aria-sort] {544 cursor: default;545}546547/* Skeletons (loading.tsx) — never look like data */548.ci-skeleton {549 background: linear-gradient(90deg, var(--color-paper-3) 0%, var(--color-paper-2) 50%, var(--color-paper-3) 100%);550 background-size: 200% 100%;551 border-radius: 2px;552 animation: ci-shimmer 1.4s ease-in-out infinite;553}554@keyframes ci-shimmer {555 from {556 background-position: 200% 0;557 }558 to {559 background-position: -200% 0;560 }561}562@media (prefers-reduced-motion: reduce) {563 .ci-skeleton {564 animation: none;565 }566}567568/* Keep the sticky provenance popover reachable by keyboard users: the panel becomes visible while569 any element inside is focused (focus-within already covers the trigger). */570.ci-pop:focus-within > .ci-pop-panel {571 display: block;572}573574/* Row-group header inside a single dense table (one <tbody> per variant / cancer group) */575.ci-table tr.ci-group th {576 position: static;577 background: var(--color-paper-2);578 border-top: 1px solid var(--color-rule-strong);579 border-bottom: 1px solid var(--color-rule);580 padding: 7px 10px;581 text-align: left;582 font-family: var(--font-sans);583 font-size: 13.5px;584 font-weight: 500;585 letter-spacing: 0;586 text-transform: none;587 color: var(--color-ink);588 white-space: normal;589 overflow-wrap: anywhere;590}591.ci-table tbody:first-of-type tr.ci-group th {592 border-top: 0;593}594.ci-evidence td.w-t {595 min-width: 160px;596}597abbr.no-underline {598 text-decoration: none;599}600601/* Compact list rows (e.g. variants on a gene page): link left, meta right */602.ci-rows {603 margin: 0;604 padding: 0;605 list-style: none;606 font-size: 13.5px;607}608.ci-rows > li {609 display: flex;610 align-items: baseline;611 justify-content: space-between;612 gap: 8px;613 border-bottom: 1px solid var(--color-rule);614 padding: 4px 0;615}616.ci-rows > li > span {617 font-size: 11.5px;618 color: var(--color-ink-3);619 text-align: right;620}621622/* Publication list */623.ci-pubs {624 margin: 0;625 padding: 0;626 list-style: none;627}628.ci-pub {629 padding: 10px 0;630 border-bottom: 1px solid var(--color-rule);631 font-size: 13.5px;632}633.ci-pub > div {634 display: flex;635 flex-wrap: wrap;636 align-items: baseline;637 column-gap: 8px;638}639.ci-pub > p {640 margin-top: 2px;641 font-size: 12.5px;642 color: var(--color-ink-3);643}644645/* Evidence table: link, level and details styles are scoped here instead of per-cell classes646 (50 rows × ~8 classes × 2 copies per page). */647.ci-evidence a {648 color: var(--color-accent);649 text-decoration: underline;650 text-decoration-color: color-mix(in oklab, var(--color-accent) 35%, transparent);651}652.ci-evidence a:hover {653 text-decoration-color: var(--color-accent);654}655.ci-evidence tr.ci-group a.ci-mono {656 color: var(--color-ink-3);657 text-decoration: none;658}659.ci-evidence tr.ci-group a.ci-mono:hover {660 color: var(--color-accent);661}662.ci-evidence abbr {663 font-family: var(--font-mono);664 font-size: 0.86em;665 font-weight: 500;666 text-decoration: none;667}668.ci-evidence td.ev {669 max-width: 360px;670 font-size: 12.5px;671 color: var(--color-ink-2);672}673.ci-evidence td.ev summary {674 color: var(--color-accent);675 text-decoration: underline;676 text-decoration-color: color-mix(in oklab, var(--color-accent) 35%, transparent);677}678.ci-evidence td.ev details p {679 margin-top: 4px;680}681682/* Theme toggle (header) */683.ci-theme-toggle {684 display: inline-flex;685 align-items: center;686 gap: 4px;687 border: 1px solid var(--color-rule);688 padding: 5px 7px;689 color: var(--color-ink-2);690 background: transparent;691 cursor: pointer;692 line-height: 1;693}694.ci-theme-toggle:hover {695 border-color: var(--color-accent);696 color: var(--color-accent);697}698