/* ilx / "Signal Ink" — house illustration format (see lib/illus.py, docs/ILLUSTRATIONS.md).
   Layout + reveal choreography. Colors come from the page: the SVG uses currentColor
   (accent set as color: on .ilx via inline style) and theme vars (--up/--down), so a
   dark/light flip or the ZH --up/--down swap flows through with no re-render. */

.ilx {
  position: relative;
  display: block;
  width: 100%;
  height: var(--ilx-h, 190px);
  margin: 0;
  color: var(--ink-info, var(--info));                 /* fallback accent; overridden inline per chart */
  font-variant-numeric: tabular-nums;
}
.ilx svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;                  /* end-dot glow + labels aren't clipped */
}

/* ── the ink ─────────────────────────────────────────────────────────────── */
.ilx-path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;  /* keep 1.6px true despite the x-stretch */
}
.ilx-up   { stroke: var(--up); }
.ilx-down { stroke: var(--down); }

.ilx-area { stroke: none; }

/* dual-tint waterline (baseline kind) + drawdown top rule */
.ilx-water {
  stroke: var(--muted);
  stroke-width: 1;
  stroke-dasharray: 3 4;
  opacity: .55;
  vector-effect: non-scaling-stroke;
}
.ilx-water-top { stroke: var(--down); opacity: .5; }

/* reference level (e.g. climate neutral 100) */
.ilx-ref {
  stroke: var(--muted);
  stroke-width: 1;
  stroke-dasharray: 2 4;
  opacity: .4;
  vector-effect: non-scaling-stroke;
}

/* soft band zones (fear/euphoria gauge) */
.ilx-band { opacity: .5; }

/* end-of-series dot — the settle point */
.ilx-dot {
  fill: currentColor;
  filter: drop-shadow(0 0 4px color-mix(in srgb, currentColor 62%, transparent));
}
.ilx-dot-up   { fill: var(--up);   filter: drop-shadow(0 0 4px color-mix(in srgb, var(--up)   62%, transparent)); }
.ilx-dot-down { fill: var(--down); filter: drop-shadow(0 0 4px color-mix(in srgb, var(--down) 62%, transparent)); }

/* ── bars ────────────────────────────────────────────────────────────────── */
.ilx-bar { fill: currentColor; opacity: .82; }
.ilx-bar-up   { fill: var(--up);   opacity: .85; }
.ilx-bar-down { fill: var(--down); opacity: .85; }

/* ── HTML labels (page font; SVG carries no <text>) ──────────────────────── */
.ilx-d {
  position: absolute;
  bottom: 1px;
  font-size: 10px;
  line-height: 1;
  color: var(--muted);
  opacity: .78;
  letter-spacing: .01em;
  pointer-events: none;
}
.ilx-d0 { left: 1px; }
.ilx-d1 { right: 1px; }

.ilx-tag {
  position: absolute;
  top: 2px;
  right: 2px;
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
  padding: 1px 6px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.35;
  color: currentColor;
  background: color-mix(in srgb, currentColor 12%, var(--panel));
  border: 1px solid color-mix(in srgb, currentColor 30%, transparent);
  border-radius: 6px;
  pointer-events: none;
}
.ilx-tag .ilx-u { font-size: 9.5px; font-weight: 600; opacity: .82; }

.ilx-reflab {
  position: absolute;
  left: 3px;                          /* left-anchored so it never collides with the
                                         right-anchored end-value tag */
  transform: translateY(-50%);
  padding: 0 3px;
  font-size: 9.5px;
  color: var(--muted);
  background: color-mix(in srgb, var(--panel) 78%, transparent);
  border-radius: 3px;
  opacity: .7;
  pointer-events: none;
}

.ilx-bandlab {
  position: absolute;
  left: 4px;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  opacity: .62;
  pointer-events: none;
}
.ilx-bandlab-top    { top: 3px; }
.ilx-bandlab-bottom { bottom: 14px; }

/* multi end-chips (name each line — no legend box) */
.ilx-chips {
  position: absolute;
  top: 2px;
  right: 3px;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 3px 8px;
  pointer-events: none;
}
.ilx-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  font-weight: 600;
  color: var(--text);
}
.ilx-chip::before {
  content: "";
  width: 8px;
  height: 2.5px;
  border-radius: 2px;
  background: var(--dot, var(--info));
}

