/*
 * Calhou.me! home page (UI v2): hero stage, "Como funciona" level map, FAQ accordion,
 * share button. Loaded only by src/views/home.tsx, after
 * app.css and motion.css. Behaviour lives in public/js/home-anim.js; everything
 * moves only under prefers-reduced-motion: no-preference.
 */

/* ---------- Hero stage ---------- */

.home-hero {
  --stage-bleed: 20px;
  overflow: hidden;
}

.stage-scene {
  --stage-h: 208px;
  /*
   * One united row: n characters, each in its own slot with a small even gap, sized to
   * fit between the two half-hidden trees. Never overlapping: on small stages the
   * sprites get smaller (in 8px steps where round() exists, so 16px pixel art stays crisp).
   */
  --n: 8;
  --tree: clamp(44px, 11cqw, 72px);
  --gap: clamp(4px, 1.4cqw, 10px);
  --fit: calc((100cqw - var(--tree) - 8px - (var(--n) - 1) * var(--gap)) / var(--n));
  --front: clamp(24px, var(--fit), 64px);
  position: relative;
  container-type: inline-size;
  cursor: pointer;
  height: var(--stage-h);
  margin: 24px calc(-1 * var(--stage-bleed)) 0;
  overflow: hidden;
  contain: layout paint;
  background: linear-gradient(
    to bottom,
    #0b1026 0 18%,
    #10173a 18% 38%,
    #18214a 38% 56%,
    #212c5c 56% 72%,
    #2b386c 72% 100%
  );
  box-shadow:
    inset 0 4px 0 0 var(--deep),
    inset 0 -4px 0 0 var(--deep);
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.stage-snow {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 4;
  pointer-events: none;
  image-rendering: pixelated;
}

/* Pixel stars: one 2px dot repeated with box-shadow. */
.stage-stars {
  position: absolute;
  top: 0;
  left: 0;
  width: 2px;
  height: 2px;
  background: transparent;
  box-shadow:
    18px 14px 0 #fff, 54px 38px 0 #c9d1dc, 96px 12px 0 #fff, 132px 46px 0 #f7d046,
    176px 22px 0 #fff, 214px 58px 0 #c9d1dc, 252px 16px 0 #fff, 300px 40px 0 #f7d046,
    346px 20px 0 #fff, 392px 52px 0 #c9d1dc, 438px 12px 0 #fff, 486px 36px 0 #fff,
    530px 60px 0 #f7d046, 572px 18px 0 #c9d1dc, 618px 44px 0 #fff, 664px 14px 0 #fff,
    706px 50px 0 #c9d1dc, 750px 26px 0 #fff, 76px 70px 0 #c9d1dc, 268px 78px 0 #fff,
    452px 84px 0 #c9d1dc, 640px 76px 0 #fff;
}

.stage-moon {
  position: absolute;
  top: 64px;
  right: 10%;
  z-index: 1;
  filter: drop-shadow(0 0 6px rgba(255, 243, 176, 0.45));
}

/* Back hill and the snowy ground: hard-edged pixel steps. */
.stage-hill {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 30px;
  height: 52px;
  z-index: 1;
  background: #3a4a80;
  clip-path: polygon(
    0 40%, 8% 40%, 8% 28%, 18% 28%, 18% 16%, 30% 16%, 30% 30%, 42% 30%, 42% 20%, 56% 20%,
    56% 8%, 68% 8%, 68% 24%, 80% 24%, 80% 14%, 92% 14%, 92% 32%, 100% 32%, 100% 100%, 0 100%
  );
}

.stage-ground {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 44px;
  z-index: 2;
  background:
    linear-gradient(to bottom, #ffffff 0 6px, #dfe8f5 6px 14px, #c9d6ea 14px 100%);
  box-shadow: 0 -4px 0 0 #9fb2d4;
}

.stage-tree {
  position: absolute;
  bottom: 30px;
  z-index: 2;
}

.stage-tree svg {
  width: var(--tree);
  height: auto;
}

@supports (width: round(down, 10px, 8px)) {
  .stage-scene {
    --front: clamp(24px, round(down, var(--fit), 8px), 64px);
  }
}

/* Trees frame the group from the edges, half of each one off stage. */
.stage-tree-l {
  left: calc(var(--tree) * -0.5);
}

.stage-tree-r {
  right: calc(var(--tree) * -0.5);
}

/* ---------- Actors: one row, one group ---------- */

.stage-cast {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 12px;
  z-index: 5;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: var(--gap);
  pointer-events: none;
}

.actor {
  --lean: 0px;
  --face: 1;
  position: relative;
  flex: none;
  transform: translateX(var(--lean));
  transition: transform 380ms var(--ease-out);
  cursor: inherit;
  pointer-events: auto;
}

.actor-sprite {
  display: block;
  transform-origin: 50% 100%;
}

.actor-sprite svg {
  display: block;
  width: var(--front);
  height: var(--front);
  transform: scaleX(var(--face));
  transition: transform 0s;
}

/* Narrow phones: 6 of the 8 server-rendered characters, same row, no layout shift. */
@media (max-width: 380px) {
  .stage-scene {
    --n: 6;
  }

  .actor:nth-child(n + 7) {
    display: none;
  }
}

/* Touch: the pixel gift pops where the stage was tapped (positioned by home-anim.js). */
.stage-gift {
  position: absolute;
  z-index: 9;
  width: 48px;
  height: 48px;
  margin: -24px 0 0 -24px;
  pointer-events: none;
  line-height: 0;
}

.stage-gift[hidden] {
  display: none;
}

/*
 * Catch the gift (home-anim.js): each catch clones this static gift at the catch point
 * (centred on it, like .stage-gift), the lid pops off and confetti bursts from it. The
 * pointer keeps its gift, so it can be handed to the next character straight away.
 */

.stage-open {
  position: absolute;
  z-index: 9;
  width: 48px;
  height: 48px;
  margin: -24px 0 0 -24px;
  pointer-events: none;
  line-height: 0;
}

.stage-open[hidden] {
  display: none;
}

.open-lid,
.open-box {
  display: block;
  width: 48px;
  height: 24px;
}

.open-lid svg,
.open-box svg {
  display: block;
}

.open-lid {
  transform-origin: 50% 100%;
}

.open-box {
  transform-origin: 50% 100%;
}

.stage-confetti {
  position: absolute;
  inset: 0;
  z-index: 10;
  width: 100%;
  height: 100%;
  pointer-events: none;
  image-rendering: pixelated;
}

.stage-confetti[hidden] {
  display: none;
}

/* ---------- Shuffle button (JS only) ---------- */



.actor-shadow {
  position: absolute;
  left: 26%;
  right: 26%;
  bottom: -2px;
  height: 4px;
  background: rgba(58, 74, 128, 0.35);
  border-radius: 1px;
}

/* Speech bubble (one per stage, positioned by home-anim.js). */
.stage-bubble {
  position: absolute;
  z-index: 8;
  max-width: calc(100% - 16px);
  padding: 7px 10px;
  background: #ffffff;
  color: var(--deep);
  font-family: var(--body-font);
  font-size: 0.9375rem;
  font-weight: 800;
  line-height: 1.25;
  white-space: nowrap;
  pointer-events: none;
  box-shadow:
    3px 0 0 0 var(--deep),
    -3px 0 0 0 var(--deep),
    0 3px 0 0 var(--deep),
    0 -3px 0 0 var(--deep),
    3px 6px 0 0 rgba(14, 19, 40, 0.35);
  transform-origin: var(--tail, 50%) 100%;
}

.stage-bubble[hidden] {
  display: none;
}

.stage-bubble::after {
  content: "";
  position: absolute;
  left: var(--tail, 50%);
  bottom: -9px;
  width: 6px;
  height: 6px;
  margin-left: -3px;
  background: #ffffff;
  box-shadow:
    3px 0 0 0 var(--deep),
    -3px 0 0 0 var(--deep),
    0 3px 0 0 var(--deep),
    0 6px 0 -0px transparent;
}

/* "Press start" style hint, only with JS (the stage reacts to taps/hover). Always visible;
   it blinks until the first interaction. */
.stage-hint {
  display: none;
  position: absolute;
  left: 10px;
  top: 10px;
  z-index: 6;
  padding: 4px 8px;
  font-family: var(--pixel-font);
  font-size: 0.5625rem;
  line-height: 1.6;
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--accent);
  background: rgba(14, 19, 40, 0.7);
  transition: opacity var(--dur) ease-out;
}

.js .stage-hint {
  display: block;
}

.hint-mouse {
  display: none;
}

@media (hover: hover) and (pointer: fine) {
  .hint-touch {
    display: none;
  }
  .hint-mouse {
    display: inline;
  }
}

/* ---------- Hero actions ---------- */

.home-hero .actions {
  gap: 16px;
}

/* ---------- Section titles ---------- */

/* The section headings use the shared .pixel-h2 (public/css/app.css). */

/* ---------- Como funciona: level map ---------- */

/* Every section with a pixel heading has the same room above it as the footer's ("Aqueles links do
   footer"): 80px from the content above (the margins collapse). */
.level-map {
  margin: 80px 0 12px;
}

.lvl-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  justify-items: stretch;
}

