/* ============================================================
   TITLE SEQUENCE — "REGISTRATION"
   Opening titles for case file SS-KD-2026. Replaces the old
   0–100 loader. Choreography lives in src/scripts/titles.js;
   this file only declares the stage and its resting state.

   Every layer starts INVISIBLE here so nothing flashes before
   GSAP takes over — titles.js is the single source of motion.
   ============================================================ */

#titles {
  --tt-bg:    #050505;
  --tt-ink:   #F2EFE8;
  --tt-dim:   rgba(242, 239, 232, 0.42);
  --tt-rule:  rgba(242, 239, 232, 0.13);
  --tt-red:   #FF1A1A;
  --tt-coral: #FF6B6B;

  position: fixed;
  inset: 0;
  z-index: 9993;              /* under grain/scanlines/cursor — they texture the piece */
  overflow: hidden;
  contain: layout paint;
  font-family: var(--mono);
  pointer-events: none;       /* only the skip button is interactive */
}
#titles.gone { display: none; }

[data-theme="light"] #titles {
  --tt-bg:   #F0EDE6;
  --tt-ink:  #14110E;
  --tt-dim:  rgba(20, 17, 14, 0.5);
  --tt-rule: rgba(20, 17, 14, 0.15);
}

/* The site scrollbar rail sits above the sequence — not part of the frame */
html.titles-active .site-scrollbar { opacity: 0; }
.site-scrollbar { transition: opacity 0.5s ease; }

/* ---- backdrop (dissolves during the match cut) ---- */
.tt-bg {
  position: absolute;
  inset: 0;
  background: var(--tt-bg);
}

/* Shared stage — the frame shake on the redaction hit moves this,
   so the backdrop and HUD stay rock steady while the art jolts. */
.tt-stage {
  position: absolute;
  inset: 0;
  will-change: transform;
}

/* ============================================================
   1 — CALIBRATION GRID  (built as <line>s by titles.js)
   ============================================================ */
.tt-grid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.tt-grid .g-rule  { stroke: var(--tt-rule); stroke-width: 1; }
.tt-grid .g-cross { stroke: var(--tt-red);  stroke-width: 1; opacity: 0.55; }
.tt-grid .g-tick  { stroke: var(--tt-red);  stroke-width: 1; opacity: 0.7; }

/* Registration marks — geometrically identical to the hero's .corner
   elements, so when the backdrop dissolves they simply persist into
   the site instead of cutting. That continuity is the whole trick. */
.tt-reg {
  position: absolute;
  width: 18px;
  height: 18px;
  opacity: 0;
  pointer-events: none;
}
.tt-reg.tl { top: 20px;    left: 20px;  border-top:    1px solid var(--tt-red); border-left:  1px solid var(--tt-red); }
.tt-reg.tr { top: 20px;    right: 20px; border-top:    1px solid var(--tt-red); border-right: 1px solid var(--tt-red); }
.tt-reg.bl { bottom: 20px; left: 20px;  border-bottom: 1px solid var(--tt-red); border-left:  1px solid var(--tt-red); }
.tt-reg.br { bottom: 20px; right: 20px; border-bottom: 1px solid var(--tt-red); border-right: 1px solid var(--tt-red); }

/* ============================================================
   2 — MEASURE  (the grid rules the disciplines, then sizes them)
   ============================================================ */
.tt-measure {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  gap: clamp(26px, 4vh, 46px);
  width: min(74vw, 720px);
}
.tt-m-row { position: relative; }

/* inline-block, not block: the sequence measures this box, and a
   block would report the full row width instead of the word's */
.tt-m-word {
  display: inline-block;
  font-size: clamp(1.5rem, 5.4vw, 3.5rem);
  line-height: 1;
  letter-spacing: 0.16em;
  color: var(--tt-ink);
  white-space: nowrap;
  opacity: 0;
  /* clip-path drives the mask reveal — set explicitly so the first
     frame is already fully clipped, never a flash of full type */
  clip-path: inset(0 0 100% 0);
}

/* baseline the word sits on — draws in just before the word lands */
.tt-m-rule {
  display: block;
  height: 1px;
  margin-top: clamp(6px, 1vh, 10px);
  background: var(--tt-red);
  opacity: 0.42;
  transform: scaleX(0);
  transform-origin: 0 50%;
}

/* dimension line: |<--------->| with a live px readout */
.tt-m-dim {
  position: absolute;
  left: 0;
  bottom: -15px;
  height: 9px;
  width: 0;
  display: flex;
  align-items: center;
  opacity: 0;
}
.tt-m-dim::before,
.tt-m-dim::after {
  content: '';
  width: 1px;
  height: 9px;
  background: var(--tt-red);
  opacity: 0.8;
}
.tt-m-dim i {
  flex: 1;
  height: 1px;
  background: var(--tt-red);
  opacity: 0.45;
}
/* readout parks at the right end of the dimension line (JS sets left) */
.tt-m-num {
  position: absolute;
  bottom: -21px;
  left: 0;
  font-size: 0.625rem;
  letter-spacing: 0.22em;
  color: var(--tt-red);
  opacity: 0;
  white-space: nowrap;
}

