/* ==========================================================================
   ARSENE GAME STUDIO — ui.css
   States driven by js/cursor.js, js/spine.js, js/dossier.js and js/ui.js:
   sheet, split-flap, proof crossfade, ticker hover, lineup attention, house
   touch rows, ledger expand + peek, letter-form seal, dossier reveal + lens.
   Base looks live in components.css; no literal colours here (tokens only).
   ========================================================================== */

/* ---- chrome ------------------------------------------------------------- */
/* programmatic focus after an anchor jump lands on the chapter itself: no ring on a non-interactive section */
.chapter:focus, .cover:focus, .spread:focus, main:focus { outline: none; }
/* the top bar is transparent: once the page scrolls, the controls sit on a small ink plate so they stay legible */
.topbar__controls, .topbar__brand { transition: background 240ms var(--ease-expo); }
.topbar.is-scrolled .topbar__controls {
  background: var(--ink);
  padding-inline: var(--space-3);
  margin-right: calc(-1 * var(--space-3));
}
/* every modal locks the page behind it (Lenis adds .lenis-stopped on pointer devices; this covers touch) */
html.has-dialog, html.has-dialog body { overflow: hidden; }
[data-lenis-prevent] { overscroll-behavior: contain; }

/* ---- cursor: the WANTED back face shrink-wraps its text (an abspos face with inset:0 would be over-constrained) */
.cursor__face--back { right: auto; width: max-content; min-width: 100%; max-width: none; }   /* .mono's max-width: 100% would clamp it to the 28px card */

/* ---- mobile index sheet -------------------------------------------------- */
.sheet { opacity: 0; transition: opacity 240ms var(--ease-expo); }
.sheet.is-open { opacity: 1; }
.sheet.is-closing { opacity: 0; transition-duration: 200ms; }
.sheet__list { transform: translateY(24px); transition: transform 420ms var(--ease-out); }
.sheet.is-open .sheet__list { transform: none; }
.sheet__link { transition: color var(--t-micro) var(--ease-expo); }
.sheet__link:hover { color: var(--hue); }

/* ---- split-flap (EN/TR) ------------------------------------------------- */
.is-flapping { text-wrap: initial; }
.flap-w { display: inline-block; white-space: nowrap; }
.flap {
  display: inline-block;
  white-space: pre;
  transform-origin: 50% 50%;
  backface-visibility: hidden;
  will-change: transform, opacity;
}

/* ---- proof: 240ms crossfade while the page re-inks ------------------------ */
html.is-reinking body { animation: ui-reink 240ms linear; }
@keyframes ui-reink { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }

/* ---- ticker: pill hover swaps silhouette → duotone (layers fade in 180ms) -- */
@media (hover: hover) {
  .pill .char.is-swapping :is(.tone, .rim, .accent, .detail, .glow) { animation: ui-layer-in var(--t-micro) var(--ease-expo) both; }
}
@keyframes ui-layer-in { from { opacity: 0; } }
/* reduced motion: the strips stand still and become ordinary horizontal scrollers */
@media (prefers-reduced-motion: reduce) {
  .ticker__strip { overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; }
  .ticker__strip:focus-visible { outline-offset: -3px; }
  .ticker__track { animation: none !important; transform: none !important; }
}

/* ---- lineup: ui.js's fallback attention model (only when lineup.js is absent; it sets .wall.has-attention) */
.wall.has-attention .suspect__char { transition: transform var(--t-micro) var(--ease-expo); }
.wall.has-attention .suspect.is-attended .suspect__char { transform: translateY(-6px); }
.wall.has-attention .suspect .char :is(.accent--base, .accent--back) { transition: opacity 600ms var(--ease-expo); }
.wall.has-attention .suspect .char .accent--print { transition: opacity 600ms var(--ease-expo), transform 600ms var(--ease-expo); }
.wall.has-attention .suspect:not(.is-attended) .char :is(.accent--base, .accent--back) { opacity: 0.4; }
.wall.has-attention .suspect:not(.is-attended) .char .accent--print { opacity: 0.36; }
.wall.has-attention .suspect.is-attended .char { --mis-x: 0px; --mis-y: 0px; }
/* with either model: the attended suspect's name takes the live accent */
.suspect__name { transition: color var(--t-micro) var(--ease-expo); }
.suspect.is-attended .suspect__name { color: var(--hue-text); }   /* Archivo 500 at body size: the AA-safe tint at rest */

/* ---- house: a tapped row behaves like a hovered one (touch has no hover) --- */
.cast__row.is-active { background: var(--plate); }
.cast__row.is-active .portrait { transform: translate(0, -50%); opacity: 1; }
.cast__row.is-active .portrait__print { transform: translate(0, 0); }

/* ---- ledger: expand in place, the character peeks and registers ----------- */
html:not(.js) .ledger__brief { height: auto; }
.ledger__toggle .ledger__no { transition: color var(--t-micro) var(--ease-expo); }
.ledger__row.is-open .ledger__no { color: var(--hue-text); }
.ledger__brief-inner {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 400ms var(--ease-out) 160ms, transform 400ms var(--ease-out) 160ms;
}
.ledger__row.is-open .ledger__brief-inner { opacity: 1; transform: none; }
.char-mount.ledger__peek { transition: transform 400ms var(--ease-expo); }
.ledger__peek .char .accent--print { transition: transform 400ms var(--ease-expo) 260ms; }
.ledger__row.is-open .ledger__peek .char { --mis-x: 0px; --mis-y: 0px; }
@media (max-width: 899px) {
  .ledger__brief-inner { padding-right: 38%; max-width: none; }   /* the brief wraps before the peeking figure */
}

