/* ═══════════════════════════════════════════════════════════════════════════
 * THE COLD OPEN
 *
 * A tall section with a pinned stage. Scroll position inside the section is the
 * film's transport; the stage itself never moves and never traps the scroll.
 *
 * Three layers, back to front:
 *   canvas #storm       the far field — hundreds of objects, out of focus
 *   .cine-field         the readable messages, positioned by JS transforms
 *   .cine-copy          the scene type, staged in one optical centre
 * ═══════════════════════════════════════════════════════════════════════════ */

.cine {
  position: relative;
  /* Roughly two viewport scrolls of transport, plus the pinned screen. */
  height: 320svh;
  isolation: isolate;
}

/* The scene family clips its own overflow, which would make the pin stick to a
   box that never scrolls. The clipping belongs on the pin itself instead. */
.scene-night.cine { overflow: visible; }

.cine-pin {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  display: grid;
  place-items: center;
}

.storm,
.cine-field,
.cine-marks {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.storm { width: 100%; height: 100%; }
.cine-field { z-index: 1; }
/* Above the field: the names are the meaning, so they must never be read
   through a card that happens to be drifting over them. */
.cine-marks { z-index: 2; }

/* ─────────── One arriving message ───────────
 * Sized so the sender and subject are legible at rest and the preview reads as
 * texture. Everything is transform/opacity driven; nothing here reflows. */
.msg {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 246px;
  margin: -33px 0 0 -123px;
  display: grid;
  grid-template-columns: 26px 1fr;
  gap: 9px;
  align-items: start;
  padding: 10px 11px;
  border: 1px solid rgba(255, 255, 255, 0.075);
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(24, 30, 44, 0.96), rgba(16, 21, 32, 0.96));
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.42);
  opacity: 0;
  will-change: transform, opacity;
  backface-visibility: hidden;
  text-align: left;
}

.msg.d1 { box-shadow: 0 8px 22px rgba(0, 0, 0, 0.38); }
.msg.d2 { box-shadow: 0 6px 16px rgba(0, 0, 0, 0.34); }

.msg-av {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.07);
  color: var(--on-night-2);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.msg-b { display: grid; gap: 2px; min-width: 0; }

.msg-top { display: flex; align-items: center; gap: 5px; min-width: 0; }

