/* ============================================================================
   Pingo — screen 1g, DIAGNOSE RESULT.  The answer a Guided diagnose run gives.

   Every selector is scoped under .pgs-diagres and there are NO @keyframes in
   this file at all. That is the design, not an omission: see section 12.

   WHY THIS SCREEN EXISTS. Tab 1f draws the symptom picker, i.e. the screen
   BEFORE a run. The thing 1.0.1 is actually about — a run that answers with one
   word and one sentence, and refuses to say "All clear" over anything it could
   not test — was depicted nowhere on the site. This file draws it.

   SOURCE OF TRUTH. There is no design-canvas artboard for this screen, so every
   value below is reconstructed from the app itself, not from a canvas:
     * lib/screens/diagnose/diagnose_run_screen.dart  — the whole composition.
       :552   AppBar title 'Diagnose'
       :1114-1131  _RunTitle, 20px w800, letter-spacing -0.4, line-height 1.15
       :1148-1190  _VerdictCard: GlassCard.solid, Tag(word, tone), 12px gap,
                   sentence at 16.5px w800 line-height 1.32. The confidence line
                   renders ONLY when a rule fired, so it is absent here.
       :1241-1271  _DetailsControl: SectionRule('DETAILS', meta: count) plus a
                   chevron, 44px minimum tap height.
       :1328-1440  _CoverageCard: label 'Checks', meta '5 of 5 done', the
                   notAnAllClear headline, then the untested-question block.
       :1756-1888  _Timeline / _StepRow: BracketPanel, 24px marker, 14px gap,
                   13.5px w700 title, a Tag, then a 12px headline at 1.35.
       :1890-1917  _StepMarker: hatched = HatchBox(radius 6); conclusive = a
                   24px tile, fill tone@12%, border tone@60%, 14px glyph.
     * lib/theme/tokens.dart — every colour, radius and type size.
     * lib/widgets/ui.dart — GlassCard (:841), SectionRule (:2920), Tag (:1910),
       _HatchSurface (:671), HonestyToneX (:91).

   TOKENS, NOT INVENTIONS. The colour names below are the ones screens/*.css
   already use (--pgs-ink, --pgs-mut, --pgs-faint, --pgs-untested, --pgs-hatch).
   The one difference from diagnose.css is the card fill: that file follows the
   canvas's rgba(9,14,21,.52); this screen has no canvas, so it follows the app,
   where GlassCard's fill is P.sur rgba(24,35,48,.82) with P.lineStrong as its
   border and a P.surFrost highlight over the top 12%.

   THE SCALE KNOB is --pgs-s, the same name diagnose.css uses, declared on this
   screen's own root. gallery.css sets --gal-scale once for the whole rail and
   the max() below enforces the 0.88 floor mechanically, because the screen is
   authored at 375x812 with 9-9.5px mono labels and 9px is the floor.

   WHAT IS ELIDED, said plainly. The app's DETAILS holds four sections in this
   run and the screen scrolls. One 812px frame cannot hold all four, so this
   mock draws the first one (WHAT WE COULDN'T CHECK) and the third (CHECKS RUN),
   which are the two that carry the doctrine, and the DETAILS row states the
   real count of four so nothing here reads as the whole of it. The list under
   CHECKS RUN runs on under the floating nav, exactly as a scrolled list does.
   ============================================================================ */


/* ---------------------------------------------------------------------------
   1. Outer box, tokens, defensive reset
   --------------------------------------------------------------------------- */

