/* ==========================================================================
   Charts — inline SVG rendered at build time, styled here.
   Rules and ticks use the kit connector grey; marks use the tier scale.
   ========================================================================== */

.chart { width: 100%; height: auto; overflow: visible; font-family: var(--font-text); }

/* Three weights of line, and the order of them is the whole hierarchy: the
   gridlines are the palest thing on the page so a bar always outweighs the
   scale behind it, the axis the bars stand on is a connector, and zero — the
   line every value is read against — is the same connector drawn heavier. It
   used to be `--ink-3`, which is the colour of the tick labels: a structural
   line as dark as the words next to it competes with the marks, and on the
   diverging charts the reader met a near-black vertical rule down the middle
   of the plot that carried no value of its own. */
.chart .grid-line { stroke: var(--rule); stroke-width: 1; }
.chart .zero-line { stroke: var(--connector); stroke-width: 1.5; }
.chart .axis-line { stroke: var(--connector); stroke-width: 1; }
/* The tick mark is the axis line's own serif and belongs to it, so it is drawn
   in the same colour and weight. It exists because a number floating under a
   plot points at nothing: the mark is what says this label is read at *this*
   position, and it is the piece that lets a chart drop its interior gridlines
   without the scale becoming a guess. */
.chart .tick-mark { stroke: var(--connector); stroke-width: 1; }
/* The hairline that divides a chart into panels. It is the palest line in the
   kit on purpose — it separates two halves of one figure, and a divider drawn
   as heavily as the axis claims to be a second axis. It also had no rule until
   now, which for a `<line>` means `stroke: none`: the divider was in the markup,
   in the accessibility tree, and invisible. */
.chart .panel-rule { stroke: var(--rule); stroke-width: 1; }

.chart .tick {
  font-family: var(--font-data);
  font-size: 11.5px;
  fill: var(--ink-3);
}
.chart .axis-title {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.005em;
  fill: var(--ink-2);
}
.chart .cat-label { font-size: 12.5px; fill: var(--ink); }
/* Two names for one treatment, because they are the same thing in two charts: a
   reading set in a column beside the mark rather than on it. The slope chart's
   tier text had no rule at all, so it inherited the SVG default — 16px of the
   body face, larger and darker than the disease name it was annotating and wide
   enough that "Tier 2 · #3 of 41" ran back into "Idiopathic pulmonary fibrosis".
   A missing declaration is not a neutral one: it is whatever the user agent
   guesses, and here the guess outranked the data. */
.chart .val-label,
.chart .tier-text {
  font-family: var(--font-data);
  font-size: 11px;
  fill: var(--ink-2);
}
.chart .quad-label {
  font-size: 11.5px;
  fill: var(--ink-3);
}
.chart .quad-label--tier { font-weight: 600; fill: var(--ink-2); }

/* Marks ------------------------------------------------------------------ */
.chart .mark {
  transition: opacity var(--dur-2) var(--ease-out),
              transform var(--dur-2) var(--ease-out);
  transform-box: fill-box;
  transform-origin: center;
  cursor: pointer;
}
/* Hover is a pointer already on the mark, so the browser's default ring adds
   nothing there and is dropped. Focus is the opposite case and the ring is the
   whole point of it: a keyboard reader has no pointer, and the ring is the only
   thing on the screen telling them which of a hundred marks they are standing
   on. `outline: none` was being applied to both, which the dot charts got away
   with because the two rules below redraw the dot bigger and give it a dark
   collar — but a bar has neither, so on the 50 bar marks of this report the ring
   was removed and nothing replaced it: tabbing into the chart moved focus
   through fifty stops with no visible change of any kind, and the reader's only
   way of knowing where they were was the tooltip.

   The declaration is repeated for `.bar` rather than being left to the general
   `:focus-visible` rule in base.css, because that rule is written inside
   `:where()` and carries zero specificity, so `.chart .mark:hover` above it —
   or anything else at all — outranks it. Named here it wins on its own terms.

   `outline-offset` is what keeps the ring off the mark. A bar is a filled
   rectangle and a ring drawn flush against its edge reads as a border on the
   bar, which is to say as part of the data. Two pixels of air says it belongs
   to the browser and not to the chart. */
