/* The interface face, SELF-HOSTED (src/ui/static/fonts/) so it works
   with no network — this tool runs on a machine holding real claim
   material and must not fetch anything. IBM Plex Sans Arabic is ONE
   family drawing BOTH scripts: the Arabic is drawn as Arabic, not a
   Latin face with Arabic bolted on, which is what the reader of this
   product actually reads. Cairo leads the stack because it is the face
   Mozn's own Arabic client documents are set in (kfca_doc/kfca_guide.html
   imports exactly these weights) — the reader of this product already
   knows it, and matching the house is worth more than my preference.
   Plex stays as the fallback and for the figures it sets well.

   It replaces 'Inter Tight', which was never installed here — every screen was silently falling back to the
   system UI face, which is most of why this looked like a default. */
@import url('/static/fonts/cairo.css');
@import url('/static/fonts/plex.css');

/* NEVER PAIR `overflow-wrap:anywhere` WITH A TRACK WHOSE MINIMUM CAN
   REACH ZERO. `anywhere` is defined to affect INTRINSIC SIZING, so it
   drops an element's min-content contribution to its widest single
   character; a `1fr` or `min-width:0` box may then legally be granted
   one glyph, and the text renders vertically, one letter per line.
   Measured on a live claim 2026-09-03: "rear bumper" came out as
   r/e/a/r/b/u/m/p/e/r inside a scene slot.
   `break-word` breaks at the same places once a line overflows and
   leaves min-content alone, so it is the safe form. All eight uses in
   this file were converted together — four of them sat on a rule that
   also set `min-width:0`, which is the exact hazardous pairing. */
/* ═══════════════════════════════════════════════════════════════════════
   Medgulf fraud assistant — design system

   Built against the `ui-refactor` skill (Refactoring UI, read in full) and
   Radix's scale semantics. The rules actually applied, so a later editor
   knows what to keep:

     · HIERARCHY comes from weight + colour, not size alone. Competing
       elements are de-emphasised rather than the important one shouted.
     · NO `Label: Value`. Labels are small, uppercase, tracked, low-contrast;
       the DATA is what carries weight.
     · SPACING is a scale where no two steps are within 25% of each other.
       Space BETWEEN groups always exceeds space WITHIN a group.
     · NEUTRALS are tinted toward the accent. A pure grey reads as unchosen.
     · SEMANTIC colour is flip-contrast — light tinted ground, dark saturated
       text — never white on a saturated fill, and never colour alone: every
       state also carries an icon or a word.
     · DEPTH is a 4-step elevation from two-part shadows (soft ambient +
       tight occlusion), light from the top.
     · Borders are a last resort. Prefer a change of ground, spacing, or a
       4px accent rail.

   Deliberately LIGHT ONLY. Every colour is painted explicitly so the page
   holds on any host ground; this is a committed choice, not an omission.
   ═══════════════════════════════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;500;600;700&family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,600;1,8..60,400&family=JetBrains+Mono:wght@400;500;700&family=Noto+Naskh+Arabic:wght@400;600&family=Noto+Sans+Arabic:wght@400;500;600;700&display=swap');

:root{
  /* ── neutral ramp, 12 steps, cooled toward the accent ────────────────
     1-2 grounds · 3-5 component · 6-8 borders · 9-10 solid · 11-12 text */
  --n1:#fcfcfe; --n2:#f7f7fc; --n3:#f0f0f8; --n4:#e8e8f3; --n5:#dedeee;
  --n6:#d2d2e6; --n7:#bfbfd8; --n8:#a3a3c2; --n9:#7b7b9c; --n10:#6c6c8c;
  --n11:#5b5b78; --n12:#171726;

  /* ── accent: the violet of the reference product this design answers
        to. It replaces an institutional blue that was chosen when nothing
        was pinned; the client has since pinned the direction, and a house
        palette the reader already recognises beats a defensible one they
        do not. Used on links, the current nav row, focus, and the panel
        ground below — never as decoration. ─────────────────────────────*/
  --a2:#f5f3fe; --a3:#eae6fd; --a4:#ddd6fb; --a6:#bfb4f6;
  --a9:#6c5ce7; --a10:#5b4bd6; --a11:#5a49d4; --a12:#3a2e9c;

  /* ── semantic, separate from the accent, always flip-contrast ───────── */
  --r2:#fff5f7; --r3:#ffe4e8; --r6:#fbc0c9; --r9:#f43f5e; --r11:#e11d48;
  --g2:#f0fdf8; --g3:#d5f5e6; --g6:#a3e6c8; --g9:#10b981; --g11:#047857;
  --m2:#fffbf0; --m3:#fef0cd; --m6:#f7dc9e; --m9:#f59e0b; --m11:#b45309;
  --v3:#f0eafb; --v6:#cfbcee; --v11:#6741a8;

  /* ── type: three roles. Machine data and human judgement must not look
        the same, so evidence is mono and the assistant's prose is serif. */
  --ui:'Cairo','IBM Plex Sans Arabic','Noto Sans Arabic',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --prose:'Source Serif 4','Noto Naskh Arabic',Georgia,'Times New Roman',serif;
  /* THE FIGURES FACE ENDS IN A JOINING ARABIC ONE. A stack of nothing but
     monospaces has no Arabic in it at all, so any Arabic word that lands in
     a `.mono` or `.num` element — the risk pill's own band word, "8 of 21
     checkable", the run footer — fell through to whatever monospaced Arabic
     the system offers, which draws each letter in its own cell and does not
     join. Browsers pick a family PER GLYPH, so the digits still come from
     JetBrains Mono and only the Arabic reaches Cairo. */
  --mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,'Cairo','IBM Plex Sans Arabic',monospace;

  /* Hand-picked scale. THE NAMES ARE STEPS, NOT PIXEL PROMISES: --t13 is
     the thirteenth step, and at scale 1 it is 13px.
     ONE KNOB moves the whole app's type. Bahgat asked for everything a
     little larger; editing nine literals in nine places would have left
     the next person hunting for them, and the names would have started
     lying the moment --t13 stopped being 13px. */
  --tscale:1.1;
  --t9:calc(9px * var(--tscale));   --t10:calc(10px * var(--tscale));
  --t11:calc(11px * var(--tscale)); --t12:calc(12px * var(--tscale));
  --t13:calc(13px * var(--tscale)); --t14:calc(14px * var(--tscale));
  --t16:calc(16px * var(--tscale)); --t18:calc(18px * var(--tscale));
  --t20:calc(20px * var(--tscale)); --t24:calc(24px * var(--tscale));
  --t30:calc(30px * var(--tscale));

  /* spacing — no two steps within 25% of each other */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px;
  --s7:48px; --s8:64px;

  --r-sm:6px; --r-md:10px; --r-lg:14px;

  /* elevation: soft ambient + tight occlusion, light from above */
  --e1:0 1px 1px rgba(16,26,36,.05);
  --e2:0 1px 2px rgba(16,26,36,.05), 0 2px 6px rgba(16,26,36,.05);
  --e3:0 2px 4px rgba(16,26,36,.05), 0 10px 24px rgba(16,26,36,.07);
  --e4:0 4px 8px rgba(16,26,36,.06), 0 24px 56px rgba(16,26,36,.12);
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:var(--ui); font-size:var(--t14); line-height:1.5;
  background:var(--n3); color:var(--n12);
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}
h1,h2,h3{margin:0; font-weight:600; letter-spacing:-.011em; text-wrap:balance}
a{color:var(--a11); text-decoration:none}
a:hover{text-decoration:underline}
:focus-visible{outline:2px solid var(--a9); outline-offset:2px; border-radius:3px}
@media(prefers-reduced-motion:reduce){*{transition:none!important; animation:none!important}}

/* Icons are visually heavy — they get a softer colour than the text they
   sit beside, and their size comes from here, never the call site. */
svg{width:14px; height:14px; flex:none; display:inline-block; vertical-align:-2px}

/* ── type utilities ─────────────────────────────────────────────────── */
/* `.prose`, `.prose.sm` and the `.sec`/`.card .prose` measure-override lived
   here too, byte for byte duplicating `scene.css`'s `.mkpage .prose` — and
   every live use of `.prose` on this page is inside `.mkpage` (the claim
   view's own prose text). Deleted; the design's copy is the only one now. */
.mono{font-family:var(--mono); font-size:var(--t12);
  font-variant-numeric:tabular-nums}
.num{font-family:var(--mono); font-variant-numeric:tabular-nums;
  text-align:right}                           /* numbers right-align, always */
.label{font-size:var(--t11); font-weight:600; text-transform:uppercase;
  letter-spacing:.06em; color:var(--n10)}     /* labels support, data leads */
.muted{color:var(--n11)}
.dim{color:var(--n10)}
.tiny{font-size:var(--t11)}
.small{font-size:var(--t13)}
.accent{color:var(--a11)}                     /* the one accent-tinted line of text */
.tracenote{text-align:center; margin-top:var(--s2)}   /* the "see the trace" line under the page */
.faint{opacity:.75}
.nudge{margin-top:2px}                        /* the half-step this scale has no name for */

/* ── spacing, without a `style=` ──────────────────────────────────────
   Every one of these replaces an inline `style="margin…"` / `style="padding…"`
   that priced a gap in raw pixels instead of the scale above. One axis per
   class, composed rather than one bespoke shorthand per call site, so the
   same eight steps still price every gap on the page (CLAUDE.md: nothing
   hardcoded). */
.mt1{margin-top:var(--s1)}
.mt2{margin-top:var(--s2)}
.mt3{margin-top:var(--s3)}
.mb1{margin-bottom:var(--s1)}
.mb3{margin-bottom:var(--s3)}
.my-half{margin:2px 0}                        /* the half-step, top and bottom */
.pt0{padding-top:0}
.pt2{padding-top:var(--s2)}
.pt3{padding-top:var(--s3)}
.pt4{padding-top:var(--s4)}
.pb0{padding-bottom:0}
.pb2{padding-bottom:var(--s2)}
.pb3{padding-bottom:var(--s3)}
.px3{padding-inline:var(--s3)}
.px4{padding-inline:var(--s4)}
.py2{padding-block:var(--s2)}
.mw70{max-width:70ch}
/* logical, not `padding-left` — the inline styles this replaces were LTR-only
   in a bilingual app; a bullet now indents from the correct edge in Arabic. */
.pl18{padding-inline-start:18px}

/* ═══════════════════════════════════════════════════ app shell ═══════ */
.app{display:flex; min-height:100vh}