.pgs-diagres {
  --pgs-s: max(.88, var(--gal-scale, .88));

  /* content-box so the optional bezel's padding and border sit OUTSIDE the
     375px, matching every other screen in the rail. */
  box-sizing: content-box;
  width: calc(375px * var(--pgs-s));
  height: calc(812px * var(--pgs-s));
  flex: none;
  position: relative;
  user-select: none;
  -webkit-user-select: none;

  /* The host page sets line-height 1.6 and its own family; both would break
     this stack, so the subtree is re-based here. */
  font-family: var(--pgs-font);
  font-size: 16px;
  font-weight: 400;
  line-height: normal;
  letter-spacing: normal;
  text-align: left;
  color: var(--pgs-ink);
  -webkit-font-smoothing: antialiased;

  --pgs-font: 'Sora', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --pgs-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Consolas, monospace;

  --pgs-ink: #F2F6FC;          /* titles, numbers, verdict sentences */
  --pgs-ink2: #D7E0EC;         /* row values, the INFO chip's ink */
  --pgs-mut: #B7C4D6;          /* body prose */
  --pgs-faint: #94A2B6;        /* mono labels and units */
  --pgs-faint2: #7F8EA4;       /* sub-captions, the section meta */
  --pgs-untested: #A3B1C3;     /* hatched values — never mint, never red */
  --pgs-on-light: #0B121C;     /* ink on the white actions */

  --pgs-sur: rgba(24, 35, 48, .82);     /* P.sur, the card fill */
  --pgs-line: rgba(255, 255, 255, .11);
  --pgs-line-strong: rgba(255, 255, 255, .14);
  --pgs-line-soft: rgba(255, 255, 255, .09);

  /* Mint = pass, amber = caution, red = fail, and there is no fourth hue. The
     info tone is neutral steel on purpose: a step that reported an inventory
     ran, so it does not hatch, and it has not passed, so it is not mint. */
  --pgs-pass: #35D6A0;
  --pgs-pass-text: #6FE0B6;
  --pgs-warn-text: #E7C08A;

  --pgs-hatch: repeating-linear-gradient(45deg, transparent 0 4px, rgba(255, 255, 255, .06) 4px 8px);
  --pgs-hatch-line: rgba(255, 255, 255, .2);
}

.pgs-diagres *,
.pgs-diagres *::before,
.pgs-diagres *::after { box-sizing: border-box; }

.pgs-diagres div,
.pgs-diagres span { margin: 0; padding: 0; }

.pgs-diagres svg { display: block; flex: none; overflow: visible; }

/* Optional device bezel, identical to the rail's other screens. */
.pgs-diagres.pgs-diagres--bezel {
  background: #060B16;
  padding: calc(9px * var(--pgs-s));
  border: calc(9px * var(--pgs-s)) solid #03060c;
  border-radius: calc(46px * var(--pgs-s));
  box-shadow: 0 0 0 2px #16223a, 0 30px 70px rgba(0, 0, 0, .6);
}

/* lbl() from ui.dart:842 — JetBrainsMono 9.5, w700, letter-spacing 1.6, faint,
   tabular. It does not uppercase; the caller does, and every caller does. */
.pgs-diagres .pgsdr-lbl {
  font: 700 9.5px var(--pgs-mono);
  letter-spacing: 1.6px;
  color: var(--pgs-faint);
  font-variant-numeric: tabular-nums;
  text-transform: uppercase;
}


/* ---------------------------------------------------------------------------
   2. Screen root + the two bloom layers. Identical to the rail's other screens
      (P.bloom over the top 46%, P.bloomCore over the top 22%).
   --------------------------------------------------------------------------- */

.pgs-diagres .pgsdr-screen {
  position: relative;
  width: 375px;
  height: 812px;
  flex: none;
  border-radius: 38px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg,
    #22303F 0%, #1A2634 13%, #111A25 36%, #0A0F16 66%, #04070B 100%);
  transform: scale(var(--pgs-s));
  transform-origin: top left;
}

.pgs-diagres .pgsdr-bloom { position: absolute; top: 0; left: 0; right: 0; }
.pgs-diagres .pgsdr-bloom--sheet {
  height: 46%;
  background: linear-gradient(180deg,
    rgba(163, 187, 214, .2), rgba(163, 187, 214, .06) 46%, transparent 100%);
}
.pgs-diagres .pgsdr-bloom--core {
  height: 22%;
  background: radial-gradient(120% 100% at 50% 0%, rgba(190, 210, 232, .16), transparent 72%);
}


/* ---------------------------------------------------------------------------
   3. Status bar. Copied from the rail's other screens so the six frames agree.
   --------------------------------------------------------------------------- */

.pgs-diagres .pgsdr-sb {
  height: 44px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 26px;
  font: 700 12px var(--pgs-font);
  color: #D7E0EC;
  position: relative;
  z-index: 3;
}
.pgs-diagres .pgsdr-sb-icons { display: flex; gap: 6px; align-items: center; }


/* ---------------------------------------------------------------------------
   4. Content column.

      20px horizontal padding, not the screen-standard 18: the run screen is a
      ListView with `padding: fromLTRB(20, 8, 20, 28)` (diagnose_run_screen
      :557) rather than a SteelScaffold, and that 2px is visible against the
      cards beside it in the rail.

      NO NAV RESERVE HERE, and that is deliberate. This list is long and the
      frame catches it mid-scroll, so the last rows pass under the floating nav
      exactly as they do on the phone. A reserve would have ended the list in
      mid-air above the pill and implied the screen had nothing more to show.
   --------------------------------------------------------------------------- */

