/* ==========================================================================
   EDIC BI board  —  v3
   --------------------------------------------------------------------------
   Rebuilt against edic-tokens.css. Same markup contract as before; only the
   presentation changed.

   What changed and why:
     - The six KPI tiles were six separately bordered, shadowed boxes, each
       with a coloured state bar down one edge. Six loud objects reading as
       equals. They are now one surface divided by hairlines, so the group
       reads as a single instrument panel.
     - State is no longer signalled by a coloured edge on every tile. A tile
       that is fine looks plain; only a breach carries colour. Colour that
       appears on everything signals nothing.
     - No gradients, no !important, no hard-coded colour or size.
   ========================================================================== */

.ebi {
    margin-block-end: var(--ed-space-10);
    font-family: var(--ed-font);
    color: var(--ed-text);
}

/* --------------------------------------------------------------------------
   HEADER
   -------------------------------------------------------------------------- */
.ebi-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--ed-space-4);
    margin-block-end: var(--ed-space-4);
}

.ebi-title {
    font-size: var(--ed-text-title);
    font-weight: var(--ed-weight-semibold);
    line-height: var(--ed-leading-snug);
    letter-spacing: var(--ed-tracking-title);
    color: var(--ed-text);
}

.ebi-head-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ed-space-2);
}

/* The board switch and the window switch are .ed-tabs / .ed-tab -- the same
   component as the module tab strip in the portal chrome. They used to be a
   second, near-identical implementation under ebi- names. */

/* --------------------------------------------------------------------------
   TRUST STRIP
   Every number below is only as good as the reports it came from, so this
   stays. It is quiet by default and only takes colour when coverage is bad.
   -------------------------------------------------------------------------- */
.ebi-trust {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ed-space-2) var(--ed-space-3);
    padding: var(--ed-space-3) var(--ed-space-5);
    margin-block-end: var(--ed-space-4);
    overflow: hidden;
    font-size: var(--ed-text-subhead);
    color: var(--ed-text-secondary);
    background: var(--ed-surface);
    border: 1px solid var(--ed-separator-soft);
    border-radius: var(--ed-radius-md);
}

.ebi-trust-lead {
    display: inline-flex;
    align-items: center;
    gap: var(--ed-space-2);
}

.ebi-trust-label {
    font-weight: var(--ed-weight-medium);
    letter-spacing: var(--ed-tracking-overline);
    text-transform: uppercase;
    font-size: var(--ed-text-caption);
    color: var(--ed-text-tertiary);
}

.ebi-trust-dot {
    inline-size: 7px;
    block-size: 7px;
    border-radius: var(--ed-radius-pill);
    background: var(--ed-text-tertiary);
}

.ebi-trust--good   .ebi-trust-dot { background: var(--ed-success); }
.ebi-trust--watch  .ebi-trust-dot { background: var(--ed-warning); }
.ebi-trust--breach .ebi-trust-dot { background: var(--ed-danger); }

.ebi-trust-facts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ed-space-2);
}

.ebi-trust-fact strong {
    font-weight: var(--ed-weight-semibold);
    color: var(--ed-text);
}

.ebi-trust-sep { color: var(--ed-grey-400); }

.ebi-trust-warn { color: var(--ed-warning); }

/* Coverage meter. A short track sitting in the strip's own flow rather than
   a rule spanning the card edge: full-width, a filled bar reads as a border
   that has gone wrong, and it dominated a strip whose job is to be quiet. */
.ebi-trust-meter {
    flex: 0 0 auto;
    inline-size: 64px;
    block-size: 4px;
    overflow: hidden;
    background: var(--ed-fill-subtle);
    border-radius: var(--ed-radius-pill);
}

/* Keyed on the meter's own state, not the strip's. The strip folds staleness
   and approval share into one verdict, so a window with every day reported
   was being drawn as a warning-coloured bar purely because approvals lagged. */
.ebi-trust-meter-fill {
    display: block;
    block-size: 100%;
    border-radius: var(--ed-radius-pill);
    background: var(--ed-text-tertiary);
}

.ebi-trust-meter--good   .ebi-trust-meter-fill { background: var(--ed-success); }
.ebi-trust-meter--watch  .ebi-trust-meter-fill { background: var(--ed-warning); }
.ebi-trust-meter--breach .ebi-trust-meter-fill { background: var(--ed-danger); }

/* --------------------------------------------------------------------------
   KPI TILES
   One surface, hairline-divided. The 1px grid gap over a separator-coloured
   background is what draws the dividers.
   -------------------------------------------------------------------------- */
/* Explicit column counts, not auto-fit. The dividers are the container's
   background showing through a 1px gap, so a partially filled last row would
   expose that background as a solid slab. Every board defines six KPIs, and
   1 / 2 / 3 columns all divide six evenly. */
