/* =========================================================================
   THOY.WORK — scale-to-fit canvas
   Two designed canvases:
     - Desktop : 1728 × 10312  (active at viewport ≥ 768px)
     - Mobile  :  402 × 8617  (active at viewport <  768px)

   Strategy: render each design at its natural Figma pixel coordinates
   inside a fixed-size canvas, then transform: scale() the whole canvas
   to fit the viewport width. All children use Figma absolute pixel
   positions — no clamps, no percentages, no edge offsets.
   ========================================================================= */

:root {
  --bg: #f6f6f6;
  --panel: #1e1e1e;
  --ink: #111111;
  --paper: #ffffff;
  --muted: #2f2f2f;

  --accent-block: #d4ed01;
  --accent-line: #d6ef01;
  --accent-title: #edff4a;

  --rule: rgba(17, 17, 17, 0.9);
  --rule-invert: rgba(255, 255, 255, 0.14);

  /* Canvas (desktop default).
     --scale is a unitless number derived from length/length division so it
     can be multiplied with px (for the stage height) and passed to scale().
     Canvas height matches the Figma frame (8532) — the big outro title
     intentionally extends past y=8532 so its bottom is cropped by the stage. */
  --canvas-w: 1728px;
  --canvas-h: 10312px;
  --scale: min(1, calc(100vw / 1728px));

  /* Canvas Y where the dark (story+outro) band begins. Used to paint the
     body background so the dark extends full viewport-width on wide screens
     and anywhere the scaled canvas leaves gutters. */
  --dark-start: 5362px;

  /* Section palette tokens. Light-mode default:
     top sections = light, bottom sections = dark. */
  --light-panel-bg: var(--bg);
  --light-panel-fg: var(--ink);
  --light-panel-rule: var(--rule);
  --light-stamp-filter: none;

  --dark-panel-bg: var(--panel);
  --dark-panel-fg: var(--paper);
  --dark-panel-rule: var(--rule-invert);
  --dark-stamp-filter: invert(1);
  --active-top-bg: var(--light-panel-bg);
  --active-top-fg: var(--light-panel-fg);
  --active-top-rule: var(--light-panel-rule);
  --active-top-stamp-filter: var(--light-stamp-filter);
}

@media (max-width: 767.98px) {
  :root {
    --canvas-w: 402px;
    --canvas-h: 8617px;
    --scale: calc(100vw / 402px);
    --dark-start: 3553px;
  }
}

html[data-theme="dark"] {
  --light-panel-bg: var(--panel);
  --light-panel-fg: var(--paper);
  --light-panel-rule: var(--rule-invert);
  --light-stamp-filter: invert(1);

  --dark-panel-bg: var(--bg);
  --dark-panel-fg: var(--ink);
  --dark-panel-rule: var(--rule);
  --dark-stamp-filter: none;
}

html[data-scroll-section="bottom"] {
  --active-top-bg: var(--dark-panel-bg);
  --active-top-fg: var(--dark-panel-fg);
  --active-top-rule: var(--dark-panel-rule);
  --active-top-stamp-filter: var(--dark-stamp-filter);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  color: var(--active-top-fg);
  font-family: "Geist Mono", ui-monospace, monospace;
  overflow-x: hidden;
  position: relative;
  background: var(--dark-panel-bg);
  transition:
    background-color 450ms ease,
    color 450ms ease;
}

img {
  display: block;
  max-width: none;
}

a {
  color: inherit;
  text-decoration: none;
}

.link-blur {
  display: inline-block;
  transition:
    filter 180ms ease,
    opacity 180ms ease;
  will-change: filter;
}

.link-blur:hover,
.link-blur:focus-visible {
  filter: blur(2px);
  opacity: 0.82;
}

/* -------------------------------------------------------------------------
   Intro reveal
   ------------------------------------------------------------------------- */

.page-intro-reveal {
  position: fixed;
  inset: 0;
  z-index: 120;
  pointer-events: none;
  overflow: hidden;
}