.pgs-diagres .pgsdr-col {
  flex: 1;
  min-height: 0;
  position: relative;
  z-index: 2;
  padding: 0 20px;
  /* MARGIN, not padding. overflow:hidden clips at the PADDING box, so a
     padding-bottom leaves the content painting right down to the frame edge and
     a row surfaces in the strip below the nav pill. A margin shortens the box
     itself, so the list disappears behind the pill instead. */
  margin-bottom: 14px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}


/* ---------------------------------------------------------------------------
   5. The app bar. AppBar(title: Text('Diagnose')) over the app's own
      AppBarTheme (tokens.dart:884-897): transparent, no elevation, left
      aligned, title in Sora 19 w800 letter-spacing -0.5.

      Drawn as a chevron and a title inside the padded column, which is the
      idiom 1b and 1c already use for a pushed screen, rather than as a
      full-bleed Material toolbar. Same information, same order, one less
      inconsistency across the rail.
   --------------------------------------------------------------------------- */

.pgs-diagres .pgsdr-head {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 46px;
  flex: none;
}
.pgs-diagres .pgsdr-head-title {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -.5px;
  color: var(--pgs-ink);
}


/* ---------------------------------------------------------------------------
   6. The run title — the recipe's own name, and nothing else.

      Once the run has answered, the live header card (chip, progress hairline,
      elapsed clock) is removed: none of it is a live measurement any more.
      What is left is the question the user asked (diagnose_run_screen:1108).
   --------------------------------------------------------------------------- */

.pgs-diagres .pgsdr-runtitle {
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -.4px;
  line-height: 1.15;
  color: var(--pgs-ink);
  flex: none;
}


/* ---------------------------------------------------------------------------
   7. Cards. GlassCard: fill P.sur, 1px P.lineStrong all round, radius 20, and
      a P.surFrost highlight painted over the top 12% AFTER the border, so it
      lifts the hairline (ui.dart:960-995). Cards carry no shadow.

      .solid is blur 0 and otherwise identical paint. Both cards on this screen
      are .solid in the app, for the reason P.blurCard's own note gives: they
      sit over a smooth gradient, and blurring a smooth ramp returns the ramp.
   --------------------------------------------------------------------------- */

.pgs-diagres .pgsdr-card {
  position: relative;
  background: var(--pgs-sur);
  border: 1px solid var(--pgs-line-strong);
  border-radius: 20px;
  flex: none;
}
.pgs-diagres .pgsdr-card::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 12%;
  border-radius: 20px 20px 0 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, .05), transparent);
  pointer-events: none;
}

/* ---- 7a. The verdict card ---- */

.pgs-diagres .pgsdr-card--verdict {
  padding: 12px 14px;
  margin-top: 14px;
}

/* THE HATCHED CHIP. Tag renders a hatched tone as a _HatchSurface with NO
   fill — hatch texture, a 1px DASHED border in P.hatchDash, and the label in
   P.mut2. That is what carries "part of this was never measured" all the way
   to the top of the screen, and it is why the verdict word here can never be
   mistaken for a pass or a fail. Radius 5, padding 6 x 3 (ui.dart:1941-1946). */
.pgs-diagres .pgsdr-tag {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  padding: 3px 6px;
  border-radius: 5px;
  font: 700 9.5px var(--pgs-mono);
  letter-spacing: 1px;
  font-variant-numeric: tabular-nums;
}
.pgs-diagres .pgsdr-tag--untested {
  background: var(--pgs-hatch);
  border: 1px dashed var(--pgs-hatch-line);
  color: var(--pgs-untested);
}
.pgs-diagres .pgsdr-tag--pass {
  background: rgba(53, 214, 160, .17);   /* Sem.pass.chipTint */
  color: var(--pgs-pass-text);
}
.pgs-diagres .pgsdr-tag--info {
  background: rgba(255, 255, 255, .07);  /* P.surCell — info has no hue */
  color: var(--pgs-ink2);
}

.pgs-diagres .pgsdr-sentence {
  margin-top: 12px;
  font-size: 16.5px;
  font-weight: 800;
  line-height: 1.32;
  color: var(--pgs-ink);
}


/* ---------------------------------------------------------------------------
   8. SectionRule, and the DETAILS control built on it.
      SectionRule (ui.dart:2920-3002): the label uppercased in lbl(P.faint), a
      9px gap, then a 1px hairline in P.lineSoft, then an optional right meta
      in lbl(P.faint2, letter-spacing 1.0), also uppercased.
   --------------------------------------------------------------------------- */