/* ── Regime Tape — cockpit signature ────────────────────────────────────── */
.ilx-regime-tape { min-height: 190px; }
.ilx-regime-span { opacity: .075; }
.ilx-regime-bull { opacity: .09; }
.ilx-regime-bear { opacity: .085; }
.ilx-tape-price {
  stroke-width: 2;
  filter: drop-shadow(0 0 5px color-mix(in srgb, currentColor 18%, transparent));
}
.ilx-tape-dot { r: 3.6; }
.ilx-projection { opacity: .42; }
.ilx-projection-hatch {
  stroke: var(--muted);
  stroke-width: 1;
  opacity: .36;
  vector-effect: non-scaling-stroke;
}
.ilx-alloc-base {
  stroke: var(--line);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.ilx-alloc-fill {
  fill: color-mix(in srgb, currentColor 15%, transparent);
  stroke: none;
}
.ilx-alloc-step {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.35;
  stroke-linecap: square;
  stroke-linejoin: miter;
  opacity: .78;
  vector-effect: non-scaling-stroke;
}
.ilx-event-tick {
  stroke: var(--text);
  stroke-width: 1;
  stroke-dasharray: 2 3;
  opacity: .34;
  vector-effect: non-scaling-stroke;
}
.ilx-event {
  --x: 50%;
  position: absolute;
  left: var(--x);
  bottom: 10px;
  width: 12px;
  height: 12px;
  transform: translateX(-50%);
  display: grid;
  place-items: center;
  cursor: help;
}
.ilx-event i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text);
  border: 1px solid var(--panel);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--text) 18%, transparent);
}
.ilx-alloc-label,
.ilx-projection-label {
  position: absolute;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 9.5px;
  line-height: 1;
  color: var(--muted);
  background: color-mix(in srgb, var(--panel) 86%, transparent);
  pointer-events: none;
}
.ilx-alloc-label { left: 3px; bottom: 22px; padding: 2px 4px 2px 0; }
.ilx-projection-label {
  --x: 75%;
  left: var(--x);
  top: 23px; /* clears the right-anchored current-value tag on narrow tapes */
  padding: 2px 5px;
  border: 1px solid var(--line);
  border-radius: 4px;
}
.ilx-regime-tape .ilx-d { bottom: 0; }

/* ── Session filmstrip — OIP W1 estate-wide signature (lib/illus.py
   session_filmstrip, W1_DESIGN_SPEC.md §3) ──────────────────────────────────
   Local fallback declarations: the filmstrip's THREE homes are options.html
   (Ticker mode — inside the .oew workspace scope, which already declares these
   four custom properties) and gex.html (NO .oew ancestor at all). Declaring the
   same pinned values here, scoped to .oew-film itself rather than only to .oew,
   means the figure resolves correctly on BOTH pages with one CSS source: inside
   .oew the two declarations are identical (no visual drift), and on gex.html
   this is the ONLY place these properties exist. Values copied verbatim from
   research/options_estate/WORKSPACE_DESIGN_SPEC.md §2.2 — never redeclare a
   *different* number here. */