.page-intro-panel {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, #0f0f10 0%, #050505 100%);
  box-shadow:
    0 -18px 36px rgba(255, 255, 255, 0.03) inset,
    0 -56px 100px rgba(0, 0, 0, 0.3);
  will-change: transform;
}

.page-intro-panel::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -16vh;
  height: 18vh;
  background: linear-gradient(
    180deg,
    rgba(5, 5, 5, 0) 0%,
    rgba(5, 5, 5, 0.42) 44%,
    rgba(5, 5, 5, 0.94) 100%
  );
  filter: blur(20px);
}

.js .hero .site-stamp,
.js .hero-title-block,
.js .hero-meta,
.js .hero-portrait {
  clip-path: inset(100% 0 0 0);
  transform: translateY(22px);
  will-change: transform, clip-path;
}

.js [data-scroll-reveal] {
  clip-path: inset(100% 0 0 0);
  transform: translateY(22px);
  will-change: transform, clip-path;
}

.js [data-scroll-reveal].is-revealed {
  animation: intro-element-reveal 420ms cubic-bezier(0.24, 1, 0.36, 1) both;
}

html.page-ready .page-intro-panel {
  animation: intro-panel-lift 1480ms cubic-bezier(0.72, 0, 0.2, 1) forwards;
}

html.page-ready .page-intro-reveal {
  animation: intro-overlay-hide 40ms linear 1480ms forwards;
}

html.page-ready .hero .site-stamp,
html.page-ready .hero-title-block,
html.page-ready .hero-meta,
html.page-ready .hero-portrait {
  animation: intro-element-reveal 360ms cubic-bezier(0.24, 1, 0.36, 1) both;
}

html.page-ready .hero .site-stamp {
  animation-delay: 1520ms;
}

html.page-ready .hero-title-block {
  animation-delay: 1600ms;
}

html.page-ready .hero-meta {
  animation-delay: 1680ms;
}

html.page-ready .hero-portrait {
  animation-delay: 1760ms;
}

@keyframes intro-panel-lift {
  0% {
    transform: translateY(0);
  }

  26% {
    transform: translateY(0);
  }

  100% {
    transform: translateY(-112%);
  }
}

@keyframes intro-overlay-hide {
  to {
    opacity: 0;
    visibility: hidden;
  }
}

@keyframes intro-element-reveal {
  0% {
    clip-path: inset(100% 0 0 0);
    transform: translateY(22px);
  }

  100% {
    clip-path: inset(0 0 0 0);
    transform: translateY(0);
  }
}

/* -------------------------------------------------------------------------
   Glitch hover treatment
   Inspired by: https://codepen.io/noahblon/pen/wKvvxX
   ------------------------------------------------------------------------- */

.glitch-hover {
  isolation: isolate;
  --glitch-base-transform: translate(0, 0);
  --glitch-x: 0px;
  --glitch-y: 0px;
  --glitch-x-alt: 0px;
  --glitch-y-alt: 0px;
  --glitch-x-neg: 0px;
  --glitch-y-neg: 0px;
  --glitch-x-alt-neg: 0px;
  --glitch-y-alt-neg: 0px;
  --glitch-scale: 1;
}

.glitch-source {
  transition:
    filter 140ms ease,
    opacity 140ms ease;
  will-change: transform, filter, opacity;
}

.glitch-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  z-index: 2;
  will-change: transform, clip-path, filter, opacity;
}

.glitch-layer-red {
  filter: saturate(2.2) hue-rotate(-28deg) contrast(1.18);
  mix-blend-mode: screen;
}

.glitch-layer-blue {
  filter: saturate(1.85) hue-rotate(155deg) contrast(1.15);
  mix-blend-mode: screen;
}

.glitch-hover::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  z-index: 2;
  background:
    linear-gradient(
      90deg,
      transparent 0 14%,
      rgba(255, 0, 111, 0.22) 14% 20%,
      transparent 20% 45%,
      rgba(0, 255, 255, 0.18) 45% 54%,
      transparent 54% 100%
    ),
    repeating-linear-gradient(
      180deg,
      rgba(255, 255, 255, 0.16) 0 1px,
      transparent 1px 4px
    );
  mix-blend-mode: screen;
}

