@font-face {
    font-family: 'Instrument Serif';
    font-style: normal; font-weight: 400; font-display: block;
    src: url('./assets/fonts/instrument-serif.woff2') format('woff2');
  }
  @font-face {
    font-family: 'Libertinus Serif Display';
    font-style: normal; font-weight: 400; font-display: block;
    src: url('./assets/fonts/libertinus-serif-display.woff2') format('woff2');
  }

  :root {
    --bg: #000611;
    --fg: #d2dcff;

    --card-h: 52.7vh;                 /* measured 442px of 838 */
    --card-w: calc(var(--card-h) * 0.5736);
    --stage-pad: 1.34;
    --card-tilt: -18deg;

    --title-top: 16px;
    --copy-top: 81.4vh;
    --copy-size: 20px;
    --copy-lh: 1.15;
    --col-max: 370px;
    --edge: 1.33vw;                   /* measured 17px of 1280 */

    --slide: .85s;                    /* background travel */
    --outro: .52s;                    /* content leaving, longest chain */
  }

  * { box-sizing: border-box; }

  html, body {
    margin: 0; height: 100%;
    background: #000611;
    color: var(--fg);
    font-family: 'Libertinus Serif Display', Georgia, serif;
    -webkit-font-smoothing: antialiased;
  }
  body { overflow: hidden; overscroll-behavior: none; }
  .stage { touch-action: none; }

  .stage {
    position: relative;
    width: 100%;
    height: 100vh; height: 100svh;
    overflow: hidden;
  }

  /* ---------- background: two panels that hand over, so the loop never ends ---------- */

  .bg {
    position: absolute;
    inset: 0;
    z-index: 0;            /* .title is z 0 too but later in the DOM, so it paints above */
    will-change: transform;
  }
  .bg.travel { transition: transform var(--slide) cubic-bezier(.65,.02,.24,1); }

  /* ---------- title: z 0, the card crosses in front of it ---------- */

  .title {
    position: absolute;
    top: var(--title-top);
    left: 0; right: 0;
    z-index: 0;
    margin: 0;
    padding: 0;
    line-height: 0;
  }
  /* textLength pins every title to the same measure, so "THE GOLDEN SUN" sets wide
     and "THE SCARLET FLAME" sets tight — exactly as the mockups do. */
  .title svg { display: block; width: 100%; height: auto; }
  .title text { fill: var(--fg); }

  .sr-only {
    position: absolute; width: 1px; height: 1px; margin: -1px;
    padding: 0; overflow: hidden; clip: rect(0 0 0 0);
    clip-path: inset(50%); white-space: nowrap;
  }

  /* ---------- card: z 10 ---------- */

  .card-stage {
    position: absolute;
    left: 50.8%; top: 51.2%;
    z-index: 10;
    width: calc(var(--card-w) * var(--stage-pad));
    height: calc(var(--card-h) * var(--stage-pad));
    transform: translate(-50%, -50%) rotate(var(--card-tilt));
    pointer-events: none;
  }

  .card-stage canvas, .card-flat, .card-hit, .card-shade {
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, -50%);
  }
  .card-stage canvas { width: 100%; height: 100%; }

  .card-shade {
    width: calc(100% / var(--stage-pad));
    height: calc(100% / var(--stage-pad));
    background: rgba(0,0,0,.5);
    border-radius: calc(var(--card-h) * 0.0207);
    transform: translate(-50%, -50%) translate(26px, 16px);
    filter: blur(34px);
  }

  .card-flat {
    width: calc(100% / var(--stage-pad));
    height: calc(100% / var(--stage-pad));
    border-radius: calc(var(--card-h) * 0.0207);
  }

  .card-hit {
    width: calc(100% / var(--stage-pad));
    height: calc(100% / var(--stage-pad));
    padding: 0; border: 0; background: transparent;
    border-radius: calc(var(--card-h) * 0.0207);
    cursor: pointer;
    pointer-events: auto;
  }
  .card-hit:focus-visible { outline: 2px solid var(--fg); outline-offset: 8px; }
  .card-flat[hidden], .card-hit[hidden] { display: none; }

  /* ---------- copy: z 20, three columns ---------- */

  .copy {
    position: absolute;
    top: var(--copy-top);
    left: 0; right: 0;
    z-index: 20;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, var(--col-max)));
    justify-content: space-between;
    align-items: start;
    padding: 0 var(--edge);
    pointer-events: none;
  }
  .copy p {
    margin: 0;
    font-size: var(--copy-size);
    line-height: var(--copy-lh);
    pointer-events: auto;
  }
  .copy p:nth-child(1) { text-align: left; }
  .copy p:nth-child(2) { text-align: center; }
  .copy p:nth-child(3) { text-align: right; }

  /* ---------- entrance, re-run on every slide change ---------- */

  @keyframes cardIn {
    from { opacity: 0; transform: translate(-50%,-50%) translate(-42px, 118px) rotate(-40deg) scale(.86); }
    to   { opacity: 1; transform: translate(-50%,-50%) translate(0,0) rotate(var(--card-tilt)) scale(1); }
  }
  @keyframes riseIn {
    from { opacity: 0; transform: translateY(var(--rise, 30px)); }
    to   { opacity: 1; transform: none; }
  }

  .card-stage { animation: cardIn .85s cubic-bezier(.22,1.28,.36,1) both; }
  .title      { animation: riseIn .72s cubic-bezier(.2,.7,.25,1) .12s both; }
  .copy p     { --rise: 14px; animation: riseIn .5s cubic-bezier(.2,.7,.25,1) both; }
  .copy p:nth-child(1) { animation-delay: .45s; }
  .copy p:nth-child(2) { animation-delay: .52s; }
  .copy p:nth-child(3) { animation-delay: .59s; }

  /* Outro is the intro run in reverse, so content leaves the way it arrived and
     nothing blanks out. The stagger flips too: copy goes first, the card last. */
  .leaving .copy p     { animation: riseIn .34s cubic-bezier(.2,.7,.25,1) reverse both; }
  .leaving .copy p:nth-child(1) { animation-delay: 0s; }
  .leaving .copy p:nth-child(2) { animation-delay: .04s; }
  .leaving .copy p:nth-child(3) { animation-delay: .08s; }
  .leaving .title      { animation: riseIn .36s cubic-bezier(.2,.7,.25,1) .06s reverse both; }
  .leaving .card-stage { animation: cardIn .42s cubic-bezier(.22,1.28,.36,1) .10s reverse both; }

  /* ---------- mobile: one column, no overlap ---------- */

  @media (max-width: 760px) {
    :root {
      --card-h: min(40vh, 72vw);
      --copy-top: auto;
      --copy-size: 13.5px;
      --col-max: 100%;
      --edge: 5vw;
    }
    .card-stage { left: 50%; top: 45%; }
    .copy {
      top: auto;
      bottom: 4.5vh;
      grid-template-columns: 1fr;
      gap: 1.1rem;
      text-align: center;
    }
    .copy p:nth-child(1), .copy p:nth-child(2), .copy p:nth-child(3) { text-align: center; }
  }

  @media (prefers-reduced-motion: reduce) {
    .bg.travel { transition: none; }
    .card-stage, .title, .copy p,
    .leaving .card-stage, .leaving .title, .leaving .copy p { animation: none; }
  }
