/* ============================================================================
   Animated placeholders

   Rendered in the browser from inline SVG, so an empty slot costs zero bytes of
   storage and zero requests. Each slot picks a scene deterministically from its
   own name — so it stays the same on every reload rather than flickering, but
   different slots show different scenes.

   Also used on the 404 page.
   ========================================================================== */

.ph {
  position: absolute; inset: 0; z-index: 0;
  display: grid; place-items: center;
  background: var(--navy);
  overflow: hidden;
  color: var(--paper);
}
.ph::before {
  /* slow drifting wash so a wall of placeholders is not flat */
  content: ""; position: absolute; inset: -30%;
  background:
    radial-gradient(40% 55% at 25% 30%, rgba(169,138,84,.30), transparent 70%),
    radial-gradient(45% 50% at 78% 68%, rgba(63,81,54,.38), transparent 70%);
  animation: ph-drift 28s ease-in-out infinite alternate;
}
@keyframes ph-drift {
  from { transform: translate3d(-3%, -2%, 0) scale(1.04); }
  to   { transform: translate3d(3%, 2%, 0) scale(1.12); }
}

.ph-inner {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; gap: .95rem;
  padding: 1.5rem; text-align: center;
}
.ph-art { width: clamp(56px, 22%, 104px); height: auto; overflow: visible; }
.ph-art path, .ph-art circle, .ph-art rect, .ph-art line, .ph-art polyline {
  vector-effect: non-scaling-stroke;
}
.ph-label {
  font-family: var(--body);
  font-size: clamp(.62rem, 1.5vw, .74rem);
  font-weight: 500; letter-spacing: .18em; text-transform: uppercase;
  color: rgba(251,249,245,.88);
}
.ph-label i { font-style: normal; opacity: 0; animation: ph-dot 1.4s steps(1) infinite; }
.ph-label i:nth-child(2) { animation-delay: .25s; }
.ph-label i:nth-child(3) { animation-delay: .5s; }
@keyframes ph-dot { 0%, 40% { opacity: 0 } 45%, 100% { opacity: .8 } }

.ph-slot {
  font-family: var(--body); font-size: .58rem; letter-spacing: .12em;
  color: rgba(251,249,245,.34); text-transform: uppercase;
}

/* ---- scene: luggage in transit ---- */
.ph-lug { animation: ph-roll 2.6s ease-in-out infinite; transform-origin: 50% 100%; }
@keyframes ph-roll {
  0%, 100% { transform: translateX(-9%) rotate(-2.5deg) }
  50%      { transform: translateX(9%) rotate(2.5deg) }
}
.ph-wheel { animation: ph-spin 1.1s linear infinite; transform-origin: center; transform-box: fill-box; }
@keyframes ph-spin { to { transform: rotate(360deg) } }
.ph-dash { stroke-dasharray: 5 9; animation: ph-dash 1.1s linear infinite; }
@keyframes ph-dash { to { stroke-dashoffset: -28 } }

/* ---- scene: camera shooting ---- */
.ph-shutter { animation: ph-shutter 3s ease-in-out infinite; transform-origin: center; transform-box: fill-box; }
@keyframes ph-shutter {
  0%, 62%, 100% { transform: scale(1); opacity: .95 }
  70%           { transform: scale(.55); opacity: .55 }
  78%           { transform: scale(1.06); opacity: 1 }
}
.ph-flash { opacity: 0; animation: ph-flash 3s ease-out infinite; }
@keyframes ph-flash { 0%, 66% { opacity: 0 } 70% { opacity: .9 } 88%, 100% { opacity: 0 } }

/* ---- scene: waveform ---- */
.ph-bar { animation: ph-eq 1.15s ease-in-out infinite; transform-origin: 50% 50%; transform-box: fill-box; }
.ph-bar:nth-child(1) { animation-delay: 0s }
.ph-bar:nth-child(2) { animation-delay: .13s }
.ph-bar:nth-child(3) { animation-delay: .26s }
.ph-bar:nth-child(4) { animation-delay: .39s }
.ph-bar:nth-child(5) { animation-delay: .52s }
.ph-bar:nth-child(6) { animation-delay: .65s }
.ph-bar:nth-child(7) { animation-delay: .78s }
@keyframes ph-eq { 0%, 100% { transform: scaleY(.28) } 50% { transform: scaleY(1) } }

/* ---- scene: film reel ---- */
.ph-reel { animation: ph-spin 4.5s linear infinite; transform-origin: center; transform-box: fill-box; }