.lvl {
  position: relative;
  display: grid;
  grid-template-columns: 76px 1fr;
  align-items: center;
  gap: 14px;
  padding: 14px 16px 14px 14px;
  margin: 4px;
  background: var(--stage);
  box-shadow:
    4px 0 0 0 var(--edge),
    -4px 0 0 0 var(--edge),
    0 4px 0 0 var(--edge),
    0 -4px 0 0 var(--edge),
    0 8px 0 0 var(--deep),
    4px 4px 0 0 var(--deep);
}

.lvl-tile {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 76px;
  height: 76px;
  background:
    repeating-linear-gradient(90deg, transparent 0 8px, rgba(255, 255, 255, 0.035) 8px 16px),
    repeating-linear-gradient(0deg, transparent 0 8px, rgba(255, 255, 255, 0.035) 8px 16px),
    var(--deep);
  box-shadow: inset 0 -6px 0 0 rgba(0, 0, 0, 0.35);
}

.lvl-icon {
  position: relative;
  display: inline-flex;
  line-height: 0;
}

.lvl-icon .icon {
  image-rendering: pixelated;
}

.lvl-sparkle {
  position: absolute;
  top: -10px;
  right: -12px;
}

.lvl-badge {
  position: absolute;
  top: -6px;
  left: -6px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: var(--accent);
  color: var(--stage);
  font-family: var(--pixel-font);
  font-size: 0.75rem;
  box-shadow: 0 3px 0 0 var(--accent-dark), 0 6px 0 0 var(--deep);
}