/* ONE GROUND, EDGE TO EDGE. The sidebar was `--n1` on an `--n3` body with
   a hairline between them: two greys a few percent apart meeting at a line
   down the whole window. At that distance the eye does not read "panel", it
   reads "seam" — a rendering fault rather than a boundary. Reported
   2026-09-04 with two crops of exactly that line.

   So the chrome is now ONE colour and carries no borders of its own. The
   only boundaries left on the page are the ones that mean something: the
   white cards holding data. Everything that is not data is ground. */
.sidebar{
  width:260px; flex:none; background:transparent; border:0;
  display:flex; flex-direction:column;
  position:sticky; top:0; height:100vh;
}
/* THE BRAND LOCKUP IS A COMPONENT, not a feature of the sidebar. Every
   rule below was scoped `.sidebar .logo`, so the sign-in page — which has
   no sidebar and cannot have one — rendered the mark as a bare letter and
   stacked the three lines. The sidebar keeps only what is genuinely its
   own: the height that matches the topbar, and the padding that lines the
   mark up with the nav rows beneath it. */
.logo{display:flex; align-items:center; gap:var(--s2)}
.sidebar .logo{height:56px; padding:0 var(--s4); flex:none}
.logo .mark{
  width:26px; height:26px; border-radius:var(--r-sm); flex:none;
  background:var(--a9); color:#fff; display:grid; place-items:center;
  font-weight:700; font-size:var(--t12); letter-spacing:-.02em;
}
.logo .name{font-weight:600; font-size:var(--t13); line-height:1.2}
.logo .sub{font-size:var(--t11); color:var(--n10); line-height:1.2}

/* The one action this app exists to start. It is the primary control on the
   page, so it looks like one — solid accent, not a nav row. */
