/* Film: a thin chrome TV on a chrome disc player, and one disc case per film.
   The chrome is painted by the engine (see shine in engine.js); the colour comes from the stills and the jackets. */

/* parts that move ease to their new place; the script sets how long each move takes */
.film-move { transition: transform var(--film-ms, 0ms) cubic-bezier(.45, 0, .25, 1); }

/* ---------- TV ---------- */
/* on a wide stage the TV comes forward alone while a film plays: its foot stays out of the picture */
.film-playing-wide .film-foot { visibility: hidden; }
.film-screen {
  position: absolute;
  inset: calc(var(--u) * var(--film-bezel)) calc(var(--u) * var(--film-bezel)) calc(var(--u) * var(--film-chin));
  overflow: hidden; background: #000; color: #fff;
}
.film-poster { width: 100%; height: 100%; object-fit: contain; }
.film-osd {
  position: absolute; left: 0; bottom: 0;
  padding: .35em .6em; background: #000;
  font-size: max(calc(var(--u) * 11), 11px); line-height: 1;
}
/* No disc: what an idle player puts on the TV. Neon green on-screen display, scan lines, a faint glow. */
.film-idle {
  position: absolute; inset: 0; overflow: hidden;
  background: radial-gradient(120% 90% at 50% 45%, #0c160b, #020402 78%);
  color: #39ff14; text-shadow: 0 0 .45em rgba(57, 255, 20, .6);
  font: 500 max(calc(var(--u) * 11), 10px)/1 ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: .06em; text-transform: uppercase;
}
.film-idle::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, 0) 0 2px, rgba(0, 0, 0, .3) 2px 3px);
}
.film-idle-tag { position: absolute; }
.film-idle-tl { left: 4%; top: 6%; }
.film-idle-tr { right: 4%; top: 6%; animation: film-blink 1.6s steps(1) infinite; }
.film-idle-bl { left: 4%; bottom: 6%; }
/* the message drifts corner to corner inside this area, bouncing off its edges */
.film-idle-area { position: absolute; inset: 17% 4% 17%; }
/* Two nested pairs, one for down-and-up and one for across. In each pair the outer box slides by its own
   size (the size of the area) and the inner one slides back by its own size (the size of the message),
   so the message travels exactly from one edge to the other. Only transforms move: no layout work. */
.film-idle-down { position: absolute; inset: 0; animation: film-drift-down 7.3s linear infinite alternate; }
.film-idle-up { position: absolute; left: 0; right: 0; top: 0; animation: film-drift-up 7.3s linear infinite alternate; }
.film-idle-right { animation: film-drift-right 11s linear infinite alternate; }
.film-idle-left { display: inline-block; white-space: nowrap; animation: film-drift-left 11s linear infinite alternate; }
@keyframes film-drift-down { to { transform: translateY(100%); } }
@keyframes film-drift-up { to { transform: translateY(-100%); } }
@keyframes film-drift-right { to { transform: translateX(100%); } }
@keyframes film-drift-left { to { transform: translateX(-100%); } }
/* nothing on the stage animates while it is off screen */
.stage.is-asleep .film-idle *, .stage.is-asleep .film-colon { animation-play-state: paused; }
/* with motion off the message sits still in the middle */
:root[data-motion="off"] .film-idle-down { transform: translateY(50%); }
:root[data-motion="off"] .film-idle-up { transform: translateY(-50%); }
:root[data-motion="off"] .film-idle-right { transform: translateX(50%); }
:root[data-motion="off"] .film-idle-left { transform: translateX(-50%); }
/* The embed is laid out at the size it has on the page once the TV has come close,
   then scaled back down to fit the screen. So the film's own controls come out full size. */
