/* MarketChronos — band.css
 * Componente canónico de la BANDA p10–p90 (rango de incertidumbre) — goal17 T2.
 *
 * Un solo lenguaje visual para toda la app: asset.html, position-detail.html y
 * projection.html usan el MISMO componente y el MISMO término — "banda p10–p90"
 * / "rango". No se reimplementan 3 bandas distintas.
 *
 * LEY (honestidad dura):
 *   - La banda es RANGO DE INCERTIDUMBRE, nunca una promesa de rentabilidad ni una
 *     dirección. El componente no dibuja flechas "sube/baja": dibuja un abanico que
 *     se ensancha con el horizonte. El área ancha ES el mensaje.
 *   - Colores desde tokens semánticos WCAG-AA (variables.css). Cero emojis, cero
 *     hex crudo. Cero nombres de modelos OSS (naming: "Motor de forecast de
 *     InferenceKey").
 *
 * Estructura canónica (self-contained por mock, el SVG vive inline):
 *   <figure class="band-figure">
 *     <svg class="band-svg" viewBox="0 0 600 240" role="img" aria-label="...">
 *       <path class="band-area"   d="..." />   área p10–p90 (el abanico)
 *       <path class="band-hist"   d="..." />   histórico realizado (sólido)
 *       <path class="band-median" d="..." />   mediana proyectada (discontinua)
 *       ... marca "hoy", ejes, etiquetas p10/p90 ...
 *     </svg>
 *     <figcaption class="band-legend"> ... swatches ... </figcaption>
 *   </figure>
 *
 * Las clases .band-legend / .swatch / .band-claim reemplazan a las copias por-mock
 * (asset/position-detail tenían .swatch-band/.swatch-median duplicadas). El SVG usa
 * clases (band-area/band-hist/band-median) en lugar de fill/stroke inline repetidos.
 */

/* ---------- Figura (contenedor responsivo del SVG) ---------- */
.band-figure {
  margin-top: var(--space-2);
  max-width: 100%;
}

.band-svg {
  display: block;
  width: 100%;
  height: auto;
  max-width: 100%;
}

/* =====================================================================
 * v3 — Fan chart PRO (G23 T1 ronda 2). Terminal-financiera look:
 * dos conos anidados (p10–p90 exterior tenue + p25–p75 interior denso),
 * gradiente de densidad que se atenúa hacia +20d, rejilla y ejes a muy
 * baja opacidad, marca "hoy" en el vértice, etiquetas ancladas al borde.
 *
 * LEY intacta: el ancho ES el mensaje, cero flechas de dirección, la
 * mediana es discontinua a propósito. Todos los colores derivan de
 * --color-accent con color-mix (cero hex crudo nuevo).
 * ===================================================================== */

/* ---------- Gradiente de densidad de los conos ---------- *
 * El abanico es más opaco cerca de "hoy" y se atenúa hacia +20d: "más
 * lejos = más incierto". Los stops derivan del acento con color-mix, sin
 * introducir hex nuevo. Cono exterior más tenue que el interior.        */
.band-grad-outer-0 { stop-color: var(--color-accent); stop-opacity: 0.30; }
.band-grad-outer-1 { stop-color: var(--color-accent); stop-opacity: 0.08; }
.band-grad-inner-0 { stop-color: var(--color-accent); stop-opacity: 0.55; }
.band-grad-inner-1 { stop-color: var(--color-accent); stop-opacity: 0.22; }

/* ---------- Trazos del SVG (tokens semánticos, sin hex inline) ---------- */
/* Área p10–p90: el abanico de incertidumbre. Su ancho es el mensaje.
 * El borde se dibuja con un accent tenue (color-mix hacia el surface) para
 * que el cono tenga contorno sin gritar. */