.lvl-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.lvl-kicker {
  font-family: var(--pixel-font);
  font-size: 0.625rem;
  line-height: 1.5;
  letter-spacing: 1px;
  color: var(--accent);
}

.lvl-text {
  font-size: 1.0625rem;
  line-height: 1.45;
}

/* Each box is a link to /criar: the text is the link, its ::after covers the whole box. */
.lvl-link {
  color: var(--text);
  text-decoration: none;
}

.lvl-link::after {
  content: "";
  position: absolute;
  inset: -4px;
  z-index: 2;
}

.lvl {
  cursor: pointer;
  transition: transform var(--dur-fast) steps(2, end), box-shadow var(--dur-fast) steps(2, end);
}

.lvl:hover,
.lvl:focus-within {
  box-shadow:
    4px 0 0 0 var(--accent),
    -4px 0 0 0 var(--accent),
    0 4px 0 0 var(--accent),
    0 -4px 0 0 var(--accent),
    0 8px 0 0 var(--deep),
    4px 4px 0 0 var(--deep);
}

.lvl:hover {
  transform: translateY(-2px);
}

.lvl:active {
  transform: translateY(2px);
}

.lvl-link:focus {
  outline: none;
}

.lvl-link:focus-visible::after {
  outline: 3px solid var(--accent);
  outline-offset: 4px;
}

/* Connector: a dotted pixel path ending in an arrow. */
.lvl-arrow {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: 64px;
  color: var(--accent);
}

