/* Shared sheet-window sprite animation. Three consumers share it: the Puffling/Seeker
   edit-page live preview (static/css/mini_sprite_preview.css supplies only that widget's
   chrome), the detail-page sprite showcase (templates/pets/_sprite_showcase.html), and
   the profile pagedoll. Keep the classes above the layout divider generic — a small set
   of rules plus custom properties, no assumptions specific to any one of those three call
   sites.
   `static/css/house.css` deliberately does NOT use this file: its sheet window is
   entangled with room/tile scaling and has different concerns.

   A sprite is one row of `--frames` equal-width columns (frames == 1 renders the whole
   picture as-is — a still image, or an animated GIF/WEBP, since background-size 100%
   leaves nothing to window). `--cell-aspect` is the stored *_cell_aspect decimal (one
   cell's width/height), applied via `aspect-ratio` so non-square cells render
   undistorted.

   `steps(var(--frames), jump-none)` below takes the custom property directly — a `var()`
   inside `steps()` is ordinary CSS, resolved like any other computed value, so the frame
   count never needs to be duplicated as a literal anywhere per-element. `jump-none` (not
   the default `jump-end`) matters: with background-size at N times the element's own
   width, the N column boundaries sit at background-position-x = 0%, 1/(N-1), 2/(N-1) ...
   100% (percentage background-position resolves against (container size - image size),
   which is negative here, so it's k/(N-1) of the range, not k/N). Plain `steps(N)`
   defaults to `jump-end`, which samples the 0%->100% ramp at k/N and never lands exactly
   on a boundary — every frame but the last shows two columns blended together. `jump-none`
   instead holds N values sampled at k/(N-1), landing precisely on every column.

   `jump-none` is only valid at N >= 2, though — at N == 1 there is nothing to step
   through and the browser treats the whole `steps()` as invalid, silently falling back to
   `ease` (a value nobody asked for, animating a background-position-x that never changes
   anyway). Rather than lean on that, `.char-sprite--animated` below is the explicit
   "this sprite has frames to step through" modifier: whichever template/script sets
   `--frames` also adds that class only when the count is >= 2, so a frames-1 sprite (the
   base `.char-sprite` alone) carries no `animation-name`/`animation-timing-function` at
   all — no animation declaration to accidentally invalidate. */

.char-sprite {
  display: block;
  background-repeat: no-repeat;
  background-position-y: 0;
  /* One row: N columns wide, one row tall. */
  background-size: calc(100% * var(--frames, 1)) 100%;
  aspect-ratio: var(--cell-aspect, 1);
  image-rendering: pixelated;
}

/* Added by the template/script only when frames >= 2 — see file header. */
.char-sprite--animated {
  animation-name: char-sprite-frames;
  animation-iteration-count: infinite;
  animation-timing-function: steps(var(--frames), jump-none);
}

/* Fixed loop length regardless of frame count, matching the edit-page preview. Inert
   without `.char-sprite--animated` (no `animation-name` to apply a duration to), which is
   fine — these are applied unconditionally alongside it for whichever sprite this is. */
.char-sprite--idle {
  animation-duration: 1.6s;
}

.char-sprite--walk {
  animation-duration: 0.7s;
}

@keyframes char-sprite-frames {
  from {
    background-position-x: 0%;
  }
  to {
    background-position-x: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .char-sprite {
    animation: none;
    background-position-x: 0%;
  }
}

/* ---------------------------------------------------------------------------------
   Detail-page Sprites section (templates/pets/_sprite_showcase.html) — layout only.
   Specific to that one consumer (not shared with the edit-page preview or the profile
   pagedoll, which each have their own surrounding layout), kept in this file only
   because it is the one stylesheet the showcase partial links. The animation itself
   still comes entirely from `.char-sprite` above.

   `.sprite-showcase` is a `<details class="detail-section sprite-showcase">` — the
   `.detail-section` base rule (static/css/site.css) supplies the top border/spacing
   shared with every other collapsible/section block on the detail pages; the
   `summary` styling below (disclosure triangle via `::before`, native marker hidden)
   mirrors `.modal-action-section summary` in that same file so collapsed sections read
   the same across the app. It holds up to two `.sprite-showcase-section` blocks
   (pagedoll, then house sprites) — the gap between them only matters when both are
   present, since a lone one has nothing to be spaced from. */

.sprite-showcase summary {
  cursor: pointer;
  font-weight: 700;
  font-size: 1.1rem;
  list-style: none;
}

.sprite-showcase summary::-webkit-details-marker {
  display: none;
}

.sprite-showcase summary::before {
  content: "▸ ";
  font-size: 0.85rem;
}

.sprite-showcase[open] summary::before {
  content: "▾ ";
}

.sprite-showcase-section {
  margin-top: 0.9rem;
}

.sprite-showcase-figures {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}

.sprite-showcase-figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.sprite-showcase-figure .char-sprite {
  height: 64px;
  width: auto;
  border-radius: 8px;
  border: 1px solid var(--line, #e3cda6);
  background-color: var(--card, #fdf5e6);
}

.sprite-showcase-figure figcaption {
  font-size: 0.78rem;
  color: var(--ink-soft, #a08a73);
}

.sprite-showcase-credit {
  margin: 0.5rem 0 0;
  font-size: 0.85rem;
}
