/* Grid-alignment figure ({{< grid-alignment >}}): why chips are 960 m.
   The SVG is generated by make_grid_figure.py, which owns the geometry and the
   step each layer appears at; this file owns colour and motion. Every layer is
   a Reveal fragment with class "custom", so Reveal hides nothing itself: each
   layer's hidden and .visible states are set here. Lengths in px are SVG user
   units, i.e. metres on the ground. */

.reveal .grid-alignment {
  /* Timing */
  --t-drop: 500ms;
  --t-draw: 700ms;
  --t-align: 600ms;
  --ease: cubic-bezier(.2, .8, .2, 1);

  /* Palette: ink, paper and fonts come from the theme, and the patch colour
     from its --accent (teal, or the CNG theme's yellow); the blue is copied
     from _extensions/dwgodwin/slides/slides.scss. Red and green are only
     used for the verdicts. */
  --ga-ink: var(--r-main-color, #F2F4F6);
  --ga-paper: var(--r-background-color, #1D232B);
  --ga-s2: #418BD9;
  --ga-ls: var(--ga-ink);
  --ga-patch: var(--accent, #2DD4BF);
  --ga-ok: #5BD68B;
  --ga-bad: #FF6B5E;
}

.reveal .grid-alignment svg {
  display: block;
  height: 760px;
  margin: 0 auto;
  overflow: visible;
}

/* ---- Colour ------------------------------------------------------------ */

.reveal .grid-alignment .s2 { stroke: var(--ga-s2); }
.reveal .grid-alignment .ls { stroke: var(--ga-ls); }
.reveal .grid-alignment .patch { stroke: var(--ga-patch); }

.reveal .grid-alignment text {
  fill: var(--ga-ink);
  stroke: none;
}

.reveal .grid-alignment .mono {
  font-family: var(--r-code-font, ui-monospace, monospace);
}

.reveal .grid-alignment .swatch { stroke: none; }
.reveal .grid-alignment .swatch.s2 { fill: var(--ga-s2); }
.reveal .grid-alignment .swatch.ls { fill: var(--ga-ls); }

.reveal .grid-alignment .name,
.reveal .grid-alignment .size,
.reveal .grid-alignment .row,
.reveal .grid-alignment .tag text {
  font-weight: 700;
}

.reveal .grid-alignment .ro-patch text { fill: var(--ga-patch); }

.reveal .grid-alignment .label {
  letter-spacing: 0.18em;
  fill-opacity: 0.6;
}

.reveal .grid-alignment .size { letter-spacing: -0.02em; }

.reveal .grid-alignment .caption .hl { fill: var(--ga-patch); }

/* ---- Pixel grids: drop in from above ----------------------------------- */

.reveal .grid-alignment .pixels {
  opacity: 0;
  transform: translateY(-30px);
  transition: opacity var(--t-drop) var(--ease), transform var(--t-drop) var(--ease);
}

.reveal .grid-alignment .pixels.visible {
  opacity: 1;
  transform: none;
}

/* Each grid has a step of its own, so none needs a delay to stack after
   another; each band's legend row keeps time with its grid */

.reveal .grid-alignment #grid-10 { stroke-opacity: 0.6; }
.reveal .grid-alignment #grid-30 { stroke-opacity: 0.7; }

/* Once patches are drawn the pixel grids step back */
.reveal .grid-alignment .pixels.visible:has(~ .patches.visible) {
  opacity: 0.4;
}

/* ---- Patch grids: each line draws itself, sweeping out from the corner -- */

.reveal .grid-alignment .patches line {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 250ms ease-in;
}

.reveal .grid-alignment .patches.visible line {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset var(--t-draw) var(--ease) calc(var(--after, 0ms) + var(--i) * 25ms);
}

/* The thicker grids lie on top, so they are see-through: where borders
   coincide the thinner lines still show inside them, and a line's weight
   says how many grids share it. (--after lets a grid wait for one it shares
   a step with; none does at present.) */
.reveal .grid-alignment #patch-30 { stroke-opacity: 0.5; }

/* ---- Legend rows -------------------------------------------------------- */

.reveal .grid-alignment :is(.ro-band, .ro-patch, .caption) {
  opacity: 0;
  transition: opacity var(--t-drop) var(--ease);
}

.reveal .grid-alignment :is(.ro-band, .ro-patch, .caption).visible {
  opacity: 1;
}

/* ---- Candidate chips: one at a time, each resizing from the last -------- */

/* A hidden candidate waits for its outline to shrink back before it goes */
.reveal .grid-alignment :is(.chip, .ro-cand, .verdict) {
  opacity: 0;
  transition: opacity 0s linear var(--t-align);
}

.reveal .grid-alignment :is(.chip, .ro-cand).visible {
  opacity: 1;
  transition: opacity 0s;
}

/* A candidate gives way as soon as a later one is shown */
.reveal .grid-alignment .chip:has(~ .chip.visible),
.reveal .grid-alignment .ro-cand:has(~ .ro-cand.visible),
.reveal .grid-alignment .verdict:has(~ .verdict.visible) {
  opacity: 0;
  transition: opacity 0s;
}

.reveal .grid-alignment .outline {
  width: var(--from);
  height: var(--from);
  stroke: var(--ga-ink);
  fill: var(--ga-ink);
  fill-opacity: 0.08;
  transition: width var(--t-align) var(--ease), height var(--t-align) var(--ease),
    stroke 300ms, fill 300ms, stroke-dashoffset 250ms ease-in;
}

.reveal .grid-alignment .chip.visible .outline {
  width: var(--to);
  height: var(--to);
  transition-delay: 0s, 0s, var(--t-align), var(--t-align), 0s;
}

/* The first candidate has nothing to resize from, so it draws itself */
.reveal .grid-alignment .chip.draw .outline {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

.reveal .grid-alignment .chip.draw.visible .outline {
  stroke-dashoffset: 0;
  transition-duration: var(--t-align), var(--t-align), 300ms, 300ms, var(--t-align);
}

.reveal .grid-alignment .chip.visible.ok .outline { stroke: var(--ga-ok); fill: var(--ga-ok); }
.reveal .grid-alignment .chip.visible.bad .outline { stroke: var(--ga-bad); fill: var(--ga-bad); }

/* Size label tucked into the outline's bottom-right corner; it rides along */
.reveal .grid-alignment .tag {
  transform: translate(calc(var(--from) - var(--to)), calc(var(--from) - var(--to)));
  transition: transform var(--t-align) var(--ease);
}

.reveal .grid-alignment .chip.visible .tag {
  transform: none;
}

.reveal .grid-alignment .tag rect {
  stroke: none;
  fill: var(--ga-ink);
  transition: fill 300ms;
}

.reveal .grid-alignment .chip.visible .tag rect { transition-delay: var(--t-align); }
.reveal .grid-alignment .chip.visible.ok .tag rect { fill: var(--ga-ok); }
.reveal .grid-alignment .chip.visible.bad .tag rect { fill: var(--ga-bad); }

.reveal .grid-alignment .tag text { fill: var(--ga-paper); }

.reveal .grid-alignment .chip.draw .tag {
  opacity: 0;
  transition: opacity 200ms;
}

.reveal .grid-alignment .chip.draw.visible .tag {
  opacity: 1;
  transition-delay: calc(var(--t-align) * 0.6);
}

/* ---- Readout: patches per side for the current candidate --------------- */

.reveal .grid-alignment .ro-cand :is(.row, .label, .size) {
  opacity: 0;
}

.reveal .grid-alignment .ro-cand.visible :is(.row, .label, .size) {
  opacity: 1;
  transition: opacity 300ms var(--ease) calc(var(--i, 0) * 80ms), fill 400ms ease var(--t-align);
}

/* Rows that tile fade to green once the outline has settled... */
.reveal .grid-alignment .ro-cand.visible .ok {
  fill: var(--ga-ok);
}

/* ...rows that don't pulse red twice, then stay red */
.reveal .grid-alignment .ro-cand.visible .bad {
  fill: var(--ga-bad);
  animation: ga-bad 1100ms ease var(--t-align) backwards;
}

@keyframes ga-bad {
  0%, 36%, 72% { fill: var(--ga-ink); }
  18%, 54%, 100% { fill: var(--ga-bad); }
}

/* ---- Verdicts: drawn once the outline has settled ---------------------- */

.reveal .grid-alignment .verdict.visible {
  opacity: 1;
  transition: opacity 0s linear var(--t-align);
}

.reveal .grid-alignment .verdict.ok { stroke: var(--ga-ok); }
.reveal .grid-alignment .verdict.bad { stroke: var(--ga-bad); }

/* A gap longer than the stroke keeps the round caps from showing early */
.reveal .grid-alignment .verdict :is(line, path) {
  stroke-dasharray: 1 2;
  stroke-dashoffset: 1;
}

.reveal .grid-alignment .verdict.visible :is(line, path) {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 400ms var(--ease) calc(var(--t-align) + var(--i, 0) * 200ms);
}

/* ---- Reduced motion and print: every state applies at once -------------- */

@media (prefers-reduced-motion: reduce) {
  .reveal .grid-alignment,
  .reveal .grid-alignment * {
    transition: none !important;
    animation: none !important;
  }
}

@media print {
  .reveal .grid-alignment,
  .reveal .grid-alignment * {
    transition: none !important;
    animation: none !important;
  }
}
