/* ============================================================================
   components/kpi-tile.css  ·  THE ONE KPI TILE
   ----------------------------------------------------------------------------
   THE DEFECT THIS CLOSES (2026-09-02, operator brief).

   Five pages carried their own copy of this tile's CSS and the Home page
   carried a sixth, different one. Same block, pasted six times, already
   drifting: 1.7rem here and 1.75rem there, --surface here and
   --surface-card-bg there, a 640px scroll rail on four pages and not on the
   fifth. Nobody had changed the tile in months, and it was already six tiles.

   Worse than the drift was the Home row. Its tiles carried a per-tile ACCENT
   COLOUR and a per-tile ICON: leads blue with a person glyph, tickets amber
   with a ticket glyph, alerts red with a warning triangle. Five numbers, five
   colours, five pictures, and none of the colours meant anything - a red tile
   read as an alarm whether the number under it was 0 or 40. Colour that does
   not track a value is decoration wearing the clothes of meaning.

   THE TILE, AS THE OPERATOR SPECIFIED IT.

       OPEN                       label, small caps, the quiet line
       1                          the number, the loudest thing on the tile
       open right now             one line saying what the number counts
       Open Tickets ->            an optional link, when the tile has a page

   No icon in the heading. No per-tile colour. The tile is the same tile on
   every surface, and the only thing that varies between two of them is the
   words and the number.

   `--kpi-strip-min` lets a surface widen or narrow its own row without
   redefining the tile; nothing else here is overridable by design, because
   "one tile style" is the whole point of the file.
   ========================================================================== */

.kpi-strip{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(var(--kpi-strip-min,180px),1fr));
  gap:var(--space-md);
  margin-bottom:var(--space-md);
}
@media (max-width:1024px){ .kpi-strip{ grid-template-columns:repeat(2,1fr) } }
/* Phone: a horizontal snap rail rather than a two-up grid that pushes the
   page's real content below the fold. */
@media (max-width:640px){
  .kpi-strip{display:flex;overflow-x:auto;gap:var(--space-sm);scroll-snap-type:x mandatory;padding-bottom:6px}
  .kpi-strip .kpi{min-width:80%;scroll-snap-align:start;flex-shrink:0}
}

.kpi{
  background:var(--surface);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);
  padding:var(--space-md);
  position:relative;
  display:flex;flex-direction:column;
  /* A tile is a tile whether or not it is a link. */
  color:inherit;text-decoration:none;
}
/* Only a LINKED tile reacts to the pointer: a static tile that lights up under
   the cursor promises a click that never comes. */
a.kpi{transition:border-color var(--duration-fast,.15s) var(--ease,ease)}
a.kpi:hover{border-color:var(--border)}
a.kpi:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.kpi-label{
  font-family:var(--font-mono);font-size:var(--text-2xs);
  letter-spacing:var(--ls-wider);text-transform:uppercase;
  color:var(--text-tertiary);margin-bottom:var(--space-sm);
}
/* The range chip that rides a label ("· 7d") is part of the label's quiet
   line, never a second heading. */
.kpi-label .range-label{text-transform:none;letter-spacing:var(--ls-normal);opacity:.8}

.kpi-value{
  font-family:var(--font-heading);font-size:var(--fs-xl);font-weight:var(--fw-semibold);
  color:var(--text);line-height:1;min-height:1em;
  display:flex;align-items:baseline;gap:6px;
}
/* A value that is a phrase rather than a figure ("awaiting", "not tracked
   yet") steps down a size: it is still the tile's answer, but it must not
   shout at the width of a headline. */
.kpi-value.small{font-size:var(--fs-lg)}
.kpi-value.kpi-unread{font-size:var(--fs-lg);color:var(--text-tertiary);font-weight:var(--fw-regular)}
.kpi-unit{font-size:var(--text-md);color:var(--text-tertiary);font-weight:var(--fw-regular)}

.kpi-foot{
  display:flex;align-items:center;gap:6px;
  font-size:var(--text-xs);margin-top:var(--space-sm);color:var(--text-tertiary);
}
.kpi-delta-up{color:var(--ok)}

/* Provenance, not decoration: the one ⓘ that says which query answered. It sits
   in the corner, out of the reading order of label -> number -> caption, and it
   is the ONLY glyph the tile is allowed to carry. */
.kpi-tip{position:absolute;top:var(--space-sm);right:var(--space-sm)}

/* The optional link, pinned to the bottom so tiles of different caption
   lengths still line their links up with each other. */
.kpi-link{
  margin-top:auto;padding-top:var(--space-sm);
  font-size:var(--text-xs);color:var(--accent);
  display:inline-flex;align-items:center;gap:6px;
}
a.kpi:hover .kpi-link{text-decoration:underline}

/* The pending skeleton the renderer emits (spec.pending). It belongs to the tile, not to
   the page: kpi-tile.js writes the class, so kpi-tile.css owns it. */
.skel{background:linear-gradient(90deg,var(--surface-raised) 0%,color-mix(in srgb,var(--surface-raised) 60%,var(--text-tertiary) 8%) 50%,var(--surface-raised) 100%);background-size:200% 100%;animation:kpi-skel 1.4s ease-in-out infinite;border-radius:var(--radius-md)}
@keyframes kpi-skel{0%{background-position:100% 0}100%{background-position:-100% 0}}
@media (prefers-reduced-motion:reduce){.skel{animation:none}}