.lvl-dots {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.lvl-dots span {
  display: block;
  width: 6px;
  height: 6px;
  background: var(--edge);
}

.arrow-h {
  display: none;
}

@media (min-width: 40rem) {
  .lvl-list {
    grid-template-columns: 1fr 64px 1fr 64px 1fr;
    align-items: stretch;
  }

  .lvl {
    grid-template-columns: 1fr;
    justify-items: center;
    align-content: start;
    text-align: center;
    padding: 18px 14px 20px;
  }

  .lvl-body {
    align-items: center;
  }

  .lvl-arrow {
    flex-direction: row;
    height: auto;
    padding-bottom: 40px;
  }

  .lvl-dots {
    flex-direction: row;
  }

  .arrow-h {
    display: inline-block;
  }

  .arrow-v {
    display: none;
  }

  .stage-scene {
    --stage-h: 248px;
    --stage-bleed: 36px;
  }

  .home-hero {
    --stage-bleed: 36px;
  }

  .stage-moon {
    top: 70px;
    right: 12%;
  }
}

/* ---------- FAQ: pixel accordion rows ---------- */

.home-faq {
  margin-top: 80px;
}

/* "Sharing is caring": the shared "Passa o Calhou.me" card under its own section heading. */
.home-share {
  margin-top: 80px;
}

.faq-row {
  margin: 0 4px 14px;
  border: 0;
  border-radius: 0;
  box-shadow:
    3px 0 0 0 var(--edge),
    -3px 0 0 0 var(--edge),
    0 3px 0 0 var(--edge),
    0 -3px 0 0 var(--edge),
    0 7px 0 0 var(--deep);
  transition: box-shadow var(--dur-fast) linear;
}

.faq-row[open],
.faq-row:hover {
  box-shadow:
    3px 0 0 0 var(--accent),
    -3px 0 0 0 var(--accent),
    0 3px 0 0 var(--accent),
    0 -3px 0 0 var(--accent),
    0 7px 0 0 var(--deep);
}

.faq-row > summary {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 10px 10px 10px 16px;
}

.faq-row > summary::after {
  content: none;
  display: none;
}

.faq-row > summary:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 4px;
}

.faq-q {
  flex: 1;
  min-width: 0;
}

.faq-chev {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  color: var(--accent);
  background: var(--deep);
  box-shadow: inset 0 -3px 0 0 rgba(0, 0, 0, 0.4);
  transition: transform var(--dur) var(--ease-back);
}

.faq-row[open] > summary .faq-chev {
  transform: rotate(180deg);
}

.faq-row[open] > summary {
  color: var(--accent);
}

.faq-row > p {
  padding: 2px 16px 18px;
  font-size: 1rem;
}

/* ---------- Motion ---------- */

@keyframes actor-out {
  0% { opacity: 1; transform: translateY(0) scale(1, 1); }
  25% { opacity: 1; transform: translateY(0) scale(1.12, 0.86); }
  55% { opacity: 1; transform: translateY(-28px) scale(0.92, 1.08); }
  100% { opacity: 0; transform: translateY(-56px) scale(0.6, 0.6); }
}

@keyframes actor-leave {
  /* Got the gift: a tiny happy squash, then sinks into the snow. */
  0% { transform: translateY(0) scale(1, 1); }
  20% { transform: translateY(-6px) scale(1.06, 0.94); }
  100% { transform: translateY(105%) scale(1, 1); }
}

@keyframes actor-rise {
  /* The newcomer pops up out of the snow and settles. */
  0% { transform: translateY(105%) scale(1, 1); }
  70% { transform: translateY(-8px) scale(0.96, 1.06); }
  85% { transform: translateY(0) scale(1.06, 0.94); }
  100% { transform: translateY(0) scale(1, 1); }
}


@keyframes actor-in {
  0% { opacity: 0; transform: translateY(-90px) scale(0.9, 1.1); }
  20% { opacity: 1; }
  60% { opacity: 1; transform: translateY(0) scale(1.16, 0.84); }
  80% { transform: translateY(-10px) scale(0.96, 1.04); }
  100% { opacity: 1; transform: translateY(0) scale(1, 1); }
}

@keyframes stage-twinkle {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

@keyframes actor-idle {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-4px); }
}

/* --hop is the jump height: a small excited hop or a big reach for the gift. */
@keyframes actor-hop {
  0% { transform: translateY(0) scale(1, 1); }
  12% { transform: translateY(0) scale(1.14, 0.84); }
  30% { transform: translateY(calc(var(--hop, 32px) * -0.8)) scale(0.9, 1.14); }
  50% { transform: translateY(calc(var(--hop, 32px) * -1)) scale(0.94, 1.08); }
  72% { transform: translateY(calc(var(--hop, 32px) * -0.3)) scale(0.96, 1.04); }
  86% { transform: translateY(0) scale(1.1, 0.9); }
  100% { transform: translateY(0) scale(1, 1); }
}

/* Reaching the gift: deep anticipation squash, a tall stretch up to --hop, a short hold
   touching the gift, then the fall and a squashy landing. */
