/* deliver.css — the client delivery page.
 *
 * A faithful port of the approved deliver.html design. Every rule is scoped
 * under `.dlv` (and `body.dlv-body`) so loading this file cannot alter the
 * review app, which keeps its own tokens in styles.css. This stylesheet is
 * linked only on /d/:slug.
 *
 * Brand tokens live on the root element and are swapped by [data-brand],
 * so the same markup renders either studio without a second template. */

body.dlv-body {
  margin: 0;
  background: var(--dlv-bg, #0A0A0A);
  color: var(--dlv-ink, #F2F0EC);
  font-family: 'Onest', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}
html.dlv-html { -webkit-text-size-adjust: 100%; }

.dlv {
  --bg: #0A0A0A;
  --surface: #111111;
  --line: rgba(255, 255, 255, 0.08);
  --red: #EE1C25;
  --ink: #F2F0EC;
  --muted: rgba(255, 255, 255, 0.60);
  --faint: rgba(255, 255, 255, 0.40);

  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
}
.dlv[data-brand="lupiction"] {
  --bg: #10141c;
  --surface: #171c26;
  --red: #6ea8ff;
}
/* Alvan Washington: black and off-white, like the logo. The accent is light,
   so the filled Download button takes dark text (below). */
.dlv[data-brand="alvan"] {
  --bg: #0A0A0A;
  --surface: #121212;
  --red: #F2F0EC;
}
.dlv[data-brand="alvan"] .dl { color: #0A0A0A; }
.dlv[data-brand="alvan"] .dl:focus-visible { outline-color: #F2F0EC; }

.dlv *, .dlv *::before, .dlv *::after {
  margin: 0; padding: 0; box-sizing: border-box;
}

.dlv .mono {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  text-transform: uppercase;
  letter-spacing: .25em;
}

/* header */
.dlv > header {
  display: flex; align-items: center; gap: 12px;
  padding: 18px 20px; border-bottom: 1px solid var(--line);
}
.dlv > header img { height: 26px; width: auto; display: block; }
.dlv .wordmark { font-size: 10px; color: var(--faint); }

/* main */
.dlv > main {
  flex: 1; width: 100%; max-width: 1100px; margin: 0 auto;
  padding: 32px 20px 56px;
}
.dlv .eyebrow { font-size: 10px; color: var(--red); margin-bottom: 14px; }
.dlv h1 {
  font-size: clamp(2rem, 7vw, 3.25rem); line-height: .98;
  font-weight: 800; letter-spacing: -.02em; margin-bottom: 10px;
}
.dlv .sub { font-size: 10px; color: var(--muted); margin-bottom: 28px; }

/* player */
.dlv .frame {
  position: relative; width: 100%; aspect-ratio: 16/9;
  background: #000; border: 1px solid var(--line); overflow: hidden;
}
.dlv .frame video {
  width: 100%; height: 100%; display: block;
  object-fit: contain; background: #000;
}

/* delivery block */
.dlv .deliver {
  margin-top: 28px; border: 1px solid var(--line); background: var(--surface);
  display: grid; grid-template-columns: 1fr auto; gap: 24px;
  align-items: center; padding: 24px;
}
/* A review link has no Download button, so the block collapses to one column
   rather than leaving a column of empty space where the button would be. */
.dlv .deliver:not(:has(.dl)) { grid-template-columns: 1fr; }

.dlv .specs { display: flex; flex-wrap: wrap; gap: 10px 28px; }
.dlv .spec .k { font-size: 9px; color: var(--faint); display: block; margin-bottom: 5px; }
.dlv .spec .v {
  font-size: 11px; color: var(--ink);
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: .08em;
}

.dlv .dl {
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  background: var(--red); color: #fff; border: 0; cursor: pointer;
  padding: 20px 34px; font-size: 11px; text-decoration: none; white-space: nowrap;
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  text-transform: uppercase; letter-spacing: .3em;
  transition: filter .18s ease, transform .18s ease;
}
.dlv .dl:hover { filter: brightness(1.12); }
.dlv .dl:active { transform: translateY(1px); }
.dlv .dl:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.dlv .dl svg { flex: none; }

/* The button plus, on a phone, the "Download not starting?" escape hatch for
   apps whose built-in browser cannot save files. Quiet by design: most
   visitors never need it. */
.dlv .dl-wrap { display: flex; flex-direction: column; align-items: stretch; gap: 12px; }
.dlv .dl-hint {
  margin: 0; font-size: 12px; line-height: 1.5; color: var(--muted); text-align: center;
}
.dlv .dl-hint a, .dlv .dl-hint .linklike {
  color: var(--ink); text-decoration: underline; text-underline-offset: 3px;
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
}

/* expiry — the signature element */
.dlv .expiry {
  margin-top: 14px; display: flex; align-items: center; gap: 10px;
  font-size: 10px; color: var(--faint);
}
.dlv .expiry .dot {
  width: 5px; height: 5px; border-radius: 50%; background: var(--red); flex: none;
  animation: dlv-pulse 2.4s ease-in-out infinite;
}
.dlv .expiry b { color: var(--muted); font-weight: 400; }
@keyframes dlv-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .25 } }
@media (prefers-reduced-motion: reduce) { .dlv .expiry .dot { animation: none } }

.dlv > footer {
  padding: 22px 20px; border-top: 1px solid var(--line);
  display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  font-size: 9px; color: rgba(255, 255, 255, 0.30);
}

/* ---- states: expired, revoked, still processing -----------------------
 * Same type scale and tokens as the live page, so a dead link still looks
 * like the studio rather than like a server error. */
.dlv .state-note {
  margin-top: 28px; border: 1px solid var(--line); background: var(--surface);
  padding: 24px;
}
.dlv .state-note p { font-size: 12px; color: var(--muted); line-height: 1.7; }
.dlv .state-note p + p { margin-top: 10px; }
.dlv .state-note .k { font-size: 10px; color: var(--red); margin-bottom: 12px; display: block; }

/* Inline notice above the player: the optimised preview is not ready yet and
 * the master is being streamed instead. Playback still works, so this is a
 * note, not a blocking state. */
.dlv .notice {
  margin-top: 14px; display: flex; align-items: center; gap: 10px;
  font-size: 10px; color: var(--faint);
}
.dlv .notice .dot {
  width: 5px; height: 5px; border-radius: 50%; background: var(--faint); flex: none;
  animation: dlv-pulse 2.4s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) { .dlv .notice .dot { animation: none } }

@media (max-width: 720px) {
  .dlv > main { padding: 26px 18px 44px; }
  .dlv .deliver { grid-template-columns: 1fr; gap: 22px; padding: 20px; }
  .dlv .dl { width: 100%; padding: 22px; }
  .dlv > footer { justify-content: center; text-align: center; }
}

/* ------------------------------------------------------------- photo grid
 * The gallery counterpart to `.frame`. Tiles reserve their aspect ratio from
 * the stored dimensions, so several hundred lazy-loading thumbnails settle in
 * without the page jumping under the reader's cursor. */
.dlv .ph-grid {
  margin-top: 28px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 10px;
}
.dlv .ph {
  position: relative; margin: 0; overflow: hidden;
  aspect-ratio: 1 / 1;
  background: var(--surface); border: 1px solid var(--line);
}
.dlv .ph-open {
  position: absolute; inset: 0;
  display: block; width: 100%; height: 100%;
  padding: 0; border: 0; background: none; cursor: zoom-in;
}
.dlv .ph-open img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dlv .ph-open:focus-visible { outline: 2px solid var(--red); outline-offset: -2px; }

/* The per-photo download sits on the tile. It stays visible on touch, where
 * there is no hover to reveal it. */
.dlv .ph-dl {
  position: absolute; right: 8px; bottom: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%;
  background: rgba(0, 0, 0, 0.66); color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.18);
  opacity: 0; transition: opacity .15s ease, transform .15s ease;
  backdrop-filter: blur(4px);
}
.dlv .ph-dl svg { width: 15px; height: 15px; }
.dlv .ph:hover .ph-dl,
.dlv .ph-dl:focus-visible { opacity: 1; }
@media (hover: none) { .dlv .ph-dl { opacity: 1; } }

/* ------------------------------------------------------------------ viewer
 * Fits the VISIBLE viewport: dvh follows the browser's own bars (100vh on a
 * phone includes the space under Safari's toolbar, which is how a tall video
 * got cut off at the bottom), and the safe-area insets keep it clear of the
 * notch and the home indicator. The stage takes whatever is left after the
 * top bar, and the file is contained inside it, never cropped. */
body.ph-locked { overflow: hidden; }
.ph-box {
  position: fixed; inset: 0; z-index: 90;
  height: 100vh; height: 100dvh;
  background: rgba(0, 0, 0, 0.96);
  display: flex; flex-direction: column;
  padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px)
           env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
  touch-action: pan-y;
}
.ph-box[hidden] { display: none; }
.phv-top { flex: none; display: flex; align-items: center; gap: 10px; height: 52px; padding: 0 8px 0 16px; color: #fff; }
.phv-count { font-size: 12px; letter-spacing: .12em; color: rgba(255,255,255,.85); }
.phv-tag { font-size: 10px; letter-spacing: .18em; text-transform: uppercase; padding: 3px 7px;
  border: 1px solid rgba(255,255,255,.35); border-radius: 4px; color: rgba(255,255,255,.85); }
.ph-box-close { margin-left: auto; width: 48px; height: 48px; background: none; border: 0; color: #fff;
  font-size: 34px; line-height: 1; cursor: pointer; opacity: .85; }
.ph-box-close:hover { opacity: 1; }
.phv-stage { position: relative; flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center;
  padding: 0 0 12px; }
.phv-stage img, .phv-stage video {
  width: 100%; height: 100%; max-width: 100%; max-height: 100%;
  object-fit: contain; display: block; background: transparent;
}
.phv-stage [hidden] { display: none; }
/* Big, quiet tap zones on the edges. They stop short of the bottom so a
   video's own controls stay reachable. */
.phv-zone { position: absolute; top: 0; bottom: 64px; width: 22%; max-width: 140px; background: none; border: 0;
  color: #fff; cursor: pointer; display: flex; align-items: center; padding: 0 10px; opacity: .55; }
.phv-zone span { font-size: 44px; line-height: 1; text-shadow: 0 1px 6px rgba(0,0,0,.6); }
.phv-zone:hover, .phv-zone:focus-visible { opacity: 1; }
.phv-zone.prev { left: 0; justify-content: flex-start; }
.phv-zone.next { right: 0; justify-content: flex-end; }
.phv-zone[hidden] { display: none; }
/* On a phone the edges of the video are where its own mute and full-screen
   buttons sit, so there are no tap zones there: ‹ › in the top bar, and a
   sideways swipe, move between files instead. */
.phv-navs { margin-left: auto; display: flex; gap: 2px; }
.phv-navs[hidden] { display: none; }
.phv-navs + .ph-box-close { margin-left: 4px; }
.phv-nav { width: 44px; height: 44px; border: 1px solid rgba(255,255,255,.28); border-radius: 50%; background: none;
  color: #fff; font-size: 28px; line-height: 1; padding: 0 0 4px; cursor: pointer; opacity: .9; }
.phv-nav:active { background: rgba(255,255,255,.15); }
@media (hover: none), (pointer: coarse) {
  .phv-zone { display: none !important; }
}

@media (max-width: 640px) {
  .dlv .ph-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 6px; }
}

/* Videos in a mixed delivery: poster in the grid, played in the viewer. */
.dlv .ph-open { position: relative; }
.dlv .ph-play { position: absolute; left: 8px; bottom: 8px; background: rgba(0,0,0,.72); color: #fff;
  font: 600 11px/1 'JetBrains Mono', ui-monospace, monospace; padding: 5px 7px; border-radius: 4px; }
.dlv .ph-novid { display: block; width: 100%; height: 100%; background: #1a1a1a; }

/* ---- viewer: download button, bottom right ----------------------------- */
.phv-stage { padding-bottom: 0; }
.phv-bottom {
  flex: none; display: flex; align-items: center; justify-content: flex-end; gap: 14px;
  min-height: 72px; padding: 10px 16px 14px;
}
.phv-bottom[hidden] { display: none; }
.phv-dl {
  --acc: #EE1C25; --acc-ink: #fff;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 48px; padding: 0 22px;
  background: var(--acc); color: var(--acc-ink); text-decoration: none; border: 0; cursor: pointer;
  font: 500 11px/1 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: .26em; text-transform: uppercase; white-space: nowrap;
  transition: filter .18s ease, transform .18s ease;
}
.phv-dl:hover { filter: brightness(1.12); }
.phv-dl:active { transform: translateY(1px); }
.phv-dl:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.phv-dl svg { flex: none; width: 14px; height: 14px; }
.ph-box[data-brand="lupiction"] .phv-dl { --acc: #6ea8ff; --acc-ink: #0b1424; }
.ph-box[data-brand="alvan"] .phv-dl { --acc: #F2F0EC; --acc-ink: #0A0A0A; }
@media (max-width: 640px) {
  .phv-bottom { justify-content: stretch; padding: 8px 12px 12px; }
  .phv-dl { flex: 1; min-height: 52px; }
}