.msg-top b {
  flex: 0 1 auto;
  font-size: 0.63rem;
  font-weight: 650;
  letter-spacing: -0.005em;
  color: var(--on-night);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.msg-top i {
  margin-left: auto;
  flex: none;
  font-style: normal;
  font-size: 0.56rem;
  font-weight: 500;
  color: var(--on-night-3);
}

.msg-clip {
  flex: none;
  width: 9px;
  height: 9px;
  fill: none;
  stroke: var(--on-night-3);
  stroke-width: 1.9;
  stroke-linecap: round;
}

.msg-sub {
  font-size: 0.635rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--on-night-2);
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.msg-pre {
  font-size: 0.585rem;
  line-height: 1.35;
  color: var(--on-night-3);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.msg-badge {
  position: absolute;
  top: -7px;
  right: 9px;
  padding: 2px 6px;
  border-radius: 5px;
  background: rgba(214, 138, 46, 0.9);
  color: #14100a;
  font-size: 0.5rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

/* Kind is carried by a hairline down the leading edge — enough to feel a mix of
   invoices, travel, security and threads without labelling every card. */
.msg::before {
  content: "";
  position: absolute;
  left: 0;
  top: 11px;
  bottom: 11px;
  width: 2px;
  border-radius: 0 2px 2px 0;
  background: rgba(255, 255, 255, 0.16);
}

.msg.k-invoice::before  { background: #7f8aa6; }
.msg.k-travel::before   { background: #3f7fe0; }
.msg.k-security::before { background: #cf8b3a; }
.msg.k-invite::before   { background: #4f9ad8; }
.msg.k-thread::before   { background: #6f7ca0; }
.msg.k-promo::before,
.msg.k-news::before,
.msg.k-system::before   { background: rgba(255, 255, 255, 0.1); }

/* The three that survive carry Xaviour's light once it is on. */
.msg.is-keeper {
  border-color: rgba(90, 150, 255, 0.42);
  background: linear-gradient(180deg, rgba(28, 40, 64, 0.97), rgba(18, 26, 42, 0.97));
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(70, 130, 245, 0.14),
              0 0 34px rgba(50, 120, 240, 0.22);
}

.msg.is-keeper::before { background: var(--blue); }

/* ─────────── Cluster marks (scene 4) ───────────
 * Positioned by JS at the same coordinates the cards are travelling to, so the
 * grouping is legible as meaning rather than as motion. */
.cl {
  position: absolute;
  left: 0;
  top: 0;
  translate: -50% -50%;
  display: grid;
  justify-items: center;
  gap: 3px;
  padding: 10px 18px;
  opacity: 0;
  white-space: nowrap;
}

/* Its own well of shadow, so the count reads cleanly over whatever is left of
   the pile it belongs to. */
.cl::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -120% -40%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(6, 9, 15, 0.92) 0%,
    rgba(6, 9, 15, 0.6) 46%, rgba(6, 9, 15, 0) 78%);
  opacity: var(--scrim, 1);
}

.cl b {
  font-size: 1.35rem;
  font-weight: 660;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--on-night-2);
}

.cl span {
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--on-night-3);
}

.cl.t-blue b { color: #cfe0ff; }
.cl.t-blue span { color: #7fa6e8; }
.cl.t-amber b { color: #f0d3a8; }

/* ─────────── Scene type ─────────── */
.cine-copy {
  position: relative;
  z-index: 3;
  display: grid;
  place-items: center;
  width: min(1180px, calc(100% - 40px));
  text-align: center;
  pointer-events: none;
}

.beat {
  grid-area: 1 / 1;
  margin: 0;
  opacity: 0;
  transform: translateY(calc(var(--beat-y, 0px) + 12px));
  filter: blur(7px);
  transition: opacity 560ms cubic-bezier(0.22, 1, 0.36, 1),
              transform 560ms cubic-bezier(0.22, 1, 0.36, 1),
              filter 560ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* The order beat is the only one that shares the frame with the clusters, so it
   is lifted clear of them and reads as a title over the sorting, not through it. */
.b-order { --beat-y: -17svh; }

.beat.is-on { opacity: 1; transform: translateY(var(--beat-y, 0px)); filter: blur(0); }

/* A well of shadow under the type: the field runs straight behind it at peak
   density and dark cards on a dark ground eat the letterforms. */
.beat.is-on::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -70% -26%;
  background: radial-gradient(50% 46% at 50% 50%, rgba(6, 9, 15, 0.93) 0%,
    rgba(6, 9, 15, 0.74) 38%, rgba(6, 9, 15, 0.3) 62%, rgba(6, 9, 15, 0) 82%);
  /* Driven by the film: full strength at peak density, gone once the field is
     empty and there is nothing left to read the type through. */
  opacity: var(--scrim, 1);
  pointer-events: none;
}

.b-away {
  font-size: clamp(1.2rem, 2.4vw, 1.75rem);
  font-weight: 500;
  letter-spacing: -0.022em;
  color: var(--on-night-2);
}

/* Scene 3 — the number is the stress. */
.beat-count { margin: 0; display: grid; justify-items: center; gap: 4px; }

.beat-count b {
  font-size: clamp(3.6rem, 12vw, 8.5rem);
  font-weight: 700;
  line-height: 0.92;
  letter-spacing: -0.058em;
  font-variant-numeric: tabular-nums;
  color: var(--on-night);
  text-shadow: 0 0 70px rgba(120, 150, 210, 0.3);
}

.beat-count span {
  font-size: clamp(0.95rem, 1.9vw, 1.3rem);
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--on-night-2);
}

.triad {
  margin: 22px 0 0;
  display: grid;
  gap: 5px;
  font-size: clamp(0.95rem, 1.8vw, 1.2rem);
  font-weight: 500;
  letter-spacing: -0.018em;
  line-height: 1.45;
}

.triad span {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 420ms ease, transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
  color: var(--on-night-3);
}

.triad span.on { opacity: 1; transform: none; }
.triad span:last-child.on { color: var(--on-night); font-weight: 600; }

/* Scene 4 — Xaviour becoming active, stated once and quietly. */
.os-line {
  margin: 0;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: clamp(1.05rem, 2.1vw, 1.5rem);
  font-weight: 500;
  letter-spacing: -0.024em;
  color: var(--on-night-2);
}

.os-mark {
  width: clamp(26px, 3vw, 34px);
  height: auto;
  filter: drop-shadow(0 0 16px rgba(60, 130, 250, 0.5));
}

/* Scene 5 — the relief. */
.beat-lead {
  margin: 0;
  font-size: clamp(2.4rem, 6.6vw, 4.6rem);
  font-weight: 680;
  line-height: 1.02;
  letter-spacing: -0.045em;
  color: var(--on-night);
}

.b-payoff .beat-sub {
  margin: 12px 0 0;
  font-size: clamp(0.92rem, 1.7vw, 1.1rem);
  color: var(--on-night-2);
}

/* ─────────── The three that remain ─────────── */
.pcards {
  margin: 30px auto 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  width: min(1080px, 100%);
  text-align: left;
}

.pc {
  position: relative;
  display: grid;
  gap: 9px;
  padding: 16px 17px 15px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 15px;
  background: linear-gradient(180deg, rgba(26, 34, 52, 0.94), rgba(17, 23, 36, 0.94));
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(70, 130, 245, 0.1);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.pc header {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 9px;
  align-items: center;
}

.pc .dc-avatar { width: 30px; height: 30px; font-size: 0.62rem; }

.pc-id { display: grid; gap: 1px; min-width: 0; }

.pc-id b {
  font-size: 0.76rem;
  font-weight: 650;
  color: var(--on-night);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pc-id span { font-size: 0.64rem; color: var(--on-night-3); }

.pc .dc-chip { grid-column: 1 / -1; justify-self: start; margin-top: 1px; }

.pc-lead {
  margin: 0;
  font-size: 0.94rem;
  font-weight: 620;
  line-height: 1.3;
  letter-spacing: -0.022em;
  color: var(--on-night);
}

.pc-why { margin: 0; font-size: 0.74rem; line-height: 1.5; color: var(--on-night-3); }

.pc-next {
  margin: 3px 0 0;
  display: flex;
  align-items: center;
  gap: 7px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
  font-size: 0.7rem;
  font-weight: 600;
  color: #9dbdf2;
}

.pc-next i {
  flex: none;
  width: 13px;
  height: 13px;
  border-radius: 3px;
  background: var(--blue);
  box-shadow: 0 0 12px rgba(60, 130, 250, 0.55);
}

/* ─────────── The quiet summary ─────────── */
.cine-sum {
  margin: 26px auto 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 30px;
}

.cine-sum li { display: flex; align-items: baseline; gap: 7px; }

.cine-sum b {
  font-size: 1.02rem;
  font-weight: 660;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--on-night-2);
}

.cine-sum span { font-size: 0.71rem; color: var(--on-night-3); }
.cine-sum .is-out b { color: #cfe0ff; }
.cine-sum .is-out span { color: #8fb0e8; }

/* ─────────── Controls ─────────── */
.intro-skip {
  position: absolute;
  z-index: 4;
  right: max(22px, calc((100vw - var(--stage-w)) / 2));
  bottom: 34px;
  padding: 9px 15px;
  border: 1px solid var(--night-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--on-night-2);
  font-size: 0.76rem;
  font-weight: 600;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition: opacity 400ms ease, background 200ms var(--spring), color 200ms var(--spring);
}

.intro-skip:hover { background: rgba(255, 255, 255, 0.09); color: var(--on-night); }

.intro-cue {
  position: absolute;
  z-index: 4;
  bottom: 34px;
  left: 50%;
  translate: -50% 0;
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--on-night-3);
  opacity: 0;
  transition: opacity 600ms ease;
  pointer-events: none;
}

.intro-cue.is-on { opacity: 1; }

.intro-cue svg {
  width: 11px; height: 18px; fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}

.intro-cue.is-on svg { animation: cue-drift 2.4s ease-in-out infinite; }

@keyframes cue-drift {
  0%, 100% { transform: translateY(-2px); opacity: 0.55; }
  50% { transform: translateY(2px); opacity: 1; }
}

.cine.is-done .intro-skip { opacity: 0; pointer-events: none; }

/* The chrome stays out of the way until the film has said its piece. */
.is-intro .topbar { opacity: 0; pointer-events: none; }
.topbar { transition: opacity 700ms ease, color 300ms var(--spring),
  background 300ms var(--spring), backdrop-filter 300ms var(--spring),
  border-color 300ms var(--spring); }

/* ─────────── Narrow ─────────── */
@media (max-width: 900px) {
  .pcards { grid-template-columns: 1fr; gap: 10px; width: min(430px, 100%); }
  .pc { padding: 13px 14px 12px; gap: 6px; }
  .pc-lead { font-size: 0.86rem; }
  .pc-why { display: none; }
  .cine-sum { gap: 8px 18px; }
}

@media (max-width: 620px) {
  .cine { height: 300svh; }
  .msg { width: 208px; margin: -31px 0 0 -104px; }
  .beat.is-on::before { inset: -60% -30%; }
  .intro-skip { right: 16px; bottom: 24px; }
  .intro-cue { bottom: 24px; }
  .cine-sum b { font-size: 0.92rem; }
  .cine-sum span { font-size: 0.66rem; }
}

/* ─────────── Reduced motion ───────────
 * No transport, no pin, no storm: the resolved frame, told as a static scene. */
@media (prefers-reduced-motion: reduce) {
  .cine { height: auto; min-height: 100svh; }
  .cine-pin { position: relative; height: auto; min-height: 100svh; padding: 120px 0 90px; }
  .storm, .cine-field, .cine-marks { display: none; }
  .beat { transition: opacity 200ms ease; transform: none; filter: none; }
  .beat:not(.b-payoff) { display: none; }
  .beat.b-payoff { opacity: 1; }
  .beat.is-on::before { display: none; }
  .intro-cue.is-on svg { animation: none; }
}