@keyframes actor-catch {
  0% { transform: translateY(0) scale(1, 1); animation-timing-function: ease-out; }
  16% { transform: translateY(0) scale(1.22, 0.76); animation-timing-function: cubic-bezier(0.2, 0.8, 0.4, 1); }
  40% { transform: translateY(calc(var(--hop, 64px) * -1)) scale(0.86, 1.18); animation-timing-function: ease-out; }
  56% { transform: translateY(calc(var(--hop, 64px) * -1 + 3px)) scale(0.96, 1.04); animation-timing-function: cubic-bezier(0.5, 0, 0.9, 0.6); }
  80% { transform: translateY(0) scale(1.18, 0.82); animation-timing-function: ease-out; }
  90% { transform: translateY(-3px) scale(0.96, 1.04); }
  100% { transform: translateY(0) scale(1, 1); }
}

/* The lid flies up and away (to the side of --dir), tumbling in pixel steps. */
@keyframes lid-pop {
  0% { transform: translate(0, 0) rotate(0deg); opacity: 1; }
  20% { transform: translate(calc(var(--dir, 1) * 6px), -26px) rotate(calc(var(--dir, 1) * 18deg)); }
  45% { transform: translate(calc(var(--dir, 1) * 16px), -44px) rotate(calc(var(--dir, 1) * 50deg)); opacity: 1; }
  70% { transform: translate(calc(var(--dir, 1) * 26px), -38px) rotate(calc(var(--dir, 1) * 95deg)); opacity: 1; }
  100% { transform: translate(calc(var(--dir, 1) * 36px), -6px) rotate(calc(var(--dir, 1) * 150deg)); opacity: 0; }
}

@keyframes box-pop {
  0% { transform: scale(1, 1); opacity: 1; }
  12% { transform: scale(1.18, 0.78); }
  30% { transform: scale(0.92, 1.12); }
  48% { transform: scale(1, 1); }
  80% { transform: scale(1, 1); opacity: 1; }
  100% { transform: scale(0.9, 0.9) translateY(4px); opacity: 0; }
}

@keyframes gift-pop {
  0% { opacity: 0; transform: translateY(8px) scale(0.3); }
  25% { opacity: 1; transform: translateY(-4px) scale(1.2); }
  45% { transform: translateY(0) scale(1); }
  80% { opacity: 1; transform: translateY(-2px) scale(1); }
  100% { opacity: 0; transform: translateY(-14px) scale(0.8); }
}

@keyframes shadow-hop {
  0%, 100% { transform: scaleX(1); opacity: 1; }
  50% { transform: scaleX(0.5); opacity: 0.5; }
}

@keyframes bubble-in {
  0% { opacity: 0; transform: translateY(6px) scale(0.4); }
  60% { opacity: 1; transform: translateY(-2px) scale(1.08); }
  100% { opacity: 1; transform: none; }
}

@keyframes hint-blink {
  0%, 60% { opacity: 1; }
  61%, 100% { opacity: 0.25; }
}

@keyframes lvl-in {
  0% { opacity: 0; transform: translateY(18px) scale(0.92); }
  60% { opacity: 1; transform: translateY(-4px) scale(1.02); }
  100% { opacity: 1; transform: none; }
}

@keyframes lvl-arrow-in {
  from { opacity: 0; clip-path: inset(0 100% 0 0); }
  to { opacity: 1; clip-path: inset(0 0 0 0); }
}

@keyframes lvl-arrow-in-v {
  from { opacity: 0; clip-path: inset(0 0 100% 0); }
  to { opacity: 1; clip-path: inset(0 0 0 0); }
}

@keyframes nudge-x {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(4px); }
}

@keyframes nudge-y {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(4px); }
}

@keyframes dot-march {
  0%, 100% { background: var(--edge); }
  33% { background: var(--accent); }
}

@keyframes pencil-write {
  0%, 100% { transform: translate(0, 0) rotate(0); }
  25% { transform: translate(3px, -2px) rotate(-6deg); }
  50% { transform: translate(-2px, 1px) rotate(4deg); }
  75% { transform: translate(2px, 1px) rotate(-3deg); }
}