.oew-film {
  --oew-accent: #8e97c8;
  --oew-stamp: #b49256;
  --hair: color-mix(in srgb, var(--line) 72%, transparent);
  --s3: 12px;
  height: 64px;
  margin-bottom: 2px;
}
html[data-theme="light"] .oew-film {
  --oew-accent: #4c55a8;
  --oew-stamp: #8a6a2e;
  --hair: color-mix(in srgb, var(--line) 92%, transparent);
}
.oew-film svg { width: 100%; height: 100%; display: block; overflow: visible; }
.oew-film-track { stroke: var(--hair); stroke-width: 1; }
.oew-film-closecap { stroke: var(--oew-stamp); stroke-width: 1.5; opacity: .85; }
.oew-film-ink {
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.oew-film-dot { fill: currentColor; }
.oew-film-tick { stroke: var(--oew-accent); stroke-width: 1.2; opacity: .65; }
.oew-film-d { position: absolute; bottom: -15px; font-size: 9.5px; color: var(--muted); }
.oew-film-d0 { left: 0; }
.oew-film-d1 { right: 0; }
.oew-film-ev {
  position: absolute; top: 0; left: var(--x); transform: translateX(-50%);
  width: 16px; height: 64px; cursor: help;
}
.oew-film-ev i {
  position: absolute; top: 8px; left: 50%; width: 6px; height: 6px; margin-left: -3px;
  border-radius: 50%; background: var(--oew-accent); opacity: 0; transition: opacity .15s;
}
.oew-film-ev:hover i, .oew-film-ev:focus-visible i { opacity: 1; }
.oew-film-ev:focus-visible { outline: 2px solid var(--oew-accent); outline-offset: 1px; border-radius: 3px; }
.oew-film-empty {
  position: absolute; top: 50%; left: var(--s3); transform: translateY(-50%);
  font-size: 11.5px; color: var(--muted);
}
.oew-film-null .oew-film-track { stroke-dasharray: 2 3; }
@media (prefers-reduced-motion: reduce) {
  .oew-film-ev i { transition: none; }
}

/* ── honest null ─────────────────────────────────────────────────────────── */
.ilx-null { display: flex; align-items: center; justify-content: center; }
.ilx-null svg { position: absolute; inset: 0; opacity: .5; }
.ilx-hair { stroke: var(--line); stroke-width: 1; stroke-dasharray: 4 5; }
.ilx-empty {
  position: relative;
  font-size: 11px;
  color: var(--muted);
  opacity: .8;
}

/* ── reveal choreography ─────────────────────────────────────────────────── */
@media (prefers-reduced-motion: no-preference) {
  /* start states (before .ilx-in) */
  .ilx-path {
    stroke-dasharray: var(--ilx-len, 600);
    stroke-dashoffset: var(--ilx-len, 600);
  }
  .ilx-area, .ilx-water, .ilx-ref, .ilx-band, .ilx-tag, .ilx-d,
  .ilx-reflab, .ilx-bandlab, .ilx-chips, .ilx-regime-span,
  .ilx-projection, .ilx-alloc-fill, .ilx-alloc-step, .ilx-event-tick,
  .ilx-event, .ilx-alloc-label, .ilx-projection-label { opacity: 0; }
  .ilx-dot { transform: scale(0); transform-box: fill-box; transform-origin: center; }
  /* bars scale up from the baseline edge of their own box (fill-box makes the origin
     local to the rect): above-baseline bars grow from their bottom edge, below-baseline
     bars from their top edge — both edges sit on the waterline. */
  .ilx-bar {
    transform: scaleY(0);
    transform-box: fill-box;
    transform-origin: center bottom;
  }
  .ilx-bar-down { transform-origin: center top; }

  /* the draw — ink laid down left→right */
  .ilx-in .ilx-path {
    animation: ilx-draw 950ms cubic-bezier(.33, .62, .26, 1) 120ms forwards;
  }
  .ilx-in .ilx-path.ilx-m {
    animation-delay: calc(120ms + var(--i, 0) * 90ms);
  }
  @keyframes ilx-draw { to { stroke-dashoffset: 0; } }

  /* the veil settles under the ink.
     `.ilx-in .ilx-area` is a DESCENDANT selector, but lib/illus.py emits an area
     figure as <figure class="ilx ilx-area"> and illus.js adds .ilx-in to that SAME
     element — so for kind="area" the reveal never matched and the figure stayed at
     opacity 0 forever (bonds' 200px Bond-health chart was a void). The self-form
     covers it without touching the nested case. */
  .ilx-in .ilx-area, .ilx-area.ilx-in {
    animation: ilx-fade 600ms ease 550ms forwards;
  }
  .ilx-in .ilx-water, .ilx-in .ilx-ref, .ilx-in .ilx-band {
    animation: ilx-fade 500ms ease 300ms forwards;
  }
  .ilx-in .ilx-regime-span,
  .ilx-in .ilx-projection,
  .ilx-in .ilx-alloc-fill,
  .ilx-in .ilx-alloc-step,
  .ilx-in .ilx-event-tick {
    animation: ilx-fade 500ms ease 260ms forwards;
  }
  .ilx-in .ilx-regime-span { animation-name: ilx-fade-regime; }
  .ilx-in .ilx-projection { animation-name: ilx-fade-projection; }
  .ilx-in .ilx-event-tick { animation-name: ilx-fade-event; }
  .ilx-in .ilx-alloc-step { animation-name: ilx-fade-alloc-step; }
  @keyframes ilx-fade-regime { to { opacity: .085; } }
  @keyframes ilx-fade-projection { to { opacity: .42; } }
  @keyframes ilx-fade-event { to { opacity: .34; } }
  @keyframes ilx-fade-alloc-step { to { opacity: .78; } }
  @keyframes ilx-fade { to { opacity: 1; } }
  /* bands + waterline hold their intrinsic opacity (set on the element) via to:1 →
     override the element's non-1 opacity by re-declaring in the final state */
  .ilx-in .ilx-band  { animation-name: ilx-fade-band; }
  .ilx-in .ilx-water { animation-name: ilx-fade-water; }
  .ilx-in .ilx-ref   { animation-name: ilx-fade-ref; }
  @keyframes ilx-fade-band  { to { opacity: .5; } }
  @keyframes ilx-fade-water { to { opacity: .55; } }
  @keyframes ilx-fade-ref   { to { opacity: .4; } }

  /* the settle point lands with an overshoot + STATIC glow (no looping pulse —
     settled data must not fake liveness) */
  .ilx-in .ilx-dot {
    animation: ilx-pop 500ms cubic-bezier(.34, 1.28, .5, 1) 900ms forwards;
  }
  .ilx-in .ilx-dot.ilx-m { animation-delay: calc(900ms + var(--i, 0) * 90ms); }
  @keyframes ilx-pop { to { transform: scale(1); } }

  /* bars rise from the baseline, gently staggered (cap total ≤ ~700ms) */
  .ilx-in .ilx-bar {
    animation: ilx-rise 480ms cubic-bezier(.22, .9, .26, 1.02) forwards;
    animation-delay: calc(120ms + var(--i, 0) * 9ms);
  }
  @keyframes ilx-rise { to { transform: scaleY(1); } }

  /* labels fade in after the draw */
  .ilx-in .ilx-tag, .ilx-in .ilx-d, .ilx-in .ilx-reflab,
  .ilx-in .ilx-bandlab, .ilx-in .ilx-chips, .ilx-in .ilx-event,
  .ilx-in .ilx-alloc-label, .ilx-in .ilx-projection-label {
    animation: ilx-fade 400ms ease 780ms forwards;
  }
}

/* reduced motion + no-JS: everything at its final resting state, no transitions.
   (These declarations also serve as the base when .ilx-in never arrives.) */
@media (prefers-reduced-motion: reduce) {
  .ilx-path { stroke-dashoffset: 0 !important; }
  .ilx-dot  { transform: scale(1) !important; }
  .ilx-bar  { transform: scaleY(1) !important; }
}
