/* Animated product demonstrations.
 *
 * The charts in here are not illustrations. They are the SVG the running
 * application drew, captured from a live monitoring page and pasted in
 * unaltered - the same .mchart/.grid/.axis/.line markup the product emits.
 * This file gives them the same appearance they have in the product, and
 * then choreographs them.
 *
 * Vector rather than a recording, for four reasons that matter here: it is
 * a few kilobytes instead of several megabytes, it stays sharp on any
 * display, the text in it is real text, and turning the motion off for
 * somebody who asked for less of it is one media query rather than a
 * second set of files.
 *
 * ONE TIMELINE. Every keyframe below is a percentage of the same
 * --demo-run duration, so the scenes cannot drift apart. Change the
 * duration and the whole walkthrough re-times itself.
 */

.demo {
  --demo-run: 16s;
  --demo-ink: #0C1B33;
  --demo-accent: #2F6FEB;
  --demo-line: #DCE4F0;
  --demo-faint: #7C89A1;
  --demo-paper: #FFFFFF;
  --demo-sunken: #F5F8FD;
  position: relative;
}

/* ---- the frame the product sits in ---------------------------------- */

.demoframe {
  position: relative;
  border-radius: var(--r-xl, 1.5rem);
  overflow: hidden;
  background: var(--demo-paper);
  border: 1px solid var(--demo-line);
  /* Lifted, not floating: a soft ambient shadow plus a tight contact one,
     which is what stops a large pale panel looking pasted on. */
  box-shadow: 0 1px 2px rgba(12, 27, 51, .06),
              0 24px 48px -24px rgba(12, 27, 51, .28),
              0 48px 96px -48px rgba(12, 27, 51, .22);
}

.demochrome {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .7rem 1rem;
  background: var(--demo-sunken);
  border-bottom: 1px solid var(--demo-line);
}

