/* ============================================================================
   tiles.css — tile aesthetics.  OWNED by the "tiles aesthetics" agent.
   Style .tile-inner and its children here. Do NOT restyle .tile (geometry box)
   or .tile .fog (ring-controlled depth fog).

   "FRAMED DIORAMA" treatment:
   - gallery FRAME  : hairline + 2-tone bevel + dark mat  (physical frame feel)
   - MEDIA          : clipped, over-scaled image that parallaxes vs. the pointer
   - VIGNETTE       : radial inset shadow for focus + depth
   - GLOSS          : diagonal light sheen that sweeps on hover (light-on-glass)
   - CAPTION        : slides up on hover (№ / title / year / category · medium)
   - MOOD           : shared film-grain + top-light overlays (filmic / futuristic)

   NOTE on 3D: .tile is `flat` (owned by hero.css), so a translateZ on
   .tile-inner would NOT be projected by the ring perspective. We therefore
   create a *local* perspective on .tile-inner itself (transform:perspective(...))
   so the hover lift (translateZ) and cursor tilt (rotateX/Y) render tactile.
   JS in tiles.js composes the full transform string every frame.
   ========================================================================== */

:root{
  --tile-radius: 2px;
  --frame-pad: clamp(6px, 0.9vw, 12px);   /* mat/frame thickness */
  --ease: cubic-bezier(.25,.46,.45,.94);
}

/* ---- FRAME : the physical gallery frame + mat -------------------------- */
/* .tile-inner is the outer frame face. Bevel = 2-tone inset highlight/shadow
   + a crisp 1px hairline. A dark mat is the padding around .media.           */
.tile-inner{
  position:absolute; inset:0;              /* fill the geometry box (contract) */
  overflow:hidden;
  border-radius:var(--tile-radius);
  background:#0c0c0d;                       /* dark mat / graceful bg */
  padding:var(--frame-pad);                 /* mat between frame edge and image */
  transform-style:preserve-3d;              /* let children tilt in local 3D */
  transform-origin:50% 50%;
  will-change:transform;
  /* 2-tone bevel: top-left catches light, bottom-right falls to shadow,
     plus a hairline rim and the base recessed drop shadow.                    */
  box-shadow:
    0 0 0 1px #ffffff26 inset,             /* crisp hairline rim */
    0 1px 0 #ffffff1f inset,               /* top bevel highlight */
    0 -1px 0 #00000080 inset,              /* bottom bevel shadow */
    2px 2px 3px -2px #0000009e inset,      /* inner bevel falloff */
    0 40px 80px -30px #000c;               /* recessed drop shadow (base) */
  transition:box-shadow .3s var(--ease);
}
/* frame face texture: faint top-light so the frame itself reads as lit */
.tile-inner::before{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  border-radius:var(--tile-radius);
  background:linear-gradient(155deg, #ffffff12 0%, #ffffff00 22%, #00000000 60%, #00000047 100%);
}

/* ---- MEDIA : clipped window holding the over-scaled, parallaxing image -- */
.tile-inner .media{
  position:absolute; inset:var(--frame-pad);   /* sits inside the mat */
  overflow:hidden;                              /* clip the parallax */
  border-radius:1px;
  background:#111;                              /* graceful bg if img not loaded */
  /* thin dark line where the mat meets the image (recessed picture edge) */
  box-shadow:
    0 0 0 1px #00000099 inset,
    0 2px 10px -4px #000000b3;
  z-index:1;
}
.tile-inner .media img{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover; display:block;
  /* over-scale so there's headroom to translate for parallax without gaps */
  transform:scale(1.14);
  transform-origin:50% 50%;
  will-change:transform;
  /* the image also fades in gracefully; keep GPU-friendly */
  backface-visibility:hidden;
}

/* ---- VIGNETTE : radial inset darkening the image corners --------------- */
.tile-inner .vignette{
  position:absolute; inset:var(--frame-pad); z-index:2; pointer-events:none;
  border-radius:1px;
  background:radial-gradient(120% 120% at 50% 42%,
             #00000000 46%, #00000042 78%, #00000085 100%);
  /* no mix-blend-mode: blend groups re-rasterize as the 3D scene moves → flicker.
     Plain alpha-black over the image darkens the corners near-identically. */
}

/* ---- GLOSS : diagonal sheen that sweeps across on hover ---------------- */
.tile-inner .gloss{
  position:absolute; inset:0; z-index:3; pointer-events:none;
  border-radius:var(--tile-radius);
  opacity:0;
  background:linear-gradient(115deg,
             #ffffff00 30%, #ffffff1c 46%, #ffffff38 50%, #ffffff1c 54%, #ffffff00 70%);
  background-size:260% 260%;
  background-position:120% 120%;             /* off-screen start (bottom-right) */
  transition:opacity .3s var(--ease);
  /* the sweep position is driven per-frame in JS on hover */
}

/* ---- MOOD : shared film-grain overlay ---------------------------------- */
/* inline SVG fractal-noise, tiled, very low opacity. One shared data-URI. */
.tile-inner .grain{
  position:absolute; inset:0; z-index:4; pointer-events:none;
  border-radius:var(--tile-radius);
  opacity:.045;
  /* no mix-blend-mode (overlay blend flickered under 3D motion); faint gray veil */
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size:140px 140px;
}

/* ---- CAPTION : slides up on hover -------------------------------------- */
.tile-inner .caption{
  position:absolute; left:0; right:0; bottom:0; z-index:6;
  padding:calc(var(--frame-pad) + 14px) 14px 10px;
  display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 8px;
  font-size:11px; font-weight:600; line-height:1.25; letter-spacing:.01em;
  color:#fff;
  /* dark scrim behind text for legibility */
  background:linear-gradient(#00000000 0%, #00000070 42%, #000000d6 100%);
  text-shadow:0 1px 6px #000, 0 0 1px #0009;
  opacity:0;
  transform:translateY(10px);
  transition:opacity .3s var(--ease), transform .3s var(--ease);
}
.tile:hover .tile-inner .caption,
.tile.is-near .tile-inner .caption{ opacity:1; transform:translateY(0); }

.tile-inner .caption .num{
  font-variant-numeric:tabular-nums; opacity:.6; font-size:10px;
  letter-spacing:.06em; white-space:nowrap;
}
.tile-inner .caption .ttl{ flex:1 1 auto; min-width:0; font-size:13px; }
.tile-inner .caption .yr{ opacity:.7; font-variant-numeric:tabular-nums; }
/* the meta line (category · medium) takes the full second row */
.tile-inner .caption .meta{
  flex:1 0 100%; font-weight:500; font-size:10px; letter-spacing:.05em;
  text-transform:uppercase; opacity:.55;
}

/* reduced-motion: keep it calm */
@media (prefers-reduced-motion: reduce){
  .tile-inner, .tile-inner .caption, .tile-inner .gloss{ transition-duration:.001ms; }
  .tile-inner .media img{ transform:scale(1.06); }
}
