/* Sparse-feature window browser. Sequence, annotations and per-base activations come from data/sae/.json; every colour is a token so dark mode is free. Two registers are kept apart on purpose. Measurements — activations read out of the dictionary — are drawn in dark, saturated hues on the card. Annotations are drawn inside a recessed panel, in pale washes and mid-tone ticks, so a glance can never mistake an annotation for a number the model produced. */ /* ---------------------------------------------------------------- tokens --- */ :root { /* Measurement palette. Twelve hues, one per available lane, so a feature keeps one colour everywhere on the page and no two lanes ever share one. The first six are the default lane set and are the furthest apart in hue *and* lightness, which is what one-pixel bars need; slots 7-12 only appear once a reader adds lanes by hand. */ --feat-1: #14539b; /* blue */ --feat-2: #c9490c; /* orange */ --feat-3: #0b7550; /* green */ --feat-4: #c0187c; /* magenta */ --feat-5: #94711b; /* gold */ --feat-6: #4a5162; /* slate */ --feat-7: #7629bb; /* violet */ --feat-8: #09708c; /* cyan */ --feat-9: #9c1734; /* crimson */ --feat-10: #56701c; /* olive */ --feat-11: #7a4a1e; /* umber */ --feat-12: #5c3a52; /* plum */ --feat-none: #ccd3ca; /* Annotation register: pale region washes, mid-tone site ticks, a muted brown for gene extents. Deliberately lower in chroma and darker only in the ticks, which have to survive being one pixel wide. */ --ann-panel: #fafbf7; --ann-panel-rule: #e2e7dd; --ann-intergenic: #f0f1eb; --ann-cds: #c7dcc2; --ann-utr5: #d6cdec; --ann-utr3: #eecdd7; --ann-intron: #e7dfc6; --ann-ncrna: #c6dee9; --ann-tss: #3f77b8; --ann-tis: #2f8878; --ann-donor: #bb4a42; --ann-acceptor: #8560ad; --ann-stop: #bd7c2a; --ann-tts: #6455a8; --ann-gene: #9c8878; --ann-gene-ink: #6d5348; /* Sequence letters. --base-* is the readout's ink, on the card. A letter in the strip sits on one of the twelve measurement hues, so each base also has a light and a dark variant; the drawing code picks whichever has more contrast against the cell it lands on. Both variants keep the base's hue, so A/C/G/T stay identifiable either way. */ --base-a: #18813f; --base-c: #3b7fe0; --base-g: #b57405; --base-t: #d8433f; --base-n: #9aa4b0; --base-a-lit: #9ce8b4; --base-c-lit: #b4daff; --base-g-lit: #ffd980; --base-t-lit: #ffcbc4; --base-n-lit: #d8ded9; --base-a-dim: #0a5a26; --base-c-dim: #14357e; --base-g-dim: #6b4a00; --base-t-dim: #8a1010; --base-n-dim: #3b4247; /* Figure furniture. */ --fig-grid: #dfe5dc; --fig-axis: #b6c1b4; /* Selected control. --ink and --lime both flip role between themes, so ink-on-lime is a light-theme-only pairing and has to be tokenised. */ --sel-bg: var(--ink); --sel-fg: var(--lime); /* Picker chrome only: the accent shared by the three kinds where the features and the annotation do not simply agree. Not used inside the plot, so it cannot be confused with either register. */ --sel-flag: #b4571f; --sel-quiet: #6f9264; /* Annotation label ink: quiet enough to stay in the paler register, dark enough to read on every region wash. */ --ann-ink: var(--ink-2); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --feat-1: #74aef0; --feat-2: #f79055; --feat-3: #45cba0; --feat-4: #f68ac4; --feat-5: #dcb84a; --feat-6: #a9b0c2; --feat-7: #c193ef; --feat-8: #55c9e6; --feat-9: #f0808f; --feat-10: #b2cd5f; --feat-11: #d3a06b; --feat-12: #c49bbb; --feat-none: #3a423b; --ann-panel: #1a201c; --ann-panel-rule: #2b332c; --ann-intergenic: #202724; --ann-cds: #31462f; --ann-utr5: #3a3150; --ann-utr3: #4a323d; --ann-intron: #423b28; --ann-ncrna: #26414c; --ann-tss: #6ea6dd; --ann-tis: #55b09c; --ann-donor: #de7d72; --ann-acceptor: #a98cd2; --ann-stop: #d9a05a; --ann-tts: #9186d6; --ann-gene: #a8917f; --ann-gene-ink: #c9b6a4; --base-a: #5cc47f; --base-c: #7fb0ea; --base-g: #e8b452; --base-t: #f0847f; --base-n: #7c848d; --fig-grid: #262d27; --fig-axis: #414a42; --sel-bg: var(--lime); --sel-fg: #10160f; --sel-flag: #d9944f; --sel-quiet: #6f9264; --sel-flag: #d9944f; --sel-quiet: #6f9264; --ann-ink: var(--ink-2); } } :root[data-theme="dark"] { --feat-1: #74aef0; --feat-2: #f79055; --feat-3: #45cba0; --feat-4: #f68ac4; --feat-5: #dcb84a; --feat-6: #a9b0c2; --feat-7: #c193ef; --feat-8: #55c9e6; --feat-9: #f0808f; --feat-10: #b2cd5f; --feat-11: #d3a06b; --feat-12: #c49bbb; --feat-none: #3a423b; --ann-panel: #1a201c; --ann-panel-rule: #2b332c; --ann-intergenic: #202724; --ann-cds: #31462f; --ann-utr5: #3a3150; --ann-utr3: #4a323d; --ann-intron: #423b28; --ann-ncrna: #26414c; --ann-tss: #6ea6dd; --ann-tis: #55b09c; --ann-donor: #de7d72; --ann-acceptor: #a98cd2; --ann-stop: #d9a05a; --ann-tts: #9186d6; --ann-gene: #a8917f; --ann-gene-ink: #c9b6a4; --base-a: #5cc47f; --base-c: #7fb0ea; --base-g: #e8b452; --base-t: #f0847f; --base-n: #7c848d; --fig-grid: #262d27; --fig-axis: #414a42; --sel-bg: var(--lime); --sel-fg: #10160f; --ann-ink: var(--ink-2); } /* ------------------------------------------------------- the browser shell --- */ /* The stage is the positioning context for the two movable surfaces, so they travel with the figure when the page scrolls instead of following the reader. */ .feat-stage { position: relative; margin: 34px 0 26px; } .feat-stage > .feat-browser { margin: 0; } .feat-float { position: absolute; z-index: 4; } /* room beside the canvas for the lanes dock, when the page is wide enough */ @media (min-width: 1081px) { .feat-stage.stage-docked { padding-right: 350px; } } .feat-float[hidden] { display: none !important; } .feat-browser { /* the figure narrows when the lanes dock takes a gutter, so its own blocks respond to its width rather than the viewport's */ container-type: inline-size; margin: 34px 0 26px; border: 1px solid var(--rule-2); border-radius: 12px; background: var(--card); overflow: hidden; font-family: var(--sans); } .feat-heading { display: flex; justify-content: space-between; align-items: flex-end; gap: 14px 20px; flex-wrap: wrap; padding: 17px 24px 15px; border-bottom: 1px solid var(--rule); background: var(--sage); } .feat-heading > div:first-child { min-width: 0; } .feat-browser h2 { margin: 0 0 6px; font-size: 21px; line-height: 1.18; letter-spacing: -0.02em; max-width: 34ch; } .feat-browser h2 i, .feat-browser h2 em { font-style: italic; font-weight: 600; } .feat-browser h2 .ft-dim { color: var(--ink-2); font-weight: 600; } .feat-browser h2 .ft-kind { display: inline-block; vertical-align: 3px; font: 600 9.5px var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2); background: var(--card); border: 1px solid var(--rule-2); border-left: 3px solid var(--sel-quiet); border-radius: 4px; padding: 2px 7px; margin-left: 6px; white-space: nowrap; } .feat-browser h2 .ft-kind[data-flag="1"] { border-left-color: var(--sel-flag); color: var(--ink); } .feat-heading > div:first-child > p { margin: 0; color: var(--ink-2); font-size: 12px; line-height: 1.5; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 9px; } .feat-heading > div:first-child > p .species { font-style: italic; } .feat-heading > div:first-child > p .uid { font-family: var(--mono); font-size: 11px; color: var(--ink-2); } .feat-heading > div:first-child > p .sep { color: var(--rule-2); } .feat-heading > div:first-child > p .split { font-family: var(--mono); font-size: 10px; letter-spacing: 0.06em; color: var(--ink-3); border: 1px solid var(--rule-2); border-radius: 3px; padding: 1px 5px; } .feat-tools { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; } .feat-tools button { font: 600 12px var(--sans); color: var(--ink-2); background: var(--card); border: 1px solid var(--rule-2); border-radius: 6px; padding: 7px 11px; cursor: pointer; min-height: 34px; } .feat-tools button.zoom { font-size: 17px; min-width: 36px; padding: 3px 9px; } .feat-tools button:hover:not(:disabled) { background: var(--lime-2); color: var(--ink); border-color: var(--lime); } .feat-tools button:disabled { opacity: .4; cursor: default; } /* the coordinate bar between the heading and the plot */ .feat-browser .feat-region { margin: 0; padding: 11px 24px 3px; max-width: none; font: 11px var(--sans); color: var(--ink-2); display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 16px; } .feat-region .fr-coord { font: 500 12.5px var(--mono); color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; } .feat-region .fr-item { color: var(--ink-3); display: inline-flex; gap: 5px; align-items: baseline; } .feat-region .fr-item b { font-weight: 500; color: var(--ink-2); font-family: var(--mono); font-variant-numeric: tabular-nums; } .feat-region .fr-key { text-transform: uppercase; letter-spacing: 0.1em; font-size: 9.5px; font-family: var(--mono); } .feat-scroll { overflow-x: hidden; padding: 2px 14px 0; } #feat-plot { min-width: 0; } #feat-plot svg { display: block; width: 100%; height: auto; touch-action: pan-y; cursor: crosshair; } /* ------------------------------------------------------------- plot marks --- */ #feat-plot text { fill: var(--ink-2); font: 10.5px var(--mono); } #feat-plot .ruler-tick { font: 10px var(--mono); fill: var(--ink-3); font-variant-numeric: tabular-nums; } #feat-plot .axis { stroke: var(--fig-axis); stroke-width: .8; fill: none; } #feat-plot .grid { stroke: var(--fig-grid); stroke-width: .7; fill: none; } /* register labels: two tiny keys in the gutter that name what each block is */ #feat-plot .reg-lab { font: 500 9px var(--mono); letter-spacing: 0.13em; fill: var(--ink-3); } #feat-plot .reg-rule { stroke: var(--rule); stroke-width: .8; } /* the headline strip */ #feat-plot .strip-frame { fill: none; stroke: var(--fig-axis); stroke-width: .8; } #feat-plot .seqletter { font: 600 10px var(--mono); } #feat-plot .nofire { fill: var(--feat-none); } /* the annotation panel. A recessed plate keeps annotations in their own register. */ #feat-plot .ann-panel { fill: var(--ann-panel); stroke: var(--ann-panel-rule); stroke-width: .8; } #feat-plot .ann-band { } #feat-plot .ann-band-rule { stroke: var(--ann-panel-rule); stroke-width: .7; fill: none; } #feat-plot .ann-sitelab { font: 9px var(--sans); fill: var(--ink-3); } #feat-plot .ann-bandlab { font: 500 8.5px var(--sans); fill: var(--ann-ink); } #feat-plot .gene-line { stroke: var(--ann-gene); stroke-width: 1.1; fill: none; } #feat-plot .gene-label { font: italic 10px var(--sans); fill: var(--ann-gene-ink); } #feat-plot .gene-exon { fill: var(--ann-cds); stroke: var(--ann-gene); stroke-width: .7; } #feat-plot .strand-name { font: 500 10px var(--sans); fill: var(--ink-2); letter-spacing: 0.01em; } /* lanes: a measurement register, so names are ink and the hue lives in a key bar */ #feat-plot .lane-key { stroke-linecap: round; } #feat-plot .lane-name { font: 600 11px var(--sans); fill: var(--ink); } #feat-plot .lane-name.lane-id-name { font-family: var(--mono); font-size: 11px; letter-spacing: -0.01em; } #feat-plot .lane-id { font: 500 10px var(--mono); fill: var(--ink-3); } #feat-plot .lane-max { font: 500 10px var(--mono); fill: var(--ink-2); font-variant-numeric: tabular-nums; } #feat-plot .lane-max .u { fill: var(--ink-3); font-weight: 400; } #feat-plot .lane-silent { font: italic 10px var(--sans); fill: var(--ink-3); } #feat-plot .lane-base { stroke: var(--fig-axis); stroke-width: .8; fill: none; } #feat-plot .lane-base.silent { stroke: var(--rule); stroke-dasharray: 2 3; } #feat-plot .lane-stems { fill: none; stroke-width: 1.05; } #feat-plot .reg-note { font: 9.5px var(--sans); fill: var(--ink-3); } /* cursor and pin */ #feat-plot .cursor { stroke: var(--ink-3); stroke-width: 1; fill: none; } #feat-plot .pin { stroke: var(--ink); stroke-width: 1.3; fill: none; } #feat-plot .pin-cap { fill: var(--ink); stroke: none; } /* The anchor is where the sampler looked, not an annotation of that base, so it is outlined, never filled, and it is labelled as its own thing. */ #feat-plot .anchor { fill: none; stroke: var(--ink); stroke-width: 1.2; stroke-dasharray: 2 2; } #feat-plot .anchor-lab { font: 500 9px var(--mono); letter-spacing: 0.1em; fill: var(--ink-2); } /* the base a window was chosen for: solid, to pair with the anchor's dashed outline */ #feat-plot .finding { fill: var(--ink); stroke: none; } #feat-plot .finding.open { fill: var(--card); stroke: var(--ink); stroke-width: 1.2; } #feat-plot .finding-bracket { fill: none; stroke: var(--ink); stroke-width: 1; } #feat-plot .finding-lab { font: 500 9px var(--mono); letter-spacing: 0.08em; fill: var(--ink); } /* halo, for the labels that sit over the plot at narrow widths */ #feat-plot .halo { paint-order: stroke; stroke: var(--card); stroke-width: 3.4px; stroke-linejoin: round; } #feat-plot .halo-panel { paint-order: stroke; stroke: var(--ann-panel); stroke-width: 3.4px; stroke-linejoin: round; } /* scale bar: a bracket the width of one round number of bases */ #feat-plot .scalebar { stroke: var(--ink-3); stroke-width: 1; fill: none; } #feat-plot .scale-pill { fill: var(--paper-2); stroke: var(--rule-2); stroke-width: .8; } #feat-plot .scale-lab { font: 500 9.5px var(--mono); fill: var(--ink-2); letter-spacing: 0.02em; } /* the global-mode key, shown only when the strip reads the whole dictionary */ #feat-plot .gkey-id { font: 500 9.5px var(--mono); fill: var(--ink-2); } /* ---------------------------------------------------------------- readout --- */ .feat-readout { display: grid; grid-template-columns: minmax(140px, 0.75fr) minmax(160px, 1fr) minmax(250px, 1.55fr); gap: 0; min-height: 104px; padding: 0; border-top: 1px solid var(--rule); background: var(--paper-2); font-family: var(--sans); color: var(--ink-2); } .feat-readout .ro-block { padding: 12px 20px 13px; min-width: 0; } .feat-readout .ro-block + .ro-block { border-left: 1px solid var(--rule); } .feat-readout .ro-lab { font: 500 9.5px var(--mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); margin: 0 0 7px; display: flex; align-items: baseline; gap: 8px; } .feat-readout .ro-lab > span:not(.pinned) { text-transform: none; letter-spacing: 0.02em; font-family: var(--sans); font-size: 10px; color: var(--ink-3); } .feat-readout .ro-lab .pinned { text-transform: none; letter-spacing: 0.04em; color: var(--ink); background: var(--lime); border-radius: 3px; padding: 1px 5px; font-size: 9px; } .feat-readout .ro-rows { display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; align-items: baseline; } .feat-readout .k { font: 11px var(--sans); color: var(--ink-3); } .feat-readout .v { font: 500 12px var(--mono); color: var(--ink); font-variant-numeric: tabular-nums; } .feat-readout .v.dim { color: var(--ink-3); font-weight: 400; } .feat-readout .seqbase { font: 700 14px var(--mono); letter-spacing: 0.06em; } .feat-readout .ro-ann .ro-rows { grid-template-columns: auto 1fr; } .feat-readout .ro-ann .v { font-family: var(--sans); font-size: 11.5px; font-weight: 500; } .feat-readout .achip { display: inline-flex; align-items: center; gap: 5px; font: 500 11px var(--sans); color: var(--ink); } .feat-readout .achip i { width: 9px; height: 9px; border-radius: 2px; border: 1px solid color-mix(in srgb, var(--ink) 16%, transparent); flex: none; } .feat-readout .achip i.site { width: 3px; height: 11px; border-radius: 0; border: 0; } .feat-readout .gname { font-style: italic; color: var(--ink-2); font-size: 11px; } .feat-readout .ro-act .rows { display: grid; grid-template-columns: 10px auto minmax(0, 1fr) auto; gap: 2px 9px; align-items: baseline; } .feat-readout .ro-act .chip { width: 9px; height: 9px; border-radius: 2px; align-self: center; } .feat-readout .ro-act .fid { font: 600 11px var(--mono); color: var(--ink); } .feat-readout .ro-act .fnm { font: 11.5px var(--sans); color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .feat-readout .ro-act .fv { font: 600 12px var(--mono); color: var(--ink); font-variant-numeric: tabular-nums; } .feat-readout .ro-foot { margin-top: 8px; font: 11px var(--sans); color: var(--ink-3); } .feat-readout .ro-foot b { font: 600 11px var(--mono); color: var(--ink-2); } .feat-readout .ro-silent { margin-top: 7px; font: 11px var(--sans); color: var(--ink-3); } .feat-readout .ro-silent code { background: none; padding: 0; font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); } .feat-readout .ro-empty { font: italic 11.5px var(--sans); color: var(--ink-3); } .feat-readout .ro-fail { grid-column: 1 / -1; } /* ------------------------------------------------------------- figcaption --- */ .feat-browser figcaption { margin: 0; padding: 11px 24px 12px; max-width: none; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 6px 24px; font: 11.5px var(--sans); color: var(--ink-2); border-top: 1px solid var(--rule); background: var(--card); } .feat-browser figcaption a { color: var(--ink-2); } .feat-browser figcaption #feat-prov { color: var(--ink-3); } .feat-browser figcaption > span:last-child { color: var(--ink-3); } .feat-browser .feat-fallback { margin: 18px 24px; font-size: 14px; font-family: var(--serif); } /* ------------------------------------------------------------- lanes dock --- */ .feat-dock { width: 336px; max-width: calc(100% - 24px); background: var(--card); color: var(--ink); border: 1px solid var(--rule-2); border-radius: 10px; box-shadow: 0 8px 26px color-mix(in srgb, var(--ink) 16%, transparent); font-family: var(--sans); display: flex; flex-direction: column; overflow: hidden; } #feat-controls .dock-title { margin: 0; max-width: none; flex: none; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 8px 8px 13px; font: 700 12.5px var(--sans); letter-spacing: -0.01em; color: var(--ink); background: var(--sage); border-bottom: 1px solid var(--rule); cursor: grab; touch-action: none; user-select: none; } #feat-controls .dock-title.dragging { cursor: grabbing; } .dock-close { font: 400 16px/1 var(--sans); color: var(--ink-2); background: none; border: 0; border-radius: 5px; width: 26px; height: 26px; flex: none; cursor: pointer; } .dock-close:hover { background: var(--paper-2); color: var(--ink); } .dock-body { padding: 4px 13px 12px; overflow-y: auto; min-height: 0; } #feat-controls .label { margin: 12px 0 6px; max-width: none; } #feat-controls .label:first-child { margin-top: 8px; } #feat-controls .seg { flex-wrap: wrap; } #feat-controls .seg button { font-size: 12px; padding: 6px 10px; } #feat-controls #feat-list { margin: 0; } #feat-controls .fl-rows { grid-template-columns: 1fr; gap: 0; } #feat-controls-toggle[aria-expanded="true"] { background: var(--sel-bg); color: var(--sel-fg); border-color: var(--sel-bg); } /* ---------------------------------------------------------- window picker --- */ .win-picker { margin: 16px 0 10px; display: grid; gap: 14px; max-width: 900px; } #win-picker.win-wide { max-width: 1120px; gap: 10px; } .win-hero { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 4px 14px; text-align: left; width: 100%; font: inherit; cursor: pointer; background: var(--card); color: var(--ink); border: 1px solid var(--rule-2); border-left: 4px solid var(--lime); border-radius: 8px; padding: 10px 15px; max-width: 540px; } .win-hero:hover { background: var(--lime-2); border-color: var(--lime); } .win-hero[aria-checked="true"] { background: var(--sage-2); border-color: var(--rule-2); border-left-width: 6px; } .win-hero[aria-checked="true"] .wh-tag { color: var(--ink-2); } .win-hero .wh-tag { grid-row: 1 / span 2; align-self: center; font: 500 9.5px var(--mono); letter-spacing: 0.13em; color: var(--ink-3); writing-mode: horizontal-tb; } .win-hero .wh-name { font: 700 15px var(--sans); letter-spacing: -0.01em; } .win-hero .wh-sub { font: 12px var(--sans); color: var(--ink-2); } .win-hero .wh-sub i { font-style: italic; } /* selection-shaped picker: species blocks of cards labelled by what the window shows, used as soon as the window files carry a `selection` field */ .win-block + .win-block { margin-top: 4px; } #win-picker .win-sp { display: flex; align-items: baseline; gap: 9px; margin: 0 0 6px; max-width: none; border-top: 1px solid var(--rule); padding-top: 8px; } #win-picker .win-block:first-of-type .win-sp { border-top: 0; padding-top: 0; } #win-picker .win-sp .b { font: italic 600 13px var(--sans); color: var(--ink); } #win-picker .win-sp .f { font: 10px var(--mono); color: var(--ink-3); letter-spacing: 0.04em; } .win-list { display: grid; grid-template-columns: repeat(var(--wl-cols, 5), minmax(0, 1fr)); gap: 7px; } .win-card { display: grid; gap: 2px; text-align: left; font: inherit; cursor: pointer; background: var(--card); color: var(--ink); border: 1px solid var(--rule-2); border-left: 3px solid var(--rule-2); border-radius: 7px; padding: 8px 11px; } .win-card[data-flag="0"] { border-left-color: var(--sel-quiet); } .win-card[data-flag="1"] { border-left-color: var(--sel-flag); } .win-card:hover { background: var(--lime-2); border-color: var(--lime); } .win-card[aria-checked="true"] { background: var(--sage-2); border-color: var(--rule-2); border-left-width: 6px; } .win-card .wk { font: 500 8.5px var(--mono); letter-spacing: 0.13em; text-transform: uppercase; color: var(--ink-3); } .win-card[data-flag="1"] .wk { color: var(--ink-2); font-weight: 600; } .win-card .wn { font: 600 13px var(--sans); letter-spacing: -0.01em; } .win-card .wh { font: 11.5px var(--sans); color: var(--ink-2); line-height: 1.35; } .win-card .wm { font: 10.5px var(--mono); color: var(--ink-3); line-height: 1.4; letter-spacing: -0.01em; overflow-wrap: anywhere; } .win-card .wu { font: 10px var(--mono); color: var(--ink-3); letter-spacing: -0.02em; } .win-matrix { display: grid; grid-template-columns: max-content repeat(var(--wm-cols, 5), minmax(0, 1fr)); gap: 5px 6px; align-items: stretch; } .win-matrix .wm-corner { } .win-matrix .wm-head { font: 500 9.5px var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); padding: 0 0 2px 2px; align-self: end; } .win-matrix .wm-sp { display: grid; align-content: center; padding: 0 14px 0 2px; min-width: 0; } .win-matrix .wm-sp .b { font: italic 600 12.5px var(--sans); color: var(--ink); } .win-matrix .wm-sp .f { font: 10px var(--mono); color: var(--ink-3); letter-spacing: 0.04em; } .win-matrix .wm-cell { font: inherit; cursor: pointer; text-align: left; display: grid; align-content: center; gap: 1px; background: var(--card); color: var(--ink); border: 1px solid var(--rule-2); border-radius: 6px; padding: 7px 9px; min-height: 38px; } .win-matrix .wm-cell:hover { background: var(--lime-2); border-color: var(--lime); } .win-matrix .wm-cell[aria-checked="true"] { background: var(--sel-bg); border-color: var(--sel-bg); } .win-matrix .wm-cell .wc-uid { font: 500 10.5px var(--mono); color: var(--ink-2); letter-spacing: -0.02em; } .win-matrix .wm-cell .wc-anchor { display: none; font: 600 11.5px var(--sans); } .win-matrix .wm-cell[aria-checked="true"] .wc-uid, .win-matrix .wm-cell[aria-checked="true"] .wc-anchor { color: var(--sel-fg); } /* site.css pairs ink-on-lime for a pressed segmented control, which inverts to an illegible 1.1:1 in dark; the token pair restores it. */ #feat-mode button[aria-pressed="true"] { background: var(--sel-bg); color: var(--sel-fg); } .win-matrix .wm-empty { border: 1px dashed var(--rule); border-radius: 6px; min-height: 38px; } /* --------------------------------------------------------- feature picker --- */ #feat-list { margin: 16px 0 8px; } .fl-bar { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 8px 16px; padding-bottom: 7px; border-bottom: 1px solid var(--rule-2); } .fl-count { font: 12px var(--sans); color: var(--ink-3); } .fl-count b { font: 600 13px var(--sans); color: var(--ink); font-variant-numeric: tabular-nums; } .fl-count .full { color: var(--ink-2); } .fl-reset { font: 600 11.5px var(--sans); color: var(--ink-2); background: var(--card); border: 1px solid var(--rule-2); border-radius: 999px; padding: 5px 12px; cursor: pointer; } .fl-reset:hover { background: var(--lime-2); border-color: var(--lime); color: var(--ink); } .fl-group { margin-top: 16px; } #feat-list .fl-group > .fl-h, #feat-list .fl-group > summary { display: flex; align-items: baseline; gap: 9px; font: 700 13px var(--sans); color: var(--ink); letter-spacing: -0.01em; margin: 0 0 6px; list-style: none; } .fl-group > summary { cursor: pointer; } .fl-group > summary::-webkit-details-marker { display: none; } .fl-group > summary::before { content: ""; width: 0; height: 0; flex: none; align-self: center; border-left: 5px solid var(--ink-2); border-top: 4px solid transparent; border-bottom: 4px solid transparent; } .fl-group[open] > summary::before { transform: rotate(90deg); } .fl-group > .fl-h .n, .fl-group > summary .n { font: 500 10.5px var(--mono); color: var(--ink-3); border: 1px solid var(--rule); border-radius: 999px; padding: 1px 7px; } .fl-group > .fl-h .why, .fl-group > summary .why { font: 400 11.5px var(--sans); color: var(--ink-3); } .fl-rows { display: grid; grid-template-columns: repeat(auto-fill, minmax(288px, 1fr)); gap: 0 28px; } #feat-list .fl-sub { grid-column: 1 / -1; display: flex; align-items: center; gap: 9px; font: 500 9.5px var(--mono); letter-spacing: 0.13em; text-transform: uppercase; color: var(--ink-3); margin: 9px 0 1px; } .fl-sub::after { content: ""; flex: 1; height: 1px; background: var(--rule); } .fl-row { display: grid; grid-template-columns: 15px auto minmax(0, 1fr) auto 40px; align-items: center; gap: 0 9px; padding: 5px 2px; cursor: pointer; border-bottom: 1px solid color-mix(in srgb, var(--rule) 55%, transparent); font-family: var(--sans); } .fl-row:hover { background: color-mix(in srgb, var(--paper-2) 70%, transparent); } .fl-row input { margin: 0; accent-color: var(--ink); justify-self: center; } .fl-row .fid { font: 500 11px var(--mono); color: var(--ink-2); } .fl-row.on .fid { color: var(--ink-2); } .fl-row .fname { font: 12.5px var(--sans); color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .fl-row.named .fname { font-weight: 600; } .fl-row .fname .un { color: var(--ink-3); font-family: var(--mono); font-size: 10.5px; font-weight: 400; } .fl-row .fpeak { font: 500 11px var(--mono); color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; } .fl-row .fpeak.zero { color: var(--ink-3); font-style: italic; font-family: var(--sans); font-size: 10.5px; } .fl-row .fcov { height: 5px; background: color-mix(in srgb, var(--rule) 60%, transparent); border-radius: 3px; overflow: hidden; } .fl-row .fcov i { display: block; height: 100%; background: var(--ink-3); border-radius: 3px; min-width: 1px; } .fl-row.on .fcov i { background: var(--ink); } .fl-row.silent { color: var(--ink-3); } .fl-row.silent .fname { color: var(--ink-3); } .fl-row input:disabled { cursor: not-allowed; } .fl-row:has(input:disabled) { cursor: default; opacity: .55; } .fl-row:has(input:disabled):hover { background: none; } #feat-list .fl-note { margin: 10px 0 0; font: 11.5px var(--sans); color: var(--ink-3); } /* ---------------------------------------------------------------- legends --- */ /* The annotation legend sits on the same recessed plate as the annotation panel in the figure, so the reader learns the register once. Region washes fill the first rows; the point sites are forced onto a fresh row so the two kinds of annotation do not read as one undifferentiated run of chips. */ .ann-legend { display: grid; grid-template-columns: repeat(auto-fit, minmax(108px, max-content)); gap: 7px 20px; margin: 20px 0 0; padding: 27px 15px 12px; border: 1px solid var(--rule); border-radius: 8px; background: var(--ann-panel); font: 11.5px var(--sans); color: var(--ink-2); position: relative; } .ann-legend::before { content: "Annotation register — never a measurement"; position: absolute; top: 9px; left: 15px; font: 500 9px var(--mono); letter-spacing: 0.13em; text-transform: uppercase; color: var(--ink-3); } .ann-legend span { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; } .ann-legend i { width: 15px; height: 11px; flex: none; display: inline-block; border: 1px solid var(--ann-panel-rule); border-radius: 2px; } .ann-legend i.site { width: 3px; height: 13px; border: 0; border-radius: 0; } /* the first point site starts a new row, whatever the column count */ .ann-legend span:nth-child(7) { grid-column-start: 1; } /* ----------------------------------------------------------- narrow widths --- */ @media (max-width: 1020px) { .feat-readout { grid-template-columns: minmax(150px, 0.9fr) minmax(0, 1.6fr); } .feat-readout .ro-act { grid-column: 1 / -1; border-left: 0; border-top: 1px solid var(--rule); } } @media (max-width: 860px) { .win-matrix { grid-template-columns: repeat(var(--wm-cols, 5), minmax(0, 1fr)); gap: 5px; } .win-matrix .wm-corner, .win-matrix .wm-head { display: none; } .win-matrix .wm-sp { grid-column: 1 / -1; padding: 8px 0 1px; display: flex; align-items: baseline; gap: 8px; border-top: 1px solid var(--rule); } .win-matrix .wm-sp:first-of-type { border-top: 0; padding-top: 2px; } .win-matrix .wm-cell { padding: 6px 6px; min-height: 40px; } .win-matrix .wm-cell .wc-uid { display: none; } .win-matrix .wm-cell .wc-anchor { display: block; font-size: 11px; line-height: 1.15; } .ann-legend { grid-template-columns: repeat(3, minmax(0, 1fr)); } } @media (max-width: 700px) { /* full-bleed the figure: at 420 px the page gutter is a third of the plot */ .feat-browser { margin-left: -28px; margin-right: -28px; margin-top: 26px; border-radius: 0; border-left: 0; border-right: 0; } .feat-heading { padding: 15px 18px 13px; gap: 12px; } .feat-browser h2 { font-size: 19px; } .feat-browser .feat-region { padding: 10px 18px 2px; gap: 2px 12px; } .feat-region .fr-coord { font-size: 11.5px; } .feat-scroll { padding: 2px 4px 0; } .feat-readout { grid-template-columns: 1fr 1fr; min-height: 0; } .feat-readout .ro-block { padding: 10px 15px; } .feat-readout .ro-rows { gap: 2px 10px; } .feat-readout .ro-ann { border-left: 1px solid var(--rule); } .feat-readout .ro-act { grid-column: 1 / -1; border-left: 0; border-top: 1px solid var(--rule); } .feat-browser figcaption { padding: 11px 18px 12px; } .feat-tools button { min-height: 40px; } .feat-tools button.zoom { min-width: 44px; font-size: 19px; } .fl-rows { grid-template-columns: 1fr; gap: 0; } .fl-row { grid-template-columns: 17px auto minmax(0, 1fr) auto 32px; padding: 7px 2px; } .win-hero { padding: 10px 13px; } } /* Between a phone and a wide screen the five cards of a species would wrap to a second row, doubling the block's height; narrower columns keep one row. */ @media (max-width: 1080px) and (min-width: 621px) { .win-list { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; } .win-card { padding: 7px 9px; } .win-card .wn { font-size: 12px; } /* the tag already says what the headline says in three words, so at this width the evidence line is the one worth the space */ .win-card .wh { display: none; } .win-card .wm { font-size: 10px; } } @media (max-width: 620px) { /* the reason a window earns its place is long prose; on a narrow screen it stays in the button's title and aria-label instead of on the card */ #win-picker.win-wide { max-width: none; } .win-list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 5px; } .win-card { padding: 7px 9px; } /* on a phone a card is the gene and the kind; the headline, the evidence and the uid stay in its title and aria-label, and the note under the figure carries the full reasoning once a window is chosen */ .win-card .wh, .win-card .wm, .win-card .wu { display: none; } .win-card .wn { font-size: 12.5px; line-height: 1.2; } .win-card .wk { font-size: 8px; } /* five columns still fit if the anchor names are allowed to wrap */ .win-matrix { gap: 4px; } .win-matrix .wm-cell { padding: 5px 5px; min-height: 42px; } .win-matrix .wm-cell .wc-anchor { font-size: 10px; line-height: 1.15; white-space: normal; } .win-hero { grid-template-columns: 1fr; gap: 1px; } .win-hero .wh-tag { grid-row: auto; } .win-hero .wh-asm { display: none; } } @media (max-width: 460px) { .ann-legend { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px 12px; } } /* ------------------------------------------- floating top-features panel --- */ /* Reads the strongest features at the cursor, so a reader can find a feature that has no lane yet and give it one. Floats over the page at wide widths, docks under the readout when there is no room to float. */ #feat-panel-toggle[aria-expanded="true"] { background: var(--sel-bg); color: var(--sel-fg); border-color: var(--sel-bg); } .fp { z-index: 5; width: 300px; max-width: calc(100% - 24px); background: var(--card); color: var(--ink); border: 1px solid var(--rule-2); border-radius: 10px; box-shadow: 0 8px 26px color-mix(in srgb, var(--ink) 18%, transparent); font-family: var(--sans); overflow: hidden; } .fp-head { display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 4px 8px; padding: 8px 8px 8px 12px; background: var(--sage); border-bottom: 1px solid var(--rule); cursor: grab; touch-action: none; user-select: none; } .fp-head.dragging { cursor: grabbing; } #feat-panel .fp-head h3 { margin: 0; font: 700 12.5px var(--sans); letter-spacing: -0.01em; } .fp-at { font: 500 10.5px var(--mono); color: var(--ink-2); font-variant-numeric: tabular-nums; } .fp-grip { grid-row: 1; width: 12px; height: 12px; opacity: .5; background: radial-gradient(circle at 2px 2px, currentColor 1px, transparent 1.2px) 0 0 / 5px 5px; color: var(--ink-3); } .fp-close { font: 400 16px/1 var(--sans); color: var(--ink-2); background: none; border: 0; border-radius: 5px; width: 26px; height: 26px; cursor: pointer; } .fp-close:hover { background: var(--paper-2); color: var(--ink); } #feat-panel .fp-src { margin: 0; padding: 7px 12px 6px; font: 10.5px var(--sans); color: var(--ink-3); line-height: 1.35; border-bottom: 1px solid var(--rule); } #feat-panel .fp-src b { font: 500 10px var(--mono); color: var(--ink-2); } #feat-panel .fp-rows { margin: 0; padding: 4px 6px; list-style: none; max-height: 268px; overflow-y: auto; } #feat-panel .fp-rows li { margin: 0; } .fp-row { display: grid; grid-template-columns: 10px auto minmax(0, 1fr) auto; align-items: center; gap: 0 8px; width: 100%; text-align: left; font: inherit; background: none; border: 0; border-radius: 5px; padding: 5px 6px; cursor: pointer; } .fp-row:hover { background: var(--paper-2); } .fp-row .chip { width: 9px; height: 9px; border-radius: 2px; background: var(--rule-2); } .fp-row[aria-pressed="true"] .chip { box-shadow: 0 0 0 2px color-mix(in srgb, var(--ink) 22%, transparent); } .fp-row .fid { font: 600 11px var(--mono); color: var(--ink); } .fp-row .fnm { font: 11.5px var(--sans); color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .fp-row .fnm .un { color: var(--ink-3); font-family: var(--mono); font-size: 10.5px; } .fp-row .fv { font: 600 11.5px var(--mono); color: var(--ink); font-variant-numeric: tabular-nums; } .fp-row[aria-pressed="true"] .fnm { color: var(--ink); } #feat-panel .fp-empty { padding: 12px; margin: 0; font: italic 11.5px var(--sans); color: var(--ink-3); } #feat-panel .fp-foot { margin: 0; padding: 8px 12px 10px; border-top: 1px solid var(--rule); background: var(--paper-2); font: 10.5px var(--sans); color: var(--ink-3); line-height: 1.4; } #feat-panel .fp-foot b { font: 600 10.5px var(--mono); color: var(--ink-2); } #feat-panel .fp-foot .hint { display: block; margin-top: 3px; } /* No room to float: both surfaces drop into the flow under the figure, in the order the reader needs them — the figure and its readout, then the lanes, then the top-features panel. */ @media (max-width: 900px) { .feat-float { position: static !important; width: auto; max-width: none; inset: auto !important; border-radius: 0; border-left: 0; border-right: 0; box-shadow: none; } .feat-dock, .fp { border-top: 1px solid var(--rule-2); border-bottom: 0; margin-top: 0; } .fp-head, #feat-controls .dock-title { cursor: default; } .fp-grip { display: none; } /* in the flow they still scroll internally: 32 ranked rows and 38 lane rows would otherwise add two screens of page */ #feat-panel .fp-rows { max-height: 320px; } #feat-controls .dock-body { max-height: 460px; } #feat-panel .fp-rows, #feat-panel .fp-src, #feat-panel .fp-foot { max-width: 620px; } #feat-controls .dock-body { max-width: 640px; } #feat-controls .fl-rows { grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 0 24px; } } /* ------------------------------------------------- figure-width responses --- */ @container (max-width: 1020px) { .feat-readout { grid-template-columns: minmax(150px, 0.9fr) minmax(0, 1.6fr); } .feat-readout .ro-act { grid-column: 1 / -1; border-left: 0; border-top: 1px solid var(--rule); } } @container (max-width: 700px) { .feat-readout { grid-template-columns: 1fr 1fr; min-height: 0; } .feat-readout .ro-ann { border-left: 1px solid var(--rule); } } @container (max-width: 430px) { .feat-readout { grid-template-columns: 1fr; } .feat-readout .ro-ann { border-left: 0; border-top: 1px solid var(--rule); } }