/* The gallery. Sits on top of guide.css, which carries the palette and the
   type, and only adds what a wall of sprites needs. */

.wrap.wide {
  max-width: 60rem;
}

.masthead nav {
  display: flex;
  gap: 16px;
}

/* A row of shelves that wraps. Sprites vary a lot in size, so the cells are
   fixed and the art centres inside them rather than the other way round. */
.shelf {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 14px;
  margin: 1.4em 0 2.4em;
}

.piece {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.frame {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 148px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--panel);
  /* a quiet checker, so a transparent sprite reads as transparent */
  background-image:
    linear-gradient(45deg, #00000018 25%, transparent 25%, transparent 75%, #00000018 75%),
    linear-gradient(45deg, #00000018 25%, transparent 25%, transparent 75%, #00000018 75%);
  background-size: 16px 16px;
  background-position: 0 0, 8px 8px;
  overflow: auto;
}

/* the one that shows real size against eight times it */
.frame.close {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  align-items: center;
  justify-content: center;
  min-height: 300px;
}

/* Whole pixels, always. Nothing here is ever drawn at a fraction of its size. */
.sp {
  display: block;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  background-repeat: no-repeat;
  flex: none;
}

/* A strip of frames stepped through one at a time, which is what the game does
   with the same file. */
@keyframes strip {
  to {
    background-position-x: var(--end);
  }
}

figcaption strong {
  display: block;
  color: var(--ink);
  font-size: 15px;
  line-height: 1.3;
}

.size {
  display: block;
  color: var(--muted);
  font-size: 12px;
  letter-spacing: 0.03em;
  font-variant-numeric: tabular-nums;
}

.say {
  margin: 6px 0 0;
  font-size: 14px;
  line-height: 1.5;
}

.foot {
  margin-top: 3em;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 14px;
}

@media (prefers-reduced-motion: reduce) {
  .sp.play {
    animation: none !important;
  }
}

/* A sheet is as long as it is. It gets the whole row rather than a scrollbar
   inside a cell the width of a thumbnail. */
.piece.wide {
  grid-column: 1 / -1;
}

.piece.wide .frame {
  /* Centred when there is room, hard left when there is not, which is what
     `safe` buys and the reason it is worth the two extra words. A sheet wider
     than the page has to start at its left edge or the beginning of it is
     scrolled off before anybody has touched anything. A piece that fits, and
     several of them are marked wide only because they are wider than one
     thumbnail, was being stranded against the left of a full row of empty. */
  justify-items: safe center;
  overflow-x: auto;
  /* A wide tile exists to hold wide art, so it keeps less to itself at the
     sides. The rock trail is 322 across at 2x and a 375 phone leaves 317 with
     the usual padding, which is five pixels of pointless scrolling. */
  padding-left: 6px;
  padding-right: 6px;
}

/* ---- figures on the systems page ---- */

.fig {
  margin: 1.6em 0;
  padding: 0;
}

.fig svg,
.fig img {
  display: block;
  width: 100%;
  height: auto;
  max-width: 100%;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--panel);
  padding: 10px;
  box-sizing: border-box;
}

.fig img.sp {
  image-rendering: pixelated;
}

.fig figcaption {
  margin-top: 8px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.5;
}

/* ---- the stack ---- */

.stack {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 12px;
  margin: 1.4em 0 2em;
}

.tool {
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--panel);
  padding: 14px 16px;
}

/* The one that matters most here is the one nobody lists on a stack page. */
.tool.big {
  grid-column: 1 / -1;
  border-color: var(--amber);
  background: linear-gradient(180deg, #3a3170, var(--panel));
}

.tool strong {
  display: block;
  font-family: Fraunces, Georgia, serif;
  font-size: 17px;
  color: var(--ink);
  margin-bottom: 4px;
}

.tool.big strong {
  font-size: 24px;
  color: var(--amber);
}

.tool span {
  color: var(--dim);
  font-size: 14px;
  line-height: 1.5;
}

/* Drawn and kept, but nothing in the game points at it. */
.not-yet {
  display: inline-block;
  margin-top: 5px;
  padding: 1px 7px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.03em;
}

/* A strip too long to show in one row.
   The ultimate bar is nine frames of 96, which is 864 pixels in a line:
   wider than the page and wider than any phone, so the end of it was simply cut
   off and the interesting half was the hidden half. Laid out as its own frames
   it wraps, every state is on screen, and each one is still at a whole multiple
   of the size it was drawn. */
.strip-frames {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  max-width: 100%;
}

/* The bar fills its frame edge to edge, so states in a row with a small gap
   read as one long smeared bar rather than as separate states. Each one gets
   its own quiet box to sit in. */
.strip-frames i {
  /* outline, not border: box-sizing is border-box here, and a 1px border would
     take two pixels out of a 96px tile and stop the sprite being at a whole
     multiple of the size it was drawn, which is the one rule this page has. */
  outline: 1px solid var(--line);
  background-color: #00000022;
}

/* Up close shows one drawing twice, at 1x and at 8x. Starry is 32 square, so
   his 8x is 256 and a normal tile is 200: he was scrolled out of his own frame.
   These get a row each, and the pair wraps rather than clipping on a phone. */
.shelf.close-up {
  grid-template-columns: 1fr;
}


/* ---- the marks ---- */
/*
 * A watermark, and it is worth being straight about what one can and cannot do.
 *
 * Nothing on a web page can stop a screenshot. The art on this page is the same
 * art the game loads, so a person who wants the file can open the network tab
 * and have it, and no overlay, right click blocker or canvas trick changes that
 * by one pixel. Anybody who tells you otherwise is selling something.
 *
 * What a mark drawn over the top does do is survive the screenshot, which is
 * the way art actually gets taken: somebody screenshots a page and posts it as
 * their own. This one rides on every frame, so the grab carries the address it
 * came from and a lie has to be told on purpose rather than by saying nothing.
 * It is deliberately faint. The page exists to be looked at.
 */
.frame::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 12px;
  pointer-events: none;
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='132' height='88'><text x='2' y='62' transform='rotate(-22 2 62)' font-family='Nunito, Helvetica, sans-serif' font-size='8.5' font-weight='700' letter-spacing='0.2' fill='%23f3ecd8' fill-opacity='0.16'>twohousesonehome.com</text></svg>"),
    repeating-linear-gradient(-22deg, rgba(243, 236, 216, 0.05) 0 1px, transparent 1px 10px);
  background-repeat: repeat, repeat;
}