/* ---- correspondence: the seal stamps, the success line appears ------------ */
/* while blanks are flagged the running text opens up so the mono error labels sit between the lines */
.letterform__line { transition: line-height 300ms var(--ease-expo); }
.letterform.has-errors .letterform__line { line-height: 2.6; }
.letterform.has-errors .blank { line-height: 1.3; }                /* the blank hugs its input, so top:100% is right under the rule */
.letterform__line .blank__error { white-space: normal; max-width: 100%; line-height: 1.2; }
@media (max-width: 639px) {
  .letterform.has-errors .letterform__line { line-height: 3.1; }
}
.letterform__stamp { transform: scale(1.4); }
.letterform.is-sealed .letterform__stamp { animation: ui-stamp 240ms var(--ease-out) both; }
@keyframes ui-stamp { from { opacity: 0; transform: scale(1.4); } to { opacity: 1; transform: scale(1); } }
.letterform__stamp::after {
  content: "";
  position: absolute;
  inset: -18.75%;                 /* 12px outside a 64px glyph */
  border-radius: 50%;
  border: var(--hairline) solid var(--rose-deep);
  opacity: 0;
  transform: scale(0.727);        /* starts on the glyph's own edge */
}
.letterform.is-sealed .letterform__stamp::after { animation: ui-ring 400ms var(--ease-out) 160ms both; }
@keyframes ui-ring { from { opacity: 1; transform: scale(0.727); } to { opacity: 0.7; transform: scale(1); } }
.letterform.is-sealed .letterform__success { animation: ui-rise 360ms var(--ease-out) 240ms both; }
@keyframes ui-rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.blank__error, .letterform__message .blank__error { animation: ui-rise 240ms var(--ease-out) both; }

/* ---- dossier: slide up, lines wipe, the lens ------------------------------ */
.dossier { transform: translateY(100%); transition: transform 600ms var(--ease-expo); }
.dossier[open] { will-change: transform; }
.dossier.is-open { transform: none; }
.dossier.is-closing { transform: translateY(100%); transition-duration: 400ms; }
.dossier__inner { overscroll-behavior: contain; }
.dossier .rv {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 520ms var(--ease-expo);
  transition-delay: calc(200ms + var(--i, 0) * 40ms);
}
.dossier.is-revealed .rv { clip-path: inset(0 0 0 0); }
.dossier:not(.is-revealed) .rv { transition: none; }
.dossier__quote::before { content: "\201C"; }
.dossier__quote::after  { content: "\201D"; }
.char-mount.dossier__char {
  transition: transform 700ms var(--ease-out) 200ms, opacity 500ms var(--ease-out) 200ms;
}
.dossier:not(.is-revealed) .char-mount.dossier__char { transform: translate(-50%, 6%); opacity: 0; transition: none; }
.dossier__char .char .accent--print { transition: transform 600ms var(--ease-expo) 500ms; }
.dossier.is-revealed .dossier__char .char { --mis-x: 0px; --mis-y: 0px; }
.dossier__plate { touch-action: pan-y; }
/* the lens: a second copy of the character showing only its Blueprint layer, clipped to a 220px circle */
.dossier__lens {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--t-micro) var(--ease-expo);
  clip-path: circle(110px at var(--lx, 50%) var(--ly, 50%));
}
.dossier__lens::before {                 /* the paint dims inside the lens so the plan reads as an x-ray */
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: 0.5;
}
.dossier__plate.is-lens .dossier__lens { opacity: 1; }
.char-mount.dossier__lens-char {
  position: absolute;
  left: 50%;
  bottom: 4%;
  height: 88%;
  max-width: 100%;
  aspect-ratio: 5 / 8;
  transform: translateX(-50%);
}
.dossier__lens .char > g:not(.plan) { display: none; }
.dossier__lens .char .plan { display: block; }
.dossier__plate.is-plan .dossier__lens { display: none; }
.dossier__lens-hint, .dossier__plan { z-index: 3; }
.dossier__lens-hint { transition: opacity 400ms var(--ease-expo); }
.dossier__plate.is-lens .dossier__lens-hint { opacity: 0; }
.dossier__plan { transition: background var(--t-micro) var(--ease-expo), color var(--t-micro) var(--ease-expo); }
.dossier__plan[aria-pressed="true"] { background: var(--paper); color: var(--ink); }

/* ---- reduced motion: fades instead of slides, no wipes, no rolls ---------- */
@media (prefers-reduced-motion: reduce) {
  .sheet, .sheet.is-closing { transition: none; opacity: 1; }
  .sheet__list { transform: none; transition: none; }
  .dossier, .dossier.is-closing { transform: none; opacity: 0; transition: opacity 200ms linear; }
  .dossier.is-open { opacity: 1; }
  .dossier .rv, .dossier.is-revealed .rv { clip-path: none; transition: none; }
  .char-mount.dossier__char, .dossier:not(.is-revealed) .char-mount.dossier__char { transform: translateX(-50%); opacity: 1; transition: none; }
  .wall.has-attention .suspect__char, .char-mount.ledger__peek, .ledger__brief-inner,
  .wall.has-attention .suspect .char :is(.accent--base, .accent--back, .accent--print),
  .ledger__peek .char .accent--print, .dossier__char .char .accent--print { transition: none; }
  .letterform.is-sealed .letterform__stamp { animation: none; transform: none; opacity: 1; }
  .letterform.is-sealed .letterform__stamp::after, .letterform.is-sealed .letterform__success, .blank__error { animation: none; opacity: 1; }
  html.is-reinking body { animation: none; }
}