.band-area {
  vector-effect: non-scaling-stroke;
}
.band-area--outer {
  fill: url(#band-fill-outer);
  stroke: color-mix(in srgb, var(--color-accent) 45%, transparent);
  stroke-width: 1;
}
.band-area--inner {
  fill: url(#band-fill-inner);
  stroke: color-mix(in srgb, var(--color-accent) 65%, transparent);
  stroke-width: 1;
}

/* ---------- Relleno PLANO de la franja de calibración (G29-T3) ---------- *
 * La mini-prueba de calibración NO es un cono: es una franja de altura constante
 * (G29-T2b). Heredaba el `url(#band-fill-outer/inner)` del abanico, cuyos
 * gradientes son de EJE HORIZONTAL (x1=300 → x2=576): eso reintroducía por
 * plomería la rampa izquierda→derecha, es decir, exactamente la progresión
 * temporal que se acababa de eliminar de la geometría.
 *
 * Se elige un relleno PLANO (sólido) y no un gradiente vertical propio: el alto
 * de la franja ES el rango p10–p90, así que una rampa vertical insinuaría que el
 * centro del rango es más probable que sus bordes — una densidad que el dato de
 * este módulo (una fecha, una cobertura y un booleano de contención) no mide.
 * Plano no afirma nada más allá de "esto es el rango".
 *
 * Las opacidades son las del stop INICIAL de cada gradiente (0.30 / 0.55), así
 * que la franja conserva exactamente el peso visual que ya tenía en su borde
 * izquierdo, sin hex nuevo y sin tocar el abanico (allí el eje horizontal SÍ
 * corresponde al cono que se abre hacia el horizonte: es su semántica). */
.ar-calib-svg .band-area--outer {
  fill: color-mix(in srgb, var(--color-accent) 30%, transparent);
}
.ar-calib-svg .band-area--inner {
  fill: color-mix(in srgb, var(--color-accent) 55%, transparent);
}

/* Rejilla de valor (Y): líneas horizontales muy tenues, sin saturar. */
.band-grid-line {
  stroke: color-mix(in srgb, var(--color-text-faint) 40%, transparent);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.band-ytick {
  fill: var(--color-text-faint);
  font-size: 10px;
  font-family: var(--font-stack);
  font-variant-numeric: tabular-nums;
}
/* Eje de tiempo (X) y sus marcas: a baja opacidad, calma sobre ruido. */
.band-axis-x {
  stroke: color-mix(in srgb, var(--color-text-faint) 55%, transparent);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.band-tick {
  stroke: color-mix(in srgb, var(--color-text-faint) 55%, transparent);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* Histórico realizado (hasta hoy): línea sólida, neutra (no es dirección futura). */
.band-hist {
  fill: none;
  stroke: var(--color-text-muted);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
/* Mediana proyectada: discontinua a propósito — es el centro del rango, no una
 * predicción de trayectoria. Nunca lleva flecha. */
.band-median {
  fill: none;
  stroke: var(--color-accent);
  stroke-width: 2.5;
  stroke-dasharray: 6 5;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
/* Marca vertical "hoy" y ejes suaves. */
.band-nowline {
  stroke: color-mix(in srgb, var(--color-accent) 40%, transparent);
  stroke-width: 1;
  stroke-dasharray: 3 4;
  vector-effect: non-scaling-stroke;
}
/* Marcador "hoy" en el vértice del abanico. */
.band-now-halo {
  fill: color-mix(in srgb, var(--color-accent) 22%, transparent);
}
.band-now-dot {
  fill: var(--color-accent-bright);
  stroke: var(--bg-base);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}
.band-axis-label {
  fill: var(--color-text-muted);
  font-size: 12px;
  font-family: var(--font-stack);
}

/* ---------- Leyenda (swatches: banda + mediana) ---------- */
.band-legend {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-2);
  flex-wrap: wrap;
  font-size: var(--font-size-caption);
  color: var(--color-text-muted);
}
.band-legend span {
  display: inline-flex;
  align-items: center;
  gap: var(--space-0);
}
.swatch {
  width: 1.1rem;
  height: 0.55rem;
  border-radius: 2px;
  display: inline-block;
  flex: none;
}
/* Two-tone swatch: mirrors the nested cones — denser p25–p75 core inside a
 * tenuous p10–p90 edge. Colours derive from the accent (no raw hex). */
.swatch-band {
  background:
    linear-gradient(
      90deg,
      color-mix(in srgb, var(--color-accent) 22%, transparent),
      color-mix(in srgb, var(--color-accent) 8%, transparent)
    );
  border: 1px solid color-mix(in srgb, var(--color-accent) 45%, transparent);
  position: relative;
}
.swatch-band::after {
  content: '';
  position: absolute;
  inset: 25% 20%;
  border-radius: 1px;
  background: color-mix(in srgb, var(--color-accent) 45%, transparent);
}
.swatch-median {
  background: var(--color-accent);
}

/* ---------- Claim de cobertura (píldora) ---------- */
.band-claim {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: var(--space-2);
  padding: var(--space-0) var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--color-accent-bg);
  color: var(--color-text);
  font-size: var(--font-size-label);
  font-weight: 600;
}
.band-claim svg {
  width: 1rem;
  height: 1rem;
  flex: none;
}

/* ---------- Cifras clave del rango: p10 · mediana · p90 (micro-visual) ---------- */
/* Trío de números con el mismo lenguaje: los extremos son el rango, el centro la
 * mediana. Sin "objetivo" ni "esperado" — son percentiles del abanico. */
.band-figures {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.band-fig {
  background: var(--surface-2);
  border: 1px solid var(--surface-3);
  border-radius: var(--radius-sm);
  padding: var(--space-2);
  text-align: center;
}
.band-fig--median {
  border-color: var(--color-accent);
  background: var(--color-accent-bg);
}
.band-fig-key {
  display: inline-flex;
  align-items: center;
  gap: var(--space-0);
  font-size: var(--font-size-caption);
  color: var(--color-text-muted);
  font-weight: 700;
  letter-spacing: 0.02em;
}
.band-fig-key .swatch {
  width: 0.9rem;
  height: 0.45rem;
}
.band-fig-value {
  display: block;
  margin-top: var(--space-0);
  font-size: var(--font-size-value);
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: var(--numeric-tabular);
}
.band-fig-sub {
  display: block;
  margin-top: 1px;
  font-size: var(--font-size-caption);
  color: var(--color-text-muted);
  font-weight: 500;
}

/* ---------- Selector de horizonte (1 / 3 / 6 / 12 meses) ---------- */
/* Segmented control accesible: radios ocultos + labels. Cambiar el horizonte
 * ensancha la banda; nunca la sesga hacia arriba ni hacia abajo. */
.band-horizon {
  display: inline-flex;
  gap: 0;
  padding: 3px;
  background: var(--surface-2);
  border: 1px solid var(--surface-3);
  border-radius: var(--radius-pill);
}
.band-horizon-opt {
  position: relative;
  cursor: pointer;
}
.band-horizon-radio {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  border: 0;
}
.band-horizon-label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 3.2rem;
  padding: var(--space-0) var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--font-size-label);
  font-weight: 700;
  color: var(--color-text-muted);
  transition: color var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out);
}
.band-horizon-opt:hover .band-horizon-label {
  color: var(--color-text);
}
.band-horizon-radio:checked + .band-horizon-label {
  background: var(--color-accent);
  color: var(--color-on-accent);
}
.band-horizon-radio:focus-visible + .band-horizon-label {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* =====================================================================
 * v3 — Trace-on-enter animation for the PRO fan (G23 T1 ronda 2).
 *
 * The band is the protagonist chart. When the figure scrolls into the
 * viewport, an IntersectionObserver adds `.is-drawn` to the .band-svg once.
 *
 *   - The nested cones REVEAL left→right from the "hoy" vertex outward to
 *     +20d, via a clip-rect that scales in X from the vertex (300). This
 *     reads as "the fan opens up with the horizon" — the widening IS the
 *     message, never a direction. Filling a closed area by dash looks wrong,
 *     so the fan uses the clip wipe, not stroke-dashoffset.
 *   - The historical line and the dashed median still draw on via
 *     stroke-dashoffset (they carry .band-draw and set their own
 *     --draw-length inline from path.getTotalLength()).
 *   - The "hoy" marker fades in at the vertex.
 *
 * Plays ONCE, under 1s (--dur-draw), never loops. Respects reduced-motion.
 * ===================================================================== */
@media (prefers-reduced-motion: no-preference) {
  /* Pre-animation state: only once JS has armed the figure (.band-armed) do we
   * hide the strokes/fan; without JS everything renders complete and static. */
  .band-armed .band-draw {
    stroke-dasharray: var(--draw-length, 1200);
    stroke-dashoffset: var(--draw-length, 1200);
  }
  /* The fan is clipped by a rect that starts collapsed at the vertex. */
  .band-armed .band-reveal-rect {
    transform: scaleX(0);
    transform-origin: 300px center;
    transform-box: view-box;
  }
  .band-armed .band-area,
  .band-armed .band-median {
    opacity: 0;
  }
  .band-armed .band-now-dot,
  .band-armed .band-now-halo {
    opacity: 0;
  }

  /* On enter: wipe the clip open, fade the fill in, trace the lines. */
  .band-svg.is-drawn .band-reveal-rect {
    animation: band-clip-open var(--dur-draw) var(--ease-out) forwards;
  }
  .band-svg.is-drawn .band-area {
    animation: band-fan-fade var(--dur-draw) var(--ease-out) forwards;
  }
  .band-svg.is-drawn .band-median {
    animation: band-fan-fade var(--dur-draw) var(--ease-out) forwards;
    animation-delay: 260ms;
  }
  .band-svg.is-drawn .band-draw {
    animation: draw-line var(--dur-draw) var(--ease-out) forwards;
  }
  .band-svg.is-drawn .band-hist.band-draw {
    animation-delay: 60ms;
  }
  .band-svg.is-drawn .band-now-dot,
  .band-svg.is-drawn .band-now-halo {
    animation: band-now-appear var(--dur-draw) var(--ease-out) forwards;
    animation-delay: 420ms;
  }
}

@keyframes band-clip-open {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}
@keyframes band-fan-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes band-now-appear {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Reduce: the JS never arms the figure, but guard anyway — full & static. */
@media (prefers-reduced-motion: reduce) {
  .band-draw {
    stroke-dasharray: none !important;
    stroke-dashoffset: 0 !important;
  }
  .band-area,
  .band-median,
  .band-now-dot,
  .band-now-halo {
    opacity: 1 !important;
  }
  .band-reveal-rect {
    transform: none !important;
  }
}

/* =====================================================================
 * v3 — Gauge-percentile SPARKLINE (G24-T3).
 *
 * band.css owns the p10–p90 fan; the article view adds this minimal
 * sparkline component (band.css had no sparkline classes). It traces the
 * gauge percentile over the trailing months — UNCERTAINTY, NOT price — as a
 * single polyline. No area fill that could read as a rising trend, no
 * direction, no arrow: a hairline over a dashed baseline.
 * ===================================================================== */
.ar-band-note {
  margin-top: var(--space-2);
  font-size: var(--font-size-caption);
  color: var(--color-text-muted);
  line-height: 1.5;
}
.ar-spark-card {
  margin-top: var(--space-2);
  background: var(--surface-1);
  border: 1px solid var(--surface-3);
  border-radius: var(--radius-card);
  padding: var(--space-3);
}
.ar-spark-svg {
  display: block;
  width: 100%;
  height: auto;
  max-width: 100%;
}
/* Ejes REALES del sparkline (G29-T2): rejilla 0/40/70/100 del propio medidor y las
 * fechas reales de la primera y la última observación. Discretos: el dato manda. */
.ar-spark-gridline {
  stroke: color-mix(in srgb, var(--color-text-faint) 35%, transparent);
  stroke-width: 1;
  stroke-dasharray: 3 4;
  vector-effect: non-scaling-stroke;
}
.ar-spark-axis-line {
  stroke: color-mix(in srgb, var(--color-text-faint) 55%, transparent);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.ar-spark-ytick,
.ar-spark-xtick {
  fill: var(--color-text-muted);
  font-size: 13px;
  font-family: var(--font-stack);
  font-variant-numeric: tabular-nums;
}
/* El SVG escala con el contenedor, así que sus `font-size` están en unidades del
 * viewBox: en móvil el mismo 13 se dibujaría a ~7 px reales. Se sube en las anchuras
 * estrechas para que las etiquetas del eje sigan siendo legibles (y las fechas, que
 * van ancladas a los extremos del plot, nunca se salen del marco ni se solapan: solo
 * hay dos y están a 550 unidades de distancia). */
@media (max-width: 40em) {
  .ar-spark-ytick,
  .ar-spark-xtick {
    font-size: 22px;
  }
}
.ar-spark-line {
  fill: none;
  stroke: var(--color-accent-bright);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.ar-spark-caption {
  margin-top: var(--space-2);
  font-size: var(--font-size-caption);
  color: var(--color-text-muted);
  line-height: 1.5;
}
.ar-spark-caption .ar-data {
  font-variant-numeric: var(--numeric-tabular);
  font-weight: 700;
  color: var(--color-text);
}

/* The sparkline traces on enter (armSparklines sets --draw-length + is-drawn). */
@media (prefers-reduced-motion: no-preference) {
  [data-sparkline].spark-armed .spark-line {
    stroke-dasharray: var(--draw-length, 1000);
    stroke-dashoffset: var(--draw-length, 1000);
  }
  [data-sparkline].is-drawn .spark-line {
    animation: draw-line var(--dur-draw) var(--ease-out) forwards;
  }
}
@media (prefers-reduced-motion: reduce) {
  .spark-line {
    stroke-dasharray: none !important;
    stroke-dashoffset: 0 !important;
  }
}

/* =====================================================================
 * v3 — CALIBRATION module (G24-T4): "did our previous band contain the
 * price?". Ported from the mock's .av-calib/.av-track to the article's
 * .ar- namespace. Reuses the fan-chart visual language (band.css classes)
 * for the containment mini-proof.
 *
 * LAW (perceptual, goal23): the realized marker is FLAT — the "today" dot
 * falling inside/outside the band is the message, never the height it
 * reached. No arrows, no celebrated halo: containment framing only.
 *
 * LAW (G29-T2b, anti-invention): the mini-proof carries NO axis. Its data
 * are a coverage figure, a window count, a date and a containment verdict
 * — no price series and no time series — so the grid, the axis, the ticks,
 * the axis-label styles (.ar-calib-label) and the invented "historical"
 * path (.ar-calib-hist) were removed with the elements they styled.
 * ===================================================================== */
.ar-calib {
  margin-top: var(--space-2);
  background: var(--surface-1);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-card);
  padding: var(--space-3);
}
.ar-calib-intro {
  font-family: var(--font-stack);
  font-size: var(--font-size-label);
  color: var(--color-text-muted);
  line-height: 1.5;
  margin-top: var(--space-1);
}
.ar-calib-proof {
  margin-top: var(--space-3);
  padding: var(--space-2);
  background: var(--surface-2);
  border: 1px solid var(--surface-3);
  border-radius: var(--radius-sm);
}
.ar-calib-svg {
  max-height: 15rem;
}
/* "today" marker: NEUTRAL, same weight as an ordinary point — no halo. The
   message is CONTAINMENT (it landed inside the band), not a milestone. */
.ar-calib-now-dot {
  r: 4.5;
}
.ar-calib-case {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
  margin-top: var(--space-3);
  padding: var(--space-2);
  background: var(--surface-2);
  border-radius: var(--radius-sm);
}
.ar-calib-check {
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: var(--radius-pill);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--color-accent-bg);
  color: var(--color-accent-bright);
}
/* A miss reads in the muted tone — reported as plainly as a hit, never
   dramatised. */
.ar-calib-check--miss {
  background: var(--surface-3);
  color: var(--color-text-muted);
}
.ar-calib-check svg {
  width: 1rem;
  height: 1rem;
}
.ar-calib-case-text {
  font-family: var(--font-serif);
  font-size: 1.0625rem;
  line-height: 1.45;
  color: var(--color-text);
}
.ar-calib-case-text b {
  font-family: var(--font-stack);
  font-variant-numeric: var(--numeric-tabular);
  font-weight: 700;
}
.ar-calib-case-detail {
  display: block;
  font-family: var(--font-stack);
  font-size: var(--font-size-caption);
  color: var(--color-text-muted);
  margin-top: var(--space-0);
}
.ar-track {
  margin-top: var(--space-3);
}
.ar-track-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.ar-track-label {
  font-family: var(--font-stack);
  font-size: var(--font-size-label);
  font-weight: 700;
  color: var(--color-text);
}
.ar-cov-tag {
  color: var(--color-text-muted);
  font-weight: 700;
}
.ar-track-value {
  font-family: var(--font-stack);
  font-variant-numeric: var(--numeric-tabular);
  font-size: var(--font-size-label);
  font-weight: 700;
  color: var(--color-accent-bright);
}
.ar-track-bar {
  position: relative;
  margin-top: var(--space-1);
  height: 0.85rem;
  background: var(--surface-3);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.ar-track-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--coverage, 0%);
  height: 100%;
  background: var(--color-accent);
  border-radius: var(--radius-pill);
}
/* Target marker (80%) — neutral hairline, labelled. */
.ar-track-target {
  position: absolute;
  top: -3px;
  bottom: -3px;
  left: 80%;
  width: 2px;
  background: var(--color-text);
  border-radius: 2px;
}
.ar-track-target-label {
  position: absolute;
  top: calc(100% + 4px);
  left: 80%;
  transform: translateX(-50%);
  font-family: var(--font-stack);
  font-size: var(--font-size-micro);
  font-variant-numeric: var(--numeric-tabular);
  color: var(--color-text-muted);
  white-space: nowrap;
}
.ar-track-note {
  font-family: var(--font-stack);
  font-size: var(--font-size-caption);
  color: var(--color-text-muted);
  line-height: 1.5;
  margin-top: var(--space-3);
}

/* ---------- Model consensus (G24-T5) ----------
   NON-DIRECTIONAL agreement badge: the dots are a neutral COUNT marker (muted, never
   a good/bad colour) and neither the badge nor the label evokes buy/sell or direction
   (goal21-T1 / goal23). Ports the mock's av-consensus block onto the article's ar- prefix. */
.ar-consensus {
  margin-top: var(--space-2);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  background: var(--surface-1);
  border: 1px solid var(--surface-3);
  border-radius: var(--radius-card);
  padding: var(--space-3);
}
.ar-consensus-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-0) var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  border: 1px solid var(--surface-3);
  font-family: var(--font-stack);
  font-weight: 700;
  font-size: var(--font-size-label);
  color: var(--color-text);
}
.ar-consensus-dots {
  display: inline-flex;
  gap: 3px;
}
.ar-consensus-dot {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--color-text-muted);
}
.ar-consensus-dot.is-off {
  background: var(--surface-3);
}
.ar-consensus-value {
  font-family: var(--font-stack);
  font-variant-numeric: var(--numeric-tabular);
  font-weight: 800;
  font-size: var(--font-size-value);
  color: var(--color-text);
}
.ar-consensus-note {
  flex-basis: 100%;
  font-family: var(--font-stack);
  font-size: var(--font-size-caption);
  color: var(--color-text-muted);
  line-height: 1.5;
}