/* The other half of it, and the half that actually catches people: long press
   to save on a phone, and drag to the desktop on a laptop. Both are one line. */
.sp {
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
  user-select: none;
}

.mine {
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--line);
  border-radius: 10px;
  font-size: 0.95rem;
  opacity: 0.86;
}

@media (prefers-reduced-motion: no-preference) {
  /* nothing here moves; the marks are static on purpose */
}

/* The fire bar, the way Two Little Fires plays it (src/games/fires/FireBar.tsx).
   The bar keeps no time: it shows one of seven states for however much fire
   there is. At full, the nine frame flare plays once at 90ms a frame and holds
   on its last frame, purple, until the fire is spent. Here the fire comes in at
   half a second a state, the flare plays at the game's own speed, holds, and it
   starts again from cold. Two layers, because the plain bar and the flare are
   two files, and step-end so nothing is ever between two frames. Still, it
   shows the full bar. */
.bar-play {
  position: relative;
  display: block;
  width: 192px;
  height: 64px;
}

.bar-play .sp {
  position: absolute;
  inset: 0;
  width: 192px;
  height: 64px;
}

.bar-states {
  background-image: url("/art/fires/bar.png");
  background-size: 1344px 64px;
  background-position: -1152px 0;
  animation: bar-states 6000ms step-end infinite;
}

.bar-flare {
  background-image: url("/art/fires/bar_ultimate.png");
  background-size: 1728px 64px;
  background-position: 0 0;
  opacity: 0;
  animation: bar-flare 6000ms step-end infinite;
}

@keyframes bar-states {
  0% { background-position: 0 0; opacity: 1; }
  8.333% { background-position: -192px 0; }
  16.67% { background-position: -384px 0; }
  25% { background-position: -576px 0; }
  33.33% { background-position: -768px 0; }
  41.67% { background-position: -960px 0; }
  50% { background-position: -1152px 0; }
  58.33% { opacity: 0; }
  100% { background-position: -1152px 0; opacity: 0; }
}

@keyframes bar-flare {
  0% { background-position: 0 0; opacity: 0; }
  58.33% { background-position: 0 0; opacity: 1; }
  59.83% { background-position: -192px 0; }
  61.33% { background-position: -384px 0; }
  62.83% { background-position: -576px 0; }
  64.33% { background-position: -768px 0; }
  65.83% { background-position: -960px 0; }
  67.33% { background-position: -1152px 0; }
  68.83% { background-position: -1344px 0; }
  70.33% { background-position: -1536px 0; }
  100% { background-position: -1536px 0; opacity: 1; }
}

/* ---- The window at the top ----
   A small island of the world, built only out of the drawings further down.
   public/art-scene.js lays it out for the width it is given and walks it. The
   height is set here too, so nothing below jumps when the script arrives. */
.diorama-frame {
  margin: 8px 0 0;
  container-type: inline-size;
}
.diorama {
  position: relative;
  height: 276px;
  overflow: hidden;
}
@container (min-width: 700px) {
  .diorama { height: 414px; }
}
.diorama-world {
  position: absolute;
  top: 0;
}
.diorama canvas {
  display: block;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}
.diorama .actor {
  position: absolute;
}
.diorama button.actor {
  padding: 0;
  border: 0;
  background-color: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.diorama button.actor:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 2px;
  border-radius: 8px;
}
.diorama-note {
  margin: 2px 0 0;
  text-align: center;
  color: var(--muted);
  font-size: 14px;
}
@keyframes diorama-rise {
  0% { opacity: 0; translate: 0 6px; }
  20%, 75% { opacity: 1; }
  100% { opacity: 0; translate: 0 -18px; }
}
