/* ══════════════════════════════════════════════════════════════
   lesson-viz.css — High-End Studio Cyber Animation & Simulation Framework
   Ultra-Professional Animated Visualizations for RiaAcademy
   ══════════════════════════════════════════════════════════════ */

:root {
  --viz-neon-cyan: #00f0ff;
  --viz-neon-pink: #ff0055;
  --viz-neon-green: #00ff88;
  --viz-neon-amber: #ffaa00;
  --viz-neon-purple: #9d4edd;
  --viz-neon-blue: #3b82f6;
  --viz-glass-bg: rgba(10, 11, 18, 0.92);
  --viz-glass-border: rgba(255, 255, 255, 0.14);
}

.viz {
  --viz-accent: var(--mod-color, #ff0055);
  --viz-dim: var(--mod-dim, rgba(255, 0, 85, 0.12));
  --viz-border: var(--mod-border, rgba(255, 0, 85, 0.35));

  position: relative;
  margin: 36px 0;
  padding: 40px 32px 28px;
  background: radial-gradient(circle at 50% -20%, var(--viz-dim), transparent 85%), var(--viz-glass-bg);
  border: 1px solid var(--viz-glass-border);
  border-radius: 22px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.75), inset 0 1px 1px rgba(255, 255, 255, 0.15);
  backdrop-filter: blur(24px);
  overflow: hidden;
  transition: border-color 0.4s ease, box-shadow 0.4s ease, transform 0.3s ease;
}

.viz:hover {
  border-color: var(--viz-border);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.85), 0 0 35px -8px var(--viz-accent);
}

/* Cyber Scanning Grid and Moving Top Laser Beam */
.viz::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: 
    linear-gradient(rgba(255, 255, 255, 0.025) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.025) 1px, transparent 1px);
  background-size: 32px 28px;
  pointer-events: none;
  z-index: 1;
}

.viz::after {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, transparent, var(--viz-accent), var(--viz-neon-cyan), transparent);
  box-shadow: 0 0 16px var(--viz-accent);
  animation: laserScan 4s linear infinite;
  z-index: 2;
}

@keyframes laserScan {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

.viz__label {
  position: absolute;
  top: 14px;
  left: 20px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--viz-accent);
  z-index: 3;
  background: rgba(0, 0, 0, 0.4);
  padding: 3px 10px;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.viz__label::before {
  content: "✦";
  font-size: 0.8rem;
  animation: v-pulse 2s ease-in-out infinite;
}

.viz__stage {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
  min-height: 170px;
  padding-top: 22px;
}

/* Playback Control Gate */
.viz *, .viz::after { animation-play-state: paused; }
.viz.run *, .viz.run::after { animation-play-state: running; }

/* ── Cyber Node Cards ─────────────────────────────────────── */
.v-node {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  cursor: pointer;
  transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

.v-node:hover {
  transform: translateY(-4px) scale(1.04);
}

.v-box {
  position: relative;
  width: 68px;
  height: 68px;
  display: grid;
  place-items: center;
  font-size: 1.55rem;
  color: #f8fafc;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 18px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 8px 24px rgba(0,0,0,0.4);
  transition: all 0.35s cubic-bezier(0.16, 1, 0.3, 1);
  overflow: hidden;
}

.v-box::before {
  content: "";
  position: absolute;
  inset: -50%;
  background: conic-gradient(from 0deg, transparent, rgba(255, 255, 255, 0.15), transparent 60%);
  animation: rotateGlow 6s linear infinite;
  opacity: 0;
  transition: opacity 0.3s;
}

.v-node:hover .v-box::before,
.v-box.is-on::before {
  opacity: 1;
}

@keyframes rotateGlow {
  100% { transform: rotate(360deg); }
}

.v-box.sm { width: 54px; height: 54px; font-size: 1.2rem; border-radius: 14px; }
.v-box.lg { width: 88px; height: 88px; font-size: 2rem; border-radius: 22px; }

.v-box.accent {
  color: var(--viz-accent);
  background: var(--viz-dim);
  border-color: var(--viz-accent);
  box-shadow: 0 0 32px -4px var(--viz-accent);
}
.v-box.good {
  color: var(--viz-neon-green);
  background: rgba(0, 255, 136, 0.14);
  border-color: rgba(0, 255, 136, 0.6);
  box-shadow: 0 0 32px -4px var(--viz-neon-green);
}
.v-box.bad {
  color: var(--viz-neon-pink);
  background: rgba(255, 0, 85, 0.18);
  border-color: rgba(255, 0, 85, 0.65);
  box-shadow: 0 0 32px -4px var(--viz-neon-pink);
}
.v-box.warn {
  color: var(--viz-neon-amber);
  background: rgba(255, 170, 0, 0.16);
  border-color: rgba(255, 170, 0, 0.6);
  box-shadow: 0 0 30px -4px var(--viz-neon-amber);
}
.v-box.cyan {
  color: var(--viz-neon-cyan);
  background: rgba(0, 240, 255, 0.14);
  border-color: rgba(0, 240, 255, 0.6);
  box-shadow: 0 0 30px -4px var(--viz-neon-cyan);
}
.v-box.purple {
  color: var(--viz-neon-purple);
  background: rgba(157, 78, 221, 0.18);
  border-color: rgba(157, 78, 221, 0.6);
  box-shadow: 0 0 30px -4px var(--viz-neon-purple);
}

.v-cap {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.72rem;
  color: #cbd5e1;
  text-align: center;
  letter-spacing: 0.03em;
  max-width: 120px;
  line-height: 1.35;
  font-weight: 500;
}
.v-cap.hi { color: #f8fafc; font-weight: 700; }

/* ── Packet Flow Wires & Glowing Trails ────────────────────── */
.v-flow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  width: 100%;
}

.v-wire {
  position: relative;
  flex: 1 1 60px;
  min-width: 60px;
  max-width: 160px;
  height: 4px;
  background: rgba(255, 255, 255, 0.12);
  align-self: center;
  border-radius: 4px;
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.5);
}
.v-wire.dashed {
  background: repeating-linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.25) 0 8px,
    transparent 8px 16px
  );
}

