/* Home page: a box of image tiles seen from inside. The back wall is a checkerboard of
   squares; the four side walls carry the grid toward the viewer in perspective and fade
   to white as they get close. Built with CSS 3D transforms only. Desktop and phone use
   different box sizes (set as variables); js/home3d.js runs the swoop-in and the tilt. */

body.home { overflow-x: hidden; }

/* The scene */
.scene {
  contain: strict;
  --w: 1500px; --h: 900px; --d: 700px; --c: 150px; --p: 1000px;
  position: relative; height: 100vh; height: 100dvh; min-height: 560px;
  overflow: hidden; background: var(--bg);
  perspective: var(--p); perspective-origin: 50% 50%;
}
.scene.phone-size { --w: 500px; --h: 1000px; --d: 380px; --c: 100px; --p: 520px; }
.box, .rig { transform-style: preserve-3d; }
.box { will-change: transform; }
.box, .rig { pointer-events: none; } /* invisible front planes must not swallow clicks */
.wall .t { pointer-events: auto; }
.wall { transform-style: flat; will-change: transform; backface-visibility: hidden; contain: layout paint; }
.box { position: absolute; left: 50%; top: 50%; width: var(--w); height: var(--h); margin: calc(var(--h) / -2) 0 0 calc(var(--w) / -2); }
.rig { position: absolute; inset: 0; }

.wall { position: absolute; display: grid; grid-auto-rows: var(--c); }
.wall.back   { left: 0; top: 0; width: var(--w); height: var(--h); transform: translateZ(calc(var(--d) * -1)); grid-template-columns: repeat(auto-fill, var(--c)); }
.wall.left   { width: var(--d); height: var(--h); left: calc(50% - var(--d) / 2); top: 0; transform: translateX(calc(var(--w) / -2)) translateZ(calc(var(--d) / -2)) rotateY(90deg); grid-template-columns: repeat(auto-fill, var(--c)); }
.wall.right  { width: var(--d); height: var(--h); left: calc(50% - var(--d) / 2); top: 0; transform: translateX(calc(var(--w) / 2)) translateZ(calc(var(--d) / -2)) rotateY(-90deg); grid-template-columns: repeat(auto-fill, var(--c)); }
.wall.top    { width: var(--w); height: var(--d); left: 0; top: calc(50% - var(--d) / 2); transform: translateY(calc(var(--h) / -2)) translateZ(calc(var(--d) / -2)) rotateX(-90deg); grid-template-columns: repeat(auto-fill, var(--c)); }
.wall.bottom { width: var(--w); height: var(--d); left: 0; top: calc(50% - var(--d) / 2); transform: translateY(calc(var(--h) / 2)) translateZ(calc(var(--d) / -2)) rotateX(90deg); grid-template-columns: repeat(auto-fill, var(--c)); }

/* Side walls fade to white toward the viewer (their near edge) */
.wall::after { content: ""; position: absolute; inset: 0; pointer-events: none; }
.wall.left::after   { background: linear-gradient(to right, var(--bg) 8%, rgba(250,250,250,0) 78%); }
.wall.right::after  { background: linear-gradient(to left,  var(--bg) 8%, rgba(250,250,250,0) 78%); }
.wall.top::after    { background: linear-gradient(to bottom, var(--bg) 8%, rgba(250,250,250,0) 78%); }
.wall.bottom::after { background: linear-gradient(to top,    var(--bg) 8%, rgba(250,250,250,0) 78%); }

/* Tint tiles: plain pale squares where a photo would otherwise repeat */
.wall .t.tint { background: var(--placeholder); }

/* Tiles: placed by grid line, square, no gaps (the white cells between them are the board) */
.wall .t { position: relative; display: block; width: var(--c); height: var(--c); overflow: hidden; }
.wall .t img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 0; filter: none; }
.wall a.t { color: var(--text); text-decoration: none; }
.wall a.t .tile-label { position: absolute; left: 0; bottom: 0; max-width: 100%; background: var(--bg); color: var(--text); padding: 4px 8px 3px; font-size: 11px; line-height: 1.3; opacity: 0; transition: opacity 150ms ease; }
.wall a.t:hover .tile-label, .wall a.t:focus-visible .tile-label { opacity: 1; }

.scene a.t:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Swoop in: the box starts almost on top of the back wall and pulls back */
@media (prefers-reduced-motion: no-preference) {
  .js .box { animation: swoop 2000ms cubic-bezier(0.3, 0, 0.15, 1) both; }
  .js .scene { animation: tile-in 500ms ease both; }
  @keyframes swoop { from { transform: translateZ(calc(var(--d) * 0.94)) rotateX(5deg) rotateY(-6deg); } to { transform: none; } }
  @keyframes tile-in { from { opacity: 0; } to { opacity: 1; } }
}

/* No skeleton shimmer on the tiles: 126 running animations is what made the page stutter. Plain white until loaded. */
.wall .t img, .js .wall .t img:not(.is-loaded) { background: var(--bg); background-image: none; animation: none; }

/* The back wall's rows 7+ only exist for the tall phone board; on desktop the wall is 6 rows */
.scene:not(.phone-size) .wall.back .t.xr { display: none; }

/* Fallback without JS or 3D: a flat board */
.no3d .scene { perspective: none; }
.no3d .wall.left, .no3d .wall.right, .no3d .wall.top, .no3d .wall.bottom { display: none; }
.no3d .wall.back { transform: none; }
