/* ============================================================================
   fx-fixes.css

   index.html has linked this file since the first wave and it did not exist,
   so every page load spent a request on a 404. It exists now, and it owns the
   two surfaces added after the original five stylesheets were frozen:

     A. #plates, the field archive contact sheet, and its lightbox
     B. .market__chart, the click to load DexScreener frame that live.js
        mounts when config.hasChart() is true

   Loaded last on purpose, so it can rely on every token from styles.css
   section 2 without redeclaring any of them. Nothing here introduces a new
   colour: the palette is still one paper, one ink, one rule hairline, one cool
   accent (witness) and one warm accent (ember).
============================================================================ */

/* ----------------------------------------------------------------------------
   A. #plates - the field archive

   A contact sheet, not a card grid. The plates were shot at different aspect
   ratios and they keep them: square cockpit plates, portrait counter plates,
   a wide broadcast plate. Forcing them all into one crop box would be the
   tidy choice and the wrong one, because a sheet of identical rectangles
   reads as a template, and the point of this section is that these are
   thirteen separate exposures of the same subject.

   Grid rather than CSS columns, decided by looking at it: columns flow
   top-to-bottom, so the first visible row read PLATE 01, PLATE 05, PLATE 09.
   That is how a physical contact strip is read and it still looked like a
   bug. Grid restores 01, 02, 03 across. The cost is ragged row bottoms,
   because align-items: start lets every plate keep its own height instead of
   stretching to its tallest neighbour. On a page of bordered plates that
   raggedness reads as evidence pinned to a board, which is the register this
   section wants anyway.
--------------------------------------------------------------------------- */

.plates__note { max-width: 58ch; }

.plates__disclosure {
  max-width: 58ch;
  margin-block-start: var(--space-4);
  padding-inline-start: var(--space-4);
  border-inline-start: 2px solid var(--moki-ember);
  font-size: var(--text-sm);
  color: var(--moki-ink);
}

.plates__sheet {
  list-style: none;
  margin: var(--space-7) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: start;
  gap: var(--space-5);
}