.v-wire__tag {
  position: absolute;
  top: -22px;
  left: 50%;
  transform: translateX(-50%);
  font-family: "JetBrains Mono", monospace;
  font-size: 0.62rem;
  color: #94a3b8;
  white-space: nowrap;
  background: rgba(0,0,0,0.6);
  padding: 1px 6px;
  border-radius: 4px;
  border: 1px solid rgba(255,255,255,0.08);
}

.v-pkt {
  position: absolute;
  top: 50%;
  left: 0;
  width: 16px;
  height: 16px;
  margin-top: -8px;
  border-radius: 5px;
  background: var(--viz-accent);
  box-shadow: 0 0 20px var(--viz-accent), 0 0 8px #fff;
  animation: v-travel 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  z-index: 2;
}
.v-pkt.good { background: var(--viz-neon-green); box-shadow: 0 0 20px var(--viz-neon-green), 0 0 8px #fff; }
.v-pkt.bad { background: var(--viz-neon-pink); box-shadow: 0 0 20px var(--viz-neon-pink), 0 0 8px #fff; }
.v-pkt.cyan { background: var(--viz-neon-cyan); box-shadow: 0 0 20px var(--viz-neon-cyan), 0 0 8px #fff; }
.v-pkt.warn { background: var(--viz-neon-amber); box-shadow: 0 0 20px var(--viz-neon-amber), 0 0 8px #fff; }
.v-pkt.round { border-radius: 50%; }
.v-pkt.rev { animation-name: v-travel-rev; }
.v-pkt.d1 { animation-delay: 0.4s; }
.v-pkt.d2 { animation-delay: 0.8s; }
.v-pkt.d3 { animation-delay: 1.2s; }
.v-pkt.slow { animation-duration: 3.5s; }
.v-pkt.fast { animation-duration: 1.2s; }

@keyframes v-travel {
  0% { left: -8px; opacity: 0; transform: scale(0.5); }
  15% { opacity: 1; transform: scale(1.1); }
  85% { opacity: 1; transform: scale(1.1); }
  100% { left: calc(100% - 8px); opacity: 0; transform: scale(0.5); }
}
@keyframes v-travel-rev {
  0% { left: calc(100% - 8px); opacity: 0; transform: scale(0.5); }
  15% { opacity: 1; transform: scale(1.1); }
  85% { opacity: 1; transform: scale(1.1); }
  100% { left: -8px; opacity: 0; transform: scale(0.5); }
}

.v-pulse { animation: v-pulse 2s ease-in-out infinite; }
@keyframes v-pulse {
  0%, 100% { transform: scale(1); filter: brightness(1); }
  50% { transform: scale(1.08); filter: brightness(1.5); }
}

/* ── Interactive Sequence Diagram Arrows ──────────────────── */
.v-seq {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  max-width: 580px;
}
.v-seq__row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 18px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  transition: all 0.35s ease;
}
.v-seq__step {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.08);
  display: grid;
  place-items: center;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.75rem;
  font-weight: 700;
  color: #94a3b8;
  flex-shrink: 0;
}
.v-seq__arrow {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.8rem;
  color: #cbd5e1;
  font-weight: 500;
}
.v-seq__arrow.rtl { flex-direction: row-reverse; text-align: right; }
.v-seq__arrow i { color: var(--viz-accent); font-size: 0.9rem; }
.v-seq__arrow.ok i { color: var(--viz-neon-green); }
.v-seq__arrow.err i { color: var(--viz-neon-pink); }

/* ── Interactive Media Controls Bar ───────────────────────── */
.viz__ctrls {
  position: relative;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 26px;
  padding-top: 18px;
  border-top: 1px dashed rgba(255, 255, 255, 0.12);
  flex-wrap: wrap;
}

.viz__btn {
  height: 36px;
  min-width: 36px;
  padding: 0 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.06);
  color: #e2e8f0;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.76rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
  box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}

.viz__btn:hover {
  background: var(--viz-dim);
  border-color: var(--viz-accent);
  color: var(--viz-accent);
  box-shadow: 0 0 18px var(--viz-dim);
  transform: translateY(-1px);
}

.viz__dots {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  flex-wrap: wrap;
  justify-content: center;
}

.viz__dot {
  height: 8px;
  width: 28px;
  padding: 0;
  border: none;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.18);
  cursor: pointer;
  transition: all 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}