.ebi-tile-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ed-space-2);
}

.ebi-tile-label {
    font-size: var(--ed-text-subhead);
    font-weight: var(--ed-weight-medium);
    line-height: var(--ed-leading-snug);
    color: var(--ed-text-secondary);
}

.ebi-tile-target {
    font-size: var(--ed-text-caption);
    color: var(--ed-text-tertiary);
    white-space: nowrap;
}

.ebi-tile-figure {
    display: flex;
    align-items: baseline;
    gap: 3px;
}

.ebi-tile-value {
    font-size: var(--ed-text-metric);
    font-weight: var(--ed-weight-semibold);
    line-height: 1.1;
    letter-spacing: var(--ed-tracking-title);
    color: var(--ed-text);
    font-variant-numeric: tabular-nums lining-nums;
}

/* Only a breach colours the number. Everything else stays neutral. */
.ed-stat--breach .ebi-tile-value { color: var(--ed-danger); }

.ebi-tile-value--empty {
    color: var(--ed-text-tertiary);
    font-weight: var(--ed-weight-regular);
}

.ebi-tile-unit {
    font-size: var(--ed-text-subhead);
    font-weight: var(--ed-weight-regular);
    color: var(--ed-text-secondary);
}

.ebi-tile-unit--tight { margin-inline-start: -1px; }

/* Sparkline */
.ebi-spark {
    block-size: 26px;
}

.ebi-spark svg {
    inline-size: 100%;
    block-size: 100%;
    display: block;
}

.ebi-spark polyline {
    stroke: var(--ed-accent);
    stroke-width: 1.5;
    opacity: .55;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.ed-stat--breach .ebi-spark polyline { stroke: var(--ed-danger); opacity: 1; }
.ed-stat--watch  .ebi-spark polyline { stroke: var(--ed-warning); opacity: .9; }

.ebi-tile-foot {
    margin-block-start: auto;
}

.ebi-delta {
    display: inline-flex;
    align-items: baseline;
    gap: 4px;
    font-size: var(--ed-text-caption);
    color: var(--ed-text-secondary);
}

/* The arrow sits on the same step as the label beside it. It still reads as
   the smaller of the two because a triangle fills far less of its em box
   than a glyph does - which is the effect the old 0.625rem was reaching for
   by hand, and which an em ratio turned into 9px once the scale came down. */
.ebi-delta-arrow { font-size: var(--ed-text-caption); }

.ebi-delta--better .ebi-delta-arrow { color: var(--ed-success); }
.ebi-delta--worse  .ebi-delta-arrow { color: var(--ed-danger); }
.ebi-delta--flat   .ebi-delta-arrow { color: var(--ed-text-tertiary); }

.ebi-delta-basis { color: var(--ed-text-tertiary); }

.ebi-tile-detail {
    font-size: var(--ed-text-caption);
    line-height: var(--ed-leading-snug);
    color: var(--ed-text-tertiary);
}

/* --------------------------------------------------------------------------
   INSIGHT CARDS
   -------------------------------------------------------------------------- */
.ebi-insights {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: var(--ed-space-4);
    margin-block-end: var(--ed-space-4);
    /* Each card sizes to its own content. Stretching the shorter one to match
       its neighbour bought nothing but a panel of empty surface. */
    align-items: start;
}

.ebi-card {
    padding: var(--ed-space-5);
    background: var(--ed-surface);
    border: 1px solid var(--ed-separator-soft);
    border-radius: var(--ed-radius-lg);
}

.ebi-card-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ed-space-2);
    margin-block-end: var(--ed-space-4);
}

.ebi-card-title {
    font-size: var(--ed-text-title);
    font-weight: var(--ed-weight-semibold);
    line-height: var(--ed-leading-snug);
    letter-spacing: var(--ed-tracking-title);
    color: var(--ed-text);
}

.ebi-card-note {
    font-size: var(--ed-text-subhead);
    color: var(--ed-text-tertiary);
}

/* ---- Material flow ---- */
.ebi-flow-stages {
    display: flex;
    flex-direction: column;
    gap: var(--ed-space-5);
}

.ebi-flow-bar {
    display: flex;
    gap: 2px;
    block-size: 8px;
    margin-block-end: var(--ed-space-3);
    overflow: hidden;
    border-radius: var(--ed-radius-pill);
}

.ebi-flow-seg { display: block; }

.ebi-flow-seg--primary { background: var(--ed-azure-700); }
.ebi-flow-seg--accent  { background: var(--ed-azure-400); }
.ebi-flow-seg--neutral { background: var(--ed-grey-300); }
.ebi-flow-seg--loss    { background: var(--ed-grey-500); }

.ebi-flow-legend {
    display: flex;
    flex-direction: column;
    gap: var(--ed-space-2);
}