.glitch-hover.is-glitching .glitch-source {
  opacity: 0.98;
  filter: contrast(1.08) saturate(1.14);
  animation: glitch-source-shift 260ms steps(2, end) infinite;
}

.glitch-hover.is-glitching .glitch-layer {
  opacity: 0.5;
}

.glitch-hover.is-glitching .glitch-layer-red {
  animation: glitch-layer-a 220ms steps(2, end) infinite;
}

.glitch-hover.is-glitching .glitch-layer-blue {
  animation: glitch-layer-b 180ms steps(2, end) infinite;
}

.glitch-hover.is-glitching::after {
  opacity: 0.26;
  animation: glitch-scan 240ms steps(2, end) infinite;
}

@keyframes glitch-source-shift {
  0%,
  100% {
    transform: var(--glitch-base-transform);
  }

  35% {
    transform: translate(var(--glitch-x), var(--glitch-y))
      var(--glitch-base-transform);
  }

  70% {
    transform: translate(var(--glitch-x-alt-neg), var(--glitch-y-alt))
      scale(var(--glitch-scale)) var(--glitch-base-transform);
  }
}

@keyframes glitch-layer-a {
  0%,
  100% {
    clip-path: inset(0 0 0 0);
    transform: var(--glitch-base-transform);
  }

  20% {
    clip-path: inset(0 0 72% 0);
    transform: translate(var(--glitch-x), var(--glitch-y))
      var(--glitch-base-transform);
  }

  45% {
    clip-path: inset(28% 0 44% 0);
    transform: translate(var(--glitch-x-neg), var(--glitch-y-alt))
      scale(var(--glitch-scale)) var(--glitch-base-transform);
  }

  70% {
    clip-path: inset(64% 0 12% 0);
    transform: translate(var(--glitch-x-alt), var(--glitch-y-neg))
      var(--glitch-base-transform);
  }
}

@keyframes glitch-layer-b {
  0%,
  100% {
    clip-path: inset(0 0 0 0);
    transform: var(--glitch-base-transform);
  }

  18% {
    clip-path: inset(12% 0 66% 0);
    transform: translate(var(--glitch-x-alt-neg), var(--glitch-y-alt-neg))
      scale(var(--glitch-scale)) var(--glitch-base-transform);
  }

  46% {
    clip-path: inset(42% 0 34% 0);
    transform: translate(var(--glitch-x-alt), var(--glitch-y))
      var(--glitch-base-transform);
  }

  76% {
    clip-path: inset(76% 0 4% 0);
    transform: translate(var(--glitch-x-neg), var(--glitch-y-alt-neg))
      var(--glitch-base-transform);
  }
}

@keyframes glitch-scan {
  0%,
  100% {
    transform: translateX(0);
  }

  50% {
    transform: translateX(var(--glitch-x-alt));
  }
}

@media (prefers-reduced-motion: reduce) {
  .page-intro-reveal {
    opacity: 0;
    visibility: hidden;
  }

  .js .hero .site-stamp,
  .js .hero-title-block,
  .js .hero-meta,
  .js .hero-portrait,
  .js [data-scroll-reveal] {
    clip-path: inset(0 0 0 0);
    transform: none;
  }

  .glitch-layer,
  .glitch-hover::after {
    display: none;
  }

  .glitch-hover.is-glitching .glitch-source {
    animation: none;
    filter: contrast(1.06) saturate(1.06);
  }
}

/* -------------------------------------------------------------------------
   Stage + canvas
   ------------------------------------------------------------------------- */

.stage {
  width: 100vw;
  height: calc(var(--canvas-h) * var(--scale));
  overflow: hidden;
  position: relative;
  z-index: 1;
  background: var(--dark-panel-bg);
  transition: background-color 450ms ease;
}

.stage::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: calc(var(--dark-start) * var(--scale));
  background: var(--active-top-bg);
  transition: background-color 450ms ease;
  z-index: 0;
}

@media (min-width: 1728px) {
  .stage {
    display: flex;
    justify-content: center;
  }
}