.viz__dot:hover {
  background: rgba(255, 255, 255, 0.4);
}

.viz__dot.is-past { background: rgba(255, 255, 255, 0.45); }
.viz__dot.is-on {
  background: var(--viz-accent);
  box-shadow: 0 0 16px var(--viz-accent);
  width: 48px;
}

.viz__counter {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--viz-accent);
  background: var(--viz-dim);
  padding: 5px 12px;
  border: 1px solid var(--viz-border);
  border-radius: 8px;
  flex-shrink: 0;
  letter-spacing: 0.05em;
  box-shadow: 0 0 12px var(--viz-dim);
}

/* Narration Box */
.viz__narrate {
  position: relative;
  z-index: 3;
  margin-top: 16px;
  min-height: 4em;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  padding: 14px 18px;
  box-shadow: inset 0 2px 8px rgba(0,0,0,0.5);
}
.viz__narrate > [data-step] {
  display: none;
  font-size: 0.92rem;
  line-height: 1.7;
  color: #e2e8f0;
  text-align: center;
}
.viz__narrate > [data-step].is-on {
  display: block;
  animation: v-narrate-in 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}
.viz__narrate b, .viz__narrate strong { color: #f8fafc; font-weight: 700; }
.viz__narrate code {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.88em;
  color: var(--viz-accent);
  background: rgba(255, 255, 255, 0.1);
  padding: 2px 7px;
  border-radius: 5px;
  border: 1px solid rgba(255,255,255,0.08);
}

@keyframes v-narrate-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* Staged reveal step highlights */
.viz--seq .viz__stage [data-step] {
  transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.16, 1, 0.3, 1),
    border-color 0.35s ease, background-color 0.35s ease, color 0.35s ease, box-shadow 0.35s ease;
}
.viz--seq .viz__stage [data-step]:not(.is-on):not(.is-past) { opacity: 0.25; filter: grayscale(0.5); }
.viz--seq .viz__stage [data-step].is-past { opacity: 0.7; }
.viz--seq .viz__stage [data-step].is-on { opacity: 1; transform: scale(1.02); }

.v-mark[data-step].is-on {
  border-color: var(--viz-accent) !important;
  background: var(--viz-dim) !important;
  color: var(--viz-accent) !important;
  box-shadow: 0 0 35px -4px var(--viz-accent);
}
.v-alarm[data-step].is-on {
  border-color: var(--viz-neon-pink) !important;
  background: rgba(255, 0, 85, 0.22) !important;
  color: #ff8fab !important;
  box-shadow: 0 0 35px -4px var(--viz-neon-pink);
}
.v-ok[data-step].is-on {
  border-color: var(--viz-neon-green) !important;
  background: rgba(0, 255, 136, 0.22) !important;
  color: #6ee7b7 !important;
  box-shadow: 0 0 35px -4px var(--viz-neon-green);
}

