/*
 * KPI strip — the joined, compact, monochrome segment strip (ISH-894).
 *
 * One bordered surface split into segments by hairlines, NOT a row of separate
 * cards. ISH-638 built it on analytics.html and ISH-681 ported it to
 * broker.html; this file is that rule extracted so the remaining pages adopt it
 * with a <link> instead of a sixth paste. The values are analytics.html's, which
 * is the canonical look — the same move css/tokens.css made for the palette
 * (ISH-520) and css/filter-toolbar.css for the filter panel (ISH-261).
 *
 * Consumers: analytics.html, broker.html, sales-pipeline-report.html,
 * uninvoiced-approved-tasks.html — every page in the app that renders a KPI card.
 *
 * Each keeps only its own deliberate overrides, and each states why in a comment
 * where its block used to be: broker.html's 1.625rem value and green trend,
 * sales-pipeline-report.html's six columns and 1.85rem value, analytics.html's
 * Scorecard goal pills. ⚠️ Link this file BEFORE the page's inline <style>, or
 * those overrides lose.
 *
 * If you add a consumer, DELETE its inline block rather than leaving both. A page
 * that links this file and still declares .kpi-card locally is exactly how the
 * pre-ISH-353 stage palette drifted.
 *
 * ── The markup contract ──────────────────────────────────────────────────────
 *
 *   .kpi-grid
 *     .kpi-card                     a SEGMENT: no border, no radius, no shadow
 *       .kpi-content
 *         .kpi-header               only needed when there is a badge
 *           .kpi-label + .info-icon
 *           .kpi-badge              the period, right-aligned in --red
 *         .kpi-value
 *         .kpi-subtext | .kpi-trend see the warning below
 *
 * `react-app/src/components/KpiCard.tsx` emits exactly this, so the island and
 * the hand-written pages render the same DOM.
 *
 * ⚠️ .kpi-subtext and .kpi-trend SWAP — they never share the line. ISH-684
 * settled this as a density decision, not a layout preference: showing both
 * takes the strip from 86.6px to 108.6px at 1440px, handing back exactly the
 * density ISH-638's strip was built to buy. Whichever carries information wins —
 * the comparison when there is one, the sublabel when there is not.
 *
 * ── Column count ─────────────────────────────────────────────────────────────
 *
 * Set --kpi-cols on .kpi-grid (default 5). The wrap breakpoints below override
 * it to 3 and then 1, and their border resets are written against those counts
 * rather than against yours, so they hold whatever --kpi-cols you pick.
 *
 * ⚠️ Above 900px only :first-child clears its border-left, which assumes the
 * strip is ONE row — cards <= columns. A page with more cards than columns needs
 * its own :nth-child reset, or the wrapped row reads as one run of segments
 * rather than as a grid.
 *
 * ── ⚠️ Why four values are pinned here instead of read from the page ────────
 *
 * The strip's own surface, dividers, radius and label colour are stated BELOW as
 * --kpi-* variables rather than taken from --border / --border-light /
 * --radius-lg / --text-label, because those four tokens have genuinely drifted
 * per page and css/tokens.css does not own them yet (its header lists them as
 * still-drifted, with unifying --text-label called out as its own job because
 * per-page compensations were built on top of it).
 *
 * Sharing the RULES while reading DRIFTED tokens gave four consumers four
 * different-looking strips, which is most of what extracting the file was
 * supposed to end. Measured on develop before this change:
 *
 *              --text-label   --border   --border-light   --radius-lg
 *   analytics    #777777      #dcdcdc      #ebebeb          8px
 *   broker       #999999      #e0e0e0      #ebebeb          8px
 *   spr          #767676      #e0e0e0      #ebebeb          8px
 *   uninvoiced   #94a3b8      #e2e8f0      #f1f5f9         12px
 *
 * The label colour is #767676 and that is NOT a new value: ISH-498 picked it for
 * this exact class, because "#999999 on white is 2.85:1 — fails WCAG AA (4.5:1)
 * for the non-large text this token is used on (.kpi-label…). #767676 clears it
 * at 4.54:1." Three of the four pages were failing AA on their KPI labels; the
 * one that was not is the one that had already had this argument.
 *
 * A page that genuinely needs to differ overrides the --kpi-* variable on
 * .kpi-grid — the same escape hatch --kpi-cols already provides. Reading the
 * page token again is not that escape hatch; it is the drift coming back.
 *
 * Still read from the page, because css/tokens.css DOES own them and they are
 * uniform: --card-bg, --red, --text-secondary.
 */