.film-embed {
  position: absolute; left: 0; top: 0; border: 0;
  /* the players are light-scheme pages: matching them stops the browser painting a white sheet behind them in dark mode */
  color-scheme: light; background: #000;
  width: calc(100% * var(--film-zoom, 1)); height: calc(100% * var(--film-zoom, 1));
  transform: scale(calc(1 / var(--film-zoom, 1))); transform-origin: 0 0;
}
.film-light {
  position: absolute; right: calc(var(--u) * 10); bottom: calc(var(--u) * 6);
  width: calc(var(--u) * 4); height: calc(var(--u) * 4); border-radius: 50%;
  background: #595959;
}
.film-light.film-on { background: #fff; }

/* ---------- player: a chrome bar with a dark display, after a bedside clock ----------
   The display glows the same neon green as the TV's no-disc screen (--film-neon). */
/* the front and back are rounded like the bar; the fan of strips around each edge blends into one curve */
.film-player-cap > .face { border-radius: calc(var(--u) * var(--film-round, 14)); }
.film-deck { position: absolute; inset: 0; }
.film-slot {
  position: absolute; left: calc(var(--u) * var(--film-slot-left, 34)); top: calc(50% - calc(var(--u) * 1.5));
  width: calc(var(--u) * var(--film-slot-w, 150)); height: calc(var(--u) * 3); border-radius: calc(var(--u) * 1.5);
  background: #2a3237; box-shadow: 0 calc(var(--u) * 0.6) 0 rgba(255, 255, 255, .9);
}
.film-lcd {
  position: absolute; right: calc(var(--u) * 10); top: calc(var(--u) * 7); bottom: calc(var(--u) * 7); width: calc(var(--u) * 190);
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); column-gap: calc(var(--u) * 8);
  padding: calc(var(--u) * 4.5) calc(var(--u) * 7); border-radius: calc(var(--u) * 3);
  --film-neon: #39ff14;
  background: radial-gradient(120% 140% at 50% 40%, #0c160b, #020402 80%); color: var(--film-neon);
  font: 500 calc(var(--u) * 4.6)/1 ui-monospace, "SF Mono", Menlo, Consolas, monospace; letter-spacing: .06em; text-transform: uppercase;
  text-shadow: 0 0 .45em rgba(57, 255, 20, .6);
  box-shadow: inset 0 0 0 calc(var(--u) * 0.6) rgba(0, 0, 0, .5), 0 calc(var(--u) * 0.6) 0 rgba(255, 255, 255, .9);
}
.film-lcd-col { display: flex; flex-direction: column; justify-content: space-between; min-width: 0; white-space: nowrap; }
.film-lcd-col--end { align-items: flex-end; }
.film-lcd-col span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
/* the digits glow: the segments are clipped to shape, so the glow is drawn around the whole clock */
.film-clock {
  display: flex; align-items: center; gap: calc(var(--u) * 2.4);
  filter: drop-shadow(0 0 calc(var(--u) * 1.6) rgba(57, 255, 20, .55));
}
/* seven-segment digits: every segment is always there, the lit ones glow and the rest are faint ghosts */
.film-digit { position: relative; width: calc(var(--u) * 12); height: calc(var(--u) * 23); }
.film-seg { position: absolute; background: rgba(57, 255, 20, .1); }
.film-seg.film-lit { background: var(--film-neon); }
.film-seg-a, .film-seg-g, .film-seg-d {
  left: calc(var(--u) * 1.5); right: calc(var(--u) * 1.5); height: calc(var(--u) * 2.6);
  clip-path: polygon(calc(var(--u) * 1.3) 0, calc(100% - calc(var(--u) * 1.3)) 0, 100% 50%, calc(100% - calc(var(--u) * 1.3)) 100%, calc(var(--u) * 1.3) 100%, 0 50%);
}
.film-seg-a { top: 0; }
.film-seg-g { top: calc(50% - calc(var(--u) * 1.3)); }
.film-seg-d { bottom: 0; }
.film-seg-f, .film-seg-b, .film-seg-e, .film-seg-c {
  width: calc(var(--u) * 2.6); height: calc(50% - calc(var(--u) * 1.9));
  clip-path: polygon(50% 0, 100% calc(var(--u) * 1.3), 100% calc(100% - calc(var(--u) * 1.3)), 50% 100%, 0 calc(100% - calc(var(--u) * 1.3)), 0 calc(var(--u) * 1.3));
}
.film-seg-f { left: 0; top: calc(var(--u) * 1.5); }
.film-seg-b { right: 0; top: calc(var(--u) * 1.5); }
.film-seg-e { left: 0; bottom: calc(var(--u) * 1.5); }
.film-seg-c { right: 0; bottom: calc(var(--u) * 1.5); }
.film-colon {
  width: calc(var(--u) * 2.6); height: calc(var(--u) * 12);
  background:
    radial-gradient(circle closest-side, var(--film-neon) 92%, rgba(57, 255, 20, 0)) top / 100% calc(var(--u) * 2.6) no-repeat,
    radial-gradient(circle closest-side, var(--film-neon) 92%, rgba(57, 255, 20, 0)) bottom / 100% calc(var(--u) * 2.6) no-repeat;
  animation: film-blink 2s steps(1) infinite;
}
@keyframes film-blink { 50% { opacity: .25; } }

/* ---------- disc cases ----------
   Everything on a case is sized in its own unit, so a case that is held up close can be drawn bigger. */
.film-case { --film-u: calc(var(--u) * var(--film-k, 1)); }
/* a case can be picked up and moved: it never scrolls the page under the finger */
.film-case { cursor: grab; touch-action: none; }
.film-case.film-grabbed { cursor: grabbing; }
/* the case held up to be read cannot be dragged: a finger on it scrolls the page, a press puts it back */
.film-case.film-held { cursor: pointer; touch-action: pan-y; }
.film-playing > .film-case, .film-playing > .film-disc, .film-playing > .film-shadow { visibility: hidden !important; }
/* on a wide stage the TV comes forward alone, so the player steps out too */
.film-playing-wide > .film-player { visibility: hidden; }
/* the slot lights up when a case is close enough to let go */
.film-near .film-slot { background: #fff; box-shadow: 0 0 0 calc(var(--u) * 1.5) #2a3237; }
.film-cover, .film-back {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  color: #161616; line-height: 1.25;
}
.film-cover {
  align-items: center; justify-content: space-between;
  padding: calc(var(--film-u) * 11) calc(var(--film-u) * 8) calc(var(--film-u) * 10);
  color: var(--film-ink, #161616); font-size: calc(var(--film-u) * 5.6); line-height: 1.15; text-align: center;
}
.film-cover-head { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 calc(var(--film-u) * 7); }
.film-cover-title { text-transform: uppercase; letter-spacing: .04em; }
.film-cover-still { width: 64%; height: auto; box-shadow: 0 0 0 .5px rgba(0, 0, 0, .3); }
.film-spine {
  position: absolute; inset: 0; padding: calc(var(--film-u) * 10) 0;
  writing-mode: vertical-rl; text-orientation: sideways; white-space: nowrap;
  font-size: calc(var(--film-u) * 7); line-height: calc(var(--film-u) * 14); color: var(--film-ink, #161616);
}
.film-back {
  --film-rule: calc(var(--film-u) * .35) solid currentColor;
  gap: 0; padding: calc(var(--film-u) * 9); background: #fff;
  font-size: calc(var(--film-u) * 5); line-height: 1.2;
}
.film-back-head, .film-back-foot { display: flex; justify-content: space-between; gap: calc(var(--film-u) * 6); }
.film-back-head { padding-bottom: calc(var(--film-u) * 5); }
.film-back-title { text-transform: uppercase; letter-spacing: .04em; }
.film-back-row {
  display: grid; grid-template-columns: 24% minmax(0, 1fr); column-gap: calc(var(--film-u) * 4);
  padding: calc(var(--film-u) * 3.5) 0 calc(var(--film-u) * 6); border-top: var(--film-rule);
}
.film-back-label, .film-back-foot { font-size: calc(var(--film-u) * 4); }
/* the laurels take the full width, under their label */
.film-back-row--wide { grid-template-columns: minmax(0, 1fr); row-gap: calc(var(--film-u) * 4); }
.film-back-laurels { display: grid; grid-template-columns: repeat(7, 1fr); gap: calc(var(--film-u) * 2.5); }
.film-back-laurels--few { grid-template-columns: repeat(5, 1fr); }
.film-back-laurels img { width: 100%; aspect-ratio: 3 / 2; object-fit: contain; }
.film-back-foot { margin-top: auto; padding-top: calc(var(--film-u) * 3.5); border-top: var(--film-rule); }

/* ---------- disc ---------- */
.film-disc > .face {
  background:
    radial-gradient(circle closest-side, transparent 34%, rgba(0, 0, 0, .12) 35% 36%, transparent 37%),
    conic-gradient(from 35deg, #e6e6e4, #fbfbfa 12%, #dcdcd9 25%, #f3f3f1 38%, #e6e6e4 50%, #fbfbfa 62%, #dcdcd9 75%, #f3f3f1 88%, #e6e6e4);
  box-shadow: inset 0 0 0 .5px rgba(0, 0, 0, .28);
  -webkit-mask: radial-gradient(circle closest-side, transparent 12%, #000 13%);
  mask: radial-gradient(circle closest-side, transparent 12%, #000 13%);
}

/* ---------- contact shadows ---------- */
.film-shadow > .face {
  background: rgba(0, 0, 0, .2); box-shadow: none;
  border-radius: calc(var(--u) * 12); filter: blur(calc(var(--u) * 12));
  transition: opacity 250ms;
}
.film-shadow.film-away > .face { opacity: 0; }

/* ---------- detail: the film in the player ---------- */
.film-info { display: grid; }
/* with no film in the player there is no detail, and its empty slot adds no gap */
.row-body > .detail:has(> .film-info:empty) { display: none; }
.film-row {
  display: grid; grid-template-columns: var(--col-label) minmax(0, 1fr); column-gap: var(--s-16);
  padding: var(--s-16) 0; border-top: 1px solid var(--line);
}
.film-row:last-child { border-bottom: 1px solid var(--line); }
.film-row-body { display: grid; gap: var(--s-8); min-width: 0; }
/* the list clips, because the scaled-up laurels below must not widen the page on a phone */
.film-laurels { display: grid; grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr)); gap: var(--s-24) var(--s-16); overflow: hidden; }
.film-laurels img { width: 100%; height: 5rem; object-fit: contain; }
/* the laurels are black artwork: turn them white on the dark page */
/* (screen drops the black box that an inverted white-backed file would otherwise leave) */
:root[data-theme="dark"] .film-laurels img { filter: invert(1); mix-blend-mode: screen; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .film-laurels img { filter: invert(1); mix-blend-mode: screen; } }
/* on a phone the laurels take the full width of their row, three or four across */
@media (max-width: 767px) {
  .film-row:has(> .film-row-body > .film-laurels) { grid-template-columns: minmax(0, 1fr); row-gap: var(--s-16); }
  .film-laurels { grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr)); gap: var(--s-16); }
  .film-laurels img { height: 4rem; }
}
/* some festivals ship their laurel small inside a big empty canvas: even them out by eye */
.film-laurels img[src*="lonely-wolf"], .film-back-laurels img[src*="lonely-wolf"] { transform: scale(1.5); }
.film-laurels img[src*="4th-dimension"], .film-back-laurels img[src*="4th-dimension"] { transform: scale(1.8); }

@media (forced-colors: active) {
  .film-shadow > .face { display: none; }
}