.portfolio-shell {
  width: var(--canvas-w);
  height: var(--canvas-h);
  position: relative;
  transform: scale(var(--scale));
  transform-origin: top left;
  z-index: 1;
}

/* On viewports wider than the desktop canvas, keep --scale at 1 and
   center the canvas. transform-origin must shift to center for that. */
@media (min-width: 1728px) {
  .portfolio-shell {
    transform: none;
  }
}

/* -------------------------------------------------------------------------
   Panels (vertical bands inside the canvas)
   ------------------------------------------------------------------------- */

.panel {
  position: absolute;
  left: 0;
  width: var(--canvas-w);
  overflow: visible;
}

.panel-light {
  background: var(--active-top-bg);
  color: var(--active-top-fg);
  transition: background-color 450ms ease, color 450ms ease;
}

/* The lower story/outro region uses the opposite palette of the current
   site mode. Scroll sets html[data-scroll-section="bottom"] near the story,
   then CSS transitions ease the upper light panels toward the lower palette. */
.panel-dark {
  background: var(--dark-panel-bg);
  color: var(--dark-panel-fg);
  transition: background-color 450ms ease, color 450ms ease;
}

/* Desktop section bands (1728 canvas). Outro ends at canvas bottom (8532);
   the big title inside extends past that and is cropped by the stage. */
.hero  { top: 0;     height: 2009px; }
.facts { top: 2009px; height: 3353px; }
.story { top: 5362px; height: 4503px; }
.outro { top: 9865px; height: 447px;  }

/* Mobile section bands (402 canvas) */
@media (max-width: 767.98px) {
  .hero  { top: 0;     height: 1352px; }
  .facts { top: 1352px; height: 2201px; }
  .story { top: 3553px; height: 4487px; }
  .outro { top: 8040px; height: 577px;  }
}

/* The grid wrappers in markup are not used as a layout system anymore —
   children are positioned absolutely inside their panel using Figma coords. */
.grid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* -------------------------------------------------------------------------
   Typography helpers
   ------------------------------------------------------------------------- */

.body-copy {
  font-size: 20px;
  line-height: normal;
  letter-spacing: 0;
  text-transform: uppercase;
}

.body-copy p {
  margin: 0;
}

.body-copy-invert {
  color: var(--dark-panel-fg);
  transition: color 450ms ease;
}

/* =========================================================================
   HERO  — desktop (default)
   ========================================================================= */

.site-stamp {
  position: absolute;
  left: 172px;
  top: 240px;
  width: 63px;
  height: 71px;
  padding: 0;
  border: 0;
  background: transparent;
  z-index: 3;
  cursor: pointer;
}

.site-stamp img {
  --stamp-filter-base: var(--active-top-stamp-filter);
  --stamp-filter-flash-a:
    brightness(0) saturate(100%) invert(32%) sepia(98%) saturate(3149%)
    hue-rotate(311deg) brightness(101%) contrast(102%);
  --stamp-filter-flash-b:
    brightness(0) saturate(100%) invert(79%) sepia(54%) saturate(3279%)
    hue-rotate(137deg) brightness(101%) contrast(103%);
  width: 100%;
  height: auto;
  filter: var(--stamp-filter-base);
  transition:
    filter 450ms ease,
    transform 180ms ease,
    opacity 180ms ease;
}

.site-stamp-footer img {
  --stamp-filter-base: var(--dark-stamp-filter);
}

.theme-toggle:hover img,
.theme-toggle:focus-visible img {
  transform: rotate(-3deg) scale(1.03);
  opacity: 0.9;
  animation: stamp-hint-blink 720ms steps(1, end) infinite;
}

.theme-toggle:focus-visible {
  outline: 2px solid var(--accent-line);
  outline-offset: 8px;
}

@keyframes stamp-hint-blink {
  0%,
  100% {
    filter: var(--stamp-filter-base);
    opacity: 1;
  }

  20% {
    filter: var(--stamp-filter-flash-a);
    opacity: 0.96;
  }

  45% {
    filter: var(--stamp-filter-base);
    opacity: 0.9;
  }

  70% {
    filter: var(--stamp-filter-flash-b);
    opacity: 0.98;
  }
}

