
.ech-fr, .ech-fr * { box-sizing: border-box; }

.ech-fr {
  --fr-orchid: var(--nilla-accent, #b98cff);
  --fr-aqua: var(--theme-accent-2, #54e0d0);
  /* the reacting light keeps a memory of the structural one — never pure aqua */
  --fr-live: color-mix(in srgb, var(--fr-aqua) 86%, var(--fr-orchid));

  position: relative;
  display: block;
  width: 96px;
  height: 18px;
  line-height: 18px;
  overflow: hidden;
  text-align: center;
  text-overflow: ellipsis;
  /* A bezel and a recessed face, both barely there. Without them 9px of text
     and a row of 2px ticks float on the plate and read as debris; with them the
     clock, this window and the buttons parse as one instrument. */
  border: 1px solid color-mix(in srgb, var(--fr-orchid) 15%, transparent);
  background: color-mix(in srgb, var(--nilla-bg, #06050e) 46%, transparent);
  transition: border-color 240ms ease, box-shadow 240ms ease;
}
/* The bloom is INSET. An outer glow on a 34px bar bleeds over the version
   stamp and the button row either side of it. */
.ech-fr[data-named="1"],
.ech-fr[data-measure="1"] {
  border-color: color-mix(in srgb, var(--fr-live) 34%, transparent);
  box-shadow: inset 0 0 10px -4px color-mix(in srgb, var(--fr-live) 62%, transparent);
}

.ech-fr-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  transition: opacity 220ms ease;
}

/* ── idle: a segmented signal bank on a baseline rule ─────────────────── */

.ech-fr-idle {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  padding: 0 5px 5px;
  opacity: 1;
}
.ech-fr[data-named="1"] .ech-fr-idle { opacity: 0; }

/* the plinth the bank stands on — static, and the quietest thing in the box */
.ech-fr-idle::after {
  content: "";
  position: absolute;
  left: 5px;
  right: 5px;
  bottom: 4px;
  height: 1px;
  background: color-mix(in srgb, var(--fr-orchid) 16%, transparent);
}

.ech-fr-seg {
  flex: 0 0 2px;
  height: var(--fr-h);
  background: var(--fr-orchid);
  opacity: var(--fr-rest);
  animation: ech-fr-scan 4.8s linear infinite;
  animation-delay: var(--fr-delay);
}

/* Opacity only. Animating the bar HEIGHTS would make this an equaliser, which
   is a decoration demanding attention; a pulse passing over a fixed profile is
   an instrument reporting that it is still powered. */
@keyframes ech-fr-scan {
  0%, 56% { opacity: var(--fr-rest); }
  64% { opacity: 0.68; }
  80%, 100% { opacity: var(--fr-rest); }
}

/* ── named / measured: the answer ─────────────────────────────────────── */

/* ONE FACE, TWO WRITERS. A name and a measurement are the same act — the
   terminal answering — so they are one declaration rather than two that would
   drift apart at the first edit to either. */
.ech-fr-name,
.ech-fr-measure {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 4px;
  opacity: 0;
  color: var(--fr-live);
  font-size: 0.5625rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  line-height: 1;
  text-transform: uppercase;
  text-shadow: 0 0 6px color-mix(in srgb, var(--fr-live) 32%, transparent);
}
.ech-fr[data-named="1"] .ech-fr-name { opacity: 1; }

/* letter-spacing appends a trailing space after the LAST glyph too, which shoves
   a centred run half a space to the left; the indent puts it back. */
.ech-fr-name > span,
.ech-fr-measure > span {
  display: block;
  max-width: 100%;
  overflow: hidden;
  text-indent: 0.18em;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* TABULAR FIGURES ARE LOAD-BEARING HERE, not typographic. The measurement is
   live under a moving hand, and proportional digits change width as they
   change value — the number would twitch sideways while it counted, which
   reads as the VALUE being unstable rather than the type being cheap. The
   mono face is named for the same reason and as a longhand, since the `font`
   shorthand would silently reset `font-variant-numeric` back to normal. */
.ech-fr-measure {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-variant-numeric: tabular-nums;
}

/* THE MEASUREMENT OUTRANKS BOTH, and it wins on source order rather than on
   weight: this selector and the `[data-named="1"]` one above are the same
   specificity, so these rules must stay BELOW them. A control being held beats
   a control being pointed at — the hand is already committed to one of them. */
.ech-fr[data-measure="1"] .ech-fr-idle,
.ech-fr[data-measure="1"] .ech-fr-name { opacity: 0; }
.ech-fr[data-measure="1"] .ech-fr-measure { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  /* The scan stops and the bank holds its profile, which still reads as an
     instrument at rest. The cross-fade STAYS: a 220ms opacity change is not
     vestibular motion, and killing it would replace the transition this readout
     exists to make with the hard cut it was written to avoid. */
  .ech-fr-seg { animation: none; }
}