.chart .mark:hover { outline: none; }
.chart .mark:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 2px;
}
.chart .dot { r: 5.5; stroke: var(--card); stroke-width: 1.5; }
.chart .mark:hover .dot, .chart .mark:focus-visible .dot { r: 7.5; }
.chart .mark:focus-visible .dot { stroke: var(--ink-strong); stroke-width: 2; }

.chart .bar { transition: opacity var(--dur-2) var(--ease-out); }
.chart .mark:hover .bar { opacity: 0.85; }

.chart .mark.is-dim { opacity: 0.12; }
.chart .is-off { display: none; }

/* Tier and series fills -------------------------------------------------- */

/* The default fill, used by any chart whose caller passes no class function.
   It has to exist: without it the kit's most general chart draws unfilled
   bars, and the only way to get a coloured one is to borrow a class named
   after some other report's series.

   The series scale is the Insilico product palette from tokens.css —
   Chemistry42 blue, PandaOmics teal, Medicine42 purple, Biology42 olive —
   drawn at full strength; nothing here mutes them. The brand green is
   deliberately absent: it belongs to the chrome and to "supports", and a
   data series must not borrow a verdict colour. Legend swatches take the
   same classes, so the key and the marks cannot drift apart. */
.s-a { fill: var(--series-a); }
.s-b { fill: var(--series-b); }
/* Two more, so a chart drawing a third or fourth series does not have to reach
   for a tier colour that means something else. */
.s-c { fill: var(--series-c); }
.s-d { fill: var(--series-d); }

.t1 { fill: var(--tier-1); }
.t2 { fill: var(--tier-2); }
.t3 { fill: var(--tier-3); }
.t4 { fill: var(--tier-4); }
/* The category neutral: the bar that is on the chart to be counted rather
   than to be looked at. It was `--ink-4`, which is a text grey for disabled
   controls and axis ticks — dark enough that on the two charts where most
   rows are neutral, the neutrals were the heaviest marks in the figure and
   the one coloured bar the chart existed to point at was the palest. The
   connector grey is the scale the rest of the kit already uses for "present,
   not the subject", and reaching it through `--cat-4` says that this is a
   category slot and not a borrowed text colour. */
.s-neutral { fill: var(--cat-4); }
.s-hold { fill: var(--ink-3); }   /* matches the slope chart's unmoved rows */
.s-caution { fill: var(--caution); }
.s-flag { fill: var(--flag); }

.chart .label-hi { font-weight: 600; fill: var(--ink-strong); }
.chart .no-data { font-family: var(--font-data); font-size: 10px; fill: var(--ink-4); }
/* The marker standing where a measurement is missing, and it is hollow for a
   reason that survives being photocopied: an outline is the one mark on a chart
   that cannot be mistaken for a quantity, because there is nothing inside it.
   It also had no rule, so it took the SVG default fill of solid black — on
   Figure 4 the six diseases the source never measured were drawn as the darkest
   marks in the figure, which is the exact opposite of what the absence means.
   Sized to the connector rather than the ink scale for the same reason the
   neutral bar is: present, not the subject. */
.chart .dot-empty { fill: none; stroke: var(--connector); stroke-width: 1.25; }

/* Small multiples and sparkbars ------------------------------------------ */
/* The bar sits beneath its value, right-aligned under it, rather than beside
   it. A numeric column is about as wide as the number it holds, so a bar on the
   same line has nowhere to go: it is drawn across the next column's figures,
   which reads as a chart overlapping the data it describes. Narrowing to fit
   keeps every bar on the same scale, because the scale is set by the viewBox. */
.spark {
  width: 76px; height: 14px; max-width: 100%;
  display: block; margin: 2px 0 0 auto;
  overflow: visible;
}
/* One datum, drawn twice in one cell: the number and the bar under it. They
   used to be coloured by two different systems that did not know about each
   other — the number took the row's tone class from the profile, the bar took
   its sign from here — so the same figure could print as violet text over a
   blue bar, while the cell next to it printed green on green. Two colours on
   one value is two claims about it, and the reader has to guess which of them
   the page meant.

   `currentColor` makes the coupling structural rather than a pair of
   declarations that happen to agree today: the bar is the cell's text colour,
   whatever that turns out to be, and no future tone class can separate them.
   The sign is still on the page twice over — the minus on the number and the
   bar's own direction from the centre axis — so nothing was carried by the
   old hue split that is not still there without it. The opacity is a weight,
   not a second colour: at full strength a bar as wide as the number above it
   reads as heavier than the figure it is annotating. `pos` and `neg` stay in
   the markup as hooks.

   0.4, not the 0.75 this started at, and the number is arrived at by area
   rather than by eye. A bar at the middle of the column's range covers about
   30 by 8 pixels, or 240 square pixels of solid fill; the six glyphs of
   "+0.414" above it lay down something near 150. At 0.75 the annotation was
   carrying more ink than the figure it annotates, which is the wrong way
   round, and in a table forty rows deep the effect was a column of dark
   dashes with the numbers reading as their captions. At 0.4 the two are about
   level, and the bar does what it is for — letting the eye run down the column
   and find the long ones without reading a single digit — without being the
   first thing the eye finds. */
