/* [ENGINE] engine.css — board / tile / flap styles + flip keyframes.
   Rendering per DESIGN-photorealism.md (G1–G15). Compositor-safe rules:
   only transform/opacity are ever animated; every shadow/gradient below is
   static (painted once per state change, then blitted). The recessed well
   (G1–G4) is a baked CSS-gradient housing, theme-independent. */

@font-face {
  font-family: 'Roboto Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: block;
  src: url('../assets/fonts/RobotoCondensed-Bold-latin.woff2') format('woff2');
}

/* ---------- board root + letterbox ---------- */

.dk-root {
  position: relative;
  overflow: hidden;
  background: var(--dk-page, #000);   /* symmetric letterbox IS the page bg */
  -webkit-user-select: none;
  user-select: none;
}
.dk-root:focus { outline: none; }

.dk-board {
  position: absolute;
  display: grid;
  gap: var(--dk-gap);                 /* webbing channel between tiles (G11) */
  grid-auto-rows: var(--dk-th);
}

/* ---------- tile housing: recessed dark well, proud webbing ---------- */

.dk-tile {
  position: relative;
  width: var(--dk-tw);
  height: var(--dk-th);
  perspective: var(--dk-persp);       /* on the tile, so flaps share the vanishing point */
  perspective-origin: 50% 45%;
  border-radius: calc(var(--dk-th) * .045);
  background:
    /* G3 top specular lip */
    linear-gradient(180deg, rgba(66,66,66,.85) 0%, rgba(38,38,38,.45) 7%, rgba(0,0,0,0) 17%),
    /* G4 bottom AO pocket */
    linear-gradient(0deg, rgba(0,0,0,.85) 0%, rgba(0,0,0,0) 22%),
    /* G2 asymmetric shadowed side walls (key light upper-left) */
    linear-gradient(90deg, rgba(0,0,0,.55) 0%, rgba(0,0,0,0) 8%, rgba(0,0,0,0) 92%, rgba(0,0,0,.42) 100%),
    /* G1 graded well floor */
    linear-gradient(180deg, #161616 0%, #101010 52%, #060606 100%);
  box-shadow: var(--dk-tile-shadow, 0 1px 0 rgba(255,255,255,.05), 0 -1px 0 rgba(0,0,0,.5), 0 2px 5px rgba(0,0,0,.7));
  contain: layout style;
}

/* ---------- card leaves (static halves + animating flaps) ---------- */

.dk-half,
.dk-flap {
  position: absolute;
  left: var(--dk-inset);
  right: var(--dk-inset);
  height: var(--dk-half);
  overflow: hidden;
  background-image: var(--dk-card-grad);   /* translucent satin — chips shine through */
  background-color: var(--dk-card, #141414);
}

.dk-ht,
.dk-ff {
  top: var(--dk-inset);
  border-radius: 2px 2px 0 0;
  box-shadow:
    inset 0 1px 0 var(--dk-top-bevel),
    inset 0 -6px 8px -6px var(--dk-crease),
    inset 6px 0 8px -6px var(--dk-side-ao),
    inset -6px 0 8px -6px var(--dk-side-ao);
}

.dk-hb,
.dk-fr {
  top: calc(var(--dk-inset) + var(--dk-half) + var(--dk-seam));
  border-radius: 0 0 2px 2px;
  box-shadow:
    inset 0 6px 8px -6px var(--dk-crease),
    inset 6px 0 8px -6px var(--dk-side-ao),
    inset -6px 0 8px -6px var(--dk-side-ao);
}

/* G5 — fanned flap-stack striations on the static bottom half. Pure
   gradients (no mask-image, no blurred inset) so all tiles stay one flat
   cached layer; the dissolve + AO are folded into the gradient stops. */
.dk-hb::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 20%;
  z-index: 2;
  pointer-events: none;
  border-radius: 0 0 2px 2px;
  --dk-leaf: clamp(1.8px, calc(var(--dk-th) * .014), 3px);
  background:
    linear-gradient(180deg, var(--dk-card) 0, rgba(0,0,0,0) 50%),
    linear-gradient(180deg, var(--dk-stack-ao) 0, rgba(0,0,0,0) 30%),
    radial-gradient(130% 200% at 50% 100%, var(--dk-stack-fan-hi) 0%, var(--dk-stack-fan-lo) 72%),
    repeating-linear-gradient(180deg,
      var(--dk-stack-seam) 0 calc(var(--dk-leaf) * .5),
      var(--dk-stack-line) calc(var(--dk-leaf) * .5) calc(var(--dk-leaf) * .62),
      var(--dk-stack-base) calc(var(--dk-leaf) * .62) var(--dk-leaf));
}
/* Hide the stack band while an image face is shown (it would smear the photo). */
.dk-hb.dk-imgface::after { opacity: 0; }

/* ---------- glyph (G9 — matte ink, seated shadow, NO glow) ---------- */

.dk-g {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: calc(var(--dk-half) * 2 + var(--dk-seam)); /* exact card inner height → seam bisects glyph */
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Roboto Condensed', 'Arial Narrow', Arial, sans-serif;
  font-weight: 700;
  font-size: var(--dk-font);          /* 0.78 × tileH — the readability contract */
  line-height: 1;
  letter-spacing: -0.02em;
  white-space: nowrap;
  color: var(--dk-ink, #e6e0d2);
  text-shadow: var(--dk-ink-shadow, 0 1px 0 rgba(0,0,0,.55));
  z-index: 5;                         /* above the stack band */
  pointer-events: none;
  -webkit-font-smoothing: antialiased;
}
.dk-hb .dk-g,
.dk-fr .dk-g { top: calc(-1 * (var(--dk-half) + var(--dk-seam))); }
.dk-g.dk-b { color: var(--dk-ink-bold, #fff); }

/* ---------- split seam + spindle axle caps (G7, G8) ---------- */

.dk-split {
  position: absolute;
  left: var(--dk-inset);
  right: var(--dk-inset);
  top: calc(var(--dk-inset) + var(--dk-half));
  height: var(--dk-seam);
  z-index: 3;
  background: var(--dk-split-core);
  box-shadow: 0 1px 0 var(--dk-split-lip), 0 3px 4px -1px var(--dk-split-shadow);
}
.dk-split::before,
.dk-split::after {
  content: '';
  position: absolute;
  top: -1px;
  width: calc(var(--dk-th) * .05);
  height: calc(var(--dk-seam) + 2px);
  border-radius: 2px;
  background: var(--dk-cap-bg);
  box-shadow: inset 0 1px 0 var(--dk-cap-hi), 0 1px 1px rgba(0,0,0,.7);
}
.dk-split::before { left: calc(var(--dk-th) * -.012); }
.dk-split::after { right: calc(var(--dk-th) * -.012); }

/* ---------- flaps: transform/opacity-only animation ---------- */

.dk-flap {
  visibility: hidden;
  z-index: 6;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.dk-ff { transform-origin: 50% calc(100% + var(--dk-seam) / 2); transform: rotateX(0); }
.dk-fr { transform-origin: 50% calc(var(--dk-seam) / -2); transform: rotateX(90deg); }
.dk-anim .dk-flap { visibility: visible; will-change: transform; }

/* G12 — progressive flip shading: permanent shade child, opacity-animated,
   riding INSIDE the flap's compositor layer (never its own promoted layer). */
.dk-shade {
  position: absolute;
  inset: 0;
  z-index: 7;
  pointer-events: none;
}
.dk-ff .dk-shade { background: linear-gradient(180deg, rgba(0,0,0,0), var(--dk-flap-shade)); opacity: 0; }
.dk-fr .dk-shade { background: linear-gradient(180deg, var(--dk-flap-shade), rgba(0,0,0,0)); opacity: 1; }

/* A/B keyframe pairs: swapping animation-name retriggers the animation with
   no forced reflow and no per-flip allocation. Rise overshoots to -4° at 82%
   then snaps back — the mechanical bounce (G13). */
@keyframes dkFallA { from { transform: rotateX(0); } to { transform: rotateX(-90deg); } }
@keyframes dkFallB { from { transform: rotateX(0); } to { transform: rotateX(-90deg); } }
@keyframes dkRiseA { 0% { transform: rotateX(90deg); } 82% { transform: rotateX(-4deg); } 100% { transform: rotateX(0); } }
@keyframes dkRiseB { 0% { transform: rotateX(90deg); } 82% { transform: rotateX(-4deg); } 100% { transform: rotateX(0); } }
@keyframes dkShadeInA { to { opacity: 1; } }
@keyframes dkShadeInB { to { opacity: 1; } }
@keyframes dkShadeOutA { to { opacity: 0; } }
@keyframes dkShadeOutB { to { opacity: 0; } }

.dk-anim .dk-ff {
  animation: dkFallA calc(var(--dk-frame) * .5) cubic-bezier(.55, .06, .68, .19) both;
}
.dk-anim .dk-fr {
  animation: dkRiseA calc(var(--dk-frame) * .55) cubic-bezier(.22, .61, .36, 1) both;
  animation-delay: calc(var(--dk-frame) * .45);
}
.dk-anim .dk-ff .dk-shade {
  animation: dkShadeInA calc(var(--dk-frame) * .5) ease-in both;
}
.dk-anim .dk-fr .dk-shade {
  animation: dkShadeOutA calc(var(--dk-frame) * .55) ease-out both;
  animation-delay: calc(var(--dk-frame) * .45);
}
.dk-anim.dk-alt .dk-ff { animation-name: dkFallB; }
.dk-anim.dk-alt .dk-fr { animation-name: dkRiseB; }
.dk-anim.dk-alt .dk-ff .dk-shade { animation-name: dkShadeInB; }
.dk-anim.dk-alt .dk-fr .dk-shade { animation-name: dkShadeOutB; }

/* ---------- image faces (photo mode) ---------- */

.dk-imgface {
  background-repeat: no-repeat;
  /* inline style supplies background-image/size/position per tile slice */
}

/* ---------- interactive cursor (control preview) ---------- */

.dk-cursor {
  position: absolute;
  left: 0; top: 0;
  width: var(--dk-tw);
  height: var(--dk-th);
  z-index: 30;
  pointer-events: none;
  border-radius: calc(var(--dk-th) * .045);
  outline: 2px solid var(--dk-cursor, #f5a623);
  outline-offset: -2px;
  animation: dkCursorBlink 1.1s ease-in-out infinite;
  transition: transform .08s ease-out;
}
@keyframes dkCursorBlink { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }

.dk-root[data-dk-interactive] { cursor: pointer; }