.cta{
  display:flex; align-items:center; justify-content:center; gap:6px;
  margin:var(--s3) var(--s3) 0; padding:9px var(--s3);
  background:var(--a9); color:#fff; border-radius:var(--r-sm);
  font:600 var(--t13)/1.4 var(--ui); box-shadow:var(--e2);
}
.cta:hover{background:var(--a10); color:#fff; text-decoration:none}
.cta svg{color:#fff; width:13px; height:13px}

.sidebar /* NOT STRETCHED. `flex:1` pinned the footer links to the bottom of a
   100vh column, so on every surface without a claim list the sidebar was
   two small clusters separated by 400px of nothing, which reads as a page
   that failed to load rather than one with a short menu. It grows only as
   far as its content, and scrolls when there is more. */
.scroll{flex:0 1 auto; min-height:0; overflow-y:auto;
  padding:var(--s3) var(--s2)}
/* THE NAVIGATION IS ONE THING. This has now been tried three ways: footer
   links pinned to the bottom (400px of nothing in the middle), everything
   at the top (the same emptiness below), and the two anchored apart (the
   gap back in the middle, which is what Bahgat called "too far").

   The mistake was treating the empty space as something to distribute.
   Every row in this sidebar goes to a page; splitting them across a void
   makes two menus out of one. So all of it stays together as one cluster,
   with only a little more air before the administrative rows — enough to
   say they are a different kind of destination, not enough to say they are
   a different menu.

   The ONE thing that genuinely belongs at the bottom edge is the name the
   handler is acting as: it is not navigation, it is who you are, and it
   anchors the column so the space below the menu reads as margin. */
.sidebar > .foot-links{margin-top:var(--s4)}
.sidebar > .foot{margin-top:auto; flex:none}
.navgroup + .navgroup{margin-top:var(--s5)}   /* between > within */
/* the sidebar's second group (guide/underwriting links) sits outside the
   scrolling claim list and needs the same inset the list itself gets from
   `.sidebar .scroll`'s padding — app.html's own inline style, until now */
.navgroup.foot-links{padding:0 var(--s2) var(--s3)}
.navgroup > /* A GROUP HEADING THAT DOES SOMETHING. It was a label; it is now the
   control that opens and shuts its own group, because a sidebar of five
   flat links with a heading over them is a list, not a navigation. */
.glabel{
  display:flex; align-items:center; gap:var(--s2); width:100%;
  font-size:var(--t11); font-weight:600; text-transform:uppercase;
  letter-spacing:.06em; color:var(--n9);
  padding:var(--s1) var(--s2) 6px;
  border:0; background:none; cursor:pointer; font-family:var(--ui);
  text-align:start;
}
.glabel:hover{color:var(--n11)}
.glabel .gspace{flex:1}
.glabel .gchev{width:12px; height:12px; color:var(--n8);
  transition:transform .15s ease}
.navgroup.shut .glabel .gchev{transform:rotate(-90deg)}
[dir="rtl"] .navgroup.shut .glabel .gchev{transform:rotate(90deg)}
.navgroup.shut .gitems{display:none}
@media (prefers-reduced-motion:reduce){.glabel .gchev{transition:none}}

/* The icon carries the row's state with the label rather than beside it —
   a nav where only the text changes colour reads as a link list. */
.navitem .ni{width:15px; height:15px; color:var(--n9); flex:none}
.navitem:hover .ni{color:var(--n11)}
.navitem.on .ni{color:var(--a10)}
.navitem .nt{min-width:0; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap}
.navitem{
  display:flex; align-items:center; gap:10px; width:100%;
  padding:7px var(--s2); border-radius:var(--r-sm); cursor:pointer;
  color:var(--n11); font:500 var(--t13)/1.4 var(--ui);
  border:0; background:none; text-align:start;
  /* `text-align:left` here was a physical property in an RTL-first app:
     every nav label hugged the wrong edge of its own row in Arabic. */
  position:relative;
}
.navitem + .navitem{margin-top:1px}
.navitem:hover{background:var(--a2); color:var(--n12); text-decoration:none}
.navitem .ico{color:var(--n9)}                /* soften the icon */
.navitem.on{background:var(--a3); color:var(--a12); font-weight:600}
.navitem.on .ico{color:var(--a9)}
/* A RAIL ON THE CURRENT ITEM. The tint alone is easy to miss against a
   tinted sidebar; a 3px rail on the inline-start edge is not, and it
   mirrors for free. */
.navitem.on::before{content:""; position:absolute; inset-block:5px;
  inset-inline-start:0; width:3px; border-radius:0 var(--r-xs) var(--r-xs) 0;
  background:var(--a9)}
.navitem .txt{flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}

.sidebar .foot{
  padding:var(--s3) var(--s4); flex:none;
  font-family:var(--mono); font-size:var(--t11); color:var(--n10);
  line-height:1.6; overflow-wrap:break-word;
}

.content{flex:1; min-width:0; display:flex; flex-direction:column}
/* A STICKY BAR MUST BE OPAQUE. This was made transparent when the page
   gained its own heading and the bar stopped needing to shout — but it is
   still `position:sticky`, so every row of a 77-row table scrolled UNDER
   it and showed through: the claim id and the bar's own title rendered on
   top of each other, which reads as a broken page and not a subtle one.
   Reported 2026-09-04 with a screenshot of exactly that overlap.

   Frosted rather than flat, so the bar still recedes: it takes the page's
   own ground at 85% with a blur behind it, which is opaque enough to cut
   the text underneath and light enough that the bar never looks like a
   second header competing with the real one. The hairline appears only
   once there is something scrolled beneath it to separate from. */
.topbar{
  height:56px; flex:none;
  background:rgba(240,240,248,.86);
  -webkit-backdrop-filter:saturate(180%) blur(10px);
  backdrop-filter:saturate(180%) blur(10px);
  border-bottom:1px solid transparent;
  display:flex; align-items:center; gap:var(--s3);
  padding:0 var(--s5); position:sticky; top:0; z-index:20;
}
.topbar.scrolled{border-bottom-color:var(--n4)}
.topbar .title{font-size:var(--t14); font-weight:600}
.topbar .crumb{color:var(--n10); font-size:var(--t12)}
.topbar .spacer{flex:1}
/* Shrink the canvas: don't fill 1600px just because it is there. */
/* CENTRED. The canvas is capped at 1280px so a line of text never runs the
   width of a 2000px monitor — but without an auto margin the whole app sat
   against one edge with a dead column beside it, which reads as a layout
   that failed rather than one that was measured. In RTL that column landed
   on the left, which is exactly where a reader of Arabic expects the page
   to continue. */
.page{padding:0 var(--s5) var(--s5); max-width:1400px; width:100%;
  margin-inline:auto}

/* COLLAPSING THE MENU HAS TO BUY SOMETHING. The page was capped at 1280px,
   so folding the sidebar from 260px to 68px handed the 192px it freed
   straight back as margin — the reader pressed a button, the table did not
   move, and the gap beside it grew. That is a control that does nothing,
   which is the defect this app keeps having to fix.

   Railed, the cap rises so the width actually reaches the table. It is
   still a cap: a claim id and a status pill do not want to be 2000px
   apart, and the eye loses the row it is following. */
.sidebar.rail ~ .content .page{max-width:1800px}

/* ═════════════════════════════════════════════ the page's own head ════
   A 15px string in a sticky bar is a browser tab label, not a heading.
   Every reference screen this design answers to opens with the page
   naming itself at full size, and ours opened with nothing — which is
   why four surfaces read as the same grey slab. The sub-line is the
   corpus denominator, which every count below is read against; it is
   the one sentence this page owes the reader before any number. */
.pagehead{padding:var(--s5) 0 var(--s4)}
.pagehead h1{font-size:var(--t30); font-weight:600; letter-spacing:-.02em;
  color:var(--n12); line-height:1.15}
.pagehead .sub{margin-top:5px; font-size:var(--t13); color:var(--n10)}
@media(max-width:900px){.sidebar{display:none} .page{padding:var(--s4)}}

/* ═══════════════════════════════════════════════════════ card ════════ */
.card{
  background:#fff; border:1px solid var(--n5); border-radius:var(--r-lg);
  box-shadow:var(--e1); overflow:hidden;
}
.stack{display:flex; flex-direction:column; gap:var(--s4)}
.card > .head{
  padding:var(--s3) var(--s4); display:flex; align-items:center;
  gap:var(--s2); background:var(--n1); border-bottom:1px solid var(--n4);
}
.card > .head .ico{color:var(--n9)}
.card > .head h2{
  font-size:var(--t11); font-weight:600; text-transform:uppercase;
  letter-spacing:.06em; color:var(--n11); flex:1;
}
.card > .body{padding:var(--s4)}
.card > .body.flush{padding:0}

.grid2{display:grid; grid-template-columns:1fr 1fr; gap:var(--s4); align-items:start}
.split{display:grid; grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);
  gap:var(--s4); align-items:start}
@media(max-width:1080px){.grid2,.split{grid-template-columns:1fr}}

/* ═════════════════════════════════════════════════════ badge ═════════ */
/* Flip-contrast, and never colour alone — callers pair these with a word. */
.badge{
  display:inline-flex; align-items:center; gap:var(--s1);
  font:600 var(--t11)/1.5 var(--ui); letter-spacing:.02em;
  padding:1px 7px; border-radius:99px;
  background:var(--n3); color:var(--n11); border:1px solid var(--n5);
  white-space:nowrap;
}
.badge.red   {background:var(--r3); color:var(--r11); border-color:var(--r6)}
.badge.green {background:var(--g3); color:var(--g11); border-color:var(--g6)}
.badge.grey  {background:var(--n3); color:var(--n11); border-color:var(--n6)}
/* SEVERITY IS THE AUTHORITY'S RANKING, so it carries its own colour rather
   than sitting in the same grey as every other chip. A reviewer scanning
   the detail should see High without reading it. */
.badge.sev-hi{background:var(--r3); color:var(--r11); border-color:var(--r6)}
.badge.sev-md{background:var(--y3,#fdf4e3); color:var(--y11,#9a6b12);
  border-color:#efd9a8}
.badge.sev-lo{background:var(--n3); color:var(--n11); border-color:var(--n6)}
.badge.amber {background:var(--m3); color:var(--m11); border-color:var(--m6)}
.badge.blue  {background:var(--a3); color:var(--a11); border-color:var(--a6)}
.badge.violet{background:var(--v3); color:var(--v11); border-color:var(--v6)}
.badge.mono{font-family:var(--mono); font-weight:500}

/* ═══════════════════════════════════════════════════ verdict ═════════ */
/* The one place the page raises its voice. Everything else stays quiet. */
/* THE CALL AND ITS EVIDENCE, IN ONE FRAME. They were two cards with a gap
   between them, which put a border between a claim and its own support and
   made the assessment read as a separate topic. The wrapper owns the frame
   now; the verdict is its head and the assessment its body. */
/* A REASON, CLAMPED — never cut. The model's sentence used to be sliced at
   220 characters and ended mid-word; the rule's was shown whole, so one
   side of a comparison was truncated and the other was not. The full text
   is in the DOM and the limit is visual, so a click restores it and nothing
   is ever destroyed. */
.why{font-size:var(--t12); color:var(--n10); line-height:1.6;
  margin-top:var(--s2); cursor:pointer}
.why.clamp{display:-webkit-box; -webkit-line-clamp:4; -webkit-box-orient:vertical;
  overflow:hidden}
.why:focus-visible{outline:2px solid var(--a9); outline-offset:3px;
  border-radius:var(--r-sm)}


/* confidence: form as well as number, so a confident wrong answer is loud */
.conf{display:flex; flex-direction:column; align-items:flex-end;
  gap:var(--s1); flex:none}
.conf .lv{display:flex; gap:3px}
.conf .lv i{width:20px; height:4px; border-radius:2px; background:var(--n5)}
.conf .lv i.on{background:var(--a9)}
.conf.high .lv i.on{background:var(--r9)}
.conf .cap{font-size:var(--t11); font-weight:600; text-transform:uppercase;
  letter-spacing:.06em; color:var(--n10)}

/* ═════════════════════════════════════════════ the case, both ways ═══ */
.twoup{display:grid; grid-template-columns:1fr 1fr}
@media(max-width:800px){.twoup{grid-template-columns:1fr}}
.twoup > div{padding:var(--s4)}
.twoup > div + div{border-inline-start:1px solid var(--n4)}
@media(max-width:800px){.twoup > div + div{border-inline-start:0;
  border-top:1px solid var(--n4)}}
.twoup h3{display:flex; align-items:center; gap:6px; margin-bottom:var(--s2);
  font-size:var(--t11); font-weight:600; text-transform:uppercase;
  letter-spacing:.06em}
.twoup h3 svg{width:12px; height:12px}
.twoup .against h3{color:var(--r11)}
.twoup .for h3{color:var(--g11)}
.twoup .against{background:var(--r2)}
.twoup .for{background:var(--g2)}


.dline{display:flex; align-items:center; gap:var(--s3); flex-wrap:wrap;
  font-size:var(--t12)}
.dline .dk{display:inline-flex; align-items:center; gap:6px; font-weight:700;
  color:var(--n12); text-transform:uppercase; letter-spacing:.06em;
  font-size:var(--t11)}
.dline .dk svg{width:13px; height:13px; color:var(--n9)}
.dline .dpolicy{color:var(--n11)}
.dline .darrow{color:var(--n8)}
.dline .dcall{font-weight:700; letter-spacing:.02em}
.dline .dcall.bad{color:var(--r11)} .dline .dcall.ok{color:var(--g11)}
.dline .dagree{display:inline-flex; align-items:center; gap:5px;
  font-size:var(--t11); font-weight:600; padding:2px 9px;
  border-radius:999px; border:1px solid transparent}
.dline .dagree svg{width:12px; height:12px}
.dline .dagree.yes{background:var(--g3); color:var(--g11);
  border-color:var(--g6)}
.dline .dagree.no{background:var(--y3,#fdf4e3); color:var(--y11,#9a6b12);
  border-color:var(--y6,#e8c98a)}
.dline .dmore{margin-inline-start:auto; background:none; border:0; padding:0;
  cursor:pointer; font-size:var(--t12); font-weight:600; color:var(--a11)}
.dline .dmore::after{content:"\00a0\25be"}
.dline .dmore[aria-expanded="true"]::after{content:"\00a0\25b4"}

/* ═══════════════════════════════════════════════ indicators ══════════ */
.ind{padding:var(--s4); border-top:1px solid var(--n4)}
.ind:first-child{border-top:0}
.ind .top{display:flex; gap:var(--s2); align-items:baseline; flex-wrap:wrap}
.ind .n{
  font:700 var(--t11)/1.6 var(--mono); color:var(--a11);
  background:var(--a3); border-radius:var(--r-sm); padding:0 6px; flex:none;
}
.ind .txt{flex:1; min-width:200px; font-weight:600; font-size:var(--t14);
  line-height:1.4}
.ind .why{font-family:var(--prose); font-size:var(--t14); line-height:1.55;
  color:var(--n11); margin:var(--s2) 0 0; max-width:66ch}

/* Evidence is a ledger: source de-emphasised, VALUE carries the weight. */
/* THE PORTED DESIGN IS ARABIC-FIRST. `design/claim-page-mockup.html` sets
   `html{direction:rtl}`, which the port turned into `.mkpage{direction:rtl}` —
   so the scene rendered right-to-left even in the English view, with the
   parties in reverse order. The app is bilingual and already sets `dir` on
   the document, so the scene inherits it. This override is hand-written and
   belongs here, not in the generated file. */

/* THE CAR MUST HAVE A HEIGHT. The design sizes `.vsvg` by width alone and
   relies on the viewBox for the rest; inside the app's flex column the SVG
   collapsed to nothing and only its red damage zone showed — a dot under
   the vehicle's name. An explicit ratio costs nothing and cannot collapse. */
.mkpage .vsvg{aspect-ratio:120/132; height:auto}
/* `.cwrap{min-height:120px}` stood here as an earlier, cruder attempt at the
   same fix `.vsvg`'s aspect-ratio above now makes unnecessary — `.cwrap` caps
   the car at 112px wide (scene.css's own `.mkpage .cwrap{max-width:112px}`),
   and 112 / (120/132) is ~123px tall on its own, already past 120. The real
   cause of the dead band between the top card and the tier-3 heading, MEASURED
   2026-09-03: TWO `.mkpage` scopes, one from `tier2()` and one from
   `details()`, each carrying the design's own `.mkpage`'s own body padding —
   a rule meant for the bottom of ONE page, doubled onto the middle of this
   one. Fixed by unifying the page to one `.mkpage` scope (`render()`); the
   design's own padding value is scene.css's to set and has moved since. */

/* The hand-written scene CSS that stood here until 2026-09-03 is deleted.
   The design is now ported from the mockup into `scene.css` and scoped
   under `.mk`; two stylesheets describing one component is how `.vcard`
   ended up styled twice and drawn wrong. */

/* The two decision lanes were restated here at higher specificity while
   the real cause was hunted — and the real cause was one missing `}` in the
   generated stylesheet. Deleted: the design's own `.dlanes` is `1.05fr 1fr`,
   deliberately UNEQUAL ("equal columns claim equal weight, and that was the
   original defect here"), and an auto-fit override substituted equal ones. */

/* `.gcause`/`.gch`/`.gcn`/`.gcv`/`.gcw` stood here as the hand-written fix
   for UI_AUDIT section 1 finding 15, from before the design carried its own
   three-causes card. It now does — `scene.css`'s `.mkpage .gcause` sets
   `border-inline-start` alone where this set a full `border` on every side,
   so the two together drew a box with a 1px border on three sides and a 3px
   one on the fourth. Deleted; the design's copy is the only one now.
   `.lfull .lwrap` stays — the design has no rule for it. */
.mkpage .lfull .lwrap{display:flex; gap:var(--s3); flex-wrap:wrap}

/* `.vmain` — `mkVerdict()`'s flexible, shrinkable sibling for `.glyph`, so
   the headline can wrap instead of pushing the card wide — was written here
   as a hand override (the mockup hard-coded the same rule as an inline
   style, and `scene.js` used to carry it too). `scene.css` has since grown
   its own `.mkpage .vmain{flex:1; min-width:0}`, so this file's copy would
   now be the 49th duplicate this sweep exists to prevent; deleted in favour
   of the design's own rule.

   THE LEGEND'S SWATCH COLOUR. `.mkpage .ialeg > span > b:first-child`
   (scene.css) draws the swatch's SHAPE — a 10px dot — but never its fill;
   the mockup painted that inline too, one value of the same five-state
   closed set `mkState()` returns (`fired`/`clear`/`nc`/`unk`/`na`). `na`
   already has a class for its hatch (`.hatch`, scene.css); these four give
   the other states the same treatment instead of a `style="background:…"`
   per call site. Colours match `.iagrid .fired`/`.clear`/`.nc`/`.unk`
   (scene.css) — the same states, named the same way, in a different part of
   the card. */
.mkpage .ialeg > span > b.fired{background:var(--r9)}
.mkpage .ialeg > span > b.clear{background:var(--g6)}
.mkpage .ialeg > span > b.nc{background:var(--n3)}
.mkpage .ialeg > span > b.unk{background:var(--n4)}

/* THE INDICATORS PANEL'S OWN INTRO BAND. `indicators()`'s notice sat inside
   a one-off padded, bottom-ruled strip; the design has no class for it (the
   panel it lives in is `.lyr`'s own body padding everywhere else). */
.mkpage .introband{padding:var(--s3) var(--s4); border-bottom:1px solid var(--n4)}

/* ONE SCENE, FIVE LAYERS. Sections stack down the page, all open. The
   layer bar filters; it does not reveal. */
/* INSIDE THE CARD IT CONTROLS. It used to carry its own background,
   border and radius and sit above the scene as a separate slab — one more
   seam on a page the mockup draws as a single surface. It is the scene's
   header now: a hairline under it, no frame of its own. */
.layerbar{display:flex; gap:var(--s2); align-items:center; flex-wrap:wrap;
  margin:0; padding:var(--s3) var(--s4);
  border-bottom:1px solid var(--n4); background:transparent}
.layerbar .lbl{font-size:var(--t11); font-weight:600; letter-spacing:.04em;
  text-transform:uppercase; color:var(--n10)}
.layerbar .lbw{flex-basis:100%}
.lay{padding:4px 10px; border-radius:999px; border:1px solid var(--n6);
  background:var(--n1); color:var(--n11); font-size:var(--t12);
  font-family:var(--ui); cursor:pointer; box-shadow:none}
.lay.on{background:var(--a3); border-color:var(--a6); color:var(--a11);
  font-weight:600}
.lay.fixed{cursor:default; opacity:1}
/* A layer with nothing left to hide — every section it names is drawn
   inside the claim picture. Dimmed rather than removed, so the reader
   can still see that the layer exists and where its content went. */
.lay.dead{cursor:default; opacity:.45; text-decoration:line-through}
.lay:focus-visible{outline:2px solid var(--a9); outline-offset:2px}

#scene{display:flex; flex-direction:column; gap:var(--s4)}
/* `.lyr`, `.limits`, `.cfgfoot`, `.oursnote` and `.proof` stood here too,
   duplicating `scene.css`'s `.mkpage` copies — and every element `details()`
   and `settingsFooter()` give these classes now renders inside the single
   `.mkpage` scope, so the design's rule is the only one that was ever live.
   Deleted; `.iagrp.ever` below is not one of the design's classes and stays. */
.iagrp.ever summary{color:var(--n10)}
.iagrp.ever .iabody{background:var(--n1)}

/* THE REVIEW'S OBJECTION. Amber, never red: it reports, it does not remove,
   and its accuracy is unmeasured. A red block would read as a correction. */
.disp{margin-top:var(--s3); padding:var(--s3); border-radius:var(--r-md);
  background:var(--m2); border:1px solid var(--m6)}
.disp .dh{margin-bottom:var(--s2)}
.disp .quote{margin-top:var(--s2); padding:var(--s2) var(--s3);
  border-inline-start:3px solid var(--m6); background:var(--n1);
  font-size:var(--t12); line-height:1.55}

.ev{margin-top:var(--s3); border-radius:var(--r-md); overflow:hidden;
  border:1px solid var(--n4)}
.ev .row{display:grid; grid-template-columns:minmax(0,1fr) auto;
  gap:var(--s3); align-items:baseline; padding:6px var(--s3);
  background:var(--n1); font-size:var(--t12);}
.ev .row + .row{border-top:1px solid var(--n4)}
.ev .where{min-width:0; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; font-family:var(--mono); font-size:var(--t11);
  color:var(--n10)}
.ev .where b{color:var(--n11); font-weight:500}
.ev .val{font-family:var(--mono); font-weight:700; color:var(--n12);
  font-variant-numeric:tabular-nums; text-align:right}
.ev .none{padding:var(--s2) var(--s3); background:var(--m2); color:var(--m11);
  font-size:var(--t12)}
/* A sentence is not a number: long values get their own line in the prose
   face, quoted, instead of a right-aligned bold wall. Short values keep the
   compact ledger row. */
.ev .row.block{display:block}
.ev .row.block .where{white-space:normal}
.ev .quote{font-family:var(--prose); font-size:var(--t13); line-height:1.55;
  color:var(--n12); margin-top:2px; max-width:66ch}
.ev .quote::before{content:"\201C"; color:var(--n8)}
.ev .quote::after{content:"\201D"; color:var(--n8)}

/* group label between collapsed sections on the claim page */
.secgroup{font-size:var(--t11); font-weight:700; text-transform:uppercase;
  letter-spacing:.07em; color:var(--n9); margin:var(--s2) 0 calc(-1 * var(--s2))}

/* ═══════════════════════════════════════════════ severity ════════════ */
/* A stepper, not five paragraphs. Only the chosen step is expanded. */
.sev{display:flex; align-items:stretch; gap:2px}
.sev .step{
  flex:1; min-width:0; padding:var(--s2); border-radius:var(--r-sm);
  background:var(--n2); text-align:center; border:1px solid transparent;
}
.sev .step .n{font:700 var(--t11)/1.4 var(--mono); color:var(--n9)}
.sev .step .l{font-size:var(--t11); color:var(--n10); margin-top:1px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.sev .step.on{flex:2.4; background:var(--a3); border-color:var(--a6);
  box-shadow:var(--e1)}
.sev .step.on .n{color:var(--a11)}
.sev .step.on .l{color:var(--a12); font-weight:600; font-size:var(--t13);
  white-space:normal}
/* `.sev-def` duplicated `scene.css`'s `.mkpage .sev-def`; deleted. `.sev`
   above is unrelated to the design (no rule for it there) and dead in this
   app besides — `severity()` renders `.kv`/`.ph`/`.pr`/`.nar2` instead — but
   is out of this sweep's scope (not a name the two stylesheets share). */

/* ═══════════════════════════════════════════════════ table ═══════════ */
table{width:100%; border-collapse:collapse; font-size:var(--t12)}
/* Sentence case, not tracked capitals. A column head is a NAME,
   and shouting it in 11px tracked caps is the single commonest
   tell of a generated interface — it appeared on every table in
   this app because this one element selector said so. */
thead th{
  text-align:start; padding:var(--s2) var(--s3);
  font:600 var(--t12)/1.4 var(--ui); text-transform:none;
  letter-spacing:0; color:var(--n10);
  background:var(--n1); border-bottom:1px solid var(--n5);
  position:sticky; top:0; z-index:1; white-space:nowrap; cursor:pointer;
  user-select:none;
}
thead th:hover{color:var(--n12)}
thead th.num{text-align:right}
tbody td{padding:7px var(--s3); border-top:1px solid var(--n4);
  vertical-align:top}
tbody td.nw{white-space:nowrap}
tbody tr:hover{background:var(--n1)}
tr.bad{background:var(--r2)}   tr.bad:hover{background:var(--r3)}
tr.warn{background:var(--m2)}  tr.warn:hover{background:var(--m3)}
tr.click{cursor:pointer}
.scroll{overflow:auto; max-height:520px}
.scroll.tall{max-height:none}

/* ═══════════════════════════════════════════════════ kpi ════════════ */
.kpis{display:grid; grid-template-columns:repeat(auto-fit,minmax(124px,1fr));
  gap:var(--s3)}
.kpi{background:#fff; border:1px solid var(--n5); border-radius:var(--r-md);
  padding:var(--s3); box-shadow:var(--e1)}
.kpi .k{font-size:var(--t11); font-weight:600; text-transform:uppercase;
  letter-spacing:.06em; color:var(--n10)}
.kpi .v{font:700 var(--t24)/1.15 var(--mono); letter-spacing:-.02em;
  margin-top:var(--s1); font-variant-numeric:tabular-nums; color:var(--n12)}
.kpi .v.bad{color:var(--r11)} .kpi .v.ok{color:var(--g11)}
.kpi .n{font-size:var(--t11); color:var(--n10); margin-top:2px}

/* ═══════════════════════════════════════════════════ notice ══════════ */
.notice{
  border-radius:var(--r-md); padding:var(--s3); font-size:var(--t12);
  line-height:1.55; display:flex; gap:var(--s2); align-items:flex-start;
  background:var(--m2); color:var(--m11); border:1px solid var(--m6);
}
.notice svg{margin-top:2px; opacity:.9}
.notice.info{background:var(--a2); color:var(--a11); border-color:var(--a6)}
.notice.grey{background:var(--n2); color:var(--n11); border-color:var(--n5)}
.notice.ok  {background:var(--g2); color:var(--g11); border-color:var(--g6)}
.notice b{font-weight:700}
.notice a{color:inherit; text-decoration:underline}

/* ═══════════════════════════════════════════════════ controls ════════ */
button,.btn{
  font:500 var(--t13)/1.4 var(--ui);
  background:#fff; color:var(--n12); border:1px solid var(--n6);
  border-radius:var(--r-sm); padding:5px var(--s3); cursor:pointer;
  display:inline-flex; align-items:center; gap:6px; box-shadow:var(--e1);
}
button:hover{background:var(--n2); border-color:var(--n7)}
button svg{width:13px; height:13px; color:var(--n9)}
button.on,button.primary{background:var(--a9); border-color:var(--a9);
  color:#fff; font-weight:600; box-shadow:var(--e2)}
button.on svg,button.primary svg{color:#fff}
button.on:hover,button.primary:hover{background:var(--a10)}
button:disabled{opacity:.45; cursor:not-allowed}
input[type=text],input[type=search],select{
  font:400 var(--t13)/1.4 var(--ui); color:var(--n12);
  border:1px solid var(--n6); border-radius:var(--r-sm);
  padding:5px var(--s2); background:#fff;
}
.toolbar{display:flex; gap:var(--s2); flex-wrap:wrap; align-items:center}
.searchbox{padding:var(--s2)}
.searchbox input{width:100%}
/* the reviewer-feedback form's own two fields — named by id, since each is
   used exactly once and a class would only ever match itself */
#fbname{width:180px}
#fbtext{width:100%; margin-top:var(--s2); font:400 var(--t13)/1.5 var(--ui);
  border:1px solid var(--n6); border-radius:var(--r-sm); padding:var(--s2)}

/* The plain disclosure widget. Anything that draws its OWN chevron — .sec,
   .dsec, #mapwrap — must be excluded, or it gets two markers. This exact
   collision has now happened twice; keep the exclusion list next to the rule. */
.plainfold{border-top:1px solid var(--n4)}
.plainfold > summary{
  cursor:pointer; padding:var(--s2) var(--s4); font-size:var(--t12);
  font-weight:600; color:var(--a11); list-style:none; user-select:none;
}
details > summary::-webkit-details-marker{display:none}
details > summary::marker{content:""}
.plainfold > summary::before{content:"\25B8 "; color:var(--n9)}
.plainfold[open] > summary::before{content:"\25BE "}

pre{
  margin:0; padding:var(--s3) var(--s4);
  background:var(--n1); color:var(--n12); border:1px solid var(--n4);
  border-radius:var(--r-sm);
  font-family:var(--mono); font-size:var(--t11); line-height:1.65;
  overflow:auto; max-height:440px; white-space:pre-wrap; word-break:break-word;
}

.bar{height:5px; background:var(--n4); border-radius:3px; overflow:hidden}
.bar > i{display:block; height:100%; background:var(--a9); border-radius:3px;
  transition:width .3s ease}
.bar > i.amber{background:var(--m9)}

/* Never leave a container blank. */
.empty{padding:var(--s6) var(--s4); text-align:center; color:var(--n10);
  font-size:var(--t13)}
.empty svg{width:22px; height:22px; color:var(--n8); margin-bottom:var(--s2)}
.spin{display:inline-block; width:14px; height:14px;
  border:2px solid var(--n5); border-top-color:var(--a9);
  border-radius:50%; animation:sp .7s linear infinite}
@keyframes sp{to{transform:rotate(360deg)}}

/* ══════════════════════════════ trace tree (admin debug, LangSmith) ══ */
/* Left: the run as a connected tree — rails from parent to child, a type
   icon per node, duration inline. Right: the selected step's INPUT and
   OUTPUT as collapsible sections. The tree never scrolls out from under
   you: the map above it folds away, and selecting a node keeps it in view. */
.trace{display:grid; grid-template-columns:420px minmax(0,1fr);
  gap:var(--s4); align-items:start}
@media(max-width:1150px){.trace{grid-template-columns:1fr}}
.ttree{position:sticky; top:72px; max-height:calc(100vh - 90px);
  overflow:auto; background:#fff; border:1px solid var(--n5);
  border-radius:var(--r-md); box-shadow:var(--e1)}
.tbody{padding:var(--s2)}
.tbody > .tlabel{font:600 var(--t11)/1.4 var(--ui); letter-spacing:.06em;
  text-transform:uppercase; color:var(--n10); padding:var(--s1) 6px var(--s2)}

.trow{display:flex; align-items:center; gap:6px; padding:5px 6px;
  border-radius:var(--r-sm); cursor:pointer; min-width:0; position:relative}
.trow:hover{background:var(--n2)}
.trow.on{background:var(--a3); box-shadow:inset 2px 0 0 var(--a9)}
.trow.on .tname{color:var(--a12); font-weight:650}
.trow .twist{width:12px; flex:none; color:var(--n9); display:grid;
  place-items:center; transition:transform .12s}
.trow .twist.openx{transform:rotate(90deg)}
.trow .twist svg{width:11px; height:11px}
.trow .tico{width:19px; height:19px; border-radius:5px; flex:none;
  display:grid; place-items:center; background:var(--n3); color:var(--n10)}
.trow .tico svg{width:11px; height:11px}
.trow.on .tico{background:var(--a9); color:#fff}
.trow.err .tico{background:var(--r3); color:var(--r11)}
.trow .tname{flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; font-size:var(--t12); color:var(--n12)}
.trow .tname.mono{font-family:var(--mono); font-size:var(--t11)}
.trow .tsecs{flex:none; font:400 var(--t10)/1.5 var(--mono); color:var(--n9)}
.trow .tchip{flex:none; font:500 var(--t10)/1.5 var(--mono); color:var(--n10);
  background:var(--n2); border:1px solid var(--n4); border-radius:99px;
  padding:0 6px; white-space:nowrap}
.trow .tchip.tok{color:var(--v11); background:var(--v3); border-color:var(--v6)}
.trow .tchip.bad{color:var(--r11); background:var(--r2); border-color:var(--r6)}

/* rails: the hierarchy readable at a glance */
.tkids{position:relative; margin-inline-start:15px; padding-inline-start:12px}
.tkids::before{content:""; position:absolute; inset-inline-start:0; top:0; bottom:12px;
  width:1px; background:var(--n5)}
.tkids > .tnode{position:relative}
.tkids > .tnode > .trow::before{content:""; position:absolute; left:-12px;
  top:50%; width:9px; height:1px; background:var(--n5)}

/* the pipeline map, foldable so the tree stays put */
#mapwrap{border-bottom:1px solid var(--n4)}
#mapwrap > summary{cursor:pointer; list-style:none;
  padding:var(--s2) var(--s3); display:flex; align-items:center; gap:6px;
  font:600 var(--t11)/1.4 var(--ui); letter-spacing:.06em;
  text-transform:uppercase; color:var(--n10)}
#mapwrap > summary::-webkit-details-marker{display:none}
#mapwrap > summary::marker{content:""}
#mapwrap > summary:hover{color:var(--n12)}
#mapwrap > summary .twist{transition:transform .12s; width:11px; height:11px}
#mapwrap[open] > summary .twist{transform:rotate(90deg)}
#miniflow .flow{padding:var(--s1) var(--s1) var(--s3)}
#miniflow .fnode{min-width:0; width:100%; padding:4px var(--s2)}
#miniflow .fnode .ft{font-size:var(--t11)}
#miniflow .fnode .fs{font-size:var(--t10)}
#miniflow .fbranch{gap:var(--s2); width:100%}
#miniflow .fbranch .fcol{flex:1; min-width:0}
#miniflow .fedge{height:10px}
#miniflow .fsplit{height:9px}
#miniflow .fnode.on{border-color:var(--a9); background:var(--a2);
  box-shadow:inset 0 0 0 1px var(--a9)}
#miniflow .fnode.quiet[data-go]{cursor:pointer}
#miniflow .fnode.quiet[data-go]:hover{border-color:var(--a9);
  background:var(--a2)}

/* detail pane */
.dhead{display:flex; align-items:center; gap:var(--s2); flex-wrap:wrap;
  padding:var(--s3) var(--s4); background:#fff; border:1px solid var(--n5);
  border-radius:var(--r-md); box-shadow:var(--e1)}
.dhead .dt{font:600 var(--t14)/1.3 var(--mono); min-width:0;
  overflow-wrap:break-word}
.dsec{background:#fff; border:1px solid var(--n5); border-radius:var(--r-md);
  box-shadow:var(--e1); overflow:hidden}
.dsec > .dlab{display:flex; align-items:center; gap:var(--s2);
  padding:var(--s2) var(--s4); font-size:var(--t11); font-weight:700;
  letter-spacing:.06em; text-transform:uppercase; color:var(--n10);
  background:var(--n1); border-bottom:1px solid var(--n4);
  cursor:pointer; list-style:none}
.dsec > .dlab::-webkit-details-marker{display:none}
.dsec > .dlab::marker{content:""}
.dsec > .dlab:hover{color:var(--n12)}
.dsec .dchev{width:11px; height:11px; color:var(--n9); flex:none;
  transition:transform .12s}
.dsec[open] > .dlab .dchev{transform:rotate(90deg)}
.dsec:not([open]) > .dlab{border-bottom:0}
.dsec pre{border:0; border-radius:0; max-height:380px}
.dsec .kv{width:100%}
.dsec .kv td:first-child{font-family:var(--mono); font-size:var(--t11);
  color:var(--n10); width:190px; white-space:nowrap}
.dsec .kv td:last-child{font-family:var(--mono); font-size:var(--t12);
  overflow-wrap:break-word}
.dsec img{display:block; width:100%; height:auto; background:#fff}


/* ═══════════════════════════════════ pipeline graph (admin debug) ════ */
/* Sequential stages stack down the page; work that genuinely ran at the
   same time sits side by side. Concurrency here is MEASURED from the event
   timings, never assumed from the design. */
.pipe{display:flex; flex-direction:column; gap:0}
.pstage{border:1px solid var(--n5); border-radius:var(--r-md); background:#fff;
  box-shadow:var(--e1); overflow:hidden}
.pstage > .ph{display:flex; align-items:center; gap:var(--s2);
  padding:var(--s3) var(--s4); background:var(--n1);
  border-bottom:1px solid var(--n4)}
.pstage > .ph .pn{width:22px; height:22px; border-radius:50%; flex:none;
  background:var(--a9); color:#fff; display:grid; place-items:center;
  font:700 var(--t11)/1 var(--mono)}
.pstage > .ph h3{font-size:var(--t13); font-weight:650; flex:1}
.pstage > .pb{padding:var(--s3)}
.pflow{display:grid; place-items:center; padding:var(--s2) 0; color:var(--n8)}
.pflow svg{width:16px; height:16px}
.plane{display:flex; gap:var(--s2); align-items:stretch}
.plane + .plane{margin-top:var(--s2)}
.plane .lbl{width:56px; flex:none; font:600 var(--t11)/1.6 var(--mono);
  color:var(--n9); padding-top:5px}
.ptrack{flex:1; display:flex; flex-wrap:wrap; gap:var(--s1)}
.pnode{
  border:1px solid var(--n5); border-radius:var(--r-sm); background:var(--n1);
  padding:5px var(--s2); cursor:pointer; max-width:230px;
  font-size:var(--t11); line-height:1.35;
}
.pnode:hover{border-color:var(--a6); background:var(--a2)}
.pnode.on{border-color:var(--a9); background:var(--a3); box-shadow:var(--e1)}
.pnode.err{border-color:var(--r6); background:var(--r2)}
.pnode .nm{font-family:var(--mono); overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; color:var(--n12)}
.pnode .mt{color:var(--n10); font-family:var(--mono); font-size:var(--t10)}
.pill-row{display:flex; gap:var(--s1); flex-wrap:wrap}

/* what the model saw */
.saw{border:1px solid var(--n5); border-radius:var(--r-md); overflow:hidden;
  background:var(--n2)}
.saw img{display:block; width:100%; height:auto; background:#fff}
.saw pre{max-height:340px; border-radius:0}
.io2{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:var(--s4); align-items:start}
@media(max-width:1100px){.io2{grid-template-columns:1fr}}

/* ═══════════════════════════════ progressive disclosure (claim view) ══ */
/* The page opens as a BRIEF. Everything below the fold is collapsed behind a
   heading that says what it is in a claims handler's words, so the page can
   be read in ten seconds or in ten minutes. */
.glance{display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:var(--s3)}
.gtile{background:#fff; border:1px solid var(--n5); border-radius:var(--r-md);
  padding:var(--s3); box-shadow:var(--e1)}
.gtile .k{font-size:var(--t11); font-weight:600; text-transform:uppercase;
  letter-spacing:.06em; color:var(--n10)}
.gtile .v{font-size:var(--t20); font-weight:700; letter-spacing:-.02em;
  margin-top:var(--s1); line-height:1.15}
.gtile .n{font-size:var(--t12); color:var(--n11); margin-top:2px; line-height:1.4}
.gtile.warn{border-color:var(--m6); background:var(--m2)}
.gtile.warn .v{color:var(--m11)}
.gtile.bad{border-color:var(--r6); background:var(--r2)}
.gtile.bad .v{color:var(--r11)}
.gtile.good{border-color:var(--g6); background:var(--g2)}
.gtile.good .v{color:var(--g11)}

/* `.sec`'s OWN top-level rule is deleted — ui.js's `section()` disclosure
   helper duplicated `scene.css`'s `.mkpage .sec .prose` collision surface,
   and the claim page's own disclosure is `.lyr` (`details()`, below), not
   `section()`, which has no caller left anywhere in this app. `.inner` and
   `.pad` stay: `section()` still emits them, `test_ui_contracts.py`'s own
   "styled or queried" guard checks every class ANY script emits regardless
   of whether it is called today (the same rule that keeps `assessment()`
   dressed for `render_assessment.js`). Written bare rather than qualified
   under `.sec >` — qualified, `.sec` becomes this rule's own leftmost class
   and the duplicate-class guard above catches THIS file reintroducing the
   very name it just deleted. Bare, `.inner`/`.pad` collide with nothing
   `scene.css` defines either way — a wider net than `section()` needs, and
   the honest one, since `.sec` is not a name this file gets to own again. */
.inner{border-top:1px solid var(--n4)}
.inner > .pad{padding:var(--s4)}

/* ── detail-pane tabs (Prompt / JSON, Page / Prompt) ─────────────────── */
/* The admin config tab strip. Found by the CSS-class guard the moment it
   was turned on: it had rendered as two undecorated browser buttons since
   the day it was written, and nothing failed. */
.tabs{display:flex; gap:2px}
.tabs button{border:1px solid var(--n5); background:#fff; color:var(--n11);
  font-size:var(--t12); font-weight:600; padding:5px 12px; cursor:pointer;
  border-radius:var(--r-sm)}
.tabs button:hover{background:var(--n2); color:var(--n12)}
.tabs button.on{background:var(--a3); color:var(--a11); border-color:var(--a6)}
/* the muted suffix on a claim row — "IA 4", or an em dash when nothing fired */
.tail{font-size:var(--t12); font-variant-numeric:tabular-nums; color:var(--n11)}
.tail.muted{color:var(--n8)}

.dtabs{display:flex; gap:2px; margin-inline-start:auto}
.dtabs button{border:0; box-shadow:none; background:none; color:var(--n10);
  font:600 var(--t11)/1.4 var(--ui); padding:2px 8px; border-radius:99px}
.dtabs button:hover{background:var(--n3); color:var(--n12)}
.dtabs button.on{background:var(--a3); color:var(--a11)}

/* ── the pipeline as a GRAPH ─────────────────────────────────────────── */
/* A picture of the flow with this run's real numbers on it. Sequential
   stages stack; the extract fan draws its branches side by side. */
.flow{display:flex; flex-direction:column; align-items:center;
  padding:var(--s5) var(--s4)}
.fnode{
  background:#fff; border:1.5px solid var(--n6); border-radius:var(--r-md);
  box-shadow:var(--e1); padding:var(--s2) var(--s4); min-width:230px;
  text-align:center; cursor:pointer;
}
.fnode:hover{border-color:var(--a9); background:var(--a2)}
.fnode.quiet{cursor:default; border-style:dashed}
.fnode.quiet:hover{border-color:var(--n6); background:#fff}
.fnode .ft{font-weight:650; font-size:var(--t13)}
.fnode .fs{font-size:var(--t11); color:var(--n10); margin-top:1px;
  font-family:var(--mono)}
.fnode.verdict-sus{border-color:var(--r6); background:var(--r2)}
.fnode.verdict-sus .ft{color:var(--r11)}
.fnode.verdict-clean{border-color:var(--g6); background:var(--g2)}
.fnode.verdict-clean .ft{color:var(--g11)}
.fedge{width:2px; height:22px; background:var(--n6); position:relative}
.fedge::after{content:""; position:absolute; bottom:-1px; left:50%;
  transform:translateX(-50%); border:5px solid transparent;
  border-top-color:var(--n6); border-bottom:0}
.fbranch{display:flex; gap:var(--s5); align-items:stretch;
  justify-content:center}
.fbranch .fcol{display:flex; flex-direction:column; align-items:center}
.fsplit{display:flex; justify-content:center; width:100%; position:relative;
  height:20px}
.fsplit::before{content:""; position:absolute; top:0; left:25%; right:25%;
  border-top:2px solid var(--n6); border-left:2px solid var(--n6);
  border-right:2px solid var(--n6); height:100%;
  border-radius:var(--r-md) var(--r-md) 0 0; border-bottom:0}
.fsplit.down::before{top:auto; bottom:0; border-top:0;
  border-bottom:2px solid var(--n6);
  border-radius:0 0 var(--r-md) var(--r-md)}

/* ── Arabic mode (customer view only) ─────────────────────────────────── */
[dir="rtl"] .prose{max-width:60ch}
/* plaintext bidi: each paragraph takes the direction of its own first strong
   character, so an untranslated English sentence on an Arabic page reads
   left-to-right with its punctuation in place, instead of ".backwards" */
[dir="rtl"] :is(.prose, .headline, .why, .quote, .basis, .note, .sev-def){
  unicode-bidi:plaintext; text-align:start}
[dir="rtl"] thead th{text-align:right}
[dir="rtl"] .ev .val{text-align:left}
.langtabs{display:flex; gap:2px; background:var(--n3); padding:2px;
  border-radius:99px}
.langtabs button{border:0; box-shadow:none; background:none; padding:3px 11px;
  border-radius:99px; font:600 var(--t12)/1.4 var(--ui); color:var(--n10)}
.langtabs button.on{background:#fff; color:var(--n12); box-shadow:var(--e1)}

/* ── the in-page tour ────────────────────────────────────────────────── */
/* The guide walks the REAL page: dim everything, lift one section above the
   veil, say one or two sentences about it, move on. */
/* THE VEIL WAS A SHIELD, NOT A SPOTLIGHT — every first visit, and every
   visit in a fresh profile. No `pointer-events` here defaults to `auto`, so
   this full-viewport div at z-index 60 caught every click meant for the page
   under it: a layer chip, a grid square, the nav — all inert while the tour
   ran. Measured with a real browser driving real clicks
   (`src/tests/test_interaction.py`): tour up, clicking a layer chip changes
   nothing — chip class, canvas class and URL all unchanged; tour dismissed,
   the same click works exactly as designed.
   The design already solved this and the port dropped it:
   `design/claim-page-mockup.html`'s own veil is
   `#tourveil{pointer-events:none} #tourveil.on{pointer-events:auto}` — a
   SPOTLIGHT that highlights an element without trapping the reader in a
   modal, which is the whole reason it dims the page instead of opening a
   dialog over it. `none` here restores that: the overlay still paints the
   dimming, and stops intercepting anything. `ol.onclick = endTour`
   (i18n.js) — dismiss-by-clicking-the-backdrop — goes dead with it, which is
   correct for a spotlight, not a modal: Escape and the tip's own Skip button
   still end the tour, and a tour that says "press any square" must not also
   refuse the press. */
.tour-overlay{position:fixed; inset:0; background:rgba(16,26,36,.45);
  z-index:60; pointer-events:none}
.tour-target{position:relative; z-index:61; outline:3px solid var(--a9);
  outline-offset:4px; border-radius:var(--r-md);
  box-shadow:0 0 0 9999px rgba(16,26,36,0)}   /* keep its own paint above */
/* Not `.tour-overlay`'s child — a separate `position:fixed` sibling
   (i18n.js appends both straight to `body`) — so `auto` here is untouched
   by the `none` above. Stated anyway: the one thing on this veil that must
   always answer a click is its own Next/Skip. */
.tour-tip{position:fixed; z-index:62; max-width:380px; background:#fff;
  border:1px solid var(--n5); border-radius:var(--r-md); box-shadow:var(--e4);
  padding:var(--s3) var(--s4); pointer-events:auto}
.tour-tip .tt{font-weight:700; font-size:var(--t13); margin-bottom:var(--s1)}
.tour-tip .tb{font-size:var(--t13); line-height:1.6; color:var(--n11)}
.tour-tip .tf{display:flex; gap:var(--s2); align-items:center;
  margin-top:var(--s3)}
.tour-tip .tc{font-family:var(--mono); font-size:var(--t11);
  color:var(--n10); margin-inline-end:auto}

/* ── in-app document viewer ──────────────────────────────────────────── */
/* Every citation is a link to the PAGE ITSELF — the exact bytes the model
   read — and the gallery lays every file out, classified, for inspection. */
.srclink{cursor:pointer; color:var(--a11); text-decoration:none;
  border-bottom:1px dashed var(--a6)}
.srclink:hover{background:var(--a2)}
/* flex, not an auto-fill grid: auto-fill kept reserving empty tracks, which
   in RTL pushed five thumbnails against one edge with a dead half-row beside
   them. Flex wraps and fills the line. */
.docgrid{display:flex; flex-wrap:wrap; gap:var(--s2);
  padding:var(--s3) var(--s4)}
.docgrid .dthumb{width:132px; flex:none}
.dthumb{border:1px solid var(--n5); border-radius:var(--r-sm); overflow:hidden;
  cursor:pointer; background:#fff; box-shadow:var(--e1)}
.dthumb:hover{border-color:var(--a9)}
.dthumb .im{height:110px; background:var(--n2); display:grid;
  place-items:center; overflow:hidden}
.dthumb img{width:100%; height:110px; object-fit:cover; object-position:top}
.dthumb .im svg{width:22px; height:22px; color:var(--n8)}
.dthumb .cap{padding:4px 6px; font-family:var(--mono); font-size:var(--t10);
  color:var(--n11); overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; direction:ltr; text-align:left}
.dgroup{padding:var(--s3) var(--s4) 0; display:flex; gap:var(--s2);
  align-items:baseline}
.dgroup .label{margin:0}

.lightbox{position:fixed; inset:0; z-index:70; background:rgba(16,26,36,.7);
  display:flex; flex-direction:column}
.lightbox .lb-top{display:flex; align-items:center; gap:var(--s2);
  padding:var(--s2) var(--s4); background:#fff;
  border-bottom:1px solid var(--n5)}
.lightbox .lb-top .src{font-family:var(--mono); font-size:var(--t12);
  font-weight:700; min-width:0; overflow-wrap:break-word; direction:ltr}
.lightbox .lb-main{flex:1; overflow:auto; display:grid; place-items:center;
  padding:var(--s4)}
.lightbox .lb-main img{max-width:min(96vw,1100px); max-height:78vh;
  background:#fff; box-shadow:var(--e4); border-radius:var(--r-sm)}
.lightbox .lb-main pre{max-width:min(96vw,900px); max-height:76vh;
  background:#fff; width:100%}
.lightbox .lb-foot{background:#fff; border-top:1px solid var(--n5);
  padding:var(--s2) var(--s4); font-size:var(--t12); color:var(--n11);
  max-height:130px; overflow:auto}
/* input -> classification -> extraction, all in one click: the fields the
   EXTRACT step produced, directly under what the CLASSIFY step said it saw */
.lightbox .lb-fields{background:var(--n1); border-top:1px solid var(--n5);
  padding:var(--s2) var(--s4); max-height:220px; overflow:auto}
.lightbox .lb-fields .label{display:block; margin-bottom:var(--s2)}
/* a low-confidence classification flagged right on the thumbnail — a
   reviewer scanning a whole role group sees which pages need a second look
   without opening each one */
.dthumb{position:relative}
.dthumb .cf{position:absolute; top:2px; inset-inline-end:2px;
  background:var(--m9); color:#fff; font-size:var(--t9); font-weight:700;
  text-transform:uppercase; letter-spacing:.03em; padding:1px 4px;
  border-radius:3px}

/* ── live strip on /running ──────────────────────────────────────────── */
.livegrid{display:grid; grid-template-columns:repeat(auto-fill,minmax(96px,1fr));
  gap:var(--s2)}
.livegrid .dthumb .im{height:86px}
.livegrid img{height:86px}

/* evidence citations carry a thumbnail of the page itself */
.evthumb{width:28px; height:28px; object-fit:cover; object-position:top;
  border:1px solid var(--n5); border-radius:3px; vertical-align:middle;
  cursor:pointer; margin-inline-end:6px; background:#fff}
.evthumb:hover{border-color:var(--a9)}

/* conflict pairs: the contradiction itself, not a pile of values */
.pair{display:flex; gap:var(--s2); align-items:baseline; flex-wrap:wrap;
  margin-top:var(--s1)}
.pair .pv{font-family:var(--mono); font-size:var(--t12); font-weight:700}
.pair .ne{color:var(--r11); font-weight:700}
.pair .ps{font-size:var(--t11); color:var(--n10)}

/* feedback card */
.fbrow{display:flex; gap:var(--s2); flex-wrap:wrap}
.fbrow button.sel{background:var(--a9); border-color:var(--a9); color:#fff}
.fbdone{display:flex; gap:var(--s2); align-items:flex-start;
  padding:var(--s2) var(--s3); border:1px solid var(--n4);
  border-radius:var(--r-sm); background:var(--n1); margin-top:var(--s2)}

/* thumbnails of the cited pages, right under the sentence that cites them */
.citethumbs{display:flex; gap:var(--s2); margin-top:var(--s3); flex-wrap:wrap}
.citethumbs .dthumb{width:96px; flex:none}
.citethumbs .im{height:70px}
.citethumbs img{height:70px}

/* `.checkgrid`/`.chk` — the old checks-as-cards grid — duplicated
   `scene.css`'s `.mkpage .checkgrid`/`.chk` and is emitted by nothing:
   `buildSecDefs()` renders the checks as `.lyr` disclosures now. Deleted. */

/* ── the detail area as a REASONING CHAIN, not category buckets ──────── */
/* Evidence -> checks -> conclusion, numbered and connected, so the layout
   itself teaches how to think about the claim. Dead in this app — nothing
   emits `.rstage`/`.rgap`/`.rn-d` any more — and duplicated in `scene.css`
   under `.mkpage` besides (the mockup drew the same chain). `.rjoin` is
   neither dead nor a name the design shares, so it stays; the rest of the
   chain's rules are deleted with it. */
.rjoin{display:grid; place-items:center; padding:var(--s2) 0; color:var(--n7)}
.rjoin svg{width:16px; height:16px}

/* ── the chain draws its own arrows ──────────────────────────────────── */
/* Every card visibly FEEDS the next stage: thin curves from each card
   converge on the next stage's node. The SVG sits behind the stages, so
   lines surface only in the gaps — a clean fan, no clutter over cards. */
#rchain{position:relative}
/* the global 14px icon rule would shrink this canvas to a dot — override */
#rlinks{position:absolute; inset:0; width:100%; height:100%;
  pointer-events:none; z-index:0}

/* ── the flow graph, compact, living INSIDE the left trace panel ─────── */
#miniflow{border-bottom:1px solid var(--n4); margin-bottom:var(--s2)}
#miniflow .flow{padding:var(--s3) var(--s1)}
#miniflow .fnode{min-width:0; width:100%; padding:5px var(--s2)}
#miniflow .fnode .ft{font-size:var(--t12)}
#miniflow .fnode .fs{font-size:var(--t10)}
#miniflow .fbranch{gap:var(--s2); width:100%}
#miniflow .fbranch .fcol{flex:1; min-width:0}
#miniflow .fedge{height:12px}
#miniflow .fsplit{height:10px}
#miniflow .fnode.on{border-color:var(--a9); background:var(--a2);
  box-shadow:inset 0 0 0 1px var(--a9)}
/* a dashed "pure code" box is still inspectable when it addresses a node */
#miniflow .fnode.quiet[data-go]{cursor:pointer}
#miniflow .fnode.quiet[data-go]:hover{border-color:var(--a9); background:var(--a2)}

/* thumbnails inside the trace tables, so a classification can be checked
   against the page without leaving the step you are on */
.pthumb{width:30px; height:30px; object-fit:cover; object-position:top;
  border:1px solid var(--n5); border-radius:3px; background:#fff;
  cursor:zoom-in; vertical-align:middle}
.pthumb:hover{border-color:var(--a9)}
.jumplink{font-size:var(--t11); color:var(--a11); cursor:pointer;
  white-space:nowrap}
.jumplink:hover{text-decoration:underline}

/* ---- stage 2: the structurer's raw output ------------------------------
   Plain by intent for this round. Enough structure to read, no more, so the
   real design is chosen against real output rather than against a mock. */
/* `.sgrid` duplicated `scene.css`'s `.mkpage .sgrid` and is unused (nothing
   left in this app renders that grid). `.card > .body > h3` is real — split
   off rather than dropped. `.stx` is deleted for a sharper reason: it is a
   LIVE COLLISION, not a dead rule. `mkScene()` (scene.js, live) emits
   `class="stx"` for the scene's header info-bar — a horizontal, wrapped chip
   row — and this unscoped `.stx{flex-direction:column}` reached inside
   `.mkpage` and forced it to stack vertically instead, since neither file's
   `.stx` rule fully overrides the other at equal specificity. UI_AUDIT.md
   section 3 finding 8, applied. */
.card > .body > h3{font-size:var(--t11); text-transform:uppercase;
       letter-spacing:.06em; color:var(--n9); margin:var(--s4) 0 var(--s2)}
.stable{width:100%; border-collapse:collapse; font-size:var(--t13)}
.stable td{border-top:1px solid var(--n4); padding:var(--s2) var(--s2);
           vertical-align:top}
.stable td.k{color:var(--n10); white-space:nowrap; width:1%}

/* `.verdict .call .pct` duplicated `scene.css`'s copy of the same rule and
   is live only inside `.mkpage` (`mkVerdict()`'s confidence span) — the
   design's rule was the only one that ever painted it. Deleted. */

/* reviewer decision — four mutually exclusive calls, then a required reason */
.decide textarea, .decide input[type=text]{width:100%; margin-top:var(--s2);
  font:400 var(--t13)/1.5 var(--ui); padding:var(--s2) var(--s3);
  border:1px solid var(--n5); border-radius:var(--r-sm); background:var(--n1)}


/* ── the flag IS the decision control ─────────────────────────────────
   Four buttons in a row down the page read as a form to fill in. A handler
   reads the call, then acts on it, so the action sits on the call itself.
   `.decwrap` and `.verdict .glyph.decflag*` are deleted from here — they
   duplicated `scene.css`'s copies and are besides emitted by nothing live:
   only the old `verdict()` (superseded by `mkVerdict()`, scene.js) ever
   wrote `class="decwrap"` or `class="glyph decflag"`. `.decmenu` and what
   follows are not a name the design shares and stay, unlike `verdict()`
   itself, wiring them up in case the flag returns. */
.decmenu{
  position:absolute; top:calc(100% + 6px); inset-inline-start:0; z-index:40;
  min-width:210px; padding:var(--s2);
  background:var(--n1); border:1px solid var(--n5); border-radius:10px;
  box-shadow:0 10px 28px rgba(0,0,0,.14), 0 2px 6px rgba(0,0,0,.06);
}
.decmenu[hidden]{display:none}
.decmenu-h{
  font:700 var(--t11)/1.4 var(--ui); color:var(--n10);
  letter-spacing:.04em; padding:var(--s2) var(--s2) var(--s1);
}
.dopt{
  display:block; width:100%; text-align:start;
  font:600 var(--t13)/1.5 var(--ui); color:var(--n12);
  padding:8px var(--s3); margin-top:2px;
  background:transparent; border:0; border-radius:7px; cursor:pointer;
}
.dopt:hover{background:var(--n3)}
.dopt.warn:hover{background:var(--m3); color:var(--m11)}
.dopt.good:hover{background:var(--g3); color:var(--g11)}
.dopt.bad:hover{background:var(--r3); color:var(--r11)}
.dopt.sel{background:var(--n4)}
.dchosen{
  display:inline-block; font:700 var(--t13)/1.4 var(--ui);
  padding:6px var(--s3); border-radius:7px;
  background:var(--n3); color:var(--n12); border:1px solid var(--n5);
}
.dchosen.warn{background:var(--m2); color:var(--m11); border-color:var(--m7)}
.dchosen.good{background:var(--g2); color:var(--g11); border-color:var(--g7)}
.dchosen.bad {background:var(--r2); color:var(--r11); border-color:var(--r7)}
.dpick:empty{display:none}


/* A glance tile that opens its own detail. */
.gtile.go{cursor:pointer; transition:border-color .12s, transform .12s}
.gtile.go:hover{border-color:var(--n7); transform:translateY(-1px)}
.gtile.go:focus-visible{outline:2px solid var(--b8); outline-offset:2px}
.gtile .tgo{
  margin-top:var(--s2); font:600 var(--t11)/1.4 var(--ui); color:var(--b11);
  opacity:0; transition:opacity .12s;
}
.gtile.go:hover .tgo, .gtile.go:focus-visible .tgo{opacity:1}


/* All 21 indicators in one place: fired above, the rest folded away. */
.iagrp{border-top:1px solid var(--n4)}
.iagrp > summary{
  cursor:pointer; padding:var(--s3) var(--s4);
  font:500 var(--t13)/1.5 var(--ui); color:var(--n11);
  list-style:none; display:flex; gap:var(--s2); align-items:baseline;
}
.iagrp > summary::-webkit-details-marker{display:none}
.iagrp > summary::before{content:'▸'; color:var(--n9); font-size:var(--t11)}
.iagrp[open] > summary::before{content:'▾'}
.iagrp > summary:hover{background:var(--n2)}
.iagrp > summary b{color:var(--n12); font-weight:700}
.iagrp.nc > summary b{color:var(--a11)}
/* `.iabody` and this ledger-shaped `.iarow` (a second, grid-shaped `.iarow`
   follows below) duplicated `scene.css`'s `.mkpage` copies. Both are live
   only inside `.mkpage` — `iaAll()`'s cleared/not-checked lists — so the
   design's rule was the only one ever painting them. Deleted. */


/* Where two documents disagree — shown side by side so the reviewer can
   argue with the choice, not hunt for the conflict. */
.dis{padding:var(--s4); border-bottom:1px solid var(--n4)}
.dis:last-child{border-bottom:0}
.dis-h{display:flex; gap:var(--s2); align-items:baseline; flex-wrap:wrap;
  margin-bottom:var(--s3); font:600 var(--t13)/1.4 var(--ui)}
.dis-two{display:grid; grid-template-columns:1fr 1fr; gap:var(--s3)}
@media (max-width:620px){.dis-two{grid-template-columns:1fr}}
.dis .side{padding:var(--s3); border-radius:8px; border:1px solid var(--n5)}
.dis .side.win{background:var(--g2); border-color:var(--g6)}
.dis .side.lose{background:var(--n2)}
.dis .lab{font:700 var(--t11)/1.4 var(--ui); letter-spacing:.05em;
  text-transform:uppercase; color:var(--n10); margin-bottom:4px}
.dis .side.win .lab{color:var(--g11)}
.dis .val{font:600 var(--t14)/1.5 var(--ui); color:var(--n12);
  word-break:break-word; margin-bottom:2px}
.dis .why{margin:var(--s3) 0 0; font:400 var(--t12)/1.6 var(--ui);
  color:var(--n11)}


/* One card, four kinds of gap, each with its own heading inside. */
.gaphead{
  display:flex; align-items:center; gap:var(--s2);
  padding:var(--s3) var(--s4) var(--s2);
  font:600 var(--t13)/1.4 var(--ui); color:var(--n12);
}
.gaphead svg{width:15px; height:15px; color:var(--n10)}
.gapsep{height:1px; background:var(--n4); margin:var(--s3) 0}


/* This whole final stretch of the old stylesheet — `.chk` (a second
   cluster; the grid this styled was deleted above), `.assess`, `.arail`,
   `.astat`, `.minibar`, `.abody`, `.acol`, `.argcol`, `.iagrid`, `.iarow`
   (a second, grid-shaped cluster — a ledger-shaped `.iarow` was deleted
   above), `.ialeg`, `.iapick`, `.whatis` and the closing `.lyr` rules —
   duplicated `scene.css`'s `.mkpage` copies of the SAME classes, name for
   name. Every element that carries one of them is built by `mkRail()`,
   `mkGrid()`, `mkArgue()`, `whatIs()` or `details()`'s own `.lyr` sections
   (scene.js / app.js), all of which render inside the claim page's single
   `.mkpage` scope — so the design's rule was the only one of the pair ever
   live. Deleted entire; nothing here styled anything the design does not
   already style, and better. */

/* ═══════════════════════ ARABIC IS A JOINING SCRIPT ═══════════════════
   Letter-spacing pulls a script apart at the joins. In Latin that is
   "tracking" and it helps small capitals read; in Arabic it severs the
   connections that make a word a word — بـاسم instead of باسم — and the
   reader sees something broken, not something styled.

   There are 48 positive `letter-spacing` declarations across this file
   and the mockup. Every one was written while looking at English, and
   every one of them damages the Arabic view of the same component. It
   showed up twice on the same day from two different directions: the
   queue's three numeric column headers, and the sidebar's "acting as"
   label. Fixing those two would have left forty-six.

   So it is reset once, for the whole right-to-left view, rather than
   audited rule by rule — and with `!important` deliberately, because it
   has to beat every component rule in both stylesheets including
   `.mkpage`-scoped ones that outrank any selector written here. This is
   the case that mechanism exists for: a script-wide correction that is
   never wrong and must never be overridden by a component.

   `test_arabic_typography.py` reads the rendered page and asserts no
   element containing Arabic ends up with tracking. */
[dir="rtl"] *{letter-spacing:normal !important}

/* ═══════════════════════ THE SIDEBAR, COLLAPSED ═══════════════════════
   260px of chrome sits between the reader and the work on every screen,
   and on a laptop that is a fifth of the window spent on five links they
   already know. Collapsed it keeps the icons — which is the whole reason
   the rows got icons — so the navigation is still navigable, still shows
   where you are, and gives the width back to the table.

   The state is remembered per browser. The toggle is in the brand row
   because that is the one part of the sidebar that survives collapsing. */
.sidebar.rail{width:68px}
.sidebar.rail .logo{padding:0; justify-content:center; gap:0}
.sidebar.rail .logo .brandtext{display:none}
.sidebar.rail .glabel span, .sidebar.rail .glabel .gchev,
.sidebar.rail .glabel .gspace{display:none}
.sidebar.rail .glabel{padding:var(--s3) 0 6px; justify-content:center}
.sidebar.rail .glabel::after{content:""; display:block; width:20px;
  height:1px; background:var(--n6)}
.sidebar.rail .navitem{justify-content:center; padding:9px 0; gap:0}
.sidebar.rail .navitem .nt{display:none}
.sidebar.rail .navitem .ni{width:17px; height:17px}
.sidebar.rail .cta{justify-content:center; padding:9px 0}
.sidebar.rail .cta .txt, .sidebar.rail .searchbox,
.sidebar.rail .foot, .sidebar.rail #actorbox,
.sidebar.rail #claimlist, .sidebar.rail #nclaims,
.sidebar.rail #claimshead{display:none}
.sidebar.rail .scroll{padding:var(--s3) var(--s2)}

/* The toggle itself: quiet until wanted, and it keeps its place in the
   brand row in both directions so the sidebar does not jump on collapse. */
.railtog{
  margin-inline-start:auto; flex:none; width:26px; height:26px;
  display:grid; place-items:center; border:0; background:none;
  border-radius:var(--r-sm); color:var(--n9); cursor:pointer;
}
.railtog:hover{background:var(--a2); color:var(--a11)}
.railtog svg{width:15px; height:15px; transition:transform .15s ease}
.sidebar.rail .railtog{margin-inline-start:0}
[dir="rtl"] .railtog svg{transform:rotate(180deg)}
.sidebar.rail .railtog svg{transform:rotate(180deg)}
[dir="rtl"] .sidebar.rail .railtog svg{transform:none}
@media (prefers-reduced-motion:reduce){.railtog svg{transition:none}}

/* ══════════════════════════ THE SIGN-IN SURFACE ═══════════════════════
   The only page in this app that stands alone: no sidebar, no topbar,
   nothing navigable, because until there is a session there is nowhere to
   navigate to. Centred on the same ground as everything else so it reads
   as the front door of THIS app rather than a stock login screen. */
.signin{min-height:100vh; display:grid; place-items:center;
  padding:var(--s5); background:var(--n3)}
.signinbox{width:100%; max-width:380px; background:#fff;
  border:1px solid var(--n5); border-radius:var(--r-lg);
  box-shadow:var(--e3); padding:var(--s6) var(--s5);
  display:flex; flex-direction:column; gap:var(--s3)}
.signinbox .logo{height:auto; padding:0; margin-bottom:var(--s2)}
.signinbox h1{font-size:var(--t24); font-weight:600; letter-spacing:-.02em}
.signinbox .sub{color:var(--n10); font-size:var(--t13); margin:0 0 var(--s2)}
.sifield{display:flex; flex-direction:column; gap:6px}
.sifield span{font-size:var(--t12); font-weight:500; color:var(--n11)}
.sifield input{height:38px; padding:0 var(--s3); border-radius:var(--r-md);
  border:1px solid var(--n5); background:#fff; color:var(--n12);
  font:400 var(--t14)/1 var(--ui)}
.sifield input:focus{outline:2px solid var(--a6); outline-offset:1px;
  border-color:var(--a6)}
/* The failure is a statement, not an alarm: one wrong password is the most
   ordinary thing that happens on this screen. */
.sierr{background:var(--r2); border:1px solid var(--r6); color:var(--r11);
  border-radius:var(--r-md); padding:var(--s2) var(--s3);
  font-size:var(--t13)}
.signinbox .cta{justify-content:center; margin-top:var(--s2)}
.signinbox .langtabs{justify-content:center; margin-top:var(--s2)}

/* WHO IS SIGNED IN, at the foot of the sidebar. Not a form: the name is a
   fact the server states, and the only thing to do with it is stop being
   it. Hidden when the menu is a rail — 68px cannot hold a name, and a
   truncated one is worse than none. */
.whoami{display:flex; flex-wrap:wrap; align-items:baseline; gap:6px}
.whoami .wtag{flex-basis:100%; font-size:var(--t11); color:var(--n9)}
.whoami .wname{font-size:var(--t13); font-weight:600; color:var(--n12);
  font-family:var(--ui)}
.whoami .wrole{font-size:var(--t11); color:var(--n10); background:var(--n2);
  border:1px solid var(--n5); border-radius:999px; padding:1px 8px}
.whoami .wout{margin-inline-start:auto; border:0; background:none;
  color:var(--a11); font:500 var(--t12)/1 var(--ui); cursor:pointer;
  padding:2px 0}
.whoami .wout:hover{text-decoration:underline}
