@charset "utf-8";

/* ============================================================================
   Animated product illustrations
   ----------------------------------------------------------------------------
   The eight archetypes drawn by src/microsite-demo.mjs: reel, dashboard,
   terminal, window, board, route, grid and trace. Every rule is scoped under
   `.demo`, and every colour is read from custom properties rather than named
   here, so the same stylesheet serves the microsites — where the palette is set
   on <html> — and the Bottega suite, where it is mapped onto Bottega's own
   tokens on the figure itself.

   It lives in its own file because two design systems need it and neither
   should have to swallow the other's reset, layout and typography to get it.

   Properties expected from the host:
     --accent --accent-deep --accent-soft --on-accent --counter --counter-deep
     --raise --sink --line --line-soft --dim --text --ui --mono --ease
   ========================================================================== */

/* --- the animated illustrations ------------------------------------------ */

.demo {
  width: 100%;
  height: auto;
}

.demo .d-panel {
  fill: var(--raise);
  stroke: var(--line-soft);
}

.demo .d-well {
  fill: var(--sink);
  stroke: var(--line-soft);
}

.demo .d-rule,
.demo .d-threshold {
  stroke: var(--line-soft);
  stroke-width: 1;
}

.demo .d-threshold {
  stroke: var(--accent);
  stroke-dasharray: 4 6;
  opacity: 0.6;
}

.demo .d-dot {
  fill: var(--line);
}

.demo .d-chrome {
  fill: var(--dim);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.06em;
}

.demo .d-chrome--on {
  fill: var(--on-accent);
}

.demo .d-label {
  fill: var(--accent);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
}

.demo .d-micro {
  fill: var(--dim);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
}

.demo .d-micro--chip {
  fill: var(--on-accent);
  font-size: 13px;
}

.demo .d-value,
.demo .d-figure {
  fill: var(--text);
  font-family: var(--ui);
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.03em;
}

.demo .d-value {
  font-family: var(--mono);
  font-size: 17px;
  font-weight: 400;
}

.demo .d-mono {
  fill: var(--dim);
  font-family: var(--mono);
  font-size: 14px;
}

.demo .d-mono--cmd {
  fill: var(--text);
}

.demo .d-mono--ok {
  fill: var(--accent);
}

.demo .d-pad {
  fill: var(--accent-deep);
}

.demo .d-chip {
  fill: var(--accent);
}

.demo .d-bar,
.demo .d-wave {
  fill: var(--accent);
}

.demo .d-row rect {
  fill: var(--line);
}

.demo .d-row .d-row__alt {
  fill: var(--accent-deep);
}

.demo .d-nav rect {
  fill: var(--accent);
}

.demo .d-badge {
  fill: var(--accent);
}

