/* ═══════════════════════════════════════════════════════════════════════
   signals-rail.css — the desk rail and its interrupt banner.
   pages/signals/rail.js only.

   The spine of the Signals page: one sticky 46px strip of eight cells that
   stays under the top bar in every view, so "is the machine healthy and
   where is the money" is answered without scrolling, all session.

   Three things this file is careful about.

   Z-INDEX. 28 — strictly below .page-head (30) and the top bar (60), both
   and below body.sg-full (66), so the full-screen chart hides the rail
   instead of poking eight buttons through itself.

   QUIET BY DEFAULT. A cell tinted green for being fine teaches the eye to
   ignore colour, so .ok only colours the number. .warn and .bad tint the
   whole cell, because those are the two states that must survive being
   glanced at from across a desk.

   FIXED SHAPE. rail.js patches text nodes into this markup and never
   rebuilds it, so nothing here may depend on a node being added, removed
   or reordered — including the stale watermark, which is a sibling of the
   cell strip rather than an overlay on top of it.
   ═══════════════════════════════════════════════════════════════════════ */

/* One geometry token and one surface, declared in all three theme blocks
   the way styles.css does it. --rail-stale-bg is the "these numbers are not
   live" wash: warm enough to read as a caution, pale enough that the last
   good numbers underneath stay legible. */
:root {
  --rail-h: 46px;
  --rail-stale-bg: color-mix(in srgb, var(--warn) 9%, var(--surface));
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --rail-h: 46px;
    --rail-stale-bg: color-mix(in srgb, var(--warn) 13%, var(--surface));
  }
}
:root[data-theme="dark"] {
  --rail-h: 46px;
  --rail-stale-bg: color-mix(in srgb, var(--warn) 13%, var(--surface));
}

/* ── the strip ─────────────────────────────────────────────────────── */
.sg-rail {
  position: sticky;
  top: var(--stick);
  z-index: 28;
  margin-bottom: 16px;
  background: var(--surface);       /* opaque: content scrolls underneath */
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--shadow);
  overflow: hidden;                 /* keeps the cell corners inside the radius */
}
.rail-cells {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
}

/* ── a cell ────────────────────────────────────────────────────────── */
.rail-cell {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 2px;
  min-height: 46px;                /* a floor, not --rail-h: rail.js writes --rail-h FROM this strip's height */
  min-width: 0;
  padding: 8px 12px 9px;
  border: none;
  border-left: 1px solid var(--border);
  background: transparent;
  text-align: left;
  cursor: pointer;
  transition: background var(--dur) var(--spring), border-color var(--dur), color var(--dur);
}
.rail-cell:first-child { border-left: none; }
.rail-cell:hover { background: var(--surface-hover); }
.rail-cell:active { background: var(--surface-3); }
.rail-cell:focus-visible { outline: none; box-shadow: inset 0 0 0 3px var(--accent-ring); }

