/* ==========================================================================
   Interactive report — design tokens
   Palette, neutrals, card and connector specs are taken from the house
   design kit. Type is Inter, the face the house products ship, with the
   kit's Arial as the fallback. Values marked EXTRAPOLATED are not in
   the kit and are documented in METHOD.md.
   ========================================================================== */

:root {
  /* --- Brand primaries, exactly as published in the kit ------------------ */
  --house-green:      #00A607;
  --house-green-tint: #BAFFBD;
  --house-teal:       #01CB83;
  --house-teal-tint:  #C2FFE9;
  --house-olive:      #82AC3D;
  --house-olive-tint: #E7F0D6;
  --house-blue:       #0E8CFF;
  --house-blue-tint:  #CFE8FF;
  --house-purple:     #583BA8;
  --house-purple-tint: #DCD5F0;

  /* --- Kit neutrals ------------------------------------------------------ */
  --rule:             #E8E8E8;  /* kit: card and box outlines, 0.75pt */
  --connector:        #C3C3C3;  /* kit: all arrows and lines */

  /* --- Reading surface ---------------------------------------------------
     White, like the products and the kit's slides. Cards separate from the
     page by the kit outline rather than by a tinted ground. */
  --paper:            #FFFFFF;
  --paper-sunk:       #F4F6F4;  /* wells, table zebra, inactive chips (EXTRAPOLATED) */
  --card:             #FFFFFF;  /* kit node card fill */

  /* --- Ink ramp (EXTRAPOLATED from the kit's #000000 on white) ----------- */
  --ink:              #101418;  /* body text */
  --ink-strong:       #000000;  /* kit value, display headings */
  --ink-2:            #333B42;  /* secondary prose */
  --ink-3:            #5C666E;  /* captions, labels, metadata */
  --ink-4:            #878F96;  /* disabled, axis ticks */

  /* --- Accent ------------------------------------------------------------
     The brand green is the page's structural color, as it is across every
     product in the family: the masthead mark, section icons, eyebrows, links,
     active navigation and metric accents all take it. #00A607 on white is
     about 3.0:1, below the 4.5:1 needed for text, so wherever the accent
     carries words it darkens to --accent-ink; fills, marks and rules use the
     exact brand value. Because green also means "supports" in the evidence
     vocabulary below, every evidence judgment on the page is carried by a
     labeled chip — words first, color second — so a green link and a green
     verdict cannot be confused by a reader who can read. */
  --accent:           var(--house-green);
  --accent-ink:       #046B08;  /* 6.0:1 on white */
  --accent-wash:      #EFFAEF;
  --accent-tint:      var(--house-green-tint);

  /* --- Evidence direction -------------------------------------------------
     Two hues carry judgment on this page and no more: the brand green, which
     in the house materials *is* the affirmative mark, and a claret against it
     (EXTRAPOLATED; the kit has no red). Every use of either carries a text
     label; the color is reinforcement, never the sole carrier.

     Caution and flag are graphite, and that is a decision rather than a
     shortage of colors. They used to be an amber #9A6B12 and a wine #8C2F4E,
     which put four saturated hues on a page whose brand has one, and two of
     them appeared nowhere in the company's palette. Worse, the page never
     printed a key: a reader met a mustard rule and a wine rule side by side
     with nothing anywhere to say which was the more serious, so the color was
     decoration wearing the clothes of information.

     They are also not directions. Supports and opposes say which way the
     evidence points; caution and flag say how hard to look at it, which is a
     degree and reads better as weight than as hue. So the two are one color
     at two values — flag darker than caution — and the word beside them does
     the naming, as it already did. A page that runs nine of these now reads as
     a page with two opinions and some gray, which is what it is. */
  --supports:         var(--house-green);
  --supports-ink:     #046B08;
  --supports-wash:    #EFFAEF;
  --opposes:          #B3271E;
  --opposes-wash:     #FCEFED;
  --caution:          #6B6257;  /* warm graphite, 5.9:1 on white */
  --caution-wash:     #F5F4F2;
  /* "The same gray, darker" is what the block above promises and what this
     line did not deliver. It was #3F4448, which is a cool gray — blue is its
     strongest channel — while caution above it is warm, with red strongest. On
     most of the page they are far enough apart that nobody could compare them,
     but the method section stacks a caution note directly above a flag note,
     and the reader met a brown bar and a blue-black one: two colors reading as
     two different meanings, over two headings that name no direction and so
     leave the color to say it alone.
     Now literally the same hue and saturation as caution at a lower value
     (H 33°, S 10%, L 38% → 25%), which is the ramp the comment describes: one
     gray, twice, darker for the more serious of the two. 10.2:1 on white, so it
     also gains a little contrast over the color it replaces. */
  --flag:             #464039;  /* the same gray as caution, darker */
  --flag-wash:        #F3F2EF;  /* and its wash follows it out of the blues */
  --neutral-mark:     #878F96;

  /* --- Categorical data: the product palette ------------------------------
     Series take the kit's product primaries — the blue, teal, purple and
     olive above — which is how the house charts are colored. The brand green itself is not a series: it belongs to the
     chrome and to "supports", and a data series must not borrow either. */
  --cat-1:            #0E8CFF;
  --cat-2:            #583BA8;
  --cat-3:            #01CB83;
  --cat-4:            var(--connector);

  --series-a:         #0E8CFF;  /* the kit blue */
  --series-b:         #01CB83;  /* the kit teal */
  --series-c:         #583BA8;  /* the kit purple */
  --series-d:         #82AC3D;  /* the kit olive */

  /* --- Tier scale, used by the indication charts --------------------------
     A tier is a rank and the rank is an endorsement, so the scale is one hue
     ordered by depth: Tier 1 darkest, Tier 4 the connector gray the kit
     already uses for "nothing to say". Depth survives grayscale and
     color-blindness where hue does not.

     The steps are wide on purpose. They were three values within about a third
     of the lightness range, and at the 5.5px the scatter draws its points at
     they were one color: a chart whose whole subject is which tier a disease
     falls in showed thirty-eight dots and no tiers. Ordering by depth only
     works if the reader can see the depth, so tier 1 is nearly black and tier 3
     nearly white, with the product value between them.

     The hue is the kit purple, and it is purple because it cannot be
     green and cannot be either of the other two. It was a green ramp, and the
     middle step of it was #00A607 exactly: the brand value, painted on a data
     series, thirty-eight times, under a rule written twenty lines above this
     one saying a series must not borrow it. The neighboring figures in the same
     subsection are also the reason it cannot simply move to blue or teal —
     there a mark's color names a gene, one in the kit blue and its paralog
     in the kit teal, so a tier drawn in either would mean one thing in one
     figure and another in the next. Purple is unspoken in that subsection,
     which is the whole of its qualification. */
  --tier-1:           #1B1233;
  --tier-2:           #583BA8;
  --tier-3:           #C1B4E6;
  --tier-4:           var(--connector);

  /* --- Development stage --------------------------------------------------
     Phase 3 is further along than Phase 1, not better news, so stage wears
     the kit blue (darkened to carry text), never the green. */
  --stage-ink:        #0A62BE;
  --stage-wash:       #E9F4FF;

  /* --- Strength ramps ------------------------------------------------------
     Confidence is not a direction, so the ramp carries no hue: filled dark,
     filled light, outline. It survives black-and-white printing. */
  --strength-hi-ink:   var(--ink-strong);
  --strength-hi-wash:  #E5E8EA;
  --strength-mid-ink:  var(--ink-2);
  --strength-mid-wash: var(--paper-sunk);

  /* --- Interface chrome ----------------------------------------------------
     Links and active states are brand green, dark enough for text. The focus
     ring is azure so the browser's position marker never looks like a claim
     or a link. */
  --link:             var(--accent-ink);
  --link-wash:        var(--accent-wash);
  --link-tint:        var(--house-green-tint);
  --focus:            #0B57A8;

  /* --- Type ----------------------------------------------------------------
     Inter is the typeface the house products ship; the kit's Arial
     is the metric-compatible fallback. One family for
     display, text and data — hierarchy is carried by size and weight,
     numerals go tabular via font-variant-numeric where they line up in
     columns. */
  --font-display: 'Inter', -apple-system, 'Helvetica Neue', Arial, sans-serif;
  --font-text:    'Inter', -apple-system, 'Helvetica Neue', Arial, sans-serif;
  --font-data:    'Inter', -apple-system, 'Helvetica Neue', Arial, sans-serif;
  --font-mono:    ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  --step--2: 0.75rem;     /* 12px — figure ticks, footnote marks */
  --step--1: 0.875rem;    /* 14px — captions, table cells, rail */
  --step-0:  1rem;        /* 16px — body */
  --step-1:  1.1875rem;   /* 19px — lead paragraph, h4 */
  --step-2:  1.5rem;      /* 24px — h3 */
  --step-3:  2rem;        /* 32px — h2 */
  --step-4:  2.75rem;     /* 44px — h1 */
  --step-5:  3.75rem;     /* 60px — display numbers */

  --lh-tight: 1.08;
  --lh-snug:  1.32;
  --lh-body:  1.6;

  --measure: 70ch;

  /* --- Space, on a 4px base --------------------------------------------- */
  --s-1: 0.25rem; --s-2: 0.5rem;  --s-3: 0.75rem; --s-4: 1rem;
  --s-5: 1.5rem;  --s-6: 2rem;    --s-7: 3rem;    --s-8: 4rem;
  --s-9: 6rem;    --s-10: 8rem;

  /* --- Card and connector geometry, from the kit ------------------------- */
  --card-radius: 10px;
  --card-border: 1px solid var(--rule);
  --port-size: 7px;              /* kit: 0.08in ellipse port at connector joins */

  /* --- Motion. Transform and opacity only, so nothing triggers layout. --- */
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0.05, 0.36, 1);
  --dur-1: 120ms;
  --dur-2: 220ms;
  --dur-3: 420ms;

  /* Entrances get their own curve, and the difference between it and
     `--ease-out` above is the difference between a thing arriving and a thing
     drifting. `--ease-out` is close to a quadratic: it spends the middle of its
     run still visibly moving, which is right for a hover state covering three
     pixels and wrong for an entrance covering fourteen, where it reads as the
     page catching up with itself. This one is near-exponential — most of the
     distance is gone in the first third and the rest is a settle — so an
     element that travels further does not take longer to feel finished. */
  --ease-entrance: cubic-bezier(0.16, 1, 0.3, 1);
  /* For a mark growing out of an axis. It differs from the entrance curve above
     by launching more slowly: at a seventh of the way through it is 0.192 of the
     distance behind — 77px on a 400px bar — and it does not catch up until about
     three quarters through. That is the right shape for something whose length
     is the reading, because a bar that is 49% grown after a twentieth of its
     duration has not been drawn so much as revealed, and the eye reads the final
     length without ever having watched it accumulate.

     The `1.02` control point looks like an overshoot and is not one. The curve
     peaks at 1.000028 — 0.015 of a pixel on the widest bar in this report — so
     nothing on this page ever exceeds its own value. That is the correct outcome
     and it must stay the correct outcome. For scale, a control point of 1.20
     gives a real 1.25% overshoot and 1.30 gives 3.0%; at 3% the median
     fold-change chart draws a bar reading 0.50 out to 0.515 and pulls it back.
     A figure that states the wrong number for even one frame is indefensible in
     a report somebody forwards, so this is a floor, not a preference: a measured
     length must never exceed its own value. */
  --ease-mark: cubic-bezier(0.32, 1.02, 0.36, 1);

  /* Entrance durations. Both are longer than the interface durations above and
     shorter than the 420ms the old blanket fade used, which is the wrong shape
     twice over: too slow for a block, and far too fast for a chart with fifty
     marks to place. Motion is only legible when its length matches how much
     there is to see. */
  --dur-enter: 320ms;
  --dur-mark: 520ms;
  /* How far apart two things in the same group start. Below about 40ms a
     sequence reads as one simultaneous event with a soft edge; above about 90ms
     the reader is waiting for the last of it. 55ms sits in the middle of that
     window, which is where a step wants to be: four steps of a method are four
     things, and the reader should be able to count them. */
  --stagger: 55ms;
  /* Deliberately below that window, and the two numbers are not in disagreement
     — they answer different questions. A chart's marks are not a list of things
     to be counted one at a time; forty bars arriving as forty separate events is
     a queue, and the reader stops reading the chart and starts waiting for it.
     At 26ms a row of marks reads as a single wipe with direction, which is the
     only thing the sequence needs to carry. The sub-threshold value is the
     point, not an oversight. */
  --stagger-mark: 26ms;

  --rail-w: 13.5rem;     /* 216px at the base size */

  /* The running head, named rather than repeated. Eight rules across three
     files position something beneath this bar and all eight were carrying the
     literal, so the bar could not change height without one of them being
     missed. Held in rem so it grows with the wordmark inside it instead of
     trapping a larger lockup in a bar sized for a smaller one. */
  --masthead-h: 3.5rem;  /* 56px at the base size */

  /* 1320px was the width of a page with three columns in it: a contents rail,
     the text, and a provenance column down the right. With the third column
     removed the track it had occupied stayed in the grid as empty paper, so
     every section rule and every row of figures ran roughly three hundred
     pixels past the last word of the paragraph above it and the document read
     as though a column had failed to load. Narrowing the shell brings the frame
     back to the text rather than holding the text to a frame built for material
     that is no longer there.
     63.5rem is not a round number picked for looks; it is what the page has to
     be for the two edges to meet. The widest table in the document needs 697px
     of track at the base size, so the track cannot be taken below about 44rem
     whatever the prose would prefer. Add the 13.5rem contents rail, the 3rem
     gap beside it and 1.5rem of page padding on each flank and the shell comes
     to 63.5rem, at which point the reading column ends about 38px short of the
     rule that closes the section, which reads as a margin rather than as a
     missing column.
     Stated in rem rather than in pixels because the base size is no longer
     fixed. The type grows with the window, and this grows with the type, so
     those proportions hold at every width instead of only at 16px: a 2000px
     display receives a 1334px page set in 21px type, where a fixed 1016px shell
     left it a half-width strip with 492px of blank paper down each flank. */
  --shell-max: 63.5rem;  /* 1016px at the base size */
}

/* Reduced motion zeroes the clocks rather than unpicking the rules, so every
   transition and every keyframe still runs — instantly. That is deliberate: a
   rule switched off has to be switched off correctly in every one of the
   thirty-odd places it appears, and one missed leaves a reader who asked for
   stillness watching the only thing on the page that still moves. A duration
   of zero cannot be got wrong.
   The one thing a zero duration does not stop is a keyframe with a delay, which
   would still hold its first frame for the length of the delay. The stagger
   steps go to zero here for that reason, not for tidiness. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-1: 0ms; --dur-2: 0ms; --dur-3: 0ms;
    --dur-enter: 0ms; --dur-mark: 0ms;
    --stagger: 0ms; --stagger-mark: 0ms;
  }
}