/* Title — horizontal slit mask.
   Figma: mask band at canvas y=791, height=177, width=1728 (full canvas).
   THOMMY (DM Sans Black 128) at canvas (734, 724) → inside mask (734, -67)
   NOZAKI (DM Sans SemiBold 128) at (584, 867) → inside mask (584, 76)
   Only the bottom of THOMMY and the top of NOZAKI show through. */
.hero-title-block {
  position: absolute;
  left: 0;
  top: 791px;
  width: var(--canvas-w);
  height: 177px;
  pointer-events: none;
  z-index: 2;
}

.hero-title-mask {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.hero-title {
  position: absolute;
  inset: 0;
}

.title-line {
  position: absolute;
  display: block;
  color: var(--active-top-fg);
  font-family: "DM Sans", sans-serif;
  font-size: 128px;
  line-height: normal;
  letter-spacing: 0;
  white-space: nowrap;
  transition: color 450ms ease;
}

.title-line-top {
  left: 734px;
  top: -67px;
  font-weight: 900;
}

.title-line-bottom {
  left: 584px;
  top: 76px;
  font-weight: 600;
}

.meta-glitch {
  isolation: isolate;
}

.meta-glitch > p,
.meta-glitch > p > a {
  display: inline-block;
  will-change: transform, text-shadow, opacity;
  animation: meta-glitch-text 1800ms steps(2, end) infinite;
}

.meta-glitch > p:nth-child(odd) {
  animation-name: meta-glitch-text-alt;
  animation-duration: 2200ms;
}

.meta-glitch > p > a {
  animation-duration: 2400ms;
}

.meta-glitch > p:nth-child(odd) > a {
  animation-name: meta-glitch-text-alt;
  animation-duration: 2600ms;
}

@keyframes meta-glitch-text {
  0%,
  100% {
    transform: translate(0, 0);
    text-shadow: none;
    opacity: 1;
  }

  25% {
    transform: translate(1px, -1px);
    text-shadow:
      2px 0 0 rgba(255, 61, 110, 0.75),
      -2px 0 0 rgba(0, 214, 255, 0.72);
  }

  50% {
    transform: translate(-1px, 1px);
    text-shadow:
      -3px 0 0 rgba(255, 61, 110, 0.62),
      3px 0 0 rgba(0, 214, 255, 0.58);
    opacity: 0.92;
  }

  75% {
    transform: translate(0, -1px);
    text-shadow:
      1px 0 0 rgba(255, 61, 110, 0.82),
      -1px 0 0 rgba(0, 214, 255, 0.82);
  }
}

@keyframes meta-glitch-text-alt {
  0%,
  100% {
    transform: translate(0, 0);
    text-shadow: none;
    opacity: 1;
  }

  20% {
    transform: translate(-1px, 0);
    text-shadow:
      -2px 0 0 rgba(255, 61, 110, 0.68),
      2px 0 0 rgba(0, 214, 255, 0.78);
  }

  56% {
    transform: translate(1px, 1px);
    text-shadow:
      3px 0 0 rgba(255, 61, 110, 0.56),
      -3px 0 0 rgba(0, 214, 255, 0.56);
    opacity: 0.9;
  }

  82% {
    transform: translate(-1px, -1px);
    text-shadow:
      -1px 0 0 rgba(255, 61, 110, 0.86),
      1px 0 0 rgba(0, 214, 255, 0.86);
  }
}

/* Hero portrait — overflows left edge by 63px */
.hero-portrait {
  position: absolute;
  left: -63px;
  top: 968px;
  width: 656px;
  height: 1034px;
  margin: 0;
  overflow: hidden;
  z-index: 1;
}

.hero-portrait img {
  position: absolute;
  inset: 0;
  width: 656px;
  height: 1034px;
  object-fit: cover;
  transform: var(--glitch-base-transform);
}

/* Hero portrait swipe — positioned relative to .hero-portrait. */
.accent-swipe {
  position: absolute;
  left: 310px;
  top: 447px;
  width: 124.7px;
  height: 22.6px;
  background: transparent;
  z-index: 2;
}

.accent-swipe::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent-block);
  transform: rotate(-4.68deg);
  transform-origin: center;
}

