/* ELLA — in-bubble component library (`eui-*`).
 *
 * THE CONTRACT: this file owns every pixel of these components. ELLA emits
 * STRUCTURE ONLY — `html.Div(className="eui-metric")` — and never a style dict,
 * never a hex, never a `C[...]` lookup for chrome. That inversion is the whole
 * point:
 *
 *   · themes for free      — the classes read tokens, so dark mode is automatic
 *   · consistent by build  — one definition, not one per turn
 *   · ~40 tokens per card  — instead of ~400 of inline style JSON
 *   · fewer render errors  — short code strings escape cleanly; no bare-Unicode
 *                            SyntaxError, no re-derived styling to get wrong
 *
 * `C[...]` (ELEMENT_COLORS) survives for ONE job: Plotly figures, which cannot
 * read CSS variables. Never for a `<dyn_layout>` component's chrome.
 *
 * Append to assets/copilot.css, or ship as assets/ella-ui.css (Dash serves the
 * whole assets/ dir, so either works; a separate file is easier to diff).
 * Requires the token layer from copilot-tokens.css.
 *
 * Width discipline (the "per component" decision): components that want the
 * full chat column carry `.eui-wide`, which cancels the bubble's side padding
 * the same way `.script-card-full-width` does. Everything else stays inside
 * the bubble's readable cap.
 */

/* ========================================================================
   Shared shell
   ======================================================================== */
