.viz {
      border: 1.5px solid var(--ink);
      border-radius: 18px;
      background: rgba(255, 248, 222, 0.74);
      box-shadow: 9px 9px 0 rgba(23, 21, 18, 0.12);
      margin: 34px 0 40px;
      overflow: hidden;
    }
    .viz svg { display: block; width: 100%; height: auto; }
    .viz-toolbar {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      border-bottom: 1px solid var(--line);
      padding: 10px 14px;
    }
    .viz-kicker {
      font-size: 11px;
      font-weight: 900;
      letter-spacing: 0.14em;
      text-transform: uppercase;
    }
    .viz-replay {
      border: 1.5px solid var(--ink);
      border-radius: 999px;
      background: rgba(255, 225, 92, 0.55);
      color: var(--ink);
      cursor: pointer;
      font: 800 11px/1 Inter, sans-serif;
      letter-spacing: 0.08em;
      padding: 7px 12px;
      text-transform: uppercase;
    }
    .viz figcaption {
      border-top: 1px solid var(--line);
      color: var(--ink-soft);
      font-size: 13px;
      font-weight: 700;
      line-height: 1.45;
      padding: 14px 18px 16px;
    }
    .article-aside .notion-window {
      border: 1.5px solid var(--ink);
      border-radius: 18px;
      background: rgba(255, 250, 240, 0.8);
      box-shadow: 8px 8px 0 rgba(23, 21, 18, 0.1);
      overflow: hidden;
    }
    .window-bar { display: flex; gap: 7px; padding: 12px 14px; border-bottom: 1px solid var(--line); }
    .window-bar span { width: 10px; height: 10px; border-radius: 50%; background: var(--ink); opacity: 0.22; }
    .window-row { display: flex; justify-content: space-between; gap: 12px; padding: 14px 16px; border-bottom: 1px solid var(--line); font-size: 13px; }
    .window-row span { color: var(--ink-soft); flex: 0 0 auto; }
    .window-row strong { color: var(--ink); text-align: right; overflow-wrap: anywhere; }
    .ghost {
      display: inline-block; margin-top: 18px; border: 1.5px solid var(--ink);
      border-radius: 999px; padding: 10px 16px; color: var(--ink); text-decoration: none; font-weight: 800; font-size: 13px;
    }
    /* ---- animations ---- */
    .grain { opacity: 0.18; }
    .pulse { transform-box: fill-box; transform-origin: center; animation: pulse 3.6s ease-in-out infinite; }
    .rise { animation: rise 7s ease-in-out infinite; }
    .drift { animation: drift 8s ease-in-out infinite; }
    .flow { animation: flow 5.5s linear infinite; }
    .stamp { animation: stamp 6s ease-in-out infinite; }
    .gate-pass { animation: pass 7s ease-in-out infinite; }
    .gate-bounce { animation: bounce 7s ease-in-out infinite; }
    .bar-fill { transform-box: fill-box; transform-origin: left center; animation: grow 6.5s ease-in-out infinite; }
    .sort-1 { animation: sort1 8s ease-in-out infinite; }
    .sort-2 { animation: sort2 8s ease-in-out infinite; }
    .sort-3 { animation: sort3 8s ease-in-out infinite; }
    .drop { animation: drop 6.5s ease-in-out infinite; }
    .pipe-dot { animation: pipe 8s cubic-bezier(.4,0,.2,1) infinite; }
    .stage-1 { animation: stage 8s ease-in-out infinite; }
    .stage-2 { animation: stage 8s ease-in-out infinite; animation-delay: -2s; }
    .stage-3 { animation: stage 8s ease-in-out infinite; animation-delay: -4s; }
    .stage-4 { animation: stage 8s ease-in-out infinite; animation-delay: -6s; }
    .sweep { animation: sweep 8s ease-in-out infinite; }
    .viz:not(.inview) .pulse,
    .viz:not(.inview) .rise,
    .viz:not(.inview) .drift,
    .viz:not(.inview) .flow,
    .viz:not(.inview) .stamp,
    .viz:not(.inview) .gate-pass,
    .viz:not(.inview) .gate-bounce,
    .viz:not(.inview) .bar-fill,
    .viz:not(.inview) .sort-1,
    .viz:not(.inview) .sort-2,
    .viz:not(.inview) .sort-3,
    .viz:not(.inview) .drop,
    .viz:not(.inview) .pipe-dot,
    .viz:not(.inview) .stage-1,
    .viz:not(.inview) .stage-2,
    .viz:not(.inview) .stage-3,
    .viz:not(.inview) .stage-4,
    .viz:not(.inview) .sweep {
      animation: none !important;
    }
    @keyframes pulse {
      0%, 100% { opacity: 0.55; transform: scale(0.96); }
      50% { opacity: 1; transform: scale(1.04); }
    }
    @keyframes rise {
      0%, 100% { transform: translateY(10px); opacity: 0.55; }
      50% { transform: translateY(-8px); opacity: 1; }
    }
    @keyframes drift {
      0%, 100% { transform: translateX(0); }
      50% { transform: translateX(8px); }
    }
    @keyframes flow {
      0% { stroke-dashoffset: 120; opacity: 0.2; }
      40%, 70% { opacity: 1; }
      100% { stroke-dashoffset: 0; opacity: 0.35; }
    }
    @keyframes stamp {
      0%, 18% { transform: scale(0.2); opacity: 0; }
      28%, 72% { transform: scale(1); opacity: 1; }
      88%, 100% { transform: scale(0.92); opacity: 0.2; }
    }
    @keyframes pass {
      0% { transform: translateX(-40px); opacity: 0; }
      22% { opacity: 1; }
      48% { transform: translateX(118px); }
      100% { transform: translateX(210px); opacity: 1; }
    }
    @keyframes bounce {
      0% { transform: translateX(-20px); opacity: 0; }
      20% { opacity: 1; }
      40% { transform: translateX(78px); }
      52% { transform: translateX(64px) rotate(-6deg); }
      70%, 100% { transform: translateX(18px) rotate(-2deg); opacity: 0.35; }
    }
    @keyframes grow {
      0%, 12% { transform: scaleX(0.08); }
      38%, 78% { transform: scaleX(1); }
      100% { transform: scaleX(0.2); }
    }
    @keyframes sort1 {
      0%, 35% { transform: translate(0, 0); }
      55%, 100% { transform: translate(0, -86px); }
    }
    @keyframes sort2 {
      0%, 35% { transform: translate(0, 0); }
      55%, 100% { transform: translate(0, 0); }
    }
    @keyframes sort3 {
      0%, 35% { transform: translate(0, 0); }
      55%, 100% { transform: translate(0, 86px); }
    }
    @keyframes drop {
      0%, 30% { transform: translateY(-18px); opacity: 0; }
      42%, 78% { transform: translateY(0); opacity: 1; }
      100% { transform: translateY(6px); opacity: 0.2; }
    }
    @keyframes pipe {
      0% { offset-distance: 0%; opacity: 0; }
      8% { opacity: 1; }
      88% { opacity: 1; }
      100% { offset-distance: 100%; opacity: 0; }
    }
    @keyframes stage {
      0%, 18% { opacity: 0.38; }
      28%, 48% { opacity: 1; }
      62%, 100% { opacity: 0.38; }
    }
    @keyframes sweep {
      0% { transform: translateX(-80px); opacity: 0; }
      18% { opacity: 0.55; }
      100% { transform: translateX(760px); opacity: 0; }
    }
    @media (prefers-reduced-motion: reduce) {
      .pulse, .rise, .drift, .flow, .stamp, .gate-pass, .gate-bounce,
      .bar-fill, .sort-1, .sort-2, .sort-3, .drop, .pipe-dot,
      .stage-1, .stage-2, .stage-3, .stage-4, .sweep {
        animation: none !important;
      }
    }