.hero-meta {
  position: absolute;
  left: 1014px;
  top: 1032px;
  width: 682px;
  margin: 0;
}

/* =========================================================================
   FACTS — desktop
   ========================================================================= */

/* Vertical accent guide spans hero → facts → start of story.
   Figma absolute: x=313, y=1894, height=3300. Inside .facts (top=2009),
   that is y = 1894 - 2009 = -115. */
.vertical-guide {
  position: absolute;
  left: 313px;
  top: -115px;
  width: 1px;
  height: 3300px;
  background: var(--accent-line);
  opacity: 0.85;
  z-index: 1;
}

/* Fact table: x=593, y=2009, width=1134, height=863 (Figma absolute).
   Inside .facts (top=2009) → top: 0. */
.fact-table {
  position: absolute;
  left: 593px;
  top: 0;
  width: 1134px;
  display: flex;
  flex-direction: column;
}

.fact-row {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: 20px;
  padding: 24px 0;
  position: relative;
}

/* Row separator lines:
   Each separator is the full 1134px line under each row.
   The 95px short caps on the very first and very last separators are
   handled by leaving the side rules open (they sit on top of the long line). */
.fact-row::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 1134px;
  height: 1px;
  background: var(--active-top-rule);
  transition: background-color 450ms ease;
}

/* First row also gets a top rule at y=0 */
.fact-table > .fact-row:first-child::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 1134px;
  height: 1px;
  background: var(--active-top-rule);
  transition: background-color 450ms ease;
}

.fact-row-complex {
  align-items: start;
}

.fact-label {
  margin: 0;
  font-size: 16px;
  line-height: normal;
  text-transform: uppercase;
}

.fact-content {
  font-size: 20px;
  line-height: normal;
}

.fact-content p {
  margin: 0;
}

.fact-stack {
  display: flex;
  flex-direction: column;
  gap: 19px;
}

/* Desktop fact-pair: name + date side-by-side, date right-shifted */
.fact-pair {
  display: flex;
  align-items: baseline;
  gap: 20px;
  white-space: nowrap;
}

.fact-pair p {
  margin: 0;
  font-size: 20px;
  line-height: normal;
}

.fact-pair span {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 14px;
  font-weight: 300;
  line-height: normal;
  text-transform: uppercase;
  white-space: nowrap;
}

.fact-links {
  display: flex;
  flex-direction: column;
  gap: 25px;
  font-size: 20px;
  line-height: normal;
}

/* =========================================================================
   STORY — desktop
   ========================================================================= */

/* Story container is overlay-only; children are absolutely positioned
   using panel-relative coordinates. The top slice is now a dedicated
   transition scene: some empty dark scroll, then white ASCII art, then
   the original story content starts lower. */