/* ---- scene: map pin ---- */
.ph-pin { animation: ph-hop 2.4s ease-in-out infinite; transform-origin: 50% 100%; transform-box: fill-box; }
@keyframes ph-hop {
  0%, 100% { transform: translateY(0) }
  35%      { transform: translateY(-14%) }
  55%      { transform: translateY(0) }
  62%      { transform: translateY(-4%) }
  70%      { transform: translateY(0) }
}
.ph-ring { animation: ph-ping 2.4s ease-out infinite; transform-origin: center; transform-box: fill-box; }
@keyframes ph-ping {
  0%, 55% { transform: scale(.4); opacity: 0 }
  70%     { opacity: .55 }
  100%    { transform: scale(1.5); opacity: 0 }
}

/* ---- scene: coffee / editing ---- */
.ph-steam { animation: ph-steam 2.8s ease-in-out infinite; }
.ph-steam:nth-child(2) { animation-delay: .5s }
.ph-steam:nth-child(3) { animation-delay: 1s }
@keyframes ph-steam {
  0%   { opacity: 0; transform: translateY(3px) }
  35%  { opacity: .75 }
  100% { opacity: 0; transform: translateY(-9px) }
}

/* ---- scene: plate / food ---- */
.ph-sparkle { animation: ph-twinkle 2.2s ease-in-out infinite; transform-origin: center; transform-box: fill-box; }
.ph-sparkle:nth-child(2) { animation-delay: .6s }
.ph-sparkle:nth-child(3) { animation-delay: 1.2s }
@keyframes ph-twinkle {
  0%, 100% { opacity: .15; transform: scale(.7) }
  50%      { opacity: 1; transform: scale(1.1) }
}

/* Respect the setting. Everything holds a sensible static pose. */
@media (prefers-reduced-motion: reduce) {
  .ph::before, .ph-lug, .ph-wheel, .ph-dash, .ph-shutter, .ph-flash, .ph-bar,
  .ph-reel, .ph-pin, .ph-ring, .ph-steam, .ph-sparkle, .ph-label i {
    animation: none !important;
  }
  .ph-label i { opacity: .8 }
  .ph-bar { transform: scaleY(.65) }
}

/* ---- 404 ---- */
.ph--full {
  position: relative; min-height: clamp(280px, 46vh, 460px);
  border: 1px solid rgba(251,249,245,.14);
}
.ph--full .ph-art { width: clamp(88px, 16vw, 150px) }
.ph--full .ph-label { font-size: clamp(.7rem, 1.7vw, .84rem) }

/* ---------------------------------------------------------------- video cards

   A card shows the thumbnail and opens the video. Default is to open on the
   platform, because a view there counts toward the algorithm and toward what we
   can show a brand. Inline play is opt-in per card.
*/
.vcard { position: relative; display: block; overflow: hidden; background: var(--navy); }
.vcard img { width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .7s var(--ease) }
.vcard:hover img { transform: scale(1.04) }
.vplay {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: linear-gradient(180deg, rgba(15,29,43,0) 40%, rgba(15,29,43,.55));
  transition: background .3s var(--ease);
}
.vcard:hover .vplay { background: linear-gradient(180deg, rgba(15,29,43,.12) 30%, rgba(15,29,43,.62)) }
.vplay i {
  width: clamp(44px, 13%, 62px); aspect-ratio: 1; border-radius: 50%;
  background: rgba(251,249,245,.94); display: grid; place-items: center;
  transition: transform .3s var(--ease);
}
.vcard:hover .vplay i { transform: scale(1.08) }
.vplay i::after {
  content: ""; width: 0; height: 0; margin-left: 3px;
  border-left: 13px solid var(--navy);
  border-top: 8px solid transparent; border-bottom: 8px solid transparent;
}
.vmeta {
  position: absolute; left: 0; right: 0; bottom: 0; padding: .85rem 1rem;
  display: flex; align-items: center; gap: .5rem;
  font-size: .68rem; letter-spacing: .12em; text-transform: uppercase;
  color: rgba(251,249,245,.9);
}
.vmeta .plat { padding: .16rem .5rem; border: 1px solid rgba(251,249,245,.35) }
.vframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; z-index: 3 }
@media (prefers-reduced-motion: reduce) {
  .vcard img, .vplay, .vplay i { transition: none }
  .vcard:hover img { transform: none }
}


/* A loaded photograph covers the scene; a broken one leaves it visible. */
.media > img { position: relative; z-index: 1; }
.media > img[data-slot]:not([src]) { display: none; }