.kpi-grid {
  --kpi-cols: 5;
  /* See the header. Override one of these on .kpi-grid if a page must differ. */
  --kpi-border: #e0e0e0;
  --kpi-divider: #ebebeb;
  --kpi-radius: 8px;
  --kpi-label-color: #767676;

  display: grid;
  grid-template-columns: repeat(var(--kpi-cols), 1fr);
  background: var(--card-bg);
  border: 1px solid var(--kpi-border);
  border-radius: var(--kpi-radius);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
  /* On .kpi-grid rather than .kpi-card, to clip the segments to the rounded
     outer border. This is therefore the ancestor the portaled .info-icon tooltip
     has to escape — see css/info-tooltip.css (ISH-700). */
  overflow: hidden;
  margin-bottom: 0.75rem;
}

/* A segment, not a card: no border, no radius, no shadow, no hover lift. The
   hairline is a border-left so the first segment of each row has none — which is
   also what makes the 3-up and 1-up wraps below fall out correctly. */
.kpi-card {
  background: none;
  border: none;
  border-left: 1px solid var(--kpi-divider);
  border-radius: 0;
  box-shadow: none;
  padding: 0.6rem 0.85rem 0.65rem;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  position: relative;
  min-width: 0;
}

.kpi-card:first-child {
  border-left: none;
}

.kpi-content {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}

/* The gap is load-bearing, not cosmetic (ISH-1279). This row is `space-between`
   with a label that wraps and a badge that does not, so once the label is long
   enough to take the full remaining width its box ends flush against the badge
   and the two strings touch. Measured on the Scorecard strip at a 1024px
   viewport: "ISD WORKING DAYS" and "Through Aug" sat 0px apart. */
.kpi-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
}

.kpi-label {
  font-size: 0.625rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--kpi-label-color);
}

/* ⚠️ `nowrap` is what decides WHICH of the two strings wraps when the segment is
   too narrow for both (ISH-1279). The badge names the reporting period — a
   "Through Aug" broken across two lines reads as two separate chips — while the
   label is a fixed term the reader already knows and survives wrapping. Hosts
   whose badge is "MTD"/"YTD"/"1Y" are unaffected: those never wrapped. */
.kpi-badge {
  font-size: 0.625rem;
  font-weight: 700;
  color: var(--red);
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* Line heights are pinned rather than left to font metrics so the segment's
   height is a property of this stylesheet and can be reasoned about without
   rendering it — js/broker-kpi-strip-parity.test.js checks that arithmetic. */
.kpi-value {
  font-size: 1.375rem;
  font-weight: 700;
  color: #333333;
  letter-spacing: -0.02em;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

/* The unit after a figure ("47 days"). Smaller and lighter, so the number keeps
   the weight. */
.kpi-value small {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--text-secondary);
}

.kpi-subtext {
  font-size: 0.7rem;
  line-height: 1.3;
  color: var(--kpi-label-color);
  margin-top: 0.15rem;
}

/* The period-over-period comparison.
 *
 * ⚠️ No base `color` on purpose, and this is a real difference between the two
 * source pages rather than an omission: analytics.html lets the line inherit,
 * while broker.html paints an improvement green. Declaring either one here would
 * silently restyle the other page, so the base inherits and broker.html keeps a
 * one-line override. Only `.is-down` is shared, because both pages agree a
 * decline is red. */
.kpi-trend {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.25rem;
  row-gap: 0.25rem;
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.3;
  margin-top: 0.25rem;
}

.kpi-trend.is-down {
  color: var(--red);
}

@media (max-width: 900px) {
  .kpi-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .kpi-card:nth-child(3n + 1) {
    border-left: none;
  }

  /* Rows after the first need a rule above them, or the 3-up wrap reads as one
     run of segments rather than as a grid. */
  .kpi-card:nth-child(n + 4) {
    border-top: 1px solid var(--kpi-divider);
  }
}

@media (max-width: 600px) {
  .kpi-grid {
    grid-template-columns: 1fr;
  }

  .kpi-card {
    border-left: none;
  }

  .kpi-card + .kpi-card {
    border-top: 1px solid var(--kpi-divider);
  }
}
