/* Home page: the mark and the name over a moving star chart.
 *
 * The background is a looping video with a still poster behind it (the
 * poster is the loop's first frame, so the hand-off is invisible). Video and
 * poster files are versioned (/assets/home/home-v<N>-...) and generated by
 * the script in scripts/home-video/, which also updates the references here
 * and in index.html.
 *
 * The intro runs once on load: the field comes into focus, the six stars of
 * the mark gather out of it, the links are drawn in order, the ring closes,
 * and the name resolves. Its timings are the custom properties below.
 */

.home {
  --mark: min(40vmin, 21rem);
  --name-size: calc(var(--mark) * 0.122);
  --name-tracking: 0.32em;

  --intro-field: 2.8s;
  --intro-stars: 0.5s;      /* first star; the rest follow 0.16s apart */
  --intro-links: 1.35s;     /* first link; the rest follow 0.3s apart */
  --intro-ring: 2.35s;
  --intro-name: 3.1s;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-draw: cubic-bezier(0.65, 0, 0.35, 1);

  background: var(--bg);
}

@media (max-width: 30em) {
  .home {
    --mark: 46vw;
  }
}

/* ---- Field ---------------------------------------------------------------- */

.field {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: var(--bg) url("/assets/home/home-v1-landscape.jpg") center / cover no-repeat;
  animation: field-focus var(--intro-field) var(--ease-out) backwards;
}

@media (orientation: portrait) and (max-width: 47.99em) {
  .field {
    background-image: url("/assets/home/home-v1-portrait.jpg");
  }
}

.field__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

/* Keeps the lockup on clear paper whatever the loop is doing. */
.field::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: radial-gradient(ellipse 34% 40% at 50% 50%, rgb(255 255 255 / 0.55), rgb(255 255 255 / 0) 100%);
}

/* Paper grain, over the field and under the lockup. */
.field::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: url("/assets/home/grain.png") repeat;
  background-size: 64px 64px;
}

@keyframes field-focus {
  from {
    opacity: 0;
    transform: scale(1.06);
    filter: blur(14px);
  }
  55% {
    opacity: 1;
  }
}

/* ---- Lockup --------------------------------------------------------------- */

.lockup {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: calc(var(--mark) * 0.17);
  padding: var(--gutter) var(--gutter) calc(var(--gutter) + 4vh);
}

.mark {
  display: block;
  width: var(--mark);
  height: auto;
  overflow: visible;
}

.name {
  margin: 0;
  /* Trailing tracking would push the word off centre. */
  margin-right: calc(var(--name-tracking) * -1);
  color: var(--ink);
  font-size: var(--name-size);
  font-stretch: 125%;
  font-weight: 340;
  line-height: 1;
  letter-spacing: var(--name-tracking);
  font-kerning: normal;
  animation: name-resolve 1.9s var(--ease-out) var(--intro-name) backwards;
}

/* Stars gather out of the field, each from its own direction. */
.mark__stars circle {
  transform-box: fill-box;
  transform-origin: center;
  animation: star-gather 1.5s var(--ease-out) backwards;
}

.mark__stars circle:nth-child(1) { --from: -70px, 80px; animation-delay: var(--intro-stars); }
.mark__stars circle:nth-child(2) { --from: -90px, -60px; animation-delay: calc(var(--intro-stars) + 0.16s); }
.mark__stars circle:nth-child(3) { --from: 40px, 110px; animation-delay: calc(var(--intro-stars) + 0.32s); }
.mark__stars circle:nth-child(4) { --from: 100px, 70px; animation-delay: calc(var(--intro-stars) + 0.48s); }
/* The cobalt star lands as the last link reaches it. */
.mark__stars circle:nth-child(5) { --from: 80px, -90px; animation-duration: 1.7s; animation-delay: calc(var(--intro-links) + 0.45s); }
.mark__stars circle:nth-child(6) { --from: 130px, 20px; animation-delay: calc(var(--intro-links) + 0.95s); }

@keyframes star-gather {
  from {
    opacity: 0;
    transform: translate(var(--from)) scale(0.3);
  }
  35% {
    opacity: 0.5;
  }
}

/* Links are drawn star to star. */
.mark__links line {
  stroke-dasharray: 1 1;
  animation: draw 0.62s var(--ease-draw) backwards;
}

.mark__links line:nth-child(1) { animation-delay: var(--intro-links); }
.mark__links line:nth-child(2) { animation-delay: calc(var(--intro-links) + 0.3s); }
.mark__links line:nth-child(3) { animation-delay: calc(var(--intro-links) + 0.6s); }
.mark__links line:nth-child(4) { animation-delay: calc(var(--intro-links) + 0.9s); }

.mark__ring {
  stroke-dasharray: 1 1;
  animation: draw 1.6s var(--ease-draw) var(--intro-ring) backwards;
}

.mark__ticks {
  animation: fade-in 0.9s ease-out calc(var(--intro-ring) + 1.1s) backwards;
}

@keyframes draw {
  from {
    stroke-dashoffset: 1;
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
}

@keyframes name-resolve {
  from {
    opacity: 0;
    letter-spacing: 1.1em;
    margin-right: -1.1em;
    filter: blur(6px);
  }
}

/* ---- Stillness ------------------------------------------------------------ */

/* No motion: the sources don't match, so the poster is all that loads; the
 * rules here also cover a preference changed after load. Data saver gets the
 * same treatment (home.js handles browsers that only expose it to scripts). */
@media (prefers-reduced-motion: reduce) {
  .field__video {
    display: none;
  }

  .field,
  .name,
  .mark__stars circle,
  .mark__links line,
  .mark__ring,
  .mark__ticks {
    animation: none;
  }
}

@media (prefers-reduced-data: reduce) {
  .field__video {
    display: none;
  }
}

/* Trace the N (home.js): a lit star, and the ring closing in cobalt on the way in. */
.mark__stars circle.is-lit { fill: #2b59ff; transition: fill 160ms ease-out; }
.mark--open .mark__ring { stroke: #2b59ff; transition: stroke 300ms ease-out; }
@media (prefers-reduced-motion: reduce) {
  .mark__stars circle.is-lit, .mark--open .mark__ring { transition: none; }
}