@media (prefers-reduced-motion: no-preference) {
  .stage-stars {
    animation: stage-twinkle 2.4s steps(2, jump-none) infinite;
  }

  .actor-body {
    display: block;
    animation: actor-idle var(--bt, 1.2s) steps(2, jump-none) infinite;
    animation-delay: var(--bd, 0s);
  }

  .stage-gift.is-on {
    animation: gift-pop 740ms steps(8, end) both;
  }

  .actor.is-hop .actor-sprite {
    animation: actor-hop 620ms cubic-bezier(0.3, 0.7, 0.4, 1) both;
  }

  .actor.is-catch .actor-sprite {
    animation: actor-catch var(--catch-ms, 900ms) linear both;
  }

  .actor.is-catch .actor-shadow {
    animation: shadow-hop var(--catch-ms, 900ms) ease-in-out both;
  }

  .stage-open.is-open .open-lid {
    animation: lid-pop 720ms steps(9, end) both;
  }

  .stage-open.is-open .open-box {
    animation: box-pop 1100ms steps(11, end) both;
  }

  .actor.is-hop .actor-shadow {
    animation: shadow-hop 620ms ease-in-out both;
  }

  .actor.is-out {
    animation: actor-out 340ms steps(6, end) both;
    animation-delay: calc(var(--k, 0) * 45ms);
  }

  /* Swap after a catch: clip at the feet so it looks like going into / coming out of the ground. */
  .actor.is-leave,
  .actor.is-rise {
    clip-path: inset(-300px -60px 0 -60px);
  }

  .actor.is-leave .actor-sprite {
    animation: actor-leave 460ms steps(8, end) both;
  }

  .actor.is-rise .actor-sprite {
    animation: actor-rise 520ms steps(9, end) both;
  }

  .actor.is-in {
    animation: actor-in 460ms steps(8, end) both;
    animation-delay: calc(var(--k, 0) * 55ms);
  }

  .stage-bubble.is-on {
    animation: bubble-in 260ms var(--ease-out) both;
  }

  .stage-hint {
    animation: hint-blink 1.4s steps(1, end) infinite;
  }

  .stage-scene.played .stage-hint {
    animation: none;
  }

  /* Level map: armed by home-anim.js (so no-JS always shows the content). */
  .level-map.is-armed:not(.is-in) .lvl,
  .level-map.is-armed:not(.is-in) .lvl-arrow {
    opacity: 0;
  }

  /* backwards, not both: once in, the boxes are plain CSS again (so :hover can lift them). */
  .level-map.is-in .lvl {
    animation: lvl-in 520ms var(--ease-out) backwards;
    animation-delay: calc(var(--n) * 170ms);
  }

  .level-map.is-in .lvl-arrow {
    animation: lvl-arrow-in-v 360ms steps(4, end) both;
    animation-delay: calc(var(--n) * 170ms + 80ms);
  }

  .level-map.is-in .lvl-dots span {
    animation: dot-march 1.2s steps(1, end) infinite;
    animation-delay: calc(var(--n) * 170ms + 500ms);
  }

  .level-map.is-in .lvl-dots span:nth-child(2) {
    animation-delay: calc(var(--n) * 170ms + 900ms);
  }

  .level-map.is-in .lvl-dots span:nth-child(3) {
    animation-delay: calc(var(--n) * 170ms + 1300ms);
  }

  .level-map.is-in .arrow-v {
    animation: nudge-y 900ms steps(2, jump-none) infinite;
    animation-delay: calc(var(--n) * 170ms + 500ms);
  }

  .level-map.is-in .arrow-h {
    animation: nudge-x 900ms steps(2, jump-none) infinite;
    animation-delay: calc(var(--n) * 170ms + 500ms);
  }

  .level-map.is-in .lvl-1 .icon-pencil {
    animation: pencil-write 1.6s steps(4, end) 700ms 2;
  }

  .level-map.is-in .lvl-2 .icon-dice {
    animation: dice-roll 700ms steps(8, end) 600ms both;
  }

  .level-map.is-in .lvl-3 .icon-envelope {
    animation: calhou-bob 1.6s steps(4, end) 1s infinite;
  }

  .lvl-sparkle {
    animation: stage-twinkle 1.2s steps(2, jump-none) infinite;
  }

  .lvl:hover .lvl-icon {
    animation: calhou-bob 600ms steps(2, end) infinite;
  }

  @media (min-width: 40rem) {
    .level-map.is-in .lvl-arrow {
      animation-name: lvl-arrow-in;
    }
  }
}

@keyframes dice-roll {
  0% { transform: rotate(0) scale(0.6); }
  25% { transform: rotate(90deg) scale(1.1); }
  50% { transform: rotate(180deg) scale(0.9); }
  75% { transform: rotate(270deg) scale(1.05); }
  100% { transform: rotate(360deg) scale(1); }
}