.eui{--eui-tone-ink:var(--accent-ink);--eui-tone-bg:var(--accent-bg);--eui-tone-border:var(--accent-border);--eui-tone-accent:var(--accent);--eui-tone-solid:var(--darkgreen);--eui-tone-on-solid:#fff;font-size:13px;line-height:1.5;color:var(--ink)}
.eui-card{background:var(--card-bg);border:1px solid var(--border);border-radius:11px;overflow:hidden}
.eui-wide{width:calc(100% + 32px);margin-left:-16px;margin-right:-16px}
.eui+.eui{margin-top:10px}

/* Tone modifiers. Set on the OUTERMOST eui element; every child reads the
   --eui-tone-* vars, so one class recolours a whole composite. Four tones only
   — a fifth makes severity unreadable at a glance.

   Note the FIVE vars, and why there are five rather than three:
     --eui-tone-accent   a hairline, dot, or rule. Graphical, so the 3:1 floor
                         applies and the bright brand value is fine.
     --eui-tone-solid    a fill that will carry TEXT on top of it. Must be dark
                         enough for its ink at 4.5:1, which #4CB748 (2.6:1 with
                         white) and #F2A436 (2.1:1) are not — so the solid steps
                         DOWN the ramp to --darkgreen / --warn-ink while the
                         accent stays bright.
     --eui-tone-on-solid ink for that fill.
   Never use a surface token (--card-bg) as an ink value: that is exactly how
   white-on-orange happens. */
.eui-t-good{--eui-tone-ink:var(--accent-ink);--eui-tone-bg:var(--accent-bg);--eui-tone-border:var(--accent-border);--eui-tone-accent:var(--accent);--eui-tone-solid:var(--darkgreen);--eui-tone-on-solid:#fff}
.eui-t-warn{--eui-tone-ink:var(--warn-ink);--eui-tone-bg:var(--warn-bg);--eui-tone-border:var(--warn-border);--eui-tone-accent:var(--warn-accent);--eui-tone-solid:#7a4a00;--eui-tone-on-solid:#fff}
.eui-t-fault{--eui-tone-ink:var(--fault-ink);--eui-tone-bg:var(--fault-bg);--eui-tone-border:var(--fault-border);--eui-tone-accent:var(--fault-accent);--eui-tone-solid:var(--fault-deep);--eui-tone-on-solid:#fff}
.eui-t-info{--eui-tone-ink:var(--ink-soft);--eui-tone-bg:var(--bg-soft);--eui-tone-border:var(--border);--eui-tone-accent:var(--muted);--eui-tone-solid:var(--muted);--eui-tone-on-solid:#fff}

/* Dark theme: the surface is dark, so the ramp inverts — the bright brand value
   becomes the text-bearing fill and the ink goes dark. */
#app-shell[data-theme='dark'] .eui,
#app-shell[data-theme='dark'] .eui-t-good{--eui-tone-solid:var(--lightgreen);--eui-tone-on-solid:#08210d}
#app-shell[data-theme='dark'] .eui-t-warn{--eui-tone-solid:var(--orange);--eui-tone-on-solid:#3d2600}
#app-shell[data-theme='dark'] .eui-t-fault{--eui-tone-solid:#E8615C;--eui-tone-on-solid:#2b0a09}
#app-shell[data-theme='dark'] .eui-t-info{--eui-tone-solid:var(--muted-2);--eui-tone-on-solid:#15181a}

/* Section label used across components */
.eui-label{font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}

/* ========================================================================
   1. Verdict header — the "so what" line at the top of a diagnostic answer.
   One per answer, always first. Its job is to make the conclusion readable
   without reading anything else.
   ======================================================================== */
.eui-verdict{display:flex;align-items:flex-start;gap:12px;padding:13px 16px;border-radius:11px;background:var(--eui-tone-bg);border:1px solid var(--eui-tone-border);border-left:3px solid var(--eui-tone-accent)}
.eui-verdict-mark{width:22px;height:22px;border-radius:50%;flex-shrink:0;display:grid;place-items:center;font-size:12px;font-weight:800;background:var(--eui-tone-solid);color:var(--eui-tone-on-solid);margin-top:1px}
.eui-verdict-body{display:block;min-width:0;flex:1}
.eui-verdict-title{display:block;font-size:14.5px;font-weight:700;color:var(--eui-tone-ink);letter-spacing:-.005em}
.eui-verdict-sub{display:block;font-size:12.5px;color:var(--ink-soft);margin-top:3px;text-wrap:pretty}
.eui-verdict-meta{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}

/* Every text slot in a composite declares its own `display`. The library is
   the contract — ELLA emits structure only — so correctness must never depend
   on the caller reaching for html.Div over html.Span. She will eventually pick
   the other one, and that is precisely the class of failure this inversion
   exists to remove. */

/* ========================================================================
   2. Metric row — label / value / delta / sparkline.
   The delta tone is EXPLICIT, never derived from the sign: falling SOH is bad,
   falling failure counts are good. Direction and meaning are different axes,
   and conflating them is how a dashboard tells you the wrong thing.
   ======================================================================== */
.eui-metrics{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:1px;background:var(--border);border:1px solid var(--border);border-radius:11px;overflow:hidden}
.eui-metric{background:var(--card-bg);padding:12px 15px 13px;min-width:0}
.eui-metric-label{font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.eui-metric-row{display:flex;align-items:baseline;gap:7px;margin-top:5px;flex-wrap:wrap}
.eui-metric-value{display:inline-block;font-size:24px;font-weight:700;line-height:1.05;color:var(--ink);letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.eui-metric-unit{font-size:12.5px;font-weight:600;color:var(--muted)}
.eui-metric-sub{display:block;font-size:11px;color:var(--muted);margin-top:4px}
.eui-metric--attn .eui-metric-value{color:var(--warn-accent)}
.eui-metric--fault .eui-metric-value{color:var(--fault-accent)}

.eui-delta{display:inline-flex;align-items:center;gap:3px;font-size:11.5px;font-weight:700;padding:1px 6px;border-radius:5px;font-variant-numeric:tabular-nums}
.eui-delta--good{color:var(--accent-ink);background:var(--accent-bg)}
.eui-delta--bad{color:var(--fault-ink);background:var(--fault-bg)}
.eui-delta--watch{color:var(--warn-ink);background:var(--warn-bg)}
.eui-delta--flat{color:var(--muted);background:var(--bg-soft)}

/* Sparkline. ELLA supplies the polyline points; the class owns the size and
   colour so a spark can never arrive off-palette. */
/* Bars, not an SVG path: dash.html has no Svg/Path/Circle, so a path-based
   spark raises inside the sandbox and the user gets a red error box instead of
   their answer. Only each bar's height is inline (geometry); every colour here
   is a token, so a spark can never arrive off-palette. */
.eui-spark{display:flex;align-items:flex-end;gap:2px;width:100%;height:26px;margin-top:8px}
.eui-spark-bar{flex:1;min-width:2px;border-radius:1.5px;background:var(--accent);opacity:.45}
.eui-spark-bar--last{opacity:1}
.eui-spark--warn .eui-spark-bar{background:var(--warn-accent)}
.eui-spark--fault .eui-spark-bar{background:var(--fault-accent)}

/* ========================================================================
   3. Callout — one important fact, pulled out of prose.
   Deliberately NOT a card: no elevation, no title row. A callout that looks
   like a card competes with the real cards around it.
   ======================================================================== */
.eui-callout{display:flex;gap:10px;align-items:flex-start;padding:10px 13px;border-radius:9px;background:var(--eui-tone-bg);border:1px solid var(--eui-tone-border);font-size:12.5px;line-height:1.5;color:var(--ink)}
.eui-callout-mark{flex-shrink:0;font-size:12.5px;font-weight:800;color:var(--eui-tone-accent);line-height:1.45}
.eui-callout-body{display:block;min-width:0}
.eui-callout-body>strong,.eui-callout-title{color:var(--eui-tone-ink);font-weight:700}
.eui-callout-title{display:block;margin-bottom:2px;font-size:12.5px}
.eui-callout code{font-family:"JetBrains Mono",SFMono-Regular,Menlo,monospace;font-size:11.5px;background:var(--card-bg);border:1px solid var(--eui-tone-border);border-radius:4px;padding:0 4px}

/* ========================================================================
   4. Comparison — A vs B. Wants width, so it ships with .eui-wide.
   Collapses to stacked columns under 520px rather than squeezing both.
   ======================================================================== */
.eui-compare{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--border);border:1px solid var(--border);border-radius:11px;overflow:hidden}
.eui-compare--3{grid-template-columns:repeat(3,1fr)}
.eui-compare-col{background:var(--card-bg);padding:0;min-width:0}
.eui-compare-head{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 14px;background:var(--bg-soft);border-bottom:1px solid var(--border)}
.eui-compare-title{font-size:12.5px;font-weight:700;color:var(--ink);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.eui-compare-col--pick .eui-compare-head{background:var(--accent-bg);border-bottom-color:var(--accent-border)}
.eui-compare-col--pick .eui-compare-title{color:var(--accent-ink)}
.eui-compare-tag{font-size:9.5px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;padding:2px 7px;border-radius:999px;background:var(--btn-accent-bg);color:var(--btn-accent-ink);flex-shrink:0}
.eui-compare-rows{padding:4px 0}
.eui-compare-row{display:flex;align-items:baseline;justify-content:space-between;gap:10px;padding:7px 14px;font-size:12.5px}
.eui-compare-row+.eui-compare-row{border-top:1px solid var(--border)}
.eui-compare-k{display:block;color:var(--muted);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.eui-compare-v{display:block;color:var(--ink);font-weight:600;text-align:right;font-variant-numeric:tabular-nums;flex-shrink:0}
.eui-compare-v .eui-delta{margin-left:6px}
.eui-compare-note{padding:9px 14px;border-top:1px solid var(--border);font-size:11.5px;color:var(--muted);text-wrap:pretty}
@media (max-width:520px){.eui-compare,.eui-compare--3{grid-template-columns:1fr}}

/* ========================================================================
   5. Property inspector — one entity's fields, dense and scannable.
   Replaces a markdown bullet list of "key: value" pairs, which wastes a full
   line per pair and can't align values.
   ======================================================================== */
.eui-props{display:grid;grid-template-columns:auto 1fr;gap:0;border:1px solid var(--border);border-radius:10px;overflow:hidden;background:var(--card-bg)}
.eui-props-k{padding:7px 12px;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);background:var(--bg-soft);border-bottom:1px solid var(--border);white-space:nowrap}
.eui-props-v{padding:7px 13px;font-size:12.5px;color:var(--ink);border-bottom:1px solid var(--border);font-variant-numeric:tabular-nums;min-width:0;overflow-wrap:anywhere}
.eui-props-k:last-of-type,.eui-props-v:last-of-type{border-bottom:0}
.eui-props-v--mono{font-family:"JetBrains Mono",SFMono-Regular,Menlo,monospace;font-size:11.5px}

/* ========================================================================
   6. Chips — inline severity/identity tokens. Work inside prose too.
   ======================================================================== */
.eui-chip{display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border-radius:999px;background:var(--chip-bg);border:1px solid var(--chip-border);font-size:11.5px;font-weight:600;color:var(--ink-soft);white-space:nowrap;vertical-align:1px}
.eui-chip-dot{width:6px;height:6px;border-radius:50%;background:var(--muted-2);flex-shrink:0}
.eui-chip--good{border-color:var(--accent-border);color:var(--accent-ink)}
.eui-chip--good .eui-chip-dot{background:var(--accent)}
.eui-chip--warn{border-color:var(--warn-border);color:var(--warn-ink)}
.eui-chip--warn .eui-chip-dot{background:var(--warn-accent)}
.eui-chip--fault{border-color:var(--fault-border);color:var(--fault-ink)}
.eui-chip--fault .eui-chip-dot{background:var(--fault-accent)}
.eui-chip--mono{font-family:"JetBrains Mono",SFMono-Regular,Menlo,monospace;font-size:11px}

/* ========================================================================
   7. Findings list — a severity-ranked list of items with detail.
   Backs the PR-review template; also right for diagnostic results.
   ======================================================================== */
.eui-findings{border:1px solid var(--border);border-radius:11px;overflow:hidden;background:var(--card-bg)}
.eui-finding{display:flex;gap:11px;padding:11px 14px;align-items:flex-start}
.eui-finding+.eui-finding{border-top:1px solid var(--border)}
.eui-finding-sev{flex-shrink:0;width:20px;height:20px;border-radius:6px;display:grid;place-items:center;font-size:11px;font-weight:800;background:var(--eui-tone-bg);color:var(--eui-tone-ink);border:1px solid var(--eui-tone-border);margin-top:1px}
.eui-finding-body{display:block;min-width:0;flex:1}
.eui-finding-title{display:block;font-size:12.5px;font-weight:700;color:var(--ink)}
.eui-finding-detail{display:block;font-size:12px;color:var(--ink-soft);margin-top:3px;text-wrap:pretty}
.eui-finding-where{display:block;font-family:"JetBrains Mono",SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--muted);margin-top:4px;overflow-wrap:anywhere}
.eui-finding-where a{color:var(--accent-ink)}

/* ========================================================================
   8. File rows — a path list with a one-line responsibility and a change stat.
   Replaces the shallow-file-tree ASCII block the prompt currently asks for.
   ======================================================================== */
.eui-files{border:1px solid var(--border);border-radius:11px;overflow:hidden;background:var(--card-bg)}
.eui-file{display:flex;align-items:baseline;gap:10px;padding:9px 14px;font-size:12px}
.eui-file+.eui-file{border-top:1px solid var(--border)}
.eui-file-path{font-family:"JetBrains Mono",SFMono-Regular,Menlo,monospace;font-size:11.5px;color:var(--accent-ink);min-width:0;overflow-wrap:anywhere;flex:1}
.eui-file-note{display:block;color:var(--muted);font-size:11.5px;flex:1.4;min-width:0}
.eui-file-stat{display:block;font-family:"JetBrains Mono",SFMono-Regular,Menlo,monospace;font-size:11px;flex-shrink:0;font-variant-numeric:tabular-nums}
.eui-file-stat .add{color:var(--accent-ink);font-weight:700}
.eui-file-stat .del{color:var(--fault-ink);font-weight:700;margin-left:5px}

/* ========================================================================
   9. Checklist — acceptance criteria / done-when.
   Backs the instruction-brief template.
   ======================================================================== */
.eui-checks{display:flex;flex-direction:column;gap:0;border:1px solid var(--border);border-radius:11px;overflow:hidden;background:var(--card-bg)}
.eui-check{display:flex;gap:10px;align-items:flex-start;padding:9px 14px;font-size:12.5px;color:var(--ink)}
.eui-check+.eui-check{border-top:1px solid var(--border)}
.eui-check-box{flex-shrink:0;width:15px;height:15px;border-radius:4px;border:1.5px solid var(--border-strong);display:grid;place-items:center;font-size:9px;color:transparent;margin-top:2px}
.eui-check--done .eui-check-box{background:var(--btn-accent-bg);border-color:var(--btn-accent-bg);color:var(--btn-accent-ink)}
.eui-check-body{min-width:0;text-wrap:pretty}

/* ========================================================================
   10. Card header — a titled wrapper when a component needs naming.
   Optional: an untitled card in a bubble ELLA already introduced in prose
   does not need a title, and a redundant one just costs a line.
   ======================================================================== */
.eui-head{display:flex;align-items:center;gap:9px;padding:9px 14px;background:var(--bg-soft);border-bottom:1px solid var(--border)}
.eui-head-title{font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--accent-ink)}
.eui-head-meta{margin-left:auto;font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}

/* ========================================================================
   11. Section — a titled block inside a template.
   ======================================================================== */
.eui-section+.eui-section{margin-top:12px}
.eui-section-title{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--muted);margin-bottom:7px}
.eui-section-title::after{content:"";flex:1;height:1px;background:var(--border)}