.story-transition {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.story-ascii {
  position: absolute;
  left: 172px;
  top: 210px;
  transform: none;
  margin: 0;
  color: var(--dark-panel-fg);
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 7px;
  line-height: 7px;
  font-weight: 400;
  letter-spacing: 0;
  white-space: pre;
  opacity: 0.96;
  text-align: left;
  z-index: 1;
}

.story-columns {
  position: absolute;
  inset: 0;
}

.story-copy {
  position: absolute;
  font-size: 16px;
  line-height: normal;
}

.story-copy p {
  margin: 0;
}

.story-copy p + p {
  margin-top: 1em;
}

.story-copy-left {
  /* Shifted down to sit after the ASCII transition scene. */
  left: 311px;
  top: 1812px;
  width: 403px;
}

.story-copy-right {
  /* Shifted down to sit after the ASCII transition scene. */
  left: 595px;
  top: 2312px;
  width: 400px;
}

.story-accent {
  position: absolute;
  /* Shifted with the rest of the story content. */
  left: 1014px;
  top: 2881px;
  width: 110px;
  height: 107px;
}

.story-accent img {
  width: 110px;
  height: 107px;
  object-fit: cover;
  transform: var(--glitch-base-transform);
}

/* Vertical line under tennis ball:
   Figma x=1069, y=6719, height=811 → panel-relative (1069, 1717) */
.story-accent span {
  position: absolute;
  left: 55px; /* 1069 - 1014 to align with ball center */
  top: 256px; /* 1717 - 1461 below the ball */
  width: 1px;
  height: 811px;
  background: var(--accent-line);
  opacity: 0.85;
}

/* Song line: Figma x=-37, y=7835, w=1922, h=208 (≈ 4 wrapped lines at 40px).
   pushed down so it lands after the longer transition scene. */
.song-line {
  position: absolute;
  left: -37px;
  top: 4253px;
  width: 1922px;
  font-size: 40px;
  font-weight: 500;
  line-height: normal;
  white-space: normal;
  overflow: hidden;
}

.song-line p {
  margin: 0;
}

.song-line span {
  color: var(--accent-line);
}

/* Subtle transition when tracks are swapped in */
.song-line[data-state="loading"] p,
.song-line[data-state="error"] p {
  opacity: 0.5;
}

/* =========================================================================
   OUTRO — desktop
   ========================================================================= */

.outro-meta {
  position: absolute;
  left: 172px;
  top: 215px; /* y=8300 in canvas, panel top=8085 → 215 */
  width: 822px;
  font-size: 20px;
}

.site-stamp-footer {
  position: absolute;
  left: 172px;
  top: 129px; /* y=8214 - 8085 */
  width: 55px;
  height: 61px;
}

.site-stamp-footer img {
  width: 100%;
  height: auto;
}

.outro-visual {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Polaroid card: Group 29 at x=1264, y=8085 → panel-relative (1264, 0)
   Card is 391×548 with the inner image rotated 5.09° */
.outro-card {
  position: absolute;
  left: 1264px;
  top: 0;
  width: 391px;
  height: 548px;
  margin: 0;
  pointer-events: auto;
  z-index: 1;
}

.outro-card img {
  width: 346px;
  height: 519px;
  object-fit: cover;
  position: absolute;
  left: 50%;
  top: 50%;
  --glitch-base-transform: translate(-50%, -50%) rotate(5.09deg);
  transform: var(--glitch-base-transform);
}

/* Outro polaroid swipe — relative to .outro-card.
   Figma absolute (1432, 8256), card at (1264, 8085) → relative (168, 171). */
.accent-swipe-small {
  position: absolute;
  left: 168px;
  top: 171px;
  width: 40.6px;
  height: 9.66px;
  transform: none;
  pointer-events: none;
  z-index: 3;
}

.accent-swipe-small::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent-block);
  transform: rotate(-1.14deg);
  transform-origin: center;
}

/* Big "THOMMY NOZAKI" title: x=-38, y=8383, w=1804, font 210, color #edff4a
   → panel-relative (-38, 298) */
.outro-title-mask {
  position: absolute;
  left: -38px;
  top: 298px;
  width: 1804px;
  height: 273px;
  overflow: hidden;
  z-index: 2;
}

.outro-visual h2 {
  margin: 0;
  position: absolute;
  left: 0;
  top: 0;
  font-family: "DM Sans", sans-serif;
  font-weight: 900;
  font-size: 210px;
  line-height: normal;
  letter-spacing: 0;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--dark-panel-fg) 16%, var(--accent-title) 84%);
  white-space: nowrap;
  transition: color 450ms ease;
}

/* =========================================================================
   MOBILE  (viewport < 768px → 402 canvas)
   All Figma coordinates are panel-relative.
   ========================================================================= */