.demo .d-check {
  fill: none;
  stroke: var(--on-accent);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.demo .d-marker {
  fill: var(--counter);
}

.demo .d-fill {
  fill: var(--accent);
  transform-box: fill-box;
  transform-origin: left center;
}

.demo .d-signal {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.demo .d-trace {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.demo .d-cell {
  fill: var(--line-soft);
}

.demo .d-cell--on {
  fill: var(--accent);
}

.demo .d-caret {
  fill: var(--accent);
}

.demo .d-stage rect {
  fill: var(--line);
}

.demo .d-flag line {
  stroke: var(--counter);
  stroke-width: 2;
  stroke-dasharray: 3 5;
}

/* Per-archetype adjustment. The eight demos share a frame but not a subject,
   and a routing pass wants a calmer stroke than a case reel does. */
.demo--reel .d-tile__mark,
.demo--grid .d-cell {
  transition: fill 0.2s var(--ease);
}

.demo--route .d-trace,
.demo--board .d-trace {
  stroke-width: 1.75;
}

.demo--terminal .d-mono,
.demo--window .d-chrome {
  letter-spacing: 0.01em;
}

.demo--dashboard .d-bar {
  opacity: 0.92;
}

.demo--trace .d-signal {
  stroke-width: 3;
}

.demo .d-mono--out {
  fill: var(--dim);
}

/* The trace demo draws a much longer path than the board's settling clock, so
   its dash length has to match or the stroke finishes before the line does. */
.demo .d-signal--long {
  stroke-dasharray: 2600;
  --len: 2600;
  animation-duration: 6s;
}

/* Tier 0 is the common pull: no colour, which is the point of it. Written out
   rather than left to fall through, so it reads as a decision. */
.demo .d-tier-0 .d-tile__band,
.demo .d-tier-0 .d-tile__mark {
  fill: var(--line);
}

/* The reel.
 *
 * Every one of these used to resolve to something within a few percent of the
 * page ground, so the strip rendered as an empty black box — and the stash
 * slots had no fill rule at all, which in SVG means black. Rarity now climbs
 * the accent ramp, with the one complementary colour reserved for the rarest
 * pull, which is the only job that colour has on the page.
 */
.demo .d-tile__body {
  fill: color-mix(in srgb, var(--accent) 10%, var(--raise));
  stroke: var(--line);
}

.demo .d-tile__mark,
.demo .d-tile__band {
  fill: var(--line);
}

.demo .d-tier-1 .d-tile__band,
.demo .d-tier-1 .d-tile__mark {
  fill: var(--accent-deep);
}

.demo .d-tier-2 .d-tile__band,
.demo .d-tier-2 .d-tile__mark {
  fill: var(--accent);
}

.demo .d-tier-3 .d-tile__band,
.demo .d-tier-3 .d-tile__mark {
  fill: var(--accent-soft);
}

.demo .d-tier-4 .d-tile__body {
  fill: color-mix(in srgb, var(--counter) 18%, var(--raise));
  stroke: var(--counter);
}

.demo .d-tier-4 .d-tile__band,
.demo .d-tier-4 .d-tile__mark {
  fill: var(--counter);
}

.demo .d-slot {
  fill: color-mix(in srgb, var(--accent) 22%, var(--raise));
  stroke: var(--line);
}

/* Motion. Every animation is either a stroke being drawn, a value settling, or
   something arriving — nothing loops for decoration alone, and each carries a
   `--i` so one keyframe rule serves a whole row. */

@keyframes d-reel {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-736px);
  }
}

@keyframes d-draw {
  from {
    stroke-dashoffset: var(--len, 900);
  }
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes d-grow {
  from {
    transform: scaleY(0);
  }
  to {
    transform: scaleY(1);
  }
}

@keyframes d-fill {
  from {
    transform: scaleX(0.04);
  }
  to {
    transform: scaleX(1);
  }
}

@keyframes d-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes d-pop {
  0%,
  40% {
    opacity: 0;
    transform: scale(0.7);
  }
  60% {
    opacity: 1;
    transform: scale(1.06);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes d-blink {
  0%,
  49% {
    opacity: 1;
  }
  50%,
  100% {
    opacity: 0;
  }
}

@keyframes d-scan {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(654px);
  }
}

@keyframes d-glow {
  0%,
  100% {
    opacity: 0.28;
  }
  50% {
    opacity: 1;
  }
}

.demo .d-reel {
  animation: d-reel 7s cubic-bezier(0.12, 0.72, 0.16, 1) infinite;
}

.demo .d-fill {
  animation: d-fill 3.6s var(--ease) infinite alternate;
}

.demo .d-fill--slow {
  animation-duration: 5s;
}

.demo .d-bar,
.demo .d-wave {
  transform-box: fill-box;
  transform-origin: bottom center;
  animation: d-grow 2.4s var(--ease) infinite alternate;
  animation-delay: calc(var(--i) * 90ms);
}

.demo .d-wave {
  transform-origin: center;
  animation-duration: 1.6s;
  animation-delay: calc(var(--i) * 55ms);
}

.demo .d-pop,
.demo .d-row,
.demo .d-line,
.demo .d-rise,
.demo .d-nav,
.demo .d-stage {
  opacity: 0;
  animation: d-in 0.5s var(--ease) forwards;
  animation-delay: calc(0.25s + var(--i) * 180ms);
}

.demo .d-pop {
  transform-box: fill-box;
  transform-origin: center;
  animation: d-pop 2.6s var(--ease) infinite;
  animation-delay: calc(var(--i) * 150ms);
}

.demo .d-trace {
  stroke-dasharray: 900;
  animation: d-draw 3.2s var(--ease) infinite;
  animation-delay: calc(var(--i) * 260ms);
}

.demo .d-trace--slow {
  animation-duration: 5.2s;
  animation-delay: calc(var(--i) * 380ms);
}

.demo .d-signal {
  stroke-dasharray: 1400;
  --len: 1400;
  animation: d-draw 4.5s var(--ease) infinite;
}

.demo .d-caret {
  animation: d-blink 1.1s steps(1) infinite;
}

.demo .d-scan {
  fill: var(--accent);
  opacity: 0.7;
  animation: d-scan 3.4s linear infinite;
}

.demo .d-cell--on {
  animation: d-glow 2.8s var(--ease) infinite;
  animation-delay: calc(var(--i) * 70ms);
}

.demo .d-verdict,
.demo .d-flag {
  opacity: 0;
  animation: d-in 0.6s var(--ease) 2.6s forwards;
}

/* Reduced motion. The demos animate from an invisible or empty state, so
   switching motion off has to leave them in their finished state rather than
   their first frame — otherwise "reduce motion" would read as "delete the
   illustration". */
@media (prefers-reduced-motion: reduce) {
  .demo *,
  .demo *::before,
  .demo *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .demo .d-pop,
  .demo .d-row,
  .demo .d-line,
  .demo .d-rise,
  .demo .d-nav,
  .demo .d-stage,
  .demo .d-verdict,
  .demo .d-flag {
    opacity: 1;
    transform: none;
  }

  .demo .d-trace,
  .demo .d-signal {
    stroke-dasharray: none;
  }

  .demo .d-bar,
  .demo .d-wave,
  .demo .d-fill {
    transform: none;
  }
}

/* Severity dots on the terminal's findings list. Two levels, so the row reads
   as triaged output rather than as a uniform block of warnings. */
.demo .d-flagdot {
  fill: var(--accent);
}

.demo .d-flagdot--soft {
  fill: var(--line);
}