/* ── Terminals, Memory Stack & Meter Bars ────────────────── */
.v-term {
  width: 100%;
  max-width: 580px;
  background: #040408;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 16px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.8), 0 0 20px rgba(0,240,255,0.05);
  overflow: hidden;
  text-align: left;
}
.v-term__bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  background: rgba(255, 255, 255, 0.06);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.v-term__bar span { width: 10px; height: 10px; border-radius: 50%; }
.v-term__bar span:first-child { background: #ff5f56; }
.v-term__bar span:nth-child(2) { background: #ffbd2e; }
.v-term__bar span:nth-child(3) { background: #27c93f; }
.v-term__bar em {
  margin-left: auto;
  font-style: normal;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.68rem;
  color: #94a3b8;
  letter-spacing: 0.05em;
}

.v-term__body {
  padding: 18px 20px;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.8rem;
  line-height: 1.8;
  color: #cbd5e1;
}

.v-term__line {
  display: none;
}
.v-term__line.is-on, .v-term__line.is-past {
  display: block;
  animation: v-narrate-in 0.3s ease-out;
}

.v-term__line .g { color: #10b981; font-weight: 600; }
.v-term__line .r { color: #ff2a5f; font-weight: 600; }
.v-term__line .c { color: #00e5ff; }
.v-term__line .y { color: #f59e0b; }

.v-frame {
  width: 100%;
  max-width: 420px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.76rem;
}
.v-slot {
  position: relative;
  padding: 12px 16px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #cbd5e1;
  overflow: hidden;
  transition: all 0.35s ease;
}
.v-slot__fill {
  position: absolute;
  inset: 0;
  width: 0;
  background: linear-gradient(90deg, rgba(255, 0, 85, 0.6), rgba(255, 0, 85, 0.25));
  transition: width 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}
.v-slot.is-on .v-slot__fill, .v-slot.is-past .v-slot__fill { width: 100%; }
.v-slot span { position: relative; z-index: 2; font-weight: 500; }
.v-slot.crit { border-color: rgba(255, 170, 0, 0.6); color: #fcd34d; }
.v-slot.crit.is-on { border-color: var(--viz-neon-pink); color: #fff; box-shadow: 0 0 25px rgba(255, 0, 85, 0.7); }

.v-bars {
  width: 100%;
  max-width: 500px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.v-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.76rem;
  color: #cbd5e1;
}
.v-bar__lbl { min-width: 130px; text-align: right; color: #94a3b8; font-weight: 500; }
.v-bar__track {
  flex: 1;
  height: 12px;
  background: rgba(255, 255, 255, 0.08);
  border-radius: 6px;
  overflow: hidden;
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.5);
}
.v-bar__fill {
  height: 100%;
  width: 0;
  border-radius: 6px;
  background: linear-gradient(90deg, var(--viz-accent), #9d4edd);
  animation: v-fill 1.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
  box-shadow: 0 0 10px var(--viz-accent);
}
.v-bar__fill.good { background: linear-gradient(90deg, #00ff88, #34d399); box-shadow: 0 0 10px #00ff88; }
.v-bar__fill.warn { background: linear-gradient(90deg, #ffaa00, #fbbf24); box-shadow: 0 0 10px #ffaa00; }
.v-bar__fill.bad { background: linear-gradient(90deg, #ff0055, #f43f5e); box-shadow: 0 0 10px #ff0055; }
.v-bar__val { min-width: 80px; color: #f8fafc; font-weight: 700; }

@keyframes v-fill { to { width: var(--w, 60%); } }

.v-ladder {
  display: flex;
  flex-direction: column-reverse;
  gap: 10px;
  width: 100%;
  max-width: 440px;
}
.v-rung {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 18px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  font-size: 0.85rem;
  color: #cbd5e1;
  transition: all 0.35s ease;
}
.v-rung i { color: var(--viz-accent); width: 22px; text-align: center; font-size: 1rem; }
.v-rung code {
  margin-left: auto;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.72rem;
  color: #94a3b8;
}

.v-compare {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 18px;
  width: 100%;
}
.v-pane {
  padding: 20px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.12);
  text-align: center;
  transition: all 0.35s ease;
}
.v-pane.bad { border-color: rgba(255, 0, 85, 0.5); background: rgba(255, 0, 85, 0.08); }
.v-pane.good { border-color: rgba(0, 255, 136, 0.5); background: rgba(0, 255, 136, 0.08); }
.v-pane__title {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.74rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 14px;
  color: #cbd5e1;
  font-weight: 700;
}
.v-pane.bad .v-pane__title { color: var(--viz-neon-pink); }
.v-pane.good .v-pane__title { color: var(--viz-neon-green); }
.v-pane__body {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 76px;
  flex-wrap: wrap;
}
.v-pane__note {
  margin-top: 14px;
  font-size: 0.8rem;
  color: #94a3b8;
  line-height: 1.5;
}

/* ── Mobile Responsive Overrides ──────────────────────────── */
@media (max-width: 768px) {
  .viz {
    padding: 16px 14px 16px;
    border-radius: 16px;
    margin: 24px 0;
  }
  /* Absolute positioning only works while the caption fits on one line.
     At phone widths these titles wrap to two or three lines and landed
     on top of the diagram, so on mobile the label rejoins the flow. */
  .viz__label {
    position: static;
    display: flex;
    align-items: flex-start;
    width: -moz-fit-content;
    width: fit-content;
    max-width: 100%;
    margin-bottom: 2px;
    font-size: 0.6rem;
    line-height: 1.45;
    white-space: normal;
    padding: 3px 8px;
    background: rgba(0, 0, 0, 0.45);
  }
  .viz__label::before {
    margin-top: 1px;
  }
  /* Give the step dots their own full-width row so the speed and replay
     buttons stay on the control row instead of wrapping alone. */
  .viz__dots {
    order: 10;
    flex: 1 1 100%;
    margin-top: 2px;
  }
  .v-box {
    width: 48px;
    height: 48px;
    font-size: 1.1rem;
    border-radius: 12px;
  }
  .v-box.sm {
    width: 40px;
    height: 40px;
    font-size: 0.9rem;
  }
  .v-cap {
    font-size: 0.65rem;
    max-width: 80px;
  }
  .v-wire {
    min-width: 20px;
    flex: 1 1 30px;
  }
  .v-seq__row {
    padding: 10px 12px;
    gap: 10px;
  }
  .v-seq__step {
    width: 22px;
    height: 22px;
    font-size: 0.65rem;
  }
  .v-seq__arrow {
    font-size: 0.7rem;
  }
  .viz__ctrls {
    padding-top: 12px;
    margin-top: 20px;
    justify-content: center;
    gap: 8px;
  }
  .viz__btn {
    height: 32px;
    min-width: 32px;
    font-size: 0.7rem;
    padding: 0 8px;
  }
  .viz__dot {
    width: 16px;
  }
  .viz__dot.is-on {
    width: 28px;
  }
  .viz__counter {
    font-size: 0.65rem;
    padding: 4px 8px;
  }
  .viz__narrate {
    padding: 12px 14px;
    margin-top: 12px;
  }
  .viz__narrate > [data-step] {
    font-size: 0.85rem;
  }
  .v-term__body {
    padding: 12px 14px;
    font-size: 0.7rem;
  }
  .v-term__bar {
    padding: 8px 12px;
  }
  .v-ladder {
    max-width: 100%;
  }
  .v-rung {
    padding: 10px 14px;
    font-size: 0.75rem;
    gap: 10px;
    flex-wrap: wrap;
  }
  .v-rung i {
    width: 18px;
    font-size: 0.9rem;
  }
  .v-compare {
    grid-template-columns: 1fr;
    gap: 12px;
  }
  .v-pane {
    padding: 16px;
  }
}

/* ══════════════════════════════════════════════════════════════
   PART II — Didactic figure components
   ------------------------------------------------------------------
   Every component below is built for teaching, not decoration. They
   share one fixed semantic palette so a colour means the same thing
   in all 37 lessons — this is what `.v-legend` documents to the
   learner on figures where it is not self-evident:

     cyan   → client / requester / identity
     purple → cryptographic transform, key material
     green  → verified, allowed, safe outcome
     pink   → attacker, blocked, failed, malicious
     amber  → state, caution, intermediate value
     accent → whatever the current module is about (--mod-color)

   Every stepped component exposes `data-step`, so the sequencer in
   lesson-viz.js drives them without any per-component JS.
   ══════════════════════════════════════════════════════════════ */

/* ── Colour legend ────────────────────────────────────────── */
.v-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 18px;
  width: 100%;
  padding: 10px 14px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.07);
}
.v-legend__item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.66rem;
  letter-spacing: 0.04em;
  color: #94a3b8;
}
.v-legend__sw {
  width: 11px;
  height: 11px;
  border-radius: 4px;
  flex-shrink: 0;
  background: var(--viz-accent);
  box-shadow: 0 0 9px var(--viz-accent);
}
.v-legend__sw.cyan { background: var(--viz-neon-cyan); box-shadow: 0 0 9px var(--viz-neon-cyan); }
.v-legend__sw.purple { background: var(--viz-neon-purple); box-shadow: 0 0 9px var(--viz-neon-purple); }
.v-legend__sw.good { background: var(--viz-neon-green); box-shadow: 0 0 9px var(--viz-neon-green); }
.v-legend__sw.bad { background: var(--viz-neon-pink); box-shadow: 0 0 9px var(--viz-neon-pink); }
.v-legend__sw.warn { background: var(--viz-neon-amber); box-shadow: 0 0 9px var(--viz-neon-amber); }

/* ── Protocol lifeline / message-sequence diagram ─────────────
   Used for every handshake in the track (TCP, TLS, Kerberos,
   OAuth, NTLM relay). Actors sit in a header row; each `.v-msg`
   is one wire message and carries its own data-step. */
.v-lane {
  width: 100%;
  max-width: 640px;
}
.v-lane__actors {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  padding-bottom: 12px;
  margin-bottom: 14px;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.14);
}
.v-lane__actor {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  text-align: center;
}
.v-lane__actor i {
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  font-size: 1.05rem;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.16);
  color: #e2e8f0;
}
.v-lane__actor.cyan i { color: var(--viz-neon-cyan); border-color: rgba(0, 240, 255, 0.55); background: rgba(0, 240, 255, 0.12); box-shadow: 0 0 22px -6px var(--viz-neon-cyan); }
.v-lane__actor.purple i { color: var(--viz-neon-purple); border-color: rgba(157, 78, 221, 0.55); background: rgba(157, 78, 221, 0.14); box-shadow: 0 0 22px -6px var(--viz-neon-purple); }
.v-lane__actor.good i { color: var(--viz-neon-green); border-color: rgba(0, 255, 136, 0.55); background: rgba(0, 255, 136, 0.12); box-shadow: 0 0 22px -6px var(--viz-neon-green); }
.v-lane__actor.bad i { color: var(--viz-neon-pink); border-color: rgba(255, 0, 85, 0.55); background: rgba(255, 0, 85, 0.14); box-shadow: 0 0 22px -6px var(--viz-neon-pink); }
.v-lane__actor.warn i { color: var(--viz-neon-amber); border-color: rgba(255, 170, 0, 0.55); background: rgba(255, 170, 0, 0.12); box-shadow: 0 0 22px -6px var(--viz-neon-amber); }
.v-lane__actor b {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.66rem;
  font-weight: 700;
  color: #f8fafc;
  letter-spacing: 0.04em;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.v-lane__actor span {
  font-size: 0.6rem;
  color: #64748b;
  line-height: 1.3;
}
.v-lane__msgs {
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.v-msg {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.v-msg__n {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border-radius: 7px;
  display: grid;
  place-items: center;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.68rem;
  font-weight: 700;
  color: #94a3b8;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.1);
}
.v-msg__body {
  flex: 1;
  min-width: 0;
}
.v-msg__txt {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.74rem;
  font-weight: 600;
  color: #e2e8f0;
  line-height: 1.4;
  overflow-wrap: anywhere;
}
.v-msg__sub {
  display: block;
  margin-top: 3px;
  font-size: 0.68rem;
  color: #64748b;
  line-height: 1.4;
}
/* The wire: a rail the active step animates a packet along. */
.v-msg__wire {
  position: relative;
  height: 2px;
  margin-top: 8px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.12);
  overflow: visible;
}
.v-msg__wire::after {
  content: "";
  position: absolute;
  top: -3px;
  right: -1px;
  border-left: 7px solid rgba(255, 255, 255, 0.28);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: border-left-color 0.4s ease;
}
.v-msg.rtl .v-msg__wire::after {
  right: auto;
  left: -1px;
  border-left: none;
  border-right: 7px solid rgba(255, 255, 255, 0.28);
}
.v-msg__pkt {
  position: absolute;
  top: 50%;
  left: 0;
  width: 12px;
  height: 12px;
  margin-top: -6px;
  border-radius: 4px;
  opacity: 0;
  background: var(--viz-accent);
  box-shadow: 0 0 16px var(--viz-accent), 0 0 6px #fff;
}
.v-msg.is-on .v-msg__pkt {
  animation: v-travel 1.8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
.v-msg.rtl.is-on .v-msg__pkt {
  animation-name: v-travel-rev;
}
.v-msg.is-on {
  background: rgba(255, 255, 255, 0.06);
  border-color: var(--viz-accent);
  box-shadow: 0 0 30px -10px var(--viz-accent);
}
.v-msg.is-on .v-msg__n {
  color: #04040a;
  background: var(--viz-accent);
  border-color: var(--viz-accent);
}
.v-msg.is-on .v-msg__wire { background: var(--viz-dim); }
.v-msg.is-on .v-msg__wire::after { border-left-color: var(--viz-accent); }
.v-msg.rtl.is-on .v-msg__wire::after { border-right-color: var(--viz-accent); }
/* Per-message semantic overrides — an attacker frame stays pink even
   inside a cyan module, because meaning outranks module branding. */
.v-msg.good.is-on { border-color: var(--viz-neon-green); box-shadow: 0 0 30px -10px var(--viz-neon-green); }
.v-msg.good.is-on .v-msg__n { background: var(--viz-neon-green); border-color: var(--viz-neon-green); }
.v-msg.good.is-on .v-msg__pkt { background: var(--viz-neon-green); box-shadow: 0 0 16px var(--viz-neon-green), 0 0 6px #fff; }
.v-msg.good.is-on .v-msg__wire::after { border-left-color: var(--viz-neon-green); }
.v-msg.bad.is-on { border-color: var(--viz-neon-pink); box-shadow: 0 0 30px -10px var(--viz-neon-pink); }
.v-msg.bad.is-on .v-msg__n { background: var(--viz-neon-pink); border-color: var(--viz-neon-pink); }
.v-msg.bad.is-on .v-msg__pkt { background: var(--viz-neon-pink); box-shadow: 0 0 16px var(--viz-neon-pink), 0 0 6px #fff; }
.v-msg.bad.is-on .v-msg__wire::after { border-left-color: var(--viz-neon-pink); }
.v-msg.warn.is-on { border-color: var(--viz-neon-amber); box-shadow: 0 0 30px -10px var(--viz-neon-amber); }
.v-msg.warn.is-on .v-msg__n { background: var(--viz-neon-amber); border-color: var(--viz-neon-amber); }
.v-msg.warn.is-on .v-msg__pkt { background: var(--viz-neon-amber); box-shadow: 0 0 16px var(--viz-neon-amber), 0 0 6px #fff; }
.v-msg.warn.is-on .v-msg__wire::after { border-left-color: var(--viz-neon-amber); }
.v-msg.purple.is-on { border-color: var(--viz-neon-purple); box-shadow: 0 0 30px -10px var(--viz-neon-purple); }
.v-msg.purple.is-on .v-msg__n { background: var(--viz-neon-purple); border-color: var(--viz-neon-purple); }
.v-msg.purple.is-on .v-msg__pkt { background: var(--viz-neon-purple); box-shadow: 0 0 16px var(--viz-neon-purple), 0 0 6px #fff; }
.v-msg.cyan.is-on { border-color: var(--viz-neon-cyan); box-shadow: 0 0 30px -10px var(--viz-neon-cyan); }
.v-msg.cyan.is-on .v-msg__n { background: var(--viz-neon-cyan); border-color: var(--viz-neon-cyan); }
.v-msg.cyan.is-on .v-msg__pkt { background: var(--viz-neon-cyan); box-shadow: 0 0 16px var(--viz-neon-cyan), 0 0 6px #fff; }

/* ── Encapsulation shells ─────────────────────────────────────
   Literally nested boxes, so "the TCP segment becomes the IP
   payload" is visible rather than asserted. */
.v-encap {
  position: relative;
  width: 100%;
  max-width: 600px;
  padding: 26px 14px 14px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.025);
  transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.v-encap__tag {
  position: absolute;
  top: 7px;
  left: 12px;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.63rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #94a3b8;
}
.v-encap__sz {
  position: absolute;
  top: 7px;
  right: 12px;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.6rem;
  color: #475569;
}
.v-encap.cyan { border-color: rgba(0, 240, 255, 0.4); background: rgba(0, 240, 255, 0.05); }
.v-encap.cyan > .v-encap__tag { color: var(--viz-neon-cyan); }
.v-encap.purple { border-color: rgba(157, 78, 221, 0.4); background: rgba(157, 78, 221, 0.06); }
.v-encap.purple > .v-encap__tag { color: var(--viz-neon-purple); }
.v-encap.good { border-color: rgba(0, 255, 136, 0.4); background: rgba(0, 255, 136, 0.05); }
.v-encap.good > .v-encap__tag { color: var(--viz-neon-green); }
.v-encap.warn { border-color: rgba(255, 170, 0, 0.4); background: rgba(255, 170, 0, 0.05); }
.v-encap.warn > .v-encap__tag { color: var(--viz-neon-amber); }
.v-encap.bad { border-color: rgba(255, 0, 85, 0.4); background: rgba(255, 0, 85, 0.05); }
.v-encap.bad > .v-encap__tag { color: var(--viz-neon-pink); }
.v-encap.is-on {
  box-shadow: 0 0 34px -10px var(--viz-accent);
  border-color: var(--viz-accent);
}
.v-encap__data {
  padding: 10px 12px;
  border-radius: 9px;
  background: rgba(0, 0, 0, 0.4);
  border: 1px dashed rgba(255, 255, 255, 0.15);
  font-family: "JetBrains Mono", monospace;
  font-size: 0.7rem;
  color: #cbd5e1;
  text-align: center;
  overflow-wrap: anywhere;
}

/* ── Protocol header field strip ──────────────────────────────
   For byte-level anatomy: TCP flags, IP TTL, JWT segments. */
.v-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  width: 100%;
  max-width: 640px;
}
.v-field {
  flex: 1 1 78px;
  min-width: 0;
  padding: 8px 6px;
  border-radius: 9px;
  text-align: center;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.v-field__k {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.56rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #64748b;
  margin-bottom: 4px;
  overflow-wrap: anywhere;
}
.v-field__v {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.76rem;
  font-weight: 700;
  color: #f8fafc;
  overflow-wrap: anywhere;
}
.v-field.set {
  background: var(--viz-dim);
  border-color: var(--viz-accent);
  box-shadow: 0 0 20px -8px var(--viz-accent);
}
.v-field.set .v-field__v { color: var(--viz-accent); }
.v-field.good { background: rgba(0, 255, 136, 0.12); border-color: rgba(0, 255, 136, 0.5); }
.v-field.good .v-field__v { color: var(--viz-neon-green); }
.v-field.bad { background: rgba(255, 0, 85, 0.12); border-color: rgba(255, 0, 85, 0.5); }
.v-field.bad .v-field__v { color: var(--viz-neon-pink); }
.v-field.warn { background: rgba(255, 170, 0, 0.12); border-color: rgba(255, 170, 0, 0.5); }
.v-field.warn .v-field__v { color: var(--viz-neon-amber); }
.v-field.cyan { background: rgba(0, 240, 255, 0.1); border-color: rgba(0, 240, 255, 0.5); }
.v-field.cyan .v-field__v { color: var(--viz-neon-cyan); }
.v-field.purple { background: rgba(157, 78, 221, 0.12); border-color: rgba(157, 78, 221, 0.5); }
.v-field.purple .v-field__v { color: var(--viz-neon-purple); }

/* ── Concept tile grid (STRIDE, ATT&CK tactics, IR phases) ──── */
.v-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(126px, 1fr));
  gap: 10px;
  width: 100%;
}
.v-tile {
  padding: 13px 10px;
  border-radius: 13px;
  text-align: center;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.1);
  transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.v-tile i {
  display: block;
  font-size: 1.1rem;
  margin-bottom: 7px;
  color: #94a3b8;
  transition: color 0.4s ease;
}
.v-tile b {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.72rem;
  color: #f8fafc;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.v-tile span {
  display: block;
  margin-top: 4px;
  font-size: 0.65rem;
  color: #64748b;
  line-height: 1.4;
}
.v-tile.is-on {
  background: var(--viz-dim);
  border-color: var(--viz-accent);
  box-shadow: 0 0 32px -10px var(--viz-accent);
  transform: translateY(-3px) scale(1.03);
}
.v-tile.is-on i { color: var(--viz-accent); }

/* ── Vertical chain / trust tree (cert chains, priv-esc paths) ─ */
.v-tree {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 460px;
}
.v-tree__node {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 15px;
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.v-tree__node i {
  font-size: 1rem;
  color: #94a3b8;
  width: 20px;
  text-align: center;
  flex-shrink: 0;
  transition: color 0.4s ease;
}
.v-tree__node b {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.74rem;
  color: #f8fafc;
  overflow-wrap: anywhere;
}
.v-tree__node span {
  display: block;
  font-size: 0.66rem;
  color: #64748b;
  line-height: 1.4;
  overflow-wrap: anywhere;
}
.v-tree__node.is-on {
  background: var(--viz-dim);
  border-color: var(--viz-accent);
  box-shadow: 0 0 32px -10px var(--viz-accent);
}
.v-tree__node.is-on i { color: var(--viz-accent); }
.v-tree__node.good { border-color: rgba(0, 255, 136, 0.45); }
.v-tree__node.good i { color: var(--viz-neon-green); }
.v-tree__node.bad { border-color: rgba(255, 0, 85, 0.45); }
.v-tree__node.bad i { color: var(--viz-neon-pink); }
.v-tree__link {
  position: relative;
  width: 2px;
  height: 24px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.3));
  flex-shrink: 0;
}
.v-tree__link::after {
  content: "";
  position: absolute;
  bottom: -1px;
  left: -4px;
  border-top: 7px solid rgba(255, 255, 255, 0.3);
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
}
.v-tree__link em {
  position: absolute;
  left: 12px;
  top: 3px;
  font-style: normal;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.6rem;
  color: #64748b;
  white-space: nowrap;
}

/* ── Inline annotation inside a stage ─────────────────────────── */
.v-note {
  width: 100%;
  max-width: 600px;
  display: flex;
  gap: 10px;
  padding: 10px 14px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.32);
  border-left: 2px solid var(--viz-accent);
  font-size: 0.76rem;
  line-height: 1.55;
  color: #94a3b8;
  text-align: left;
}
.v-note i { color: var(--viz-accent); margin-top: 3px; flex-shrink: 0; }
.v-note b { color: #e2e8f0; }

/* ── Horizontal scroll rail for stages too wide for a phone ──── */
.viz__scroll {
  width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
  padding-bottom: 4px;
}
.viz__scroll::-webkit-scrollbar { height: 5px; }
.viz__scroll::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.16);
  border-radius: 3px;
}
.viz__scroll > * { min-width: min-content; }

/* ── Mobile tuning for the components above ──────────────────── */
@media (max-width: 768px) {
  .v-legend { gap: 6px 12px; padding: 8px 10px; }
  .v-legend__item { font-size: 0.6rem; }
  .v-lane__actors { gap: 6px; padding-bottom: 10px; margin-bottom: 11px; }
  .v-lane__actor i { width: 34px; height: 34px; font-size: 0.85rem; border-radius: 10px; }
  .v-lane__actor b { font-size: 0.58rem; }
  .v-lane__actor span { display: none; }
  .v-msg { padding: 9px 11px; gap: 9px; border-radius: 10px; }
  .v-msg__n { width: 21px; height: 21px; font-size: 0.6rem; }
  .v-msg__txt { font-size: 0.68rem; }
  .v-msg__sub { font-size: 0.62rem; }
  .v-encap { padding: 22px 10px 10px; }
  .v-encap__tag { font-size: 0.56rem; }
  .v-encap__sz { display: none; }
  .v-encap__data { font-size: 0.62rem; padding: 8px; }
  /* Flex-wrapping left an orphan cell on the last row; a fixed 3-up grid
     keeps header fields in readable columns. This override has to live
     here rather than in the Part I mobile block, because the base
     `.v-fields { display: flex }` is declared further down the file and
     would otherwise win on source order at equal specificity. */
  .v-fields {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 6px;
  }
  .v-field { padding: 6px 4px; }
  .v-field__k { font-size: 0.5rem; }
  .v-field__v { font-size: 0.67rem; }
  .v-grid { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 7px; }
  .v-tile { padding: 10px 6px; border-radius: 11px; }
  .v-tile i { font-size: 0.92rem; margin-bottom: 5px; }
  .v-tile b { font-size: 0.63rem; }
  .v-tile span { font-size: 0.57rem; }
  .v-tree__node { padding: 10px 12px; gap: 9px; }
  .v-tree__node b { font-size: 0.67rem; }
  .v-tree__node span { font-size: 0.6rem; }
  .v-tree__link { height: 19px; }
  .v-tree__link em { font-size: 0.55rem; }
  .v-note { font-size: 0.7rem; padding: 9px 11px; }
  .v-bar { flex-wrap: wrap; gap: 6px 10px; }
  .v-bar__lbl { min-width: 0; flex: 1 1 100%; text-align: left; font-size: 0.68rem; }
  .v-bar__track { flex: 1 1 60%; }
  .v-bar__val { min-width: 0; font-size: 0.68rem; }
  .v-seq, .v-term, .v-frame, .v-bars, .v-lane, .v-encap, .v-fields, .v-note { max-width: 100%; }
  /* The label is in normal flow on mobile, so the stage no longer needs
     to reserve space underneath it. */
  .viz__stage { gap: 16px; min-height: 0; padding-top: 6px; }
}

/* Very small phones — stop diagrams from forcing a horizontal scroll. */
@media (max-width: 420px) {
  .viz { padding: 22px 12px 16px; }
  .v-grid { grid-template-columns: repeat(auto-fit, minmax(84px, 1fr)); }
  .v-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .v-flow { gap: 8px; }
  .v-box { width: 42px; height: 42px; font-size: 1rem; }
  .v-cap { font-size: 0.6rem; max-width: 68px; }
}