.spark rect { fill: currentColor; fill-opacity: 0.4; }
/* The stroke width has to be told not to scale, and until it was, the axis this
   whole figure is built around did not draw at all.
   A stroke width inside an SVG is in user units, and these user units are not
   pixels: the box is 76 wide by declaration but 58 wide on the page, because
   `max-width: 100%` narrows it to the column and `preserveAspectRatio` then
   scales the drawing uniformly to fit. Everything in the picture is therefore
   drawn at 0.76 of its stated size, which is harmless for a rectangle and fatal
   for a hairline: one unit became three-quarters of a pixel, and a
   three-quarter-pixel line of #E8E8E8 antialiases to #F8F8F8, three per cent
   grey. Photographed, the entire spark box held exactly one colour besides
   white, and that colour was the bar. Every column of pixels either side of it
   was #FFFFFF.
   That mattered more than a missing hairline usually does, because the comment
   above claims the sign is on the page twice, "the minus on the number and the
   bar's own direction from the centre axis". With no centre axis there is no
   direction to read: thirty-nine of the sixty-three bars run left from a line
   the reader cannot see, and they look like bars at arbitrary offsets rather
   than one scale with two sides. `non-scaling-stroke` takes the width out of
   the user-unit space and puts it in device pixels, where a 1 means 1.

   `crispEdges` is the second half of the same fix. The axis sits at 38 of 76,
   which lands on 660.05 on the page, so a one-pixel stroke centred there covers
   half of column 659 and half of column 660 and paints both at about #E2: the
   right quantity of ink spread over twice the width, which is a smudge rather
   than a line. Snapped, it is one column of #C3C3C3.

   The colour is the connector grey rather than the rule grey it started with,
   and it stays lighter than the bar it references. A reference mark darker than
   the data has changed places with it. */
.spark .axis {
  stroke: var(--connector);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  shape-rendering: crispEdges;
}

/* No quadrant tint rule here any more; the reason is with the code that used to
   draw it, in charts.py. Short version: a near-black green at 5.5% is grey, and
   grey is the key's colour for a different tier. */
.chart .row-stripe { fill: var(--paper-sunk); opacity: 0.5; }

/* Rank slope: two prioritisations of the same disease, joined ------------- */
.chart .tier-chip { opacity: 0.22; }
.chart .chip-text {
  font-family: var(--font-data);
  font-size: 10px;
  fill: var(--ink-2);
}
.chart .slope-line {
  stroke: var(--connector);
  stroke-width: 1.25;
  stroke-dasharray: 2 3;
}
.chart .slope-dot { stroke: var(--card); stroke-width: 1.5; fill: var(--ink-4); }
.chart .mark:hover .slope-dot, .chart .mark:focus-visible .slope-dot { r: 7.5; }
.chart .mark:focus-visible .slope-dot { stroke: var(--ink-strong); stroke-width: 2; }
/* The move is carried by the dot and only by the dot. The leader used to take
   the state colour too, which meant a chart of eleven rows drew eleven dashed
   coloured rules across two thirds of its own width, and the colour a reader
   met first — the long line — was the piece of the row that carries no value.
   The leader is a connector: it says which dot belongs to which name, nothing
   more, and it stays the connector grey the rest of the kit uses for exactly
   that. Left with the state colour it also broke the house rule twice over,
   once for green as a fill on something that is not a verdict and once for a
   tone applied to a line rather than to a mark. */
.chart .slope-row.falls .slope-dot { fill: var(--caution); }
.chart .slope-row.rises .slope-dot { fill: var(--supports); }
.chart .slope-row.holds .slope-dot { fill: var(--ink-3); }
.chart .hit { cursor: pointer; }
