/* BSLR — animated charts (columns, wave, progress bars).
   Scoped under .viz. Base state is the finished chart; the hidden state applies
   only under .armed, added by bslr-viz.js, so any failure path still shows a
   complete chart. Only transform and opacity animate. */

.viz{
  --vbrand:#336380; --vbrand-2:#27506A; --vaccent:#EC8822;
  --vink:#0F172A; --vmuted:#64748B; --vborder:#E2E8F0; --vsoft:#F8FAFC;
  margin-top:40px;
}
.viz *{ box-sizing:border-box }

.viz-card{
  border:1px solid var(--vborder); border-radius:14px; background:#fff;
  padding:24px 26px 20px; box-shadow:0 14px 34px rgba(15,23,42,.07);
}
.viz-head{ margin-bottom:20px }
.viz-title{ font-size:16px; font-weight:700; color:var(--vink); line-height:1.35 }
.viz-sub{ font-size:12.5px; color:var(--vmuted); margin-top:4px; line-height:1.5 }
.viz-foot{
  margin-top:18px; padding-top:14px; border-top:1px solid var(--vborder);
  font-size:12px; color:#64748B; line-height:1.55;
}

/* ---- column chart ------------------------------------------------------ */
.viz-cols{ display:flex; align-items:flex-end; gap:10px; height:190px }
.viz-cols .vc{
  flex:1; min-width:0; height:100%;
  display:flex; flex-direction:column; justify-content:flex-end; align-items:center; gap:7px;
}
.viz-cols .vv{ font-size:12.5px; font-weight:700; color:var(--vink); line-height:1 }
.viz-cols .vt{
  width:100%; max-width:54px; flex:none; display:flex; align-items:flex-end;
  height:var(--pct);
}
.viz-cols .vb{
  width:100%; height:100%; border-radius:5px 5px 0 0;
  background:linear-gradient(180deg,var(--vbrand) 0%,var(--vbrand-2) 100%);
  transform-origin:50% 100%;
}
.viz-cols .vc.hi .vb{ background:linear-gradient(180deg,var(--vaccent) 0%,#D4761A 100%) }
.viz-cols .vl{ font-size:11.5px; color:var(--vmuted); line-height:1 }

/* ---- wave / area chart ------------------------------------------------- */
.viz-wave{ margin-top:6px }
.viz-wave svg{ display:block; width:100%; height:auto }
/* pathLength="100" is set in the markup so the dash maths need no measuring */
.viz-wave .wl{ stroke-dasharray:100; stroke-dashoffset:0 }
.viz-wave .wa{ opacity:1 }
.viz-wave .wd{ opacity:1 }

/* ---- horizontal progress bars ------------------------------------------ */
.viz-rows{ display:flex; flex-direction:column; gap:16px }
.viz-rows .vr{ display:grid; grid-template-columns:1fr auto; gap:6px 14px; align-items:baseline }
.viz-rows .vrl{ font-size:13.5px; font-weight:600; color:var(--vink); line-height:1.4 }
.viz-rows .vrl small{ display:block; font-weight:400; font-size:11.5px; color:var(--vmuted); margin-top:2px }
.viz-rows .vrv{ font-size:14px; font-weight:800; color:var(--vbrand-2); font-variant-numeric:tabular-nums }
.viz-rows .vrt{
  grid-column:1/-1; height:9px; border-radius:99px; background:#EDF2F5; overflow:hidden;
}
.viz-rows .vrf{
  display:block; height:100%; width:var(--pct); border-radius:99px;
  background:linear-gradient(90deg,var(--vbrand-2) 0%,var(--vbrand) 100%);
  transform-origin:0 50%;
}
.viz-rows .vr.warn .vrf{ background:linear-gradient(90deg,#B45309 0%,var(--vaccent) 100%) }
.viz-rows .vr.warn .vrv{ color:#A35A12 }

@media (max-width:640px){
  .viz{ margin-top:30px }
  .viz-card{ padding:18px 16px 16px }
  .viz-cols{ height:150px; gap:6px }
  .viz-cols .vv{ font-size:11px }
  .viz-cols .vl{ font-size:10.5px }
}

/* Motion. Scroll-triggered via bslr-viz.js rather than CSS scroll timelines,
   which proved unreliable: animation-range rejects calc()/var() offsets and a
   mixed-phase range resolves to progress:null with no animation at all. */
@media (prefers-reduced-motion:no-preference){

  @keyframes vizGrow { from{ transform:scaleY(0) }                    to{ transform:scaleY(1) } }
  @keyframes vizFill { from{ transform:scaleX(0) }                    to{ transform:scaleX(1) } }
  @keyframes vizFade { from{ opacity:0; transform:translateY(6px) }   to{ opacity:1; transform:none } }
  @keyframes vizDraw { from{ stroke-dashoffset:100 }                  to{ stroke-dashoffset:0 } }
  @keyframes vizWash { from{ opacity:0 }                              to{ opacity:1 } }

  /* armed = script is present and this chart has not been reached yet */
  .viz.armed .viz-cols .vb{ transform:scaleY(0) }
  .viz.armed .viz-cols .vv{ opacity:0 }
  .viz.armed .viz-rows .vrf{ transform:scaleX(0) }
  .viz.armed .viz-wave .wl{ stroke-dashoffset:100 }
  .viz.armed .viz-wave .wa,
  .viz.armed .viz-wave .wd{ opacity:0 }

  /* play = the chart has scrolled into view */
  .viz.armed.play .viz-cols .vb{
    animation:vizGrow .8s cubic-bezier(.22,.61,.36,1) both;
    animation-delay:calc(var(--i,0) * 100ms);
  }
  .viz.armed.play .viz-cols .vv{
    animation:vizFade .45s ease-out both;
    animation-delay:calc(var(--i,0) * 100ms + 300ms);
  }
  .viz.armed.play .viz-rows .vrf{
    animation:vizFill .95s cubic-bezier(.22,.61,.36,1) both;
    animation-delay:calc(var(--i,0) * 110ms);
  }
  .viz.armed.play .viz-wave .wl{ animation:vizDraw 1.4s ease-in-out both }
  .viz.armed.play .viz-wave .wa{ animation:vizWash 1s ease-out both; animation-delay:.45s }
  .viz.armed.play .viz-wave .wd{
    animation:vizFade .4s ease-out both;
    animation-delay:calc(.85s + var(--i,0) * 70ms);
  }
}
