/* fx.css: minimal styles for js/fx.js (overlays, masks, depth containers).
   Colours, sizes and positions come from the page; nothing here sets a palette. */

.fx-cv {
  position: absolute;
  display: block;
  pointer-events: none;
}

/* --- type-grid ---------------------------------------------------------------
   Text-only wrappers carry the mask, so arrows and Raupen inside a headline stay whole.
   The mask hole follows --fx-x / --fx-y (host coordinates) with radius --fx-r;
   --ox / --oy are each wrapper's own offset inside the host (set by JS). */
.fx-tg__t {
  padding: 0 0.14em;
  margin: 0 -0.14em;
}
.fx-tg__cv {
  left: 0;
  top: 0;
  z-index: 2;
}
.fx-tg.is-fx-on .fx-tg__t {
  -webkit-mask-image: radial-gradient(circle at calc(var(--fx-x, 0px) - var(--ox, 0px)) calc(var(--fx-y, 0px) - var(--oy, 0px)), transparent calc(var(--fx-r, 0px) * 0.62), #000 var(--fx-r, 0px));
  mask-image: radial-gradient(circle at calc(var(--fx-x, 0px) - var(--ox, 0px)) calc(var(--fx-y, 0px) - var(--oy, 0px)), transparent calc(var(--fx-r, 0px) * 0.62), #000 var(--fx-r, 0px));
}

/* --- dither-deck -------------------------------------------------------------
   One overlay per card, between the media (below) and .stackhit / .refcredit (z-index 2 and 3). */
.fx-dd__cv {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  image-rendering: crisp-edges;
  image-rendering: pixelated;
}
/* Until the poster has been read, a closed card is plain paper, never the raw poster. */
.fx-dd__cv.is-pending { background: #fff; }

/* --- grid-wipe ---------------------------------------------------------------- */
:where([data-fx="grid-wipe"]) {
  position: relative;
  height: 50vh;
}
.fx-gw { overflow: hidden; }
.fx-gw__cv { left: 0; top: 0; }
.fx-gw__raupe {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 2;
  pointer-events: none;
  will-change: transform;
}

/* --- depth ---------------------------------------------------------------------
   Put data-depth on wrappers that nothing else transforms. */
[data-fx="depth"] { perspective: 1000px; }
[data-fx="depth"] [data-depth] {
  will-change: transform;
  transform-origin: 50% 50%;
}

/* --- tile faces ----------------------------------------------------------------
   No rotation. A tile shows its grid face when is-grid XOR is-trail (sections.js sets is-grid,
   the flip-trail wake sets is-trail), otherwise its render face. Both faces share one place and
   the hidden one is visibility:hidden. js/fx.js (TileSwap) changes the visible face with a
   stepped dither reveal. It sets inline visibility and z-index only while a reveal runs, and
   inline styles win over these rules, so the outgoing face stays under the incoming one. */
.tile__b { visibility: hidden; }
.tile.is-grid:not(.is-trail) .tile__b,
.tile.is-trail:not(.is-grid) .tile__b { visibility: visible; }
.tile.is-grid:not(.is-trail) .tile__f,
.tile.is-trail:not(.is-grid) .tile__f { visibility: hidden; }
.tile__f, .tile__b {
  -webkit-mask-size: 24px 24px;
  mask-size: 24px 24px;
}

/* --- mark ------------------------------------------------------------------------
   The <img> stays in the DOM for assistive technology and as the static fallback;
   it is only hidden visually once the cells are drawing. */
:where(.fx-mark) { position: relative; }
.fx-mark__cv {
  left: 0;
  top: 0;
  z-index: 1;
}
.fx-mark.is-fx-ready > img { opacity: 0; }
.fx-mark-wrap { display: inline-block; line-height: 0; }