.rc-eyebrow {
  font-size: 10.5px;
  line-height: 12px;
  font-weight: 550;
  letter-spacing: .01em;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rc-main {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
  line-height: 17px;
}
/* Numbers in the UI face with tabular figures; mono is for the strategy
   code on the mode cell only. rail.js emits `.rc-value.mono` on every cell,
   so the reset is written at a higher specificity than that class. */
.rail-cell .rc-value {
  font-family: var(--font);
  font-variant-numeric: tabular-nums;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail-cell[data-rail="mode"] .rc-value { font-family: var(--mono); letter-spacing: 0; font-size: 13px; }
.rc-sub {
  font-size: 11.5px;
  font-weight: 550;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
  white-space: nowrap;
}
/* Up to two lines, then an ellipsis: long enough that a reason is read as a
   sentence rather than cut mid-word, short enough that the rail stays a
   strip. The cells in a row stretch to the tallest one, and rail.js
   publishes the strip's real height as --rail-h so the sticky watchlist and
   inspector below it never tuck under it. The full text is still in the
   cell's tooltip and in its drawer. */
.rc-verdict {
  font-size: 11px;
  line-height: 14px;
  color: var(--muted);
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow-wrap: anywhere;
}

/* The flag slot carries two different things and both are one short token:
   the LIVE / PAPER chip on the mode cell, and a "!" everywhere else. */
.rc-flag {
  flex: 0 0 auto;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .04em;
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--surface-3);
  color: var(--text-2);
}
.rc-flag.live { background: var(--pos-bg); color: var(--pos); }
.rc-flag.paper { background: var(--paper-bg); color: var(--paper-d); }
.rc-flag.warn { background: var(--warn-bg); color: var(--warn); padding: 0 5px; }
.rc-flag.bad { background: var(--neg); color: #fff; padding: 0 5px; }

/* ── tones ─────────────────────────────────────────────────────────── */
.rail-cell.ok .rc-value { color: var(--pos); }
.rail-cell.warn { background: var(--warn-bg); }
.rail-cell.warn:hover { background: color-mix(in srgb, var(--warn) 16%, var(--surface)); }
.rail-cell.warn .rc-value { color: var(--warn); }
.rail-cell.warn .rc-verdict { color: var(--warn); }
.rail-cell.bad { background: var(--neg-bg); }
.rail-cell.bad:hover { background: color-mix(in srgb, var(--neg) 14%, var(--surface)); }
.rail-cell.bad .rc-value { color: var(--neg); }
.rail-cell.bad .rc-verdict { color: var(--neg); }
/* P&L keeps the house colours regardless of the cell's health tone: money is
   red or green on its own sign, never on whether the machine is well. */
.rc-value.pos, .rc-sub.pos { color: var(--pos); }
.rc-value.neg, .rc-sub.neg { color: var(--neg); }
.rc-value.muted, .rc-sub.muted { color: var(--muted); }
.rc-value.faint, .rc-sub.faint { color: var(--faint); }

/* ── stale: the last good reading, visibly not live ────────────────── */
.sg-rail.stale { border-color: var(--warn-bd); }
/* A hatch, not just an opacity drop: a dimmed number still reads as a number,
   and the whole point is that these are no longer arriving. It is an overlay
   on each cell rather than a background on the strip, because a warn or bad
   cell paints its own background and would otherwise be the one cell that
   still looks live. */
.sg-rail.stale .rail-cell { position: relative; }
.sg-rail.stale .rail-cell::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: repeating-linear-gradient(135deg,
    transparent 0 7px, color-mix(in srgb, var(--warn) 12%, transparent) 7px 8px);
}
.sg-rail.stale .rc-value,
.sg-rail.stale .rc-sub { opacity: .62; }
.sg-rail.stale .rail-cell.ok .rc-value { color: var(--text-2); }

.rail-stale {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 12px;
  min-height: 24px;
  background: var(--rail-stale-bg);
  border-top: 1px solid var(--warn-bd);
  font-size: 11.5px;
  color: var(--warn);
}
.rail-stale .rs-dot {
  width: 6px; height: 6px; flex: 0 0 auto;
  border-radius: 50%;
  background: var(--warn);
  animation: railPulse 1.6s ease-in-out infinite;
}
.rail-stale .rs-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail-stale .btn { flex: 0 0 auto; }

@keyframes railPulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

/* ── the banner: at most three interrupts ──────────────────────────── */
.sg-banner {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 16px;
}
.sgb-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  border: 1px solid var(--border-2);
  border-radius: var(--r);
  background: var(--surface);
  font-size: 12.5px;
}
.sgb-row.bad { background: var(--neg-bg); border-color: var(--neg-bd); color: var(--neg); }
.sgb-row.warn { background: var(--warn-bg); border-color: var(--warn-bd); color: var(--warn); }
.sgb-dot {
  width: 7px; height: 7px; flex: 0 0 auto;
  border-radius: 50%;
  background: currentColor;
}
.sgb-row.bad .sgb-dot { animation: railPulse 1.2s ease-in-out infinite; }
.sgb-text { flex: 1; min-width: 0; font-weight: 500; }
.sgb-acts { display: flex; gap: 6px; flex: 0 0 auto; }
.sgb-acts .btn { background: var(--surface); border-color: var(--border-2); color: var(--text); }
.sgb-acts .btn.danger { color: var(--neg); }

/* ── the drawers' action row ───────────────────────────────────────── */
.rail-acts { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px; }

/* ── breakpoints ───────────────────────────────────────────────────── */
/* 1300: two rows of four. Eight cells at 1fr each are 124px wide on a
   1280 laptop with the sidebar open, which elides every verdict to a stub;
   that is the point at which the rail stops being readable at a glance and
   starts being a puzzle. */
@media (max-width: 1300px) {
  .rail-cells { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .rail-cell:nth-child(4n+1) { border-left: none; }
  .rail-cell:nth-child(n+5) { border-top: 1px solid var(--border); }
}

/* 900: one row again, scrolling sideways. Wrapping to four rows of two
   would push the chart below the fold on a phone; the rail is a strip you
   swipe, and the first two cells — mode and P&L — are the ones that stay
   in view. */
@media (max-width: 900px) {
  .rail-cells {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: minmax(168px, 1fr);
    overflow-x: auto;
    scrollbar-width: none;
  }
  .rail-cells::-webkit-scrollbar { display: none; }
  .rail-cell:nth-child(n+5) { border-top: none; }
  .rail-cell:nth-child(4n+1) { border-left: 1px solid var(--border); }
  .rail-cell:first-child { border-left: none; }
  .sgb-row { flex-wrap: wrap; }
  .sgb-text { flex: 1 0 100%; }
}

@media (max-width: 640px) {
  .sg-rail { margin-left: 0; margin-right: 0; }
  .rail-cell { padding: 8px 10px 9px; }
}

@media (prefers-reduced-motion: reduce) {
  .rail-stale .rs-dot,
  .sgb-row.bad .sgb-dot { animation: none; }
  .rail-cell { transition: none; }
}