@media (max-width: 767.98px) {
  /* ---- Hero ---- */
  .site-stamp {
    left: 20px;
    top: 117px;
    width: 43px;
    height: 49px;
  }

  /* Mobile mask band at canvas y=350, height=117, width=402.
     THOMMY at (55, 314) → inside mask (55, -36)
     NOZAKI at (-13, 406) → inside mask (-13, 56) */
  .hero-title-block {
    top: 350px;
    width: 402px;
    height: 117px;
  }

  .title-line {
    font-size: 80px;
  }

  .title-line-top {
    left: 55px;
    top: -36px;
  }

  .title-line-bottom {
    left: -13px;
    top: 56px;
  }

  .hero-portrait {
    left: -127px;
    top: 369px;
    width: 318px;
    height: 502px;
  }

  .hero-portrait img {
    width: 318px;
    height: 502px;
  }

  .accent-swipe {
    /* Mobile: portrait at (-127, 369), swipe Figma (49, 591) → (176, 222) */
    left: 150px;
    top: 215px;
    width: 55.5px;
    height: 12.7px;
  }

  .hero-meta {
    left: 84px;
    top: 911px;
    width: 298px;
    font-size: 16px;
  }

  /* ---- Facts ---- */
  .vertical-guide {
    display: none;
  }

  .fact-table {
    left: 20px;
    top: 0;
    width: 382px;
  }

  .fact-row {
    grid-template-columns: 1fr;
    gap: 12px;
    padding: 24px 0;
  }

  .fact-row::after,
  .fact-table > .fact-row:first-child::before {
    width: 382px;
  }

  .fact-label {
    font-size: 16px;
  }

  .fact-content {
    font-size: 16px;
  }

  .fact-pair {
    flex-direction: column;
    gap: 0;
    align-items: flex-start;
    white-space: normal;
  }

  .fact-pair p {
    font-size: 16px;
  }

  .fact-pair span {
    font-size: 14px;
  }

  .fact-links {
    gap: 24px;
    font-size: 16px;
  }

  .fact-stack {
    gap: 16px;
  }

  /* ---- Story ---- */
  .story-copy {
    font-size: 14px;
  }

  .story-ascii {
    left: 20px;
    top: 150px;
    font-size: 2.4px;
    line-height: 2.4px;
  }

  .story-copy-left {
    /* Shifted down to sit after the mobile ASCII transition scene. */
    left: 20px;
    top: 1975px;
    width: 234px;
  }

  .story-copy-right {
    /* Shifted down to sit after the mobile ASCII transition scene. */
    left: 147px;
    top: 2565px;
    width: 235px;
  }

  .story-accent {
    /* Shifted with the rest of the story content. */
    left: 275px;
    top: 3337px;
    width: 58px;
    height: 57px;
  }

  .story-accent img {
    width: 58px;
    height: 57px;
  }

  .story-accent span {
    /* Mobile has no vertical line under the ball */
    display: none;
  }

  .song-line {
    /* Pushed down to land after the mobile transition scene. */
    left: -12px;
    top: 4166px;
    width: 460px;
    font-size: 24px;
    white-space: normal;
  }

  .song-line p {
    width: 460px;
  }

  /* ---- Outro ---- */
  .site-stamp-footer {
    /* Figma x=20, y=6578 → panel-relative (20, 78) */
    left: 20px;
    top: 180px;
    width: 44px;
    height: 50px;
  }

  .outro-meta {
    /* Figma x=20, y=6643 → panel-relative (20, 143) */
    left: 20px;
    top: 263px;
    width: 300px;
    font-size: 16px;
  }

  .outro-card {
    /* Figma x=254, y=6806, w=226, h=317 → panel-relative (254, 306) */
    left: 254px;
    top: 306px;
    width: 226px;
    height: 317px;
  }

  .outro-card img {
    width: 200px;
    height: 300px;
  }

  .accent-swipe-small {
    /* Mobile: card at (254, 6806), swipe Figma (351, 6905) → (97, 99) */
    left: 97px;
    top: 99px;
    width: 23.5px;
    height: 5.6px;
  }

  .outro-title-mask {
    /* Figma x=-12, y=6964, w=460, h=132 → panel-relative (-12, 464) */
    left: -12px;
    top: 464px;
    width: 460px;
    height: 132px;
  }

  .outro-visual h2 {
    font-size: 96px;
    line-height: normal;
    letter-spacing: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .theme-toggle:hover img,
  .theme-toggle:focus-visible img {
    animation: none;
  }

  .meta-glitch > p,
  .meta-glitch > p > a {
    animation: none;
    transform: none;
    text-shadow: none;
    opacity: 1;
  }
}