.pgs-diagres .pgsdr-rule {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: none;
}
.pgs-diagres .pgsdr-rule-line { height: 1px; background: var(--pgs-line-soft); flex: 1 1 auto; }
.pgs-diagres .pgsdr-rule-meta { letter-spacing: 1px; color: var(--pgs-faint2); flex: none; }

/* The app's own vertical rhythm: 20px between a card and the rule that heads
   the next section (diagnose_run_screen:632), 12px between the DETAILS control
   and the first rule it reveals (:629). Written as adjacency rules, a little
   tightened, so a section added later inherits the spacing instead of carrying
   a margin of its own. */
.pgs-diagres .pgsdr-card + .pgsdr-rule { margin-top: 16px; }
.pgs-diagres .pgsdr-details + .pgsdr-rule { margin-top: 8px; }

/* 44px minimum, because it is a tap target. The chevron SWAPS rather than
   rotating: a reveal that animated would put motion on withheld readings at
   the exact moment they arrive. */
.pgs-diagres .pgsdr-details {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  margin-top: 14px;
  flex: none;
}
.pgs-diagres .pgsdr-details .pgsdr-rule { flex: 1 1 auto; }
.pgs-diagres .pgsdr-details-chev { color: var(--pgs-faint); }


/* ---------------------------------------------------------------------------
   9. The coverage card — "WHAT WE COULDN'T CHECK".

      Its headline is notAnAllClear(coverage) VERBATIM, the same function the
      verdict sentence above it came from, so the word at the top and the card
      one tap under it cannot make two different promises about one coverage
      (run_coverage.dart:268-288).

      The header states the checks arithmetic rather than a state word:
      5 OF 5 DONE. Every check in this run reached a result. The run is still
      not an all-clear, because what was not tested is not a CHECK — it is a
      question the recipe declared in advance that a run of this shape cannot
      answer, and it is counted separately for exactly that reason.
   --------------------------------------------------------------------------- */

.pgs-diagres .pgsdr-card--coverage {
  padding: 12px 14px;
  border-radius: 18px;
  margin-top: 12px;
}
.pgs-diagres .pgsdr-card--coverage::before { border-radius: 18px 18px 0 0; }

.pgs-diagres .pgsdr-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 9px;
}

.pgs-diagres .pgsdr-cov-head {
  font-size: 15px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--pgs-ink);
}

.pgs-diagres .pgsdr-cov-lead {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--pgs-mut);
  margin-top: 9px;
}

/* The glyph is △ in Sem.warn.text and the row is "title in straight double
   quotes, reason in round brackets" — RunCoverage.describe, so the row cannot
   drift from the reason the step itself carried. */
.pgs-diagres .pgsdr-cov-row {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin-top: 6px;
}
.pgs-diagres .pgsdr-cov-glyph {
  font-size: 12px;
  font-weight: 700;
  line-height: 1.45;
  color: var(--pgs-warn-text);
  flex: none;
}
.pgs-diagres .pgsdr-cov-row-txt {
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--pgs-mut);
  flex: 1 1 auto;
  min-width: 0;
}
.pgs-diagres .pgsdr-cov-refusal {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--pgs-mut);
  margin-top: 6px;
}


/* ---------------------------------------------------------------------------
   10. CHECKS RUN — the same timeline the live run used, every planned step,
       with its tag and its own headline.

       The declared untested question is NOT in here, and that is the app, not
       an omission: _Timeline iterates recipe.steps (diagnose_run_screen:1771),
       and a question nobody attempted is not a check. It appears once, in the
       coverage card above, under a lead-in that says so.
   --------------------------------------------------------------------------- */

.pgs-diagres .pgsdr-timeline {
  margin-top: 12px;
  padding: 0;
  overflow: hidden;
}
.pgs-diagres .pgsdr-timeline::before { border-radius: 20px 20px 0 0; }

.pgs-diagres .pgsdr-step {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 12px;
  position: relative;
}
/* Divider(height: 1, indent: 52, endIndent: 12) — it starts past the marker
   column so the rows read as one instrument rather than as separate plates. */
.pgs-diagres .pgsdr-step + .pgsdr-step::before {
  content: '';
  position: absolute;
  left: 52px; right: 12px; top: 0;
  height: 1px;
  background: var(--pgs-line-soft);
}