/* ============================================================
   3 — SHUTTER  (hard cut between compositions)
   ============================================================ */
.tt-shutter {
  position: absolute;
  inset: 0;
  display: flex;
  pointer-events: none;
}
.tt-shutter i {
  flex: 1;
  background: var(--tt-red);
  transform: scaleY(0);
  transform-origin: 50% 0;
  will-change: transform;
}

/* ============================================================
   4 — NAME  (the payload — flies to the hero on the match cut)
   ============================================================ */
.tt-name {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.18em;                          /* matches .hero-name */
  font-size: clamp(4rem, 11.6vw, 9.1rem);
  line-height: 0.88;
  letter-spacing: 0.02em;
  color: var(--tt-ink);
  white-space: nowrap;
}
.tt-n-line {
  --ch: 0;                              /* chromatic split, tweened to 0 */
  display: block;
  font-family: 'SHAKA', var(--display);
  opacity: 0;
  clip-path: inset(0 0 100% 0);
  text-shadow:
    calc(var(--ch) * 1px)  0 0 var(--tt-red),
    calc(var(--ch) * -1px) 0 0 var(--tt-coral);
  will-change: transform, opacity, clip-path;
}

/* ============================================================
   5 — REDACTION  (bars are sized to the name lines at runtime)
   ============================================================ */
.tt-bars {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.tt-bars i {
  position: absolute;
  background: var(--tt-red);
  transform: scaleX(0);
  will-change: transform;
}

/* Stamped over the red bars, so the ink is the paper colour —
   red on red would not read at all. */
.tt-stamp {
  position: absolute;
  top: 50%;
  left: 50%;
  padding: clamp(8px, 1.4vh, 14px) clamp(16px, 3vw, 34px);
  border: 3px solid var(--tt-ink);
  color: var(--tt-ink);
  font-size: clamp(0.9rem, 3.1vw, 2rem);
  letter-spacing: 0.3em;
  line-height: 1;
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, -50%) rotate(-7deg) scale(2.6);
  will-change: transform, opacity, filter;
}
/* offset second impression — dry ink on the second strike */
.tt-stamp-ghost {
  border-color: var(--tt-ink);
  color: var(--tt-ink);
}

/* one-frame exposure flash on the impact */
.tt-flash {
  position: absolute;
  inset: 0;
  background: var(--tt-red);
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: screen;
}
[data-theme="light"] .tt-flash { mix-blend-mode: multiply; }

/* ============================================================
   HUD — corner slugs. Deliberately quiet; the type does the work.
   ============================================================ */
.tt-hud {
  position: absolute;
  z-index: 4;
  font-size: 0.625rem;
  letter-spacing: 0.26em;
  color: var(--tt-dim);
  opacity: 0;
  white-space: nowrap;
}
.tt-hud.tl { top: 26px;    left: 30px; }
.tt-hud.tr { top: 26px;    right: 30px; }
.tt-hud.bl { bottom: 26px; left: 30px; color: var(--tt-red); }
.tt-hud.br { bottom: 26px; right: 30px; }

.tt-skip {
  position: absolute;
  z-index: 5;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  padding: 7px 16px;
  background: transparent;
  border: 1px solid var(--tt-rule);
  color: var(--tt-dim);
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.26em;
  opacity: 0;
  pointer-events: auto;
  transition: color 0.25s ease, border-color 0.25s ease;
}
.tt-skip:hover { color: var(--tt-red); border-color: var(--tt-red); }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 640px) {
  .tt-measure { width: 82vw; }
  .tt-m-word  { letter-spacing: 0.1em; }
  .tt-name    { font-size: clamp(2.6rem, 16.5vw, 4.4rem); }
  /* HUD moves inboard of the 20px registration marks instead of through them */
  .tt-hud { font-size: 0.5625rem; letter-spacing: 0.16em; }
  .tt-hud.tl { top: 22px;    left: 46px; }
  .tt-hud.tr { top: 22px;    right: 46px; }
  .tt-hud.bl { bottom: 22px; left: 46px; }
  .tt-hud.br { display: none; }          /* coordinates are the first thing to go */
  .tt-stamp  { letter-spacing: 0.2em; border-width: 2px; }
}
/* Short viewports — rows need room for the dimension line and readout
   that hang below each one, or the next word lands on top of them */
@media (max-height: 520px) {
  .tt-measure { gap: 30px; width: min(74vw, 560px); }
  .tt-m-word  { font-size: clamp(1.1rem, 4vw, 1.75rem); }
  .tt-name    { font-size: clamp(2rem, 9vw, 3.5rem); }
  .tt-stamp   { font-size: clamp(0.8rem, 1.9vw, 1.15rem); border-width: 2px; }
}

/* ============================================================
   REDUCED MOTION — titles.js plays a 3-frame static cut instead;
   kill the transforms that would still read as movement.
   ============================================================ */
[data-motion='reduced'] .tt-shutter { display: none; }
[data-motion='reduced'] .tt-stamp   { transform: translate(-50%, -50%) rotate(-7deg) scale(1); }