.plate figure {
  margin: 0;
  background-color: var(--moki-blaze);
  border: 1px solid var(--moki-rule);
  padding: var(--space-3);
  /* The lift is a transform on a compositor friendly property only, and it is
     small: this is an evidence sheet, not a carousel. */
  transition: border-color var(--duration-press, 60ms) linear,
              transform 180ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* The button is the whole plate image. Written as a block so the native
   affordances (Enter, Space, focus order, accessible name) come from the
   platform, while the visible frame stays the figure around it. */
.plate__btn {
  display: block;
  width: 100%;
  cursor: zoom-in;
}

.plate__btn img {
  display: block;
  width: 100%;
  height: auto;
}

.plate figcaption {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  align-items: baseline;
  margin-block-start: var(--space-3);
  font-size: var(--text-sm);
  line-height: 1.35;
}

.plate__no {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  color: var(--moki-rule);
  white-space: nowrap;
  transition: color var(--duration-press, 60ms) linear;
}

.plate figure:hover,
.plate:focus-within figure {
  border-color: var(--moki-ember);
  transform: translateY(-2px);
}

.plate figure:hover .plate__no,
.plate:focus-within .plate__no {
  color: var(--moki-ember);
}

@media (max-width: 1023px) {
  .plates__sheet { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 599px) {
  .plates__sheet { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .plate figure { transition: border-color var(--duration-press, 60ms) linear; }
  .plate figure:hover,
  .plate:focus-within figure { transform: none; }
}

/* ----------------------------------------------------------------------------
   A.1 the plate lightbox (built by gallery.js)

   Unlike the archive prompt dialog in app.js, this one has a CSS home, so it
   carries no inline styles. The dialog is sized to the viewport and the image
   is contained inside it: a plate is never cropped to fit the frame it was
   opened in.
--------------------------------------------------------------------------- */

.plate-lb {
  width: min(92vw, 1100px);
  max-width: none;
  max-height: 92vh;
  padding: var(--space-4);
  background-color: var(--moki-blaze);
  color: var(--moki-ink);
  border: 1px solid var(--moki-rule);
  border-radius: var(--radius-md);
}

.plate-lb::backdrop {
  background-color: rgba(16, 15, 19, 0.86);
}

.plate-lb__figure {
  margin: 0 0 var(--space-4);
}

.plate-lb__img {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: 68vh;
  margin-inline: auto;
  background-color: var(--moki-paper);
}

/* While the full plate is in flight the thumb is on screen, upscaled. Dimming
   it slightly is the honest signal that a sharper file is still coming: it is
   the same picture either way, so nothing is being hidden. */
.plate-lb__img[data-loading] { opacity: 0.75; }

.plate-lb__cap {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  align-items: baseline;
  margin-block-start: var(--space-3);
  font-size: var(--text-sm);
}

.plate-lb__stamp {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  color: var(--moki-ember);
  white-space: nowrap;
}

.plate-lb__bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  padding-block-start: var(--space-3);
  border-block-start: 1px solid var(--moki-rule);
}

.plate-lb__count {
  margin: 0;
  margin-inline-end: auto;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  color: var(--moki-rule);
}

.plate-lb__nav,
.plate-lb__close {
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  border: 1px solid var(--moki-rule);
  border-radius: var(--radius-sm);
  transition: border-color var(--duration-press, 60ms) linear,
              background-color var(--duration-press, 60ms) linear;
}

.plate-lb__nav:hover,
.plate-lb__close:hover {
  border-color: var(--moki-ember);
}

.plate-lb__close {
  background-color: var(--moki-ember);
  border-color: var(--moki-ember);
  color: var(--moki-paper);
}

.plate-lb__close:hover {
  background-color: var(--moki-ink);
  border-color: var(--moki-ink);
}

@media (max-width: 599px) {
  .plate-lb { width: 96vw; padding: var(--space-3); }
  .plate-lb__img { max-height: 56vh; }
  .plate-lb__count { order: 3; width: 100%; margin-inline-end: 0; }
}

/* ----------------------------------------------------------------------------
   B. .market__chart - the DexScreener frame

   live.js appends this to #market only when config.hasChart() is true, and
   the iframe itself is created inside the button's click handler, never
   before. The note is styled to stay legible after the frame is up, because
   which numbers are ours and which are DexScreener's is a standing question
   on this page, not a one time notice.
--------------------------------------------------------------------------- */

.market__chart {
  margin-block-start: var(--space-7);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--moki-rule);
}

.market__chart-note {
  max-width: 58ch;
  margin: 0 0 var(--space-4);
  font-size: var(--text-sm);
  color: var(--moki-ink);
}

.market__chart-btn {
  padding: var(--space-3) var(--space-5);
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  background-color: var(--moki-ember);
  color: var(--moki-paper);
  border: 1px solid var(--moki-ember);
  border-radius: var(--radius-sm);
  transition: background-color var(--duration-press, 60ms) linear,
              border-color var(--duration-press, 60ms) linear;
}

.market__chart-btn:hover:not(:disabled) {
  background-color: var(--moki-ink);
  border-color: var(--moki-ink);
}

.market__chart-btn:disabled {
  background-color: transparent;
  color: var(--moki-rule);
  cursor: default;
}

.market__chart-frame:not(:empty) {
  margin-block-start: var(--space-4);
  border: 1px solid var(--moki-rule);
  background-color: var(--moki-blaze);
}

.market__chart-iframe {
  display: block;
  width: 100%;
  /* Wide enough for the candles to be readable, tall enough on phones that the
     chart is not a letterbox slit. */
  aspect-ratio: 16 / 10;
  min-height: 380px;
  border: 0;
}

@media (max-width: 599px) {
  .market__chart-iframe { aspect-ratio: 4 / 5; min-height: 440px; }
}