.demodots { display: flex; gap: .375rem; }
.demodots i {
  width: .6rem; height: .6rem; border-radius: 50%;
  background: var(--demo-line);
}
.demoaddress {
  flex: 1;
  font-size: .75rem;
  color: var(--demo-faint);
  background: var(--demo-paper);
  border: 1px solid var(--demo-line);
  border-radius: var(--r-pill, 999px);
  padding: .25rem .75rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* A fixed aspect box, so the page does not reflow as scenes swap. */
.demostage {
  position: relative;
  aspect-ratio: 16 / 10;
  background: var(--demo-paper);
  overflow: hidden;
}

.demoscene {
  position: absolute;
  inset: 0;
  padding: 1.25rem;
  opacity: 0;
  display: flex;
  flex-direction: column;
  gap: .9rem;
}

/* ---- the product's own chart appearance ------------------------------ */

.demo .mchart { width: 100%; height: 100%; display: block; overflow: visible; }
.demo .mchart .grid { stroke: var(--demo-line); stroke-width: 1; }
.demo .mchart .axis { fill: var(--demo-faint); font-size: 10px; }
.demo .mchart .line {
  fill: none;
  stroke: var(--metric, var(--demo-accent));
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.demo .mchart .band { fill: var(--metric, var(--demo-accent)); opacity: .10; }
.demo .mchart .bar { fill: var(--metric, var(--demo-accent)); opacity: .85; }
.demo .mchart .surface { fill: transparent; }
.demo .mchart .cursor { stroke: var(--demo-faint); stroke-width: 1; stroke-dasharray: 3 3; }
.demo .mchart .knob { fill: var(--demo-accent); }
/* A gap in the data, which the product shades faintly. Without this rule
   the rectangles default to black and paint over the chart - which is
   exactly what they did the first time this was built. Any class the
   product emits needs a rule here, not just the obvious ones. */
.demo .mchart .gapband { fill: color-mix(in srgb, #9A6400 9%, transparent); }
.demo .mchart .zoomband { fill: none; stroke: none; }

/* ---- scene one: the dashboard ---------------------------------------- */

.demogrid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .9rem;
  flex: 1;
  min-height: 0;
}

.democard {
  display: flex;
  flex-direction: column;
  gap: .4rem;
  padding: .85rem .9rem;
  background: var(--demo-paper);
  border: 1px solid var(--demo-line);
  border-radius: var(--r-lg, 1rem);
  min-width: 0;
  box-shadow: 0 1px 2px rgba(12, 27, 51, .04);
}
.democard:nth-child(1) { --metric: #2F6FEB; }
.democard:nth-child(2) { --metric: #12805C; }
.democard:nth-child(3) { --metric: #9A6400; }

.demohead { display: flex; align-items: baseline; gap: .4rem; }
.demoname {
  font-size: .8rem; font-weight: 640; color: var(--demo-ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.demounit { font-size: .7rem; color: var(--demo-faint); }
.demonow {
  margin-left: auto; font-size: .95rem; font-weight: 680;
  color: var(--metric); font-variant-numeric: tabular-nums;
}
.demoplot { flex: 1; min-height: 0; }

/* ---- scene two: maximised -------------------------------------------- */

.demofull { gap: .75rem; }
.demofullhead { display: flex; align-items: center; gap: .6rem; }
.demofullhead h4 {
  margin: 0; font-size: .95rem; font-weight: 680; color: var(--demo-ink);
}
.demostats {
  margin-left: auto; font-size: .75rem; color: var(--demo-faint);
  font-variant-numeric: tabular-nums;
}
.demostats b { color: var(--demo-ink); }
.demofullplot { flex: 1; min-height: 0; position: relative; --metric: #2F6FEB; }
/* The three chart types are stacked and cross-faded, so switching looks
   like the product redrawing rather than like a slideshow. */
.demofullplot > .demolayer { position: absolute; inset: 0; opacity: 0; }

.demopills { display: flex; gap: .4rem; }
.demopill {
  font-size: .7rem; padding: .2rem .7rem;
  border: 1px solid var(--demo-line); border-radius: var(--r-pill, 999px);
  color: var(--demo-faint); background: var(--demo-paper);
}

/* ---- the cursor ------------------------------------------------------ */

.democursor {
  position: absolute;
  width: 18px; height: 18px;
  margin: -2px 0 0 -2px;
  opacity: 0;
  pointer-events: none;
  z-index: 4;
  filter: drop-shadow(0 2px 4px rgba(12, 27, 51, .35));
}
.demoripple {
  position: absolute;
  width: 34px; height: 34px; margin: -17px 0 0 -17px;
  border-radius: 50%;
  border: 2px solid var(--demo-accent);
  opacity: 0;
  pointer-events: none;
  z-index: 3;
}

/* ====================================================================== */
/* The choreography. Nothing below runs until .is-playing is set, which   */
/* the script does when the figure is actually on screen.                 */
/* ====================================================================== */

.demo.is-playing .demoscene.scene-dash { animation: demoDash var(--demo-run) infinite; }
.demo.is-playing .demoscene.scene-full { animation: demoFull var(--demo-run) infinite; }

@keyframes demoDash {
  0%        { opacity: 0; transform: scale(.995); }
  3%, 40%   { opacity: 1; transform: scale(1); }
  46%, 92%  { opacity: 0; transform: scale(1.01); }
  97%, 100% { opacity: 1; transform: scale(.995); }
}
@keyframes demoFull {
  0%, 42%   { opacity: 0; transform: scale(.99); }
  48%, 88%  { opacity: 1; transform: scale(1); }
  94%, 100% { opacity: 0; }
}

/* Each card's line draws itself, one after another. pathLength=1
   normalises every path so one rule times them all regardless of length. */
.demo.is-playing .democard .mchart .line {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: demoDraw var(--demo-run) infinite;
}
.demo.is-playing .democard:nth-child(1) .mchart .line { animation-delay: calc(var(--demo-run) * .01); }
.demo.is-playing .democard:nth-child(2) .mchart .line { animation-delay: calc(var(--demo-run) * .04); }
.demo.is-playing .democard:nth-child(3) .mchart .line { animation-delay: calc(var(--demo-run) * .07); }

@keyframes demoDraw {
  0%       { stroke-dashoffset: 1; }
  18%, 92% { stroke-dashoffset: 0; }
  100%     { stroke-dashoffset: 1; }
}

/* The value settles in rather than appearing, which reads as a figure
   arriving from the provider. */
.demo.is-playing .demonow { animation: demoValue var(--demo-run) infinite; }
.demo.is-playing .democard:nth-child(2) .demonow { animation-delay: calc(var(--demo-run) * .03); }
.demo.is-playing .democard:nth-child(3) .demonow { animation-delay: calc(var(--demo-run) * .06); }

@keyframes demoValue {
  0%, 8%   { opacity: 0; transform: translateY(.3rem); }
  16%, 90% { opacity: 1; transform: translateY(0); }
  100%     { opacity: 0; }
}

/* The card being opened lifts slightly just before the click. */
.demo.is-playing .democard:nth-child(1) { animation: demoFocus var(--demo-run) infinite; }
@keyframes demoFocus {
  0%, 30%  { box-shadow: 0 1px 2px rgba(12, 27, 51, .04); border-color: var(--demo-line); }
  36%, 44% { box-shadow: 0 8px 24px -8px rgba(47, 111, 235, .45); border-color: #2F6FEB; }
  50%, 100%{ box-shadow: 0 1px 2px rgba(12, 27, 51, .04); border-color: var(--demo-line); }
}

/* The cursor travels to the card's expand control and clicks it. */
.demo.is-playing .democursor { animation: demoCursor var(--demo-run) infinite; }
@keyframes demoCursor {
  0%, 22%   { opacity: 0; top: 72%; left: 62%; }
  26%       { opacity: 1; top: 72%; left: 62%; }
  36%       { opacity: 1; top: 20%; left: 29%; }
  38%       { opacity: 1; top: 20.5%; left: 29%; }
  44%       { opacity: 1; top: 20%; left: 29%; }
  50%, 100% { opacity: 0; top: 20%; left: 29%; }
}
.demo.is-playing .demoripple { animation: demoRipple var(--demo-run) infinite; }
@keyframes demoRipple {
  0%, 37%  { opacity: 0; transform: scale(.4); top: 20%; left: 29%; }
  39%      { opacity: .7; transform: scale(.6); top: 20%; left: 29%; }
  45%      { opacity: 0; transform: scale(1.6); top: 20%; left: 29%; }
  100%     { opacity: 0; top: 20%; left: 29%; }
}

/* In the maximised view the big chart draws, then the type changes. */
.demo.is-playing .demofullplot .mchart .line {
  stroke-dasharray: 1; stroke-dashoffset: 1;
  animation: demoDrawBig var(--demo-run) infinite;
}
@keyframes demoDrawBig {
  0%, 46%  { stroke-dashoffset: 1; }
  58%, 88% { stroke-dashoffset: 0; }
  100%     { stroke-dashoffset: 1; }
}

.demo.is-playing .demolayer.is-line { animation: demoLayerLine var(--demo-run) infinite; }
.demo.is-playing .demolayer.is-area { animation: demoLayerArea var(--demo-run) infinite; }
.demo.is-playing .demolayer.is-bar  { animation: demoLayerBar  var(--demo-run) infinite; }

@keyframes demoLayerLine { 0%,46%{opacity:0} 50%,62%{opacity:1} 66%,100%{opacity:0} }
@keyframes demoLayerArea { 0%,64%{opacity:0} 68%,76%{opacity:1} 80%,100%{opacity:0} }
@keyframes demoLayerBar  { 0%,78%{opacity:0} 82%,88%{opacity:1} 92%,100%{opacity:0} }

.demo.is-playing .demopill.is-line { animation: demoPillLine var(--demo-run) infinite; }
.demo.is-playing .demopill.is-area { animation: demoPillArea var(--demo-run) infinite; }
.demo.is-playing .demopill.is-bar  { animation: demoPillBar  var(--demo-run) infinite; }

@keyframes demoPillLine {
  0%,46%{background:var(--demo-paper);color:var(--demo-faint);border-color:var(--demo-line)}
  50%,64%{background:#EAF1FE;color:#1B4DB1;border-color:#2F6FEB}
  68%,100%{background:var(--demo-paper);color:var(--demo-faint);border-color:var(--demo-line)}
}
@keyframes demoPillArea {
  0%,64%{background:var(--demo-paper);color:var(--demo-faint);border-color:var(--demo-line)}
  68%,78%{background:#EAF1FE;color:#1B4DB1;border-color:#2F6FEB}
  82%,100%{background:var(--demo-paper);color:var(--demo-faint);border-color:var(--demo-line)}
}
@keyframes demoPillBar {
  0%,78%{background:var(--demo-paper);color:var(--demo-faint);border-color:var(--demo-line)}
  82%,90%{background:#EAF1FE;color:#1B4DB1;border-color:#2F6FEB}
  94%,100%{background:var(--demo-paper);color:var(--demo-faint);border-color:var(--demo-line)}
}

/* The caption says which step is being shown, so the motion explains
   something rather than merely happening. */
.democaption {
  display: flex; align-items: center; gap: .5rem;
  margin-top: .9rem; min-height: 1.4rem;
  font-size: .85rem; color: var(--demo-faint);
}
.democaption span { position: absolute; opacity: 0; }
.democaption { position: relative; }
.demo.is-playing .democaption span.step-1 { animation: demoCap1 var(--demo-run) infinite; }
.demo.is-playing .democaption span.step-2 { animation: demoCap2 var(--demo-run) infinite; }
.demo.is-playing .democaption span.step-3 { animation: demoCap3 var(--demo-run) infinite; }
@keyframes demoCap1 { 0%,2%{opacity:0} 6%,28%{opacity:1} 32%,100%{opacity:0} }
@keyframes demoCap2 { 0%,32%{opacity:0} 36%,58%{opacity:1} 62%,100%{opacity:0} }
@keyframes demoCap3 { 0%,62%{opacity:0} 66%,88%{opacity:1} 92%,100%{opacity:0} }

/* ---- smaller screens -------------------------------------------------- */

@media (max-width: 48rem) {
  .demostage { aspect-ratio: 4 / 3; }
  .demogrid { grid-template-columns: 1fr; gap: .5rem; }
  /* Three stacked cards do not fit; the third is dropped rather than
     squashed into something unreadable. */
  .democard:nth-child(3) { display: none; }
  .demoscene { padding: .75rem; }
  .demoaddress { font-size: .65rem; }
}

/* ---- asked for less motion -------------------------------------------- */
/*
 * Everything stops and the dashboard is shown, drawn, at rest. Not a
 * different asset and not a blank box: the same real charts, still.
 */
@media (prefers-reduced-motion: reduce) {
  .demo.is-playing .demoscene.scene-dash,
  .demo.is-playing .demoscene.scene-full,
  .demo.is-playing .democard,
  .demo.is-playing .demonow,
  .demo.is-playing .democursor,
  .demo.is-playing .demoripple,
  .demo.is-playing .demolayer,
  .demo.is-playing .demopill,
  .demo.is-playing .democaption span,
  .demo.is-playing .mchart .line {
    animation: none !important;
  }
  .demo .demoscene.scene-dash { opacity: 1; }
  .demo .demoscene.scene-full { opacity: 0; }
  .demo .mchart .line { stroke-dashoffset: 0 !important; }
  .demo .demonow { opacity: 1; }
  .demo .democaption span.step-1 { opacity: 1; }
}