/* The marker. Conclusive = a 24px tile, fill tone at 12%, border tone at 60%,
   a 14px glyph. Hatched = HatchBox(radius 6), texture only and NO border
   (HatchBox defaults bordered:false), never a green or a red one. */
.pgs-diagres .pgsdr-mark {
  width: 24px; height: 24px; flex: none;
  border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
}
.pgs-diagres .pgsdr-mark--pass {
  background: rgba(53, 214, 160, .12);
  border: 1px solid rgba(53, 214, 160, .6);
  color: var(--pgs-pass);
}
.pgs-diagres .pgsdr-mark--info {
  background: rgba(163, 177, 195, .12);
  border: 1px solid rgba(163, 177, 195, .6);
  color: var(--pgs-untested);
}

/* display:block / display:flex on these four is load-bearing, for the reason
   diagnose.css spells out at .pgs-sym-name: they are <span>s, and without it
   the step's name and its sentence reflow as one run of text instead of
   stacking. The app draws them as two stacked lines and the sentence is a
   separate, quieter statement about what that check found. */
.pgs-diagres .pgsdr-step-body { display: block; flex: 1 1 auto; min-width: 0; }
.pgs-diagres .pgsdr-step-top {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
.pgs-diagres .pgsdr-step-name {
  display: block;
  flex: 1 1 auto;
  min-width: 0;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--pgs-ink);
}
.pgs-diagres .pgsdr-step-line {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.35;
  color: var(--pgs-mut);
}


/* ---------------------------------------------------------------------------
   11. Bottom nav. Copied from diagnose.css section 12 so the rail's frames
       agree: a 72px glass pill inset 16/14, radius 26, five items, the centre
       Tools tile in the white gradient.

       The fourth label reads Insights, which is what the shipping build draws
       (lib/app.dart:41-47 with Features.askPingo false). Screen 1e still says
       "Diagnose" there; that copy is stale and is not reproduced here.

       Insights is the active item, matching 1f: this screen was pushed from the
       picker, and the six frames share one nav on purpose — a per-screen active
       item would make the pill jump between tabs.
   --------------------------------------------------------------------------- */

.pgs-diagres .pgsdr-nav {
  position: absolute;
  left: 16px; right: 16px; bottom: 14px;
  height: 72px;
  border-radius: 26px;
  background: rgba(9, 13, 20, .88);
  border: 1px solid var(--pgs-line);
  backdrop-filter: blur(22px);
  -webkit-backdrop-filter: blur(22px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 6px;
  z-index: 5;
  box-shadow: 0 14px 34px rgba(0, 0, 0, .5);
}
.pgs-diagres .pgsdr-nvi {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  color: #7C8CA1;
}
.pgs-diagres .pgsdr-nvl { font-size: 9.5px; font-weight: 600; white-space: nowrap; }
.pgs-diagres .pgsdr-nvi--active { color: var(--pgs-ink); }
.pgs-diagres .pgsdr-nvi--active .pgsdr-nvl { font-weight: 700; }
.pgs-diagres .pgsdr-nvi-tile {
  width: 34px; height: 34px; flex: none;
  border-radius: 12px;
  background: linear-gradient(150deg, #FFFFFF, #C9D6E6);
  display: flex; align-items: center; justify-content: center;
  color: var(--pgs-on-light);
  box-shadow: 0 8px 18px rgba(0, 0, 0, .45);
}


/* ---------------------------------------------------------------------------
   12. HONEST FINAL FRAMES — blocks A and B, and they are empty.

       NOTHING ON THIS SCREEN ANIMATES, in any state, and that is the cardinal
       rule applied rather than a corner cut. A verdict is not a live reading:
       the run has ended, the header card with its progress hairline and its
       elapsed clock has already been removed, and _VerdictCard's own doc says
       it in one line — "It does not animate. A verdict is not a live reading,
       and a hatched one least of all."

       So there is no .is-offstage rule to write and no reduced-motion rule to
       write: the frame this screen holds when the gallery scrolls away is the
       frame it was already holding. The two blocks are named here anyway, with
       this note, because the rail's contract is that every screen answers
       .is-offstage on its honest final frames. If a future edit ever adds an
       animation to this file, it must be stopped in BOTH blocks on the same
       commit, the way diagnose.css section 14 says.

       .pgs-diagres.is-offstage      — nothing to stop.
       @media (prefers-reduced-motion: reduce)
         html:not(.motion-opt-in) .pgs-diagres — nothing to stop.
   --------------------------------------------------------------------------- */