.ebi-flow-legend-item {
    display: flex;
    align-items: center;
    gap: var(--ed-space-2);
    font-size: var(--ed-text-subhead);
    color: var(--ed-text-secondary);
}

.ebi-flow-key {
    inline-size: 8px;
    block-size: 8px;
    flex: 0 0 auto;
    border-radius: 2px;
}

.ebi-flow-key--primary { background: var(--ed-azure-700); }
.ebi-flow-key--accent  { background: var(--ed-azure-400); }
.ebi-flow-key--neutral { background: var(--ed-grey-300); }
.ebi-flow-key--loss    { background: var(--ed-grey-500); }

.ebi-flow-name { flex: 1 1 auto; }

.ebi-flow-figure {
    font-variant-numeric: tabular-nums lining-nums;
    color: var(--ed-text);
}

.ebi-flow-share {
    min-inline-size: 3.5em;
    text-align: end;
    font-variant-numeric: tabular-nums lining-nums;
    color: var(--ed-text-tertiary);
}

/* ---- Constraint / utilisation ---- */
.ebi-constraint-reported {
    margin-block-end: var(--ed-space-4);
    font-size: var(--ed-text-subhead);
    line-height: var(--ed-leading-snug);
    color: var(--ed-text-secondary);
}

.ebi-constraint-reported strong {
    font-weight: var(--ed-weight-semibold);
    color: var(--ed-text);
}

.ebi-constraint-reported--empty { color: var(--ed-text-tertiary); }

.ebi-constraint-loads {
    display: flex;
    flex-direction: column;
    gap: var(--ed-space-3);
}

.ebi-constraint-load {
    display: grid;
    grid-template-columns: minmax(6.5em, auto) 1fr auto;
    align-items: center;
    gap: var(--ed-space-3);
    font-size: var(--ed-text-subhead);
}

.ebi-constraint-unit { color: var(--ed-text-secondary); }

.ebi-constraint-track {
    block-size: 6px;
    overflow: hidden;
    background: var(--ed-fill-subtle);
    border-radius: var(--ed-radius-pill);
}

.ebi-constraint-fill {
    display: block;
    block-size: 100%;
    background: var(--ed-azure-700);
    border-radius: var(--ed-radius-pill);
}

.ebi-constraint-figure {
    font-variant-numeric: tabular-nums lining-nums;
    color: var(--ed-text);
}

.ebi-constraint-note {
    display: block;
    margin-block-start: var(--ed-space-4);
    line-height: var(--ed-leading-snug);
}

/* --------------------------------------------------------------------------
   GRAFANA PANELS
   -------------------------------------------------------------------------- */
.ebi-panels {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: var(--ed-space-4);
}

/* Deliberately frameless. Grafana paints its own surface and hairline
   inside the iframe and gives us no way to turn that off, so a bordered
   figure around it drew every chart as a box inside a box. The panel keeps
   the caption; the chart's own surface is the card. */
.ebi-panel {
    display: flex;
    flex-direction: column;
    gap: var(--ed-space-2);
    grid-column: span 12;
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
}

.ebi-panel-title {
    padding-inline: var(--ed-space-1);
    font-size: var(--ed-text-subhead);
    font-weight: var(--ed-weight-medium);
    color: var(--ed-text-secondary);
}

/* Clipping the iframe rounds Grafana's square panel corners to the radius
   every other surface on the page uses. */
.ebi-panel-frame {
    display: block;
    inline-size: 100%;
    border: 0;
    border-radius: var(--ed-radius-lg);
    overflow: hidden;
}

@media (min-width: 900px) {
    .ebi-panel--span4  { grid-column: span 4; }
    .ebi-panel--span6  { grid-column: span 6; }
    .ebi-panel--span8  { grid-column: span 8; }
    .ebi-panel--span12 { grid-column: span 12; }
}

.ebi-deeplink {
    margin-block-start: var(--ed-space-4);
    font-size: var(--ed-text-subhead);
}

.ebi-deeplink a {
    color: var(--ed-accent);
    text-decoration: none;
}

.ebi-deeplink a:hover { text-decoration: underline; }

.ebi-offline {
    padding: var(--ed-space-4) var(--ed-space-5);
    font-size: var(--ed-text-subhead);
    line-height: var(--ed-leading-snug);
    color: var(--ed-text-secondary);
    background: var(--ed-surface-sunken);
    border: 1px solid var(--ed-separator-soft);
    border-radius: var(--ed-radius-md);
}

/* --------------------------------------------------------------------------
   RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 599px) {
    .ebi-head {
        align-items: flex-start;
    }

    .ebi-head-controls {
        inline-size: 100%;
    }

    .ebi-tile-value { font-size: var(--ed-text-title); }
}
