/* Project tile: one component for the home "Selected work" and the /projects/ list.
   Markup is literal (see the build contract): a.p-tile > span.p-tile-media > img, span.p-tile-foot > span.p-tile-cat + span.p-tile-name.
   Motion is the Lusion list flow rebuilt with DOM only: clip-path + translate/rotate/scale + opacity. js/project-tile.js adds the
   classes and splits the name. Hosts may override --p-radius, --p-ar and --p-name-size on a container. */
:root {
  --p-ease: cubic-bezier(.35, 0, 0, 1);        /* the strong ease-out Lusion uses for nearly all text motion */
  --p-ease-out: cubic-bezier(.16, 1, .3, 1);   /* expoOut */
  --p-ease-io: cubic-bezier(.87, 0, .13, 1);   /* expoInOut */
  --p-ease-cubic: cubic-bezier(.65, 0, .35, 1);/* cubicInOut (the zoom) */
  --p-radius: 20px;
  --p-ar: 65%;                                 /* image box height as a share of its width */
  --p-name-size: clamp(20px, 2.2vw, 34px);
}
@media (max-width: 812px) { :root { --p-radius: 10px; --p-name-size: clamp(22px, 6.4vw, 30px); } }

.p-tile { position: relative; display: block; color: var(--ink); text-decoration: none; text-align: left; -webkit-tap-highlight-color: transparent; cursor: pointer; }
.p-tile:focus-visible { outline: 2px solid var(--ink); outline-offset: 8px; border-radius: var(--p-radius); }

.p-tile-media { position: relative; display: block; padding-top: var(--p-ar); overflow: hidden; border-radius: var(--p-radius); background: var(--p-bg, var(--surface, #18191B)); }
.p-tile-media > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transform: translate3d(calc(var(--mx, 0) * -10px), calc(var(--my, 0) * -10px), 0) scale(var(--zoom, 1)); transition: transform 1s var(--p-ease); }

/* the foot: category line over the name line */
.p-tile-foot { display: block; padding-top: 18px; }
.p-tile-cat { display: block; min-height: 1.6em; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font: 300 12px/1.6 var(--font-display); letter-spacing: .24em; text-transform: uppercase; color: var(--soft); }
.p-tile-name { position: relative; display: block; height: 1.18em; margin-top: 6px; overflow: hidden; white-space: nowrap; font: 200 var(--p-name-size)/1.18 var(--font-display); letter-spacing: .08em; text-transform: uppercase; color: var(--ink); }
.p-tile-name::before { content: "\2192"; position: absolute; left: -1.1em; top: 0; width: 1em; font-weight: 200; opacity: 0; translate: 0 0; transition: translate .4s var(--p-ease) .12s, opacity .2s linear; }
.p-ch { display: inline-block; vertical-align: top; height: 1.18em; overflow: hidden; translate: 0 0; transition: translate .4s var(--p-ease) var(--hd, 0s); }
.p-ch-col { display: flex; flex-direction: column; }
.p-ch-col > span { display: block; height: 1.18em; line-height: 1.18; }
.p-ch--sp { width: .3em; }

/* touch and narrow screens: no hover, so the arrow is always there and the name sits 1.5em in, like the Lusion mobile layout */
@media (max-width: 812px), (hover: none), (pointer: coarse) {
  .p-tile-name { padding-left: 1.5em; }
  .p-tile-name::before { left: 0; opacity: 1; }
}

/* reveal: the box grows from 70% with a small slide and tilt while the picture un-zooms from 1.33. Replays every time the tile re-enters. */
@media (prefers-reduced-motion: no-preference) {
  .p-tile-media { scale: calc(1 - var(--rip, 0) * .5) 1; }
  .js .p-tile:not(.is-in) .p-tile-media { clip-path: inset(15% round var(--p-radius)); translate: var(--sx, 0) 0; rotate: var(--rot, 0deg); }
  .js .p-tile:not(.is-in) .p-tile-media > img { --zoom: 1.33; transition: none; }
  .js .p-tile.is-in .p-tile-media { clip-path: inset(0 round var(--p-radius)); translate: 0 0; rotate: 0deg; transition: clip-path 1.5s var(--p-ease-out) var(--rd, 0s), translate 2s var(--p-ease-out) var(--rd, 0s), rotate 2s var(--p-ease-out) var(--rd, 0s); }
  .js .p-tile.is-in .p-tile-media > img { transition: transform 1.5s var(--p-ease-out) var(--rd, 0s); }
  .p-tile:nth-child(odd of .p-tile:not([hidden])) .p-tile-media { --sx: 5vw; --rot: .05rad; }
  .p-tile:nth-child(even of .p-tile:not([hidden])) .p-tile-media { --sx: -5vw; --rot: -.05rad; }
  .js .p-tile:not(.is-in) .p-tile-name .p-ch-col { transform: translate3d(0, -500%, 0); }
  .js .p-tile.is-in .p-tile-name .p-ch-col { transform: none; transition: transform 1.25s var(--p-ease-io) var(--d, 0s); }
}

/* hover (mouse only): picture pushes in and follows the cursor, the name slides 1.5em with the arrow coming in from the left */
@media (hover: hover) and (pointer: fine) and (min-width: 813px) {
  .p-tile:hover .p-tile-media > img, .p-tile:focus-visible .p-tile-media > img { --zoom: 1.06; }
  .p-tile:hover .p-ch, .p-tile:focus-visible .p-ch { translate: 1.5em 0; }
  .p-tile:hover .p-tile-name::before, .p-tile:focus-visible .p-tile-name::before { opacity: 1; translate: 1.1em 0; transition-delay: 0s; }
  .p-tile:hover .p-tile-name:not(:has(.p-ch)), .p-tile:focus-visible .p-tile-name:not(:has(.p-ch)) { padding-left: 1.5em; }
}
.p-tile-name:not(:has(.p-ch)) { transition: padding-left .4s var(--p-ease); }

/* the host is hiding this tile (zoom clone is in flight) */
.p-tile.is-lifted .p-tile-media { visibility: hidden; }

@media (prefers-reduced-motion: reduce) {
  .p-tile-media > img, .p-ch, .p-tile-name::before { transition: none; }
}
